Re-import wmc from Wine

svn path=/trunk/; revision=19728
This commit is contained in:
Gé van Geldorp 2005-11-28 22:03:22 +00:00
parent 512b5dad2c
commit 0586868b52
17 changed files with 5402 additions and 2 deletions

View file

@ -364,7 +364,7 @@ $(BUGCODES_H) $(BUGCODES_RC): $(WMC_TARGET) $(NTOSKRNL_MC)
$(ERRCODES_H) $(ERRCODES_RC): $(WMC_TARGET) $(KERNEL32_MC)
$(ECHO_WMC)
$(Q)$(WMC_TARGET) -i -H $(ERRCODES_H) -o $(ERRCODES_RC) $(KERNEL32_MC)
$(Q)$(WMC_TARGET) -i -U -H $(ERRCODES_H) -o $(ERRCODES_RC) $(KERNEL32_MC)
.PHONY: msvc6
msvc6: $(RBUILD_TARGET)

View file

@ -30,7 +30,7 @@ reactos/tools/unicode # Synced to Wine-0_9_2
reactos/tools/wpp # Synced to Wine-0_9_2
reactos/tools/bin2res # Resource to binary converter
reactos/tools/winebuild # Synced to Wine-0_9_2
reactos/tools/wmc # Wine Message Compiler
reactos/tools/wmc # Synced to Wine-0_9_2
reactos/tools/wrc # Synced to Wine-0_9_2
reactos/tools/widl # Forked at Wine-20050930

View file

@ -0,0 +1,5 @@
---------------------------------------------------------------------------
Version 1.0.0 (12-Jun-2000)
Bertho Stultiens <bertho@akhphd.au.dk>
- Initial release

165
reactos/tools/wmc/lang.c Normal file
View file

@ -0,0 +1,165 @@
/*
* Wine Message Compiler language and codepage support
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "wmc.h"
#include "lang.h"
/*
* Languages supported
*
* MUST be sorting ascending on language ID
*/
static const language_t languages[] = {
{0x0000, 437, 1252, "Neutral", "Neutral"},
{0x0402, 866, 1251, "Bulgarian", "Bulgaria"},
{0x0403, 850, 1252, "Catalan", "Spain"},
{0x0405, 852, 1250, "Czech", "Czech Republic"},
{0x0406, 850, 1252, "Danish", "Denmark"},
{0x0407, 850, 1252, "German", "Germany"},
{0x0408, 737, 1253, "Greek", "Greece"},
{0x0409, 437, 1252, "English", "United States"},
{0x040A, 850, 1252, "Spanish - Traditional Sort", "Spain"},
{0x040B, 850, 1252, "Finnish", "Finland"},
{0x040C, 850, 1252, "French", "France"},
{0x040E, 852, 1250, "Hungarian", "Hungary"},
{0x040F, 850, 1252, "Icelandic", "Iceland"},
{0x0410, 850, 1252, "Italian", "Italy"},
{0x0411, 932, 932, "Japanese", "Japan"},
{0x0412, 949, 949, "Korean", "Korea (south)"},
{0x0413, 850, 1252, "Dutch", "Netherlands"},
{0x0414, 850, 1252, "Norwegian (Bokmål)", "Norway"},
{0x0415, 852, 1250, "Polish", "Poland"},
{0x0416, 850, 1252, "Portuguese", "Brazil"},
{0x0418, 852, 1250, "Romanian", "Romania"},
{0x0419, 866, 1251, "Russian", "Russia"},
{0x041A, 852, 1250, "Croatian", "Croatia"},
{0x041B, 852, 1250, "Slovak", "Slovakia"},
{0x041C, 852, 1250, "Albanian", "Albania"},
{0x041D, 850, 1252, "Swedish", "Sweden"},
{0x041F, 857, 1254, "Turkish", "Turkey"},
{0x0421, 850, 1252, "Indonesian", "Indonesia"},
{0x0422, 866, 1251, "Ukrainian", "Ukraine"},
{0x0423, 866, 1251, "Belarusian", "Belarus"},
{0x0424, 852, 1250, "Slovene", "Slovenia"},
{0x0425, 775, 1257, "Estonian", "Estonia"},
{0x0426, 775, 1257, "Latvian", "Latvia"},
{0x0427, 775, 1257, "Lithuanian", "Lithuania"},
/* {0x042A, ?, ?, "Vietnamese", "Vietnam"},*/
{0x042D, 850, 1252, "Basque", "Spain"},
{0x042F, 866, 1251, "Macedonian", "Former Yugoslav Republic of Macedonia"},
{0x0436, 850, 1252, "Afrikaans", "South Africa"},
/* {0x0438, 852, 1252, "Faroese", "Faroe Islands"}, FIXME: Not sure about codepages */
{0x043C, 437, 1252, "Irish", "Ireland"},
{0x043E, 850, 1252, "Malay", "Malaysia"},
/* {0x048F, ?, ?, "Esperanto", "<none>"},*/
{0x0804, 936, 936, "Chinese (People's republic of China)", "People's republic of China"},
{0x0807, 850, 1252, "German", "Switzerland"},
{0x0809, 850, 1252, "English", "United Kingdom"},
{0x080A, 850, 1252, "Spanish", "Mexico"},
{0x080C, 850, 1252, "French", "Belgium"},
{0x0810, 850, 1252, "Italian", "Switzerland"},
{0x0813, 850, 1252, "Dutch", "Belgium"},
{0x0814, 850, 1252, "Norwegian (Nynorsk)", "Norway"},
{0x0816, 850, 1252, "Portuguese", "Portugal"},
/* {0x081A, ?, ?, "Serbian (latin)", "Yugoslavia"},*/
{0x081D, 850, 1252, "Swedish (Finland)", "Finland"},
{0x0C07, 850, 1252, "German", "Austria"},
{0x0C09, 850, 1252, "English", "Australia"},
{0x0C0A, 850, 1252, "Spanish - International Sort", "Spain"},
{0x0C0C, 850, 1252, "French", "Canada"},
{0x0C1A, 855, 1251, "Serbian (Cyrillic)", "Serbia"},
{0x1007, 850, 1252, "German", "Luxembourg"},
{0x1009, 850, 1252, "English", "Canada"},
{0x100A, 850, 1252, "Spanish", "Guatemala"},
{0x100C, 850, 1252, "French", "Switzerland"},
{0x1407, 850, 1252, "German", "Liechtenstein"},
{0x1409, 850, 1252, "English", "New Zealand"},
{0x140A, 850, 1252, "Spanish", "Costa Rica"},
{0x140C, 850, 1252, "French", "Luxembourg"},
{0x1809, 850, 1252, "English", "Ireland"},
{0x180A, 850, 1252, "Spanish", "Panama"},
{0x1C09, 437, 1252, "English", "South Africa"},
{0x1C0A, 850, 1252, "Spanish", "Dominican Republic"},
{0x2009, 850, 1252, "English", "Jamaica"},
{0x200A, 850, 1252, "Spanish", "Venezuela"},
{0x2409, 850, 1252, "English", "Caribbean"},
{0x240A, 850, 1252, "Spanish", "Colombia"},
{0x2809, 850, 1252, "English", "Belize"},
{0x280A, 850, 1252, "Spanish", "Peru"},
{0x2C09, 437, 1252, "English", "Trinidad & Tobago"},
{0x2C0A, 850, 1252, "Spanish", "Argentina"},
{0x300A, 850, 1252, "Spanish", "Ecuador"},
{0x340A, 850, 1252, "Spanish", "Chile"},
{0x380A, 850, 1252, "Spanish", "Uruguay"},
{0x3C0A, 850, 1252, "Spanish", "Paraguay"},
{0x400A, 850, 1252, "Spanish", "Bolivia"},
{0x440A, 850, 1252, "Spanish", "El Salvador"},
{0x480A, 850, 1252, "Spanish", "Honduras"},
{0x4C0A, 850, 1252, "Spanish", "Nicaragua"},
{0x500A, 850, 1252, "Spanish", "Puerto Rico"}
};
#define NLAN (sizeof(languages)/sizeof(languages[0]))
void show_languages(void)
{
unsigned int i;
printf(" Code | DOS-cp | WIN-cp | Language | Country\n");
printf("-------+--------+--------+--------------+---------\n");
for(i = 0; i < NLAN; i++)
printf("0x%04x | %5d | %5d | %-12s | %s\n",
languages[i].id,
languages[i].doscp,
languages[i].wincp,
languages[i].name,
languages[i].country);
}
static int langcmp(const void *p1, const void *p2)
{
return *(const unsigned *)p1 - ((const language_t *)p2)->id;
}
const language_t *find_language(unsigned id)
{
return (const language_t *)bsearch(&id, languages, NLAN, sizeof(languages[0]), langcmp);
}
void show_codepages(void)
{
unsigned i;
const union cptable *cpp;
printf("Codepages:\n");
for(i = 0; (cpp = wine_cp_enum_table(i)); i++)
{
printf("%-5d %s\n", cpp->info.codepage, cpp->info.name);
}
}
const union cptable *find_codepage(int id)
{
return wine_cp_get_table(id);
}

39
reactos/tools/wmc/lang.h Normal file
View file

@ -0,0 +1,39 @@
/*
* Wine Message Compiler language and codepage support
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WMC_LANG_H
#define __WMC_LANG_H
#include "wine/unicode.h"
typedef struct language {
unsigned id;
unsigned doscp;
unsigned wincp;
const char *name;
const char *country;
} language_t;
void show_languages(void);
const language_t *find_language(unsigned id);
void show_codepages(void);
const union cptable *find_codepage(int id);
#endif

747
reactos/tools/wmc/mcl.c Normal file
View file

@ -0,0 +1,747 @@
/*
* Wine Message Compiler lexical scanner
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include "utils.h"
#include "wmc.h"
#include "lang.h"
#include "mcy.tab.h"
/*
* Keywords are case insenitive. All normal input is treated as
* being in codepage iso-8859-1 for ascii input files (unicode
* page 0) and as equivalent unicode if unicode input is selected.
* All normal input, which is not part of a message text, is
* enforced to be unicode page 0. Otherwise an error will be
* generated. The normal file data should only be ASCII because
* that is the basic definition of the grammar.
*
* Byteorder or unicode input is determined automatically by
* reading the first 8 bytes and checking them against unicode
* page 0 byteorder (hibyte must be 0).
* -- FIXME --
* Alternatively, the input is checked against a special byte
* sequence to identify the file.
* -- FIXME --
*
*
* Keywords:
* Codepages
* Facility
* FacilityNames
* LanguageNames
* MessageId
* MessageIdTypedef
* Severity
* SeverityNames
* SymbolicName
*
* Default added identifiers for classes:
* SeverityNames:
* Success = 0x0
* Informational = 0x1
* Warning = 0x2
* Error = 0x3
* FacilityNames:
* System = 0x0FF
* Application = 0xFFF
*
* The 'Codepages' keyword is a wmc extension.
*/
static WCHAR ustr_application[] = { 'A', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', 0 };
static WCHAR ustr_codepages[] = { 'C', 'o', 'd', 'e', 'p', 'a', 'g', 'e', 's', 0 };
static WCHAR ustr_english[] = { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 };
static WCHAR ustr_error[] = { 'E', 'r', 'r', 'o', 'r', 0 };
static WCHAR ustr_facility[] = { 'F', 'a', 'c', 'i', 'l', 'i', 't', 'y', 0 };
static WCHAR ustr_facilitynames[] = { 'F', 'a', 'c', 'i', 'l', 'i', 't', 'y', 'N', 'a', 'm', 'e', 's', 0 };
static WCHAR ustr_informational[] = { 'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'a', 'l', 0 };
static WCHAR ustr_language[] = { 'L', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 0};
static WCHAR ustr_languagenames[] = { 'L', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 'N', 'a', 'm', 'e', 's', 0};
static WCHAR ustr_messageid[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'I', 'd', 0 };
static WCHAR ustr_messageidtypedef[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'I', 'd', 'T', 'y', 'p', 'e', 'd', 'e', 'f', 0 };
static WCHAR ustr_outputbase[] = { 'O', 'u', 't', 'p', 'u', 't', 'B', 'a', 's', 'e', 0 };
static WCHAR ustr_severity[] = { 'S', 'e', 'v', 'e', 'r', 'i', 't', 'y', 0 };
static WCHAR ustr_severitynames[] = { 'S', 'e', 'v', 'e', 'r', 'i', 't', 'y', 'N', 'a', 'm', 'e', 's', 0 };
static WCHAR ustr_success[] = { 'S', 'u', 'c', 'c', 'e', 's', 's', 0 };
static WCHAR ustr_symbolicname[] = { 'S', 'y', 'm', 'b', 'o', 'l', 'i', 'c', 'N', 'a', 'm', 'e', 0 };
static WCHAR ustr_system[] = { 'S', 'y', 's', 't', 'e', 'm', 0 };
static WCHAR ustr_warning[] = { 'W', 'a', 'r', 'n', 'i', 'n', 'g', 0 };
static WCHAR ustr_msg00001[] = { 'm', 's', 'g', '0', '0', '0', '0', '1', 0 };
/*
* This table is to beat any form of "expression building" to check for
* correct filename characters. It is also used for ident checks.
* FIXME: use it more consistently.
*/
#define CH_SHORTNAME 0x01
#define CH_LONGNAME 0x02
#define CH_IDENT 0x04
#define CH_NUMBER 0x08
/*#define CH_WILDCARD 0x10*/
/*#define CH_DOT 0x20*/
#define CH_PUNCT 0x40
#define CH_INVALID 0x80
static const char char_table[256] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x00 - 0x07 */
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x08 - 0x0F */
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x10 - 0x17 */
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x18 - 0x1F */
0x80, 0x03, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, /* 0x20 - 0x27 " !"#$%&'" */
0x43, 0x43, 0x10, 0x80, 0x03, 0x03, 0x22, 0x80, /* 0x28 - 0x2F "()*+,-./" */
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, /* 0x30 - 0x37 "01234567" */
0x0b, 0x0b, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x10, /* 0x38 - 0x3F "89:;<=>?" */
0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x40 - 0x47 "@ABCDEFG" */
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x48 - 0x4F "HIJKLMNO" */
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x50 - 0x57 "PQRSTUVW" */
0x07, 0x07, 0x07, 0x80, 0x80, 0x80, 0x80, 0x07, /* 0x58 - 0x5F "XYZ[\]^_" */
0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x60 - 0x67 "`abcdefg" */
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x68 - 0x6F "hijklmno" */
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x70 - 0x77 "pqrstuvw" */
0x07, 0x07, 0x07, 0x03, 0x80, 0x03, 0x03, 0x80, /* 0x78 - 0x7F "xyz{|}~ " */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x80 - 0x87 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x88 - 0x8F */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x90 - 0x97 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x98 - 0x9F */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xA0 - 0xA7 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xA8 - 0xAF */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xB0 - 0xB7 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xB8 - 0xBF */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xC0 - 0xC7 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xC8 - 0xCF */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xD0 - 0xD7 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xD8 - 0xDF */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xE0 - 0xE7 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xE8 - 0xEF */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xF0 - 0xF7 */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x80, /* 0xF8 - 0xFF */
};
static int isisochar(int ch)
{
return !(ch & (~0xff));
}
static int codepage;
static const union cptable *codepage_def;
void set_codepage(int cp)
{
codepage = cp;
codepage_def = find_codepage(codepage);
if(!codepage_def)
xyyerror("Codepage %d not found; cannot process", codepage);
}
/*
* Input functions
*/
static int nungetstack = 0;
static int allocungetstack = 0;
static char *ungetstack = NULL;
static int ninputbuffer = 0;
static WCHAR *inputbuffer = NULL;
static char *xlatebuffer = NULL;
#define INPUTBUFFER_SIZE 2048 /* Must be larger than 4 and approx. large enough to hold a line */
/*
* Fill the input buffer with *one* line of input.
* The line is '\n' terminated so that scanning
* messages with translation works as expected
* (otherwise we cannot pre-translate because the
* language is first known one line before the
* actual message).
*/
static int fill_inputbuffer(void)
{
int n;
static const char err_fatalread[] = "Fatal: reading input failed";
static int endian = -1;
if(!inputbuffer)
{
inputbuffer = xmalloc(INPUTBUFFER_SIZE);
xlatebuffer = xmalloc(INPUTBUFFER_SIZE);
}
try_again:
if(!unicodein)
{
char *cptr;
cptr = fgets(xlatebuffer, INPUTBUFFER_SIZE, yyin);
if(!cptr && ferror(yyin))
xyyerror(err_fatalread);
else if(!cptr)
return 0;
assert(codepage_def != NULL);
n = wine_cp_mbstowcs(codepage_def, 0, xlatebuffer, strlen(xlatebuffer)+1, inputbuffer, INPUTBUFFER_SIZE);
if(n < 0)
internal_error(__FILE__, __LINE__, "Could not translate to unicode (%d)", n);
if(n <= 1)
goto try_again; /* Should not hapen */
n--; /* Strip added conversion '\0' from input length */
/*
* FIXME:
* Detect UTF-8 in the first time we read some bytes by
* checking the special sequence "FE..." or something like
* that. I need to check www.unicode.org for details.
*/
}
else
{
if(endian == -1)
{
n = fread(inputbuffer, 1, 8, yyin);
if(n != 8)
{
if(!n && ferror(yyin))
xyyerror(err_fatalread);
else
xyyerror("Fatal: file to short to determine byteorder (should never happen)");
}
if(isisochar(inputbuffer[0]) &&
isisochar(inputbuffer[1]) &&
isisochar(inputbuffer[2]) &&
isisochar(inputbuffer[3]))
{
#ifdef WORDS_BIGENDIAN
endian = WMC_BO_BIG;
#else
endian = WMC_BO_LITTLE;
#endif
}
else if(isisochar(BYTESWAP_WORD(inputbuffer[0])) &&
isisochar(BYTESWAP_WORD(inputbuffer[1])) &&
isisochar(BYTESWAP_WORD(inputbuffer[2])) &&
isisochar(BYTESWAP_WORD(inputbuffer[3])))
{
#ifdef WORDS_BIGENDIAN
endian = WMC_BO_LITTLE;
#else
endian = WMC_BO_BIG;
#endif
}
else
xyyerror("Fatal: cannot determine file's byteorder");
/* FIXME:
* Determine the file-endian with the leader-bytes
* "FF FE..."; can't remember the exact sequence.
*/
n /= 2;
#ifdef WORDS_BIGENDIAN
if(endian == WMC_BO_LITTLE)
#else
if(endian == WMC_BO_BIG)
#endif
{
inputbuffer[0] = BYTESWAP_WORD(inputbuffer[0]);
inputbuffer[1] = BYTESWAP_WORD(inputbuffer[1]);
inputbuffer[2] = BYTESWAP_WORD(inputbuffer[2]);
inputbuffer[3] = BYTESWAP_WORD(inputbuffer[3]);
}
}
else
{
int i;
n = 0;
for(i = 0; i < INPUTBUFFER_SIZE; i++)
{
int t;
t = fread(&inputbuffer[i], 2, 1, yyin);
if(!t && ferror(yyin))
xyyerror(err_fatalread);
else if(!t && n)
break;
n++;
#ifdef WORDS_BIGENDIAN
if(endian == WMC_BO_LITTLE)
#else
if(endian == WMC_BO_BIG)
#endif
{
if((inputbuffer[i] = BYTESWAP_WORD(inputbuffer[i])) == '\n')
break;
}
else
{
if(inputbuffer[i] == '\n')
break;
}
}
}
}
if(!n)
{
yywarning("Re-read line (input was or converted to zilch)");
goto try_again; /* Should not happen, but could be due to stdin reading and a signal */
}
ninputbuffer += n;
return 1;
}
static int get_unichar(void)
{
static WCHAR *b = NULL;
char_number++;
if(nungetstack)
return ungetstack[--nungetstack];
if(!ninputbuffer)
{
if(!fill_inputbuffer())
return EOF;
b = inputbuffer;
}
ninputbuffer--;
return (int)(*b++ & 0xffff);
}
static void unget_unichar(int ch)
{
if(ch == EOF)
return;
char_number--;
if(nungetstack == allocungetstack)
{
allocungetstack += 32;
ungetstack = xrealloc(ungetstack, allocungetstack * sizeof(*ungetstack));
}
ungetstack[nungetstack++] = (WCHAR)ch;
}
/*
* Normal character stack.
* Used for number scanning.
*/
static int ncharstack = 0;
static int alloccharstack = 0;
static char *charstack = NULL;
static void empty_char_stack(void)
{
ncharstack = 0;
}
static void push_char(int ch)
{
if(ncharstack == alloccharstack)
{
alloccharstack += 32;
charstack = xrealloc(charstack, alloccharstack * sizeof(*charstack));
}
charstack[ncharstack++] = (char)ch;
}
static int tos_char_stack(void)
{
if(!ncharstack)
return 0;
else
return (int)(charstack[ncharstack-1] & 0xff);
}
static char *get_char_stack(void)
{
return charstack;
}
/*
* Unicode character stack.
* Used for general scanner.
*/
static int nunicharstack = 0;
static int allocunicharstack = 0;
static WCHAR *unicharstack = NULL;
static void empty_unichar_stack(void)
{
nunicharstack = 0;
}
static void push_unichar(int ch)
{
if(nunicharstack == allocunicharstack)
{
allocunicharstack += 128;
unicharstack = xrealloc(unicharstack, allocunicharstack * sizeof(*unicharstack));
}
unicharstack[nunicharstack++] = (WCHAR)ch;
}
#if 0
static int tos_unichar_stack(void)
{
if(!nunicharstack)
return 0;
else
return (int)(unicharstack[nunicharstack-1] & 0xffff);
}
#endif
static WCHAR *get_unichar_stack(void)
{
return unicharstack;
}
/*
* Number scanner
*
* state | ch | next state
* ------+-----------------+--------------------------
* 0 | [0] | 1
* 0 | [1-9] | 4
* 0 | . | error (should never occur)
* 1 | [xX] | 2
* 1 | [0-7] | 3
* 1 | [89a-wyzA-WYZ_] | error invalid digit
* 1 | . | return 0
* 2 | [0-9a-fA-F] | 2
* 2 | [g-zG-Z_] | error invalid hex digit
* 2 | . | return (hex-number) if TOS != [xX] else error
* 3 | [0-7] | 3
* 3 | [89a-zA-Z_] | error invalid octal digit
* 3 | . | return (octal-number)
* 4 | [0-9] | 4
* 4 | [a-zA-Z_] | error invalid decimal digit
* 4 | . | return (decimal-number)
*
* All non-identifier characters [^a-zA-Z_0-9] terminate the scan
* and return the value. This is not entirely correct, but close
* enough (should check punctuators as trailing context, but the
* char_table is not adapted to that and it is questionable whether
* it is worth the trouble).
* All non-iso-8859-1 characters are an error.
*/
static int scan_number(int ch)
{
int state = 0;
int base = 10;
empty_char_stack();
while(1)
{
if(!isisochar(ch))
xyyerror("Invalid digit");
switch(state)
{
case 0:
if(isdigit(ch))
{
push_char(ch);
if(ch == '0')
state = 1;
else
state = 4;
}
else
internal_error(__FILE__, __LINE__, "Non-digit in first number-scanner state");
break;
case 1:
if(ch == 'x' || ch == 'X')
{
push_char(ch);
state = 2;
}
else if(ch >= '0' && ch <= '7')
{
push_char(ch);
state = 3;
}
else if(isalpha(ch) || ch == '_')
xyyerror("Invalid number digit");
else
{
unget_unichar(ch);
yylval.num = 0;
return tNUMBER;
}
break;
case 2:
if(isxdigit(ch))
push_char(ch);
else if(isalpha(ch) || ch == '_' || !isxdigit(tos_char_stack()))
xyyerror("Invalid hex digit");
else
{
base = 16;
goto finish;
}
break;
case 3:
if(ch >= '0' && ch <= '7')
push_char(ch);
else if(isalnum(ch) || ch == '_')
xyyerror("Invalid octal digit");
else
{
base = 8;
goto finish;
}
break;
case 4:
if(isdigit(ch))
push_char(ch);
else if(isalnum(ch) || ch == '_')
xyyerror("Invalid decimal digit");
else
{
base = 10;
goto finish;
}
break;
default:
internal_error(__FILE__, __LINE__, "Invalid state in number-scanner");
}
ch = get_unichar();
}
finish:
unget_unichar(ch);
push_char(0);
yylval.num = strtoul(get_char_stack(), NULL, base);
return tNUMBER;
}
static void newline(void)
{
line_number++;
char_number = 1;
}
static int unisort(const void *p1, const void *p2)
{
return unistricmp(((const token_t *)p1)->name, ((const token_t *)p2)->name);
}
static token_t *tokentable = NULL;
static int ntokentable = 0;
token_t *lookup_token(const WCHAR *s)
{
token_t tok;
tok.name = s;
return (token_t *)bsearch(&tok, tokentable, ntokentable, sizeof(*tokentable), unisort);
}
void add_token(tok_e type, const WCHAR *name, int tok, int cp, const WCHAR *alias, int fix)
{
ntokentable++;
tokentable = xrealloc(tokentable, ntokentable * sizeof(*tokentable));
tokentable[ntokentable-1].type = type;
tokentable[ntokentable-1].name = name;
tokentable[ntokentable-1].token = tok;
tokentable[ntokentable-1].codepage = cp;
tokentable[ntokentable-1].alias = alias;
tokentable[ntokentable-1].fixed = fix;
qsort(tokentable, ntokentable, sizeof(*tokentable), unisort);
}
void get_tokentable(token_t **tab, int *len)
{
assert(tab != NULL);
assert(len != NULL);
*tab = tokentable;
*len = ntokentable;
}
/*
* The scanner
*
*/
int yylex(void)
{
static const WCHAR ustr_dot1[] = { '.', '\n', 0 };
static const WCHAR ustr_dot2[] = { '.', '\r', '\n', 0 };
static int isinit = 0;
int ch;
if(!isinit)
{
isinit++;
set_codepage(WMC_DEFAULT_CODEPAGE);
add_token(tok_keyword, ustr_codepages, tCODEPAGE, 0, NULL, 0);
add_token(tok_keyword, ustr_facility, tFACILITY, 0, NULL, 1);
add_token(tok_keyword, ustr_facilitynames, tFACNAMES, 0, NULL, 1);
add_token(tok_keyword, ustr_language, tLANGUAGE, 0, NULL, 1);
add_token(tok_keyword, ustr_languagenames, tLANNAMES, 0, NULL, 1);
add_token(tok_keyword, ustr_messageid, tMSGID, 0, NULL, 1);
add_token(tok_keyword, ustr_messageidtypedef, tTYPEDEF, 0, NULL, 1);
add_token(tok_keyword, ustr_outputbase, tBASE, 0, NULL, 1);
add_token(tok_keyword, ustr_severity, tSEVERITY, 0, NULL, 1);
add_token(tok_keyword, ustr_severitynames, tSEVNAMES, 0, NULL, 1);
add_token(tok_keyword, ustr_symbolicname, tSYMNAME, 0, NULL, 1);
add_token(tok_severity, ustr_error, 0x03, 0, NULL, 0);
add_token(tok_severity, ustr_warning, 0x02, 0, NULL, 0);
add_token(tok_severity, ustr_informational, 0x01, 0, NULL, 0);
add_token(tok_severity, ustr_success, 0x00, 0, NULL, 0);
add_token(tok_facility, ustr_application, 0xFFF, 0, NULL, 0);
add_token(tok_facility, ustr_system, 0x0FF, 0, NULL, 0);
add_token(tok_language, ustr_english, 0x409, 437, ustr_msg00001, 0);
}
empty_unichar_stack();
while(1)
{
if(want_line)
{
while((ch = get_unichar()) != '\n')
{
if(ch == EOF)
xyyerror("Unexpected EOF");
push_unichar(ch);
}
newline();
push_unichar(ch);
push_unichar(0);
if(!unistrcmp(ustr_dot1, get_unichar_stack()) || !unistrcmp(ustr_dot2, get_unichar_stack()))
{
want_line = 0;
/* Reset the codepage to our default after each message */
set_codepage(WMC_DEFAULT_CODEPAGE);
return tMSGEND;
}
yylval.str = xunistrdup(get_unichar_stack());
return tLINE;
}
ch = get_unichar();
if(ch == EOF)
return EOF;
if(ch == '\n')
{
newline();
if(want_nl)
{
want_nl = 0;
return tNL;
}
continue;
}
if(isisochar(ch))
{
if(want_file)
{
int n = 0;
while(n < 8 && isisochar(ch))
{
int t = char_table[ch];
if((t & CH_PUNCT) || !(t & CH_SHORTNAME))
break;
push_unichar(ch);
n++;
ch = get_unichar();
}
unget_unichar(ch);
push_unichar(0);
want_file = 0;
yylval.str = xunistrdup(get_unichar_stack());
return tFILE;
}
if(char_table[ch] & CH_IDENT)
{
token_t *tok;
while(isisochar(ch) && (char_table[ch] & (CH_IDENT|CH_NUMBER)))
{
push_unichar(ch);
ch = get_unichar();
}
unget_unichar(ch);
push_unichar(0);
if(!(tok = lookup_token(get_unichar_stack())))
{
yylval.str = xunistrdup(get_unichar_stack());
return tIDENT;
}
switch(tok->type)
{
case tok_keyword:
return tok->token;
case tok_language:
codepage = tok->codepage;
/* Fall through */
case tok_severity:
case tok_facility:
yylval.tok = tok;
return tTOKEN;
default:
internal_error(__FILE__, __LINE__, "Invalid token type encountered");
}
}
if(isspace(ch)) /* Ignore space */
continue;
if(isdigit(ch))
return scan_number(ch);
}
switch(ch)
{
case ':':
case '=':
case '+':
case '(':
case ')':
return ch;
case ';':
while(ch != '\n' && ch != EOF)
{
push_unichar(ch);
ch = get_unichar();
}
newline();
push_unichar(ch); /* Include the newline */
push_unichar(0);
yylval.str = xunistrdup(get_unichar_stack());
return tCOMMENT;
default:
xyyerror("Invalid character '%c' (0x%04x)", isisochar(ch) && isprint(ch) ? ch : '.', ch);
}
}
}

2266
reactos/tools/wmc/mcy.tab.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
/* A Bison parser, made by GNU Bison 1.875c. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
tSEVNAMES = 258,
tFACNAMES = 259,
tLANNAMES = 260,
tBASE = 261,
tCODEPAGE = 262,
tTYPEDEF = 263,
tNL = 264,
tSYMNAME = 265,
tMSGEND = 266,
tSEVERITY = 267,
tFACILITY = 268,
tLANGUAGE = 269,
tMSGID = 270,
tIDENT = 271,
tLINE = 272,
tFILE = 273,
tCOMMENT = 274,
tNUMBER = 275,
tTOKEN = 276
};
#endif
#define tSEVNAMES 258
#define tFACNAMES 259
#define tLANNAMES 260
#define tBASE 261
#define tCODEPAGE 262
#define tTYPEDEF 263
#define tNL 264
#define tSYMNAME 265
#define tMSGEND 266
#define tSEVERITY 267
#define tFACILITY 268
#define tLANGUAGE 269
#define tMSGID 270
#define tIDENT 271
#define tLINE 272
#define tFILE 273
#define tCOMMENT 274
#define tNUMBER 275
#define tTOKEN 276
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 99 "tools/wmc/mcy.y"
typedef union YYSTYPE {
WCHAR *str;
unsigned num;
token_t *tok;
lanmsg_t *lmp;
msg_t *msg;
lan_cp_t lcp;
} YYSTYPE;
/* Line 1275 of yacc.c. */
#line 88 "tools/wmc/mcy.tab.h"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

677
reactos/tools/wmc/mcy.y Normal file
View file

@ -0,0 +1,677 @@
/*
* Wine Message Compiler parser
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES:
*
* The basic grammar of the file is yet another example of, humpf,
* design. There is is mix of context-insensitive and -sentitive
* stuff, which makes it rather complicated.
* The header definitions are all context-insensitive because they have
* delimited arguments, whereas the message headers are (semi-) context-
* sensitive and the messages themselves are, well, RFC82[12] delimited.
* This mixture seems to originate from the time that ms and ibm were
* good friends and developing os/2 according to the "compatibility"
* switch and reading some comments here and there.
*
* I'll ignore most of the complications and concentrate on the concept
* which allows me to use yacc. Basically, everything is context-
* insensitive now, with the exception of the message-text itself and
* the preceding language declaration.
*
*/
%{
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "utils.h"
#include "wmc.h"
#include "lang.h"
static const char err_syntax[] = "Syntax error";
static const char err_number[] = "Number expected";
static const char err_ident[] = "Identifier expected";
static const char err_assign[] = "'=' expected";
static const char err_popen[] = "'(' expected";
static const char err_pclose[] = "')' expected";
static const char err_colon[] = "':' expected";
static const char err_msg[] = "Message expected";
/* Scanner switches */
int want_nl = 0; /* Request next newlinw */
int want_line = 0; /* Request next complete line */
int want_file = 0; /* Request next ident as filename */
node_t *nodehead = NULL; /* The list of all parsed elements */
static node_t *nodetail = NULL;
lan_blk_t *lanblockhead; /* List of parsed elements transposed */
static int base = 16; /* Current printout base to use (8, 10 or 16) */
static WCHAR *cast = NULL; /* Current typecast to use */
static int last_id = 0; /* The last message ID parsed */
static int last_sev = 0; /* Last severity code parsed */
static int last_fac = 0; /* Last facility code parsed */
static WCHAR *last_sym = NULL;/* Last alias symbol parsed */
static int have_sev; /* Set if severity parsed for current message */
static int have_fac; /* Set if facility parsed for current message */
static int have_sym; /* Set is symbol parsed for current message */
static cp_xlat_t *cpxlattab = NULL; /* Codepage translation table */
static int ncpxlattab = 0;
/* Prototypes */
static WCHAR *merge(WCHAR *s1, WCHAR *s2);
static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg);
static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg);
static msg_t *complete_msg(msg_t *msg, int id);
static void add_node(node_e type, void *p);
static void do_add_token(tok_e type, token_t *tok, const char *code);
static void test_id(int id);
static int check_languages(node_t *head);
static lan_blk_t *block_messages(node_t *head);
static void add_cpxlat(int lan, int cpin, int cpout);
static cp_xlat_t *find_cpxlat(int lan);
%}
%union {
WCHAR *str;
unsigned num;
token_t *tok;
lanmsg_t *lmp;
msg_t *msg;
lan_cp_t lcp;
}
%token tSEVNAMES tFACNAMES tLANNAMES tBASE tCODEPAGE
%token tTYPEDEF tNL tSYMNAME tMSGEND
%token tSEVERITY tFACILITY tLANGUAGE tMSGID
%token <str> tIDENT tLINE tFILE tCOMMENT
%token <num> tNUMBER
%token <tok> tTOKEN
%type <str> alias lines
%type <num> optcp id msgid clan
%type <tok> token
%type <lmp> body
%type <msg> bodies msg
%type <lcp> lang
%%
file : items {
if(!check_languages(nodehead))
xyyerror("No messages defined");
lanblockhead = block_messages(nodehead);
}
;
items : decl
| items decl
;
decl : global
| msg { add_node(nd_msg, $1); }
| tCOMMENT { add_node(nd_comment, $1); }
| error { xyyerror(err_syntax); /* `Catch all' error */ }
;
global : tSEVNAMES '=' '(' smaps ')'
| tSEVNAMES '=' '(' smaps error { xyyerror(err_pclose); }
| tSEVNAMES '=' error { xyyerror(err_popen); }
| tSEVNAMES error { xyyerror(err_assign); }
| tFACNAMES '=' '(' fmaps ')'
| tFACNAMES '=' '(' fmaps error { xyyerror(err_pclose); }
| tFACNAMES '=' error { xyyerror(err_popen); }
| tFACNAMES error { xyyerror(err_assign); }
| tLANNAMES '=' '(' lmaps ')'
| tLANNAMES '=' '(' lmaps error { xyyerror(err_pclose); }
| tLANNAMES '=' error { xyyerror(err_popen); }
| tLANNAMES error { xyyerror(err_assign); }
| tCODEPAGE '=' '(' cmaps ')'
| tCODEPAGE '=' '(' cmaps error { xyyerror(err_pclose); }
| tCODEPAGE '=' error { xyyerror(err_popen); }
| tCODEPAGE error { xyyerror(err_assign); }
| tTYPEDEF '=' tIDENT { cast = $3; }
| tTYPEDEF '=' error { xyyerror(err_number); }
| tTYPEDEF error { xyyerror(err_assign); }
| tBASE '=' tNUMBER {
switch(base)
{
case 8:
case 10:
case 16:
base = $3;
break;
default:
xyyerror("Numberbase must be 8, 10 or 16");
}
}
| tBASE '=' error { xyyerror(err_number); }
| tBASE error { xyyerror(err_assign); }
;
/*----------------------------------------------------------------------
* SeverityNames mapping
*/
smaps : smap
| smaps smap
| error { xyyerror(err_ident); }
;
smap : token '=' tNUMBER alias {
$1->token = $3;
$1->alias = $4;
if($3 & (~0x3))
xyyerror("Severity value out of range (0x%08x > 0x3)", $3);
do_add_token(tok_severity, $1, "severity");
}
| token '=' error { xyyerror(err_number); }
| token error { xyyerror(err_assign); }
;
/*----------------------------------------------------------------------
* FacilityNames mapping
*/
fmaps : fmap
| fmaps fmap
| error { xyyerror(err_ident); }
;
fmap : token '=' tNUMBER alias {
$1->token = $3;
$1->alias = $4;
if($3 & (~0xfff))
xyyerror("Facility value out of range (0x%08x > 0xfff)", $3);
do_add_token(tok_facility, $1, "facility");
}
| token '=' error { xyyerror(err_number); }
| token error { xyyerror(err_assign); }
;
alias : /* Empty */ { $$ = NULL; }
| ':' tIDENT { $$ = $2; }
| ':' error { xyyerror(err_ident); }
;
/*----------------------------------------------------------------------
* LanguageNames mapping
*/
lmaps : lmap
| lmaps lmap
| error { xyyerror(err_ident); }
;
lmap : token '=' tNUMBER setfile ':' tFILE optcp {
$1->token = $3;
$1->alias = $6;
$1->codepage = $7;
do_add_token(tok_language, $1, "language");
if(!find_language($3) && !find_cpxlat($3))
yywarning("Language 0x%x not built-in, using codepage %d; use explicit codepage to override", $3, WMC_DEFAULT_CODEPAGE);
}
| token '=' tNUMBER setfile ':' error { xyyerror("Filename expected"); }
| token '=' tNUMBER error { xyyerror(err_colon); }
| token '=' error { xyyerror(err_number); }
| token error { xyyerror(err_assign); }
;
optcp : /* Empty */ { $$ = 0; }
| ':' tNUMBER { $$ = $2; }
| ':' error { xyyerror("Codepage-number expected"); }
;
/*----------------------------------------------------------------------
* Codepages mapping
*/
cmaps : cmap
| cmaps cmap
| error { xyyerror(err_ident); }
;
cmap : clan '=' tNUMBER ':' tNUMBER {
static const char err_nocp[] = "Codepage %d not builtin; cannot convert";
if(find_cpxlat($1))
xyyerror("Codepage translation already defined for language 0x%x", $1);
if($3 && !find_codepage($3))
xyyerror(err_nocp, $3);
if($5 && !find_codepage($5))
xyyerror(err_nocp, $5);
add_cpxlat($1, $3, $5);
}
| clan '=' tNUMBER ':' error { xyyerror(err_number); }
| clan '=' tNUMBER error { xyyerror(err_colon); }
| clan '=' error { xyyerror(err_number); }
| clan error { xyyerror(err_assign); }
;
clan : tNUMBER { $$ = $1; }
| tTOKEN {
if($1->type != tok_language)
xyyerror("Language name or code expected");
$$ = $1->token;
}
;
/*----------------------------------------------------------------------
* Message-definition parsing
*/
msg : msgid sevfacsym { test_id($1); } bodies { $$ = complete_msg($4, $1); }
;
msgid : tMSGID '=' id {
if($3 & (~0xffff))
xyyerror("Message ID value out of range (0x%08x > 0xffff)", $3);
$$ = $3;
}
| tMSGID error { xyyerror(err_assign); }
;
id : /* Empty */ { $$ = ++last_id; }
| tNUMBER { $$ = last_id = $1; }
| '+' tNUMBER { $$ = last_id += $2; }
| '+' error { xyyerror(err_number); }
;
sevfacsym: /* Empty */ { have_sev = have_fac = have_sym = 0; }
| sevfacsym sev { if(have_sev) xyyerror("Severity already defined"); have_sev = 1; }
| sevfacsym fac { if(have_fac) xyyerror("Facility already defined"); have_fac = 1; }
| sevfacsym sym { if(have_sym) xyyerror("Symbolname already defined"); have_sym = 1; }
;
sym : tSYMNAME '=' tIDENT { last_sym = $3; }
| tSYMNAME '=' error { xyyerror(err_ident); }
| tSYMNAME error { xyyerror(err_assign); }
;
sev : tSEVERITY '=' token {
token_t *tok = lookup_token($3->name);
if(!tok)
xyyerror("Undefined severityname");
if(tok->type != tok_severity)
xyyerror("Identifier is not of class 'severity'");
last_sev = tok->token;
}
| tSEVERITY '=' error { xyyerror(err_ident); }
| tSEVERITY error { xyyerror(err_assign); }
;
fac : tFACILITY '=' token {
token_t *tok = lookup_token($3->name);
if(!tok)
xyyerror("Undefined facilityname");
if(tok->type != tok_facility)
xyyerror("Identifier is not of class 'facility'");
last_fac = tok->token;
}
| tFACILITY '=' error { xyyerror(err_ident); }
| tFACILITY error { xyyerror(err_assign); }
;
/*----------------------------------------------------------------------
* Message-text parsing
*/
bodies : body { $$ = add_lanmsg(NULL, $1); }
| bodies body { $$ = add_lanmsg($1, $2); }
| error { xyyerror("'Language=...' (start of message text-definition) expected"); }
;
body : lang setline lines tMSGEND { $$ = new_lanmsg(&$1, $3); }
;
/*
* The newline is to be able to set the codepage
* to the language based codepage for the next
* message to be parsed.
*/
lang : tLANGUAGE setnl '=' token tNL {
token_t *tok = lookup_token($4->name);
cp_xlat_t *cpx;
if(!tok)
xyyerror("Undefined language");
if(tok->type != tok_language)
xyyerror("Identifier is not of class 'language'");
if((cpx = find_cpxlat(tok->token)))
{
set_codepage($$.codepage = cpx->cpin);
}
else if(!tok->codepage)
{
const language_t *lan = find_language(tok->token);
if(!lan)
{
/* Just set default; warning was given while parsing languagenames */
set_codepage($$.codepage = WMC_DEFAULT_CODEPAGE);
}
else
{
/* The default seems to be to use the DOS codepage... */
set_codepage($$.codepage = lan->doscp);
}
}
else
set_codepage($$.codepage = tok->codepage);
$$.language = tok->token;
}
| tLANGUAGE setnl '=' token error { xyyerror("Missing newline"); }
| tLANGUAGE setnl '=' error { xyyerror(err_ident); }
| tLANGUAGE error { xyyerror(err_assign); }
;
lines : tLINE { $$ = $1; }
| lines tLINE { $$ = merge($1, $2); }
| error { xyyerror(err_msg); }
| lines error { xyyerror(err_msg); }
;
/*----------------------------------------------------------------------
* Helper rules
*/
token : tIDENT { $$ = xmalloc(sizeof(token_t)); $$->name = $1; }
| tTOKEN { $$ = $1; }
;
setnl : /* Empty */ { want_nl = 1; }
;
setline : /* Empty */ { want_line = 1; }
;
setfile : /* Empty */ { want_file = 1; }
;
%%
static WCHAR *merge(WCHAR *s1, WCHAR *s2)
{
int l1 = unistrlen(s1);
int l2 = unistrlen(s2);
s1 = xrealloc(s1, (l1 + l2 + 1) * sizeof(*s1));
unistrcpy(s1+l1, s2);
free(s2);
return s1;
}
static void do_add_token(tok_e type, token_t *tok, const char *code)
{
token_t *tp = lookup_token(tok->name);
if(tp)
{
if(tok->type != type)
yywarning("Type change in token");
if(tp != tok)
xyyerror("Overlapping token not the same");
/* else its already defined and changed */
if(tok->fixed)
xyyerror("Redefinition of %s", code);
tok->fixed = 1;
}
else
{
add_token(type, tok->name, tok->token, tok->codepage, tok->alias, 1);
free(tok);
}
}
static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg)
{
lanmsg_t *lmp = (lanmsg_t *)xmalloc(sizeof(lanmsg_t));
lmp->lan = lcp->language;
lmp->cp = lcp->codepage;
lmp->msg = msg;
lmp->len = unistrlen(msg) + 1; /* Include termination */
if(lmp->len > 4096)
yywarning("Message exceptionally long; might be a missing termination");
return lmp;
}
static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg)
{
int i;
if(!msg)
msg = xmalloc(sizeof(msg_t));
msg->msgs = xrealloc(msg->msgs, (msg->nmsgs+1) * sizeof(*(msg->msgs)));
msg->msgs[msg->nmsgs] = lanmsg;
msg->nmsgs++;
for(i = 0; i < msg->nmsgs-1; i++)
{
if(msg->msgs[i]->lan == lanmsg->lan)
xyyerror("Message for language 0x%x already defined", lanmsg->lan);
}
return msg;
}
static int sort_lanmsg(const void *p1, const void *p2)
{
return (*(lanmsg_t **)p1)->lan - (*(lanmsg_t **)p2)->lan;
}
static msg_t *complete_msg(msg_t *mp, int id)
{
assert(mp != NULL);
mp->id = id;
if(have_sym)
mp->sym = last_sym;
else
xyyerror("No symbolic name defined for message id %d", id);
mp->sev = last_sev;
mp->fac = last_fac;
qsort(mp->msgs, mp->nmsgs, sizeof(*(mp->msgs)), sort_lanmsg);
mp->realid = id | (last_sev << 30) | (last_fac << 16);
if(custombit)
mp->realid |= 1 << 29;
mp->base = base;
mp->cast = cast;
return mp;
}
static void add_node(node_e type, void *p)
{
node_t *ndp = (node_t *)xmalloc(sizeof(node_t));
ndp->type = type;
ndp->u.all = p;
if(nodetail)
{
ndp->prev = nodetail;
nodetail->next = ndp;
nodetail = ndp;
}
else
{
nodehead = nodetail = ndp;
}
}
static void test_id(int id)
{
node_t *ndp;
for(ndp = nodehead; ndp; ndp = ndp->next)
{
if(ndp->type != nd_msg)
continue;
if(ndp->u.msg->id == id && ndp->u.msg->sev == last_sev && ndp->u.msg->fac == last_fac)
xyyerror("MessageId %d with facility 0x%x and severity 0x%x already defined", id, last_fac, last_sev);
}
}
static int check_languages(node_t *head)
{
static const char err_missing[] = "Missing definition for language 0x%x; MessageID %d, facility 0x%x, severity 0x%x";
node_t *ndp;
int nm = 0;
msg_t *msg = NULL;
for(ndp = head; ndp; ndp = ndp->next)
{
if(ndp->type != nd_msg)
continue;
if(!nm)
{
msg = ndp->u.msg;
}
else
{
int i;
msg_t *m1;
msg_t *m2;
if(ndp->u.msg->nmsgs > msg->nmsgs)
{
m1 = ndp->u.msg;
m2 = msg;
}
else
{
m1 = msg;
m2 = ndp->u.msg;
}
for(i = 0; i < m1->nmsgs; i++)
{
if(i > m2->nmsgs)
error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev);
else if(m1->msgs[i]->lan < m2->msgs[i]->lan)
error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev);
else if(m1->msgs[i]->lan > m2->msgs[i]->lan)
error(err_missing, m2->msgs[i]->lan, m1->id, m1->fac, m1->sev);
}
}
nm++;
}
return nm;
}
#define MSGRID(x) ((*(msg_t **)(x))->realid)
static int sort_msg(const void *p1, const void *p2)
{
return MSGRID(p1) > MSGRID(p2) ? 1 : (MSGRID(p1) == MSGRID(p2) ? 0 : -1);
/* return (*(msg_t **)p1)->realid - (*(msg_t **)p1)->realid; */
}
/*
* block_messages() basically transposes the messages
* from ID/language based list to a language/ID
* based list.
*/
static lan_blk_t *block_messages(node_t *head)
{
lan_blk_t *lbp;
lan_blk_t *lblktail = NULL;
lan_blk_t *lblkhead = NULL;
msg_t **msgtab = NULL;
node_t *ndp;
int nmsg = 0;
int i;
int nl;
int factor = unicodeout ? 2 : 1;
for(ndp = head; ndp; ndp = ndp->next)
{
if(ndp->type != nd_msg)
continue;
msgtab = xrealloc(msgtab, (nmsg+1) * sizeof(*msgtab));
msgtab[nmsg++] = ndp->u.msg;
}
assert(nmsg != 0);
qsort(msgtab, nmsg, sizeof(*msgtab), sort_msg);
for(nl = 0; nl < msgtab[0]->nmsgs; nl++) /* This should be equal for all after check_languages() */
{
lbp = xmalloc(sizeof(lan_blk_t));
if(!lblktail)
{
lblkhead = lblktail = lbp;
}
else
{
lblktail->next = lbp;
lbp->prev = lblktail;
lblktail = lbp;
}
lbp->nblk = 1;
lbp->blks = xmalloc(sizeof(*lbp->blks));
lbp->blks[0].idlo = msgtab[0]->realid;
lbp->blks[0].idhi = msgtab[0]->realid;
/* The plus 4 is the entry header; (+3)&~3 is DWORD alignment */
lbp->blks[0].size = ((factor * msgtab[0]->msgs[nl]->len + 3) & ~3) + 4;
lbp->blks[0].msgs = xmalloc(sizeof(*lbp->blks[0].msgs));
lbp->blks[0].nmsg = 1;
lbp->blks[0].msgs[0] = msgtab[0]->msgs[nl];
lbp->lan = msgtab[0]->msgs[nl]->lan;
for(i = 1; i < nmsg; i++)
{
block_t *blk = &(lbp->blks[lbp->nblk-1]);
if(msgtab[i]->realid == blk->idhi+1)
{
blk->size += ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4;
blk->idhi++;
blk->msgs = xrealloc(blk->msgs, (blk->nmsg+1) * sizeof(*blk->msgs));
blk->msgs[blk->nmsg++] = msgtab[i]->msgs[nl];
}
else
{
lbp->nblk++;
lbp->blks = xrealloc(lbp->blks, lbp->nblk * sizeof(*lbp->blks));
blk = &(lbp->blks[lbp->nblk-1]);
blk->idlo = msgtab[i]->realid;
blk->idhi = msgtab[i]->realid;
blk->size = ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4;
blk->msgs = xmalloc(sizeof(*blk->msgs));
blk->nmsg = 1;
blk->msgs[0] = msgtab[i]->msgs[nl];
}
}
}
free(msgtab);
return lblkhead;
}
static int sc_xlat(const void *p1, const void *p2)
{
return ((cp_xlat_t *)p1)->lan - ((cp_xlat_t *)p2)->lan;
}
static void add_cpxlat(int lan, int cpin, int cpout)
{
cpxlattab = xrealloc(cpxlattab, (ncpxlattab+1) * sizeof(*cpxlattab));
cpxlattab[ncpxlattab].lan = lan;
cpxlattab[ncpxlattab].cpin = cpin;
cpxlattab[ncpxlattab].cpout = cpout;
ncpxlattab++;
qsort(cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat);
}
static cp_xlat_t *find_cpxlat(int lan)
{
cp_xlat_t t;
if(!cpxlattab) return NULL;
t.lan = lan;
return (cp_xlat_t *)bsearch(&t, cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat);
}

254
reactos/tools/wmc/utils.c Normal file
View file

@ -0,0 +1,254 @@
/*
* Utility routines
*
* Copyright 1998,2000 Bertho A. Stultiens
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "wmctypes.h"
#include "utils.h"
#include "wmc.h"
#define SUPPRESS_YACC_ERROR_MESSAGE
static void generic_msg(const char *s, const char *t, va_list ap)
{
fprintf(stderr, "%s %s: %d, %d: ", t, input_name ? input_name : "stdin", line_number, char_number);
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
}
/*
* The yyerror routine should not exit because we use the error-token
* to determine the syntactic error in the source. However, YACC
* uses the same routine to print an error just before the error
* token is reduced.
* The extra routine 'xyyerror' is used to exit after giving a real
* message.
*/
int yyerror(const char *s, ...)
{
#ifndef SUPPRESS_YACC_ERROR_MESSAGE
va_list ap;
va_start(ap, s);
generic_msg(s, "Yacc error", ap);
va_end(ap);
#endif
return 1;
}
int xyyerror(const char *s, ...)
{
va_list ap;
va_start(ap, s);
generic_msg(s, "Error", ap);
va_end(ap);
exit(1);
return 1;
}
int yywarning(const char *s, ...)
{
va_list ap;
va_start(ap, s);
generic_msg(s, "Warning", ap);
va_end(ap);
return 0;
}
void internal_error(const char *file, int line, const char *s, ...)
{
va_list ap;
va_start(ap, s);
fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(3);
}
void error(const char *s, ...)
{
va_list ap;
va_start(ap, s);
fprintf(stderr, "Error: ");
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(2);
}
void warning(const char *s, ...)
{
va_list ap;
va_start(ap, s);
fprintf(stderr, "Warning: ");
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
va_end(ap);
}
char *dup_basename(const char *name, const char *ext)
{
int namelen;
int extlen = strlen(ext);
char *base;
char *slash;
if(!name)
name = "wmc.tab";
slash = strrchr(name, '/');
if (slash)
name = slash + 1;
namelen = strlen(name);
/* +4 for later extension and +1 for '\0' */
base = (char *)xmalloc(namelen +4 +1);
strcpy(base, name);
if(!strcasecmp(name + namelen-extlen, ext))
{
base[namelen - extlen] = '\0';
}
return base;
}
void *xmalloc(size_t size)
{
void *res;
assert(size > 0);
assert(size < 102400);
res = malloc(size);
if(res == NULL)
{
error("Virtual memory exhausted.\n");
}
/*
* We set it to 0.
* This is *paramount* because we depend on it
* just about everywhere in the rest of the code.
*/
memset(res, 0, size);
return res;
}
void *xrealloc(void *p, size_t size)
{
void *res;
assert(size > 0);
assert(size < 102400);
res = realloc(p, size);
if(res == NULL)
{
error("Virtual memory exhausted.\n");
}
return res;
}
char *xstrdup(const char *str)
{
char *s;
assert(str != NULL);
s = (char *)xmalloc(strlen(str)+1);
return strcpy(s, str);
}
int unistrlen(const WCHAR *s)
{
int n;
for(n = 0; *s; n++, s++)
;
return n;
}
WCHAR *unistrcpy(WCHAR *dst, const WCHAR *src)
{
WCHAR *t = dst;
while(*src)
*t++ = *src++;
*t = 0;
return dst;
}
WCHAR *xunistrdup(const WCHAR * str)
{
WCHAR *s;
assert(str != NULL);
s = (WCHAR *)xmalloc((unistrlen(str)+1) * sizeof(WCHAR));
return unistrcpy(s, str);
}
int unistricmp(const WCHAR *s1, const WCHAR *s2)
{
int i;
int once = 0;
static const char warn[] = "Don't know the uppercase equivalent of non acsii characters;"
"comparison might yield wrong results";
while(*s1 && *s2)
{
if((*s1 & 0xffff) > 0x7f || (*s2 & 0xffff) > 0x7f)
{
if(!once)
{
once++;
yywarning(warn);
}
i = *s1++ - *s2++;
}
else
i = toupper(*s1++) - toupper(*s2++);
if(i)
return i;
}
if((*s1 & 0xffff) > 0x7f || (*s2 & 0xffff) > 0x7f)
{
if(!once)
yywarning(warn);
return *s1 - *s2;
}
else
return toupper(*s1) - toupper(*s2);
}
int unistrcmp(const WCHAR *s1, const WCHAR *s2)
{
int i;
while(*s1 && *s2)
{
i = *s1++ - *s2++;
if(i)
return i;
}
return *s1 - *s2;
}

51
reactos/tools/wmc/utils.h Normal file
View file

@ -0,0 +1,51 @@
/*
* Utility routines' prototypes etc.
*
* Copyright 1998,2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WMC_UTILS_H
#define __WMC_UTILS_H
#include <stddef.h> /* size_t */
#include "wmctypes.h"
void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(const char *str);
#ifndef __GNUC__
#define __attribute__(X)
#endif
int yyerror(const char *s, ...) __attribute__((format (printf, 1, 2)));
int xyyerror(const char *s, ...) __attribute__((format (printf, 1, 2)));
int yywarning(const char *s, ...) __attribute__((format (printf, 1, 2)));
void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4)));
void error(const char *s, ...) __attribute__((format (printf, 1, 2)));
void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
char *dup_basename(const char *name, const char *ext);
WCHAR *xunistrdup(const WCHAR * str);
WCHAR *unistrcpy(WCHAR *dst, const WCHAR *src);
int unistrlen(const WCHAR *s);
int unistricmp(const WCHAR *s1, const WCHAR *s2);
int unistrcmp(const WCHAR *s1, const WCHAR *s2);
#endif

282
reactos/tools/wmc/wmc.c Normal file
View file

@ -0,0 +1,282 @@
/*
* Wine Message Compiler main program
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "wmc.h"
#include "utils.h"
#include "lang.h"
#include "write.h"
static char usage[] =
"Usage: wmc [options...] [inputfile.mc]\n"
" -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n"
" (default is n[ative] which equals "
#ifdef WORDS_BIGENDIAN
"big"
#else
"little"
#endif
"-endian)\n"
" -c Set 'custom-bit' in values\n"
" -d Use decimal values in output\n"
" -D Set debug flag\n"
" -h This message\n"
" -H file Write headerfile to file (default is inputfile.h)\n"
" -i Inline messagetable(s)\n"
" -o file Output to file (default is inputfile.rc)\n"
" -u Inputfile is in unicode\n"
" -U Output unicode messagetable(s)\n"
" -v Show supported codepages and languages\n"
" -V Print version end exit\n"
" -W Enable pedantic warnings\n"
"Input is taken from stdin if no inputfile is specified.\n"
"Byteorder of unicode input is based upon the first couple of\n"
"bytes read, which should be 0x0000..0x00ff.\n"
;
static char version_string[] =
"Wine Message Compiler version " PACKAGE_VERSION "\n"
"Copyright 2000 Bertho A. Stultiens\n"
;
/*
* The output byte-order of resources (set with -B)
*/
int byteorder = WMC_BO_NATIVE;
/*
* Custom bit (bit 29) in output values must be set (-c option)
*/
int custombit = 0;
/*
* Output decimal values (-d option)
*/
int decimal = 0;
/*
* Enable pedantic warnings; check arg references (-W option)
*/
int pedantic = 0;
/*
* Unicode input (-u option)
*/
int unicodein = 0;
/*
* Unicode output (-U option)
*/
int unicodeout = 0;
/*
* Inline the messagetables (don't write *.bin files; -i option)
*/
int rcinline = 0;
/*
* Debugging flag (-D option)
*/
int dodebug = 0;
char *output_name = NULL; /* The name given by the -o option */
char *input_name = NULL; /* The name given on the command-line */
char *header_name = NULL; /* The name given by the -H option */
int line_number = 1; /* The current line */
int char_number = 1; /* The current char pos within the line */
char *cmdline; /* The entire commandline */
time_t now; /* The time of start of wmc */
int getopt (int argc, char *const *argv, const char *optstring);
static void segvhandler(int sig);
int main(int argc,char *argv[])
{
extern char* optarg;
extern int optind;
int optc;
int lose = 0;
int ret;
int i;
int cmdlen;
signal(SIGSEGV, segvhandler);
now = time(NULL);
/* First rebuild the commandline to put in destination */
/* Could be done through env[], but not all OS-es support it */
cmdlen = 4; /* for "wmc " */
for(i = 1; i < argc; i++)
cmdlen += strlen(argv[i]) + 1;
cmdline = (char *)xmalloc(cmdlen);
strcpy(cmdline, "wmc ");
for(i = 1; i < argc; i++)
{
strcat(cmdline, argv[i]);
if(i < argc-1)
strcat(cmdline, " ");
}
while((optc = getopt(argc, argv, "B:cdDhH:io:p:uUvVW")) != EOF)
{
switch(optc)
{
case 'B':
switch(optarg[0])
{
case 'n':
case 'N':
byteorder = WMC_BO_NATIVE;
break;
case 'l':
case 'L':
byteorder = WMC_BO_LITTLE;
break;
case 'b':
case 'B':
byteorder = WMC_BO_BIG;
break;
default:
fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n");
lose++;
}
break;
case 'c':
custombit = 1;
break;
case 'd':
decimal = 1;
break;
case 'D':
dodebug = 1;
break;
case 'h':
printf("%s", usage);
exit(0);
/* No return */
case 'H':
header_name = xstrdup(optarg);
break;
case 'i':
rcinline = 1;
break;
case 'o':
output_name = xstrdup(optarg);
break;
case 'u':
unicodein = 1;
break;
case 'U':
unicodeout = 1;
break;
case 'v':
show_languages();
show_codepages();
exit(0);
/* No return */
case 'V':
printf(version_string);
exit(0);
/* No return */
case 'W':
pedantic = 1;
break;
default:
lose++;
break;
}
}
if(lose)
{
fprintf(stderr, "%s", usage);
return 1;
}
yydebug = dodebug;
if(dodebug)
{
setbuf(stdout, 0);
setbuf(stderr, 0);
}
/* Check for input file on command-line */
if(optind < argc)
{
input_name = argv[optind];
}
/* Generate appropriate outfile names */
if(!output_name)
{
output_name = dup_basename(input_name, ".mc");
strcat(output_name, ".rc");
}
if(!header_name)
{
header_name = dup_basename(input_name, ".mc");
strcat(header_name, ".h");
}
if(input_name)
{
if(!(yyin = fopen(input_name, "rb")))
error("Could not open %s for input\n", input_name);
}
else
yyin = stdin;
ret = yyparse();
if(input_name)
fclose(yyin);
if(ret)
{
/* Error during parse */
exit(1);
}
write_h_file(header_name);
write_rc_file(output_name);
if(!rcinline)
write_bin_files();
return 0;
}
static void segvhandler(int sig)
{
fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
fflush(stdout);
fflush(stderr);
abort();
}

75
reactos/tools/wmc/wmc.h Normal file
View file

@ -0,0 +1,75 @@
/*
* Main definitions and externals
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WMC_WMC_H
#define __WMC_WMC_H
#include <time.h> /* For time_t */
#include "wmctypes.h"
/*
* The default codepage setting is only to
* read and convert input which is non-message
* text. It doesn't really matter that much because
* all codepages map 0x00-0x7f to 0x0000-0x007f from
* char to unicode and all non-message text should
* be plain ASCII.
* However, we do implement iso-8859-1 for 1-to-1
* mapping for all other chars, so this is very close
* to what we really want.
*/
#define WMC_DEFAULT_CODEPAGE 28591
extern int pedantic;
extern int leave_case;
extern int byteorder;
extern int decimal;
extern int custombit;
extern int unicodein;
extern int unicodeout;
extern int rcinline;
extern char *output_name;
extern char *input_name;
extern char *header_name;
extern char *cmdline;
extern time_t now;
extern int line_number;
extern int char_number;
int yyparse(void);
extern int yydebug;
extern int want_nl;
extern int want_line;
extern int want_file;
extern node_t *nodehead;
extern lan_blk_t *lanblockhead;
int yylex(void);
FILE *yyin;
void set_codepage(int cp);
void add_token(tok_e type, const WCHAR *name, int tok, int cp, const WCHAR *alias, int fix);
token_t *lookup_token(const WCHAR *s);
void get_tokentable(token_t **tab, int *len);
#endif

79
reactos/tools/wmc/wmc.mak Normal file
View file

@ -0,0 +1,79 @@
WMC_BASE = $(TOOLS_BASE_)wmc
WMC_BASE_ = $(WMC_BASE)$(SEP)
WMC_INT = $(INTERMEDIATE_)$(WMC_BASE)
WMC_INT_ = $(WMC_INT)$(SEP)
WMC_OUT = $(OUTPUT_)$(WMC_BASE)
WMC_OUT_ = $(WMC_OUT)$(SEP)
$(WMC_INT): | $(TOOLS_INT)
$(ECHO_MKDIR)
${mkdir} $@
ifneq ($(INTERMEDIATE),$(OUTPUT))
$(WMC_OUT): | $(TOOLS_OUT)
$(ECHO_MKDIR)
${mkdir} $@
endif
WMC_TARGET = \
$(EXEPREFIX)$(WMC_OUT_)wmc$(EXEPOSTFIX)
WMC_SOURCES = $(addprefix $(WMC_BASE_), \
lang.c \
mcl.c \
utils.c \
wmc.c \
write.c \
mcy.tab.c \
)
WMC_OBJECTS = \
$(addprefix $(INTERMEDIATE_), $(WMC_SOURCES:.c=.o))
WMC_HOST_CFLAGS = -I$(WMC_BASE) $(TOOLS_CFLAGS) \
-D__USE_W32API -DWINE_UNICODE_API= -I$(UNICODE_BASE) \
-DDWORD="unsigned int" -DDWORD_DEFINED \
-DLONG="int" -DULONG="unsigned int" \
-DPULONG="unsigned int *" -DLONG_DEFINED \
-Dwchar_t="unsigned short" -D_WCHAR_T_DEFINED \
-Iinclude/wine -Iinclude -Iw32api/include
WMC_HOST_LFLAGS = $(TOOLS_LFLAGS)
WMC_LIBS = $(UNICODE_TARGET)
.PHONY: wmc
wmc: $(WMC_TARGET)
$(WMC_TARGET): $(WMC_OBJECTS) $(WMC_LIBS) | $(WMC_OUT)
$(ECHO_LD)
${host_gcc} $(WMC_OBJECTS) $(WMC_LIBS) $(WMC_HOST_LFLAGS) -o $@
$(WMC_INT_)lang.o: $(WMC_BASE_)lang.c | $(WMC_INT)
$(ECHO_CC)
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
$(WMC_INT_)mcl.o: $(WMC_BASE_)mcl.c | $(WMC_INT)
$(ECHO_CC)
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
$(WMC_INT_)utils.o: $(WMC_BASE_)utils.c | $(WMC_INT)
$(ECHO_CC)
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
$(WMC_INT_)wmc.o: $(WMC_BASE_)wmc.c | $(WMC_INT)
$(ECHO_CC)
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
$(WMC_INT_)write.o: $(WMC_BASE_)write.c | $(WMC_INT)
$(ECHO_CC)
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
$(WMC_INT_)mcy.tab.o: $(WMC_BASE_)mcy.tab.c | $(WMC_INT)
$(ECHO_CC)
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
.PHONY: wmc_clean
wmc_clean:
-@$(rm) $(WMC_TARGET) $(WMC_OBJECTS) 2>$(NUL)
clean: wmc_clean

View file

@ -0,0 +1,122 @@
/*
* Main definitions and externals
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WMC_WMCTYPES_H
#define __WMC_WMCTYPES_H
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
/* Byteordering defines */
#define WMC_BO_NATIVE 0x00
#define WMC_BO_LITTLE 0x01
#define WMC_BO_BIG 0x02
#define WMC_LOBYTE(w) ((WORD)(w) & 0xff)
#define WMC_HIBYTE(w) (((WORD)(w) >> 8) & 0xff)
#define WMC_LOWORD(d) ((DWORD)(d) & 0xffff)
#define WMC_HIWORD(d) (((DWORD)(d) >> 16) & 0xffff)
#define BYTESWAP_WORD(w) ((WORD)(((WORD)WMC_LOBYTE(w) << 8) + (WORD)WMC_HIBYTE(w)))
#define BYTESWAP_DWORD(d) ((DWORD)(((DWORD)BYTESWAP_WORD(WMC_LOWORD(d)) << 16) + ((DWORD)BYTESWAP_WORD(WMC_HIWORD(d)))))
/*
* Tokenizer types
*/
typedef enum tok_enum {
tok_null = 0,
tok_keyword,
tok_severity,
tok_facility,
tok_language
} tok_e;
typedef struct token {
tok_e type;
const WCHAR *name; /* Parsed name of token */
int token; /* Tokenvalue or language code */
int codepage;
const WCHAR *alias; /* Alias or filename */
int fixed; /* Cleared if token may change */
} token_t;
typedef struct lan_cp {
int language;
int codepage;
} lan_cp_t;
typedef struct cp_xlat {
int lan;
int cpin;
int cpout;
} cp_xlat_t;
typedef struct lanmsg {
int lan; /* Language code of message */
int cp; /* Codepage of message */
WCHAR *msg; /* Message text */
int len; /* Message length including trailing '\0' */
} lanmsg_t;
typedef struct msg {
int id; /* Message ID */
unsigned realid; /* Combined message ID */
WCHAR *sym; /* Symbolic name */
int sev; /* Severity code */
int fac; /* Facility code */
lanmsg_t **msgs; /* Array message texts */
int nmsgs; /* Number of message texts in array */
int base; /* Base of number to print */
WCHAR *cast; /* Typecase to use */
} msg_t;
typedef enum {
nd_msg,
nd_comment
} node_e;
typedef struct node {
struct node *next;
struct node *prev;
node_e type;
union {
void *all;
WCHAR *comment;
msg_t *msg;
} u;
} node_t;
typedef struct block {
unsigned idlo; /* Lowest ID in this set */
unsigned idhi; /* Highest ID in this set */
int size; /* Size of this set */
lanmsg_t **msgs; /* Array of messages in this set */
int nmsg; /* Number of array entries */
} block_t;
typedef struct lan_blk {
struct lan_blk *next; /* Linkage for languages */
struct lan_blk *prev;
int lan; /* The language of this block */
block_t *blks; /* Array of blocks for this language */
int nblk; /* Nr of blocks in array */
} lan_blk_t;
#endif

515
reactos/tools/wmc/write.c Normal file
View file

@ -0,0 +1,515 @@
/*
* Wine Message Compiler output generation
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "wmc.h"
#include "utils.h"
#include "lang.h"
#include "write.h"
/*
* The binary resource layout is as follows:
*
* +===============+
* Header | NBlocks |
* +===============+
* Block 0 | Low ID |
* +---------------+
* | High ID |
* +---------------+
* | Offset |---+
* +===============+ |
* Block 1 | Low ID | |
* +---------------+ |
* | High ID | |
* +---------------+ |
* | Offset |------+
* +===============+ | |
* | | | |
* ... ... | |
* | | | |
* +===============+ <-+ |
* B0 LoID | Len | Flags | |
* +---+---+---+---+ |
* | b | l | a | b | |
* +---+---+---+---+ |
* | l | a | \0| \0| |
* +===============+ |
* | | |
* ... ... |
* | | |
* +===============+ |
* B0 HiID | Len | Flags | |
* +---+---+---+---+ |
* | M | o | r | e | |
* +---+---+---+---+ |
* | b | l | a | \0| |
* +===============+ <----+
* B1 LoID | Len | Flags |
* +---+---+---+---+
* | J | u | n | k |
* +---+---+---+---+
* | \0| \0| \0| \0|
* +===============+
* | |
* ... ...
* | |
* +===============+
*
* All Fields are aligned on their natural boundaries. The length
* field (Len) covers both the length of the string and the header
* fields (Len and Flags). Strings are '\0' terminated. Flags is 0
* for normal character strings and 1 for unicode strings.
*/
static char str_header[] =
"/* This file is generated with wmc version " PACKAGE_VERSION ". Do not edit! */\n"
"/* Source : %s */\n"
"/* Cmdline: %s */\n"
"/* Date : %s */\n"
"\n"
;
static char *dup_u2c(int cp, const WCHAR *uc)
{
int len;
char *cptr;
const union cptable *cpdef = find_codepage(cp);
if(!cpdef)
internal_error(__FILE__, __LINE__, "Codepage %d not found (vanished?)", cp);
len = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, NULL, 0, NULL, NULL);
cptr = xmalloc(len);
if((len = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, cptr, len, NULL, NULL)) < 0)
internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", len);
return cptr;
}
static void killnl(char *s, int ddd)
{
char *tmp;
tmp = strstr(s, "\r\n");
if(tmp)
{
if(ddd && tmp - s > 3)
{
tmp[0] = tmp[1] = tmp[2] = '.';
tmp[3] = '\0';
}
else
*tmp = '\0';
}
tmp = strchr(s, '\n');
if(tmp)
{
if(ddd && tmp - s > 3)
{
tmp[0] = tmp[1] = tmp[2] = '.';
tmp[3] = '\0';
}
else
*tmp = '\0';
}
}
static int killcomment(char *s)
{
char *tmp = s;
int b = 0;
while((tmp = strstr(tmp, "/*")))
{
tmp[1] = 'x';
b++;
}
tmp = s;
while((tmp = strstr(tmp, "*/")))
{
tmp[0] = 'x';
b++;
}
return b;
}
void write_h_file(const char *fname)
{
node_t *ndp;
char *cptr;
char *cast;
FILE *fp;
token_t *ttab;
int ntab;
int i;
int once = 0;
int idx_en = 0;
fp = fopen(fname, "w");
if(!fp)
{
perror(fname);
exit(1);
}
cptr = ctime(&now);
killnl(cptr, 0);
fprintf(fp, str_header, input_name ? input_name : "<stdin>", cmdline, cptr);
fprintf(fp, "#ifndef __WMCGENERATED_%08lx_H\n", (long)now);
fprintf(fp, "#define __WMCGENERATED_%08lx_H\n", (long)now);
fprintf(fp, "\n");
/* Write severity and facility aliases */
get_tokentable(&ttab, &ntab);
fprintf(fp, "/* Severity codes */\n");
for(i = 0; i < ntab; i++)
{
if(ttab[i].type == tok_severity && ttab[i].alias)
{
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias);
fprintf(fp, "#define %s\t0x%x\n", cptr, ttab[i].token);
free(cptr);
}
}
fprintf(fp, "\n");
fprintf(fp, "/* Facility codes */\n");
for(i = 0; i < ntab; i++)
{
if(ttab[i].type == tok_facility && ttab[i].alias)
{
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias);
fprintf(fp, "#define %s\t0x%x\n", cptr, ttab[i].token);
free(cptr);
}
}
fprintf(fp, "\n");
/* Write the message codes */
fprintf(fp, "/* Message definitions */\n");
for(ndp = nodehead; ndp; ndp = ndp->next)
{
switch(ndp->type)
{
case nd_comment:
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.comment+1);
killnl(cptr, 0);
killcomment(cptr);
if(*cptr)
fprintf(fp, "/* %s */\n", cptr);
else
fprintf(fp, "\n");
free(cptr);
break;
case nd_msg:
if(!once)
{
/*
* Search for an english text.
* If not found, then use the first in the list
*/
once++;
for(i = 0; i < ndp->u.msg->nmsgs; i++)
{
if(ndp->u.msg->msgs[i]->lan == 0x409)
{
idx_en = i;
break;
}
}
fprintf(fp, "\n");
}
fprintf(fp, "/* MessageId : 0x%08x */\n", ndp->u.msg->realid);
cptr = dup_u2c(ndp->u.msg->msgs[idx_en]->cp, ndp->u.msg->msgs[idx_en]->msg);
killnl(cptr, 0);
killcomment(cptr);
fprintf(fp, "/* Approx. msg: %s */\n", cptr);
free(cptr);
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.msg->sym);
if(ndp->u.msg->cast)
cast = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.msg->cast);
else
cast = NULL;
switch(ndp->u.msg->base)
{
case 8:
if(cast)
fprintf(fp, "#define %s\t((%s)0%oL)\n\n", cptr, cast, ndp->u.msg->realid);
else
fprintf(fp, "#define %s\t0%oL\n\n", cptr, ndp->u.msg->realid);
break;
case 10:
if(cast)
fprintf(fp, "#define %s\t((%s)%dL)\n\n", cptr, cast, ndp->u.msg->realid);
else
fprintf(fp, "#define %s\t%dL\n\n", cptr, ndp->u.msg->realid);
break;
case 16:
if(cast)
fprintf(fp, "#define %s\t((%s)0x%08xL)\n\n", cptr, cast, ndp->u.msg->realid);
else
fprintf(fp, "#define %s\t0x%08xL\n\n", cptr, ndp->u.msg->realid);
break;
default:
internal_error(__FILE__, __LINE__, "Invalid base for number print");
}
free(cptr);
if(cast)
free(cast);
break;
default:
internal_error(__FILE__, __LINE__, "Invalid node type %d", ndp->type);
}
}
fprintf(fp, "\n#endif\n");
fclose(fp);
}
static void write_rcbin(FILE *fp)
{
lan_blk_t *lbp;
token_t *ttab;
int ntab;
int i;
get_tokentable(&ttab, &ntab);
for(lbp = lanblockhead; lbp; lbp = lbp->next)
{
char *cptr = NULL;
fprintf(fp, "LANGUAGE 0x%x, 0x%x\n", lbp->lan & 0x3ff, lbp->lan >> 10);
for(i = 0; i < ntab; i++)
{
if(ttab[i].type == tok_language && ttab[i].token == lbp->lan)
{
if(ttab[i].alias)
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias);
break;
}
}
if(!cptr)
internal_error(__FILE__, __LINE__, "Filename vanished for language 0x%0x", lbp->lan);
fprintf(fp, "1 MESSAGETABLE \"%s.bin\"\n", cptr);
free(cptr);
}
}
static char *make_string(WCHAR *uc, int len, int codepage)
{
char *str = xmalloc(7*len + 1);
char *cptr = str;
int i;
int b;
if(!codepage)
{
*cptr++ = ' ';
*cptr++ = 'L';
*cptr++ = '"';
for(i = b = 0; i < len; i++, uc++)
{
switch(*uc)
{
case '\a': *cptr++ = '\\'; *cptr++ = 'a'; b += 2; break;
case '\b': *cptr++ = '\\'; *cptr++ = 'b'; b += 2; break;
case '\f': *cptr++ = '\\'; *cptr++ = 'f'; b += 2; break;
case '\n': *cptr++ = '\\'; *cptr++ = 'n'; b += 2; break;
case '\r': *cptr++ = '\\'; *cptr++ = 'r'; b += 2; break;
case '\t': *cptr++ = '\\'; *cptr++ = 't'; b += 2; break;
case '\v': *cptr++ = '\\'; *cptr++ = 'v'; b += 2; break;
case '\\': *cptr++ = '\\'; *cptr++ = '\\'; b += 2; break;
case '"': *cptr++ = '\\'; *cptr++ = '"'; b += 2; break;
default:
if (*uc < 0x100 && isprint(*uc))
{
*cptr++ = *uc;
b++;
}
else
{
int n = sprintf(cptr, "\\x%04x", *uc & 0xffff);
cptr += n;
b += n;
}
break;
}
if(i < len-1 && b >= 72)
{
*cptr++ = '"';
*cptr++ = ',';
*cptr++ = '\n';
*cptr++ = ' ';
*cptr++ = 'L';
*cptr++ = '"';
b = 0;
}
}
if (unicodeout)
len = (len + 1) & ~1;
else
len = (len + 3) & ~3;
for(; i < len; i++)
{
*cptr++ = '\\';
*cptr++ = 'x';
*cptr++ = '0';
*cptr++ = '0';
*cptr++ = '0';
*cptr++ = '0';
}
*cptr++ = '"';
*cptr = '\0';
}
else
{
char *tmp, *cc;
int mlen;
const union cptable *cpdef = find_codepage(codepage);
assert(cpdef != NULL);
mlen = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, NULL, 0, NULL, NULL);
cc = tmp = xmalloc(mlen);
if((i = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, tmp, mlen, NULL, NULL)) < 0)
internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", i);
*cptr++ = ' ';
*cptr++ = '"';
for(i = b = 0; i < len; i++, cc++)
{
switch(*cc)
{
case '\a': *cptr++ = '\\'; *cptr++ = 'a'; b += 2; break;
case '\b': *cptr++ = '\\'; *cptr++ = 'b'; b += 2; break;
case '\f': *cptr++ = '\\'; *cptr++ = 'f'; b += 2; break;
case '\n': *cptr++ = '\\'; *cptr++ = 'n'; b += 2; break;
case '\r': *cptr++ = '\\'; *cptr++ = 'r'; b += 2; break;
case '\t': *cptr++ = '\\'; *cptr++ = 't'; b += 2; break;
case '\v': *cptr++ = '\\'; *cptr++ = 'v'; b += 2; break;
case '\\': *cptr++ = '\\'; *cptr++ = '\\'; b += 2; break;
case '"': *cptr++ = '\\'; *cptr++ = '"'; b += 2; break;
default:
if(isprint(*cc))
{
*cptr++ = *cc;
b++;
}
else
{
int n = sprintf(cptr, "\\x%02x", *cc & 0xff);
cptr += n;
b += n;
}
break;
}
if(i < len-1 && b >= 72)
{
*cptr++ = '"';
*cptr++ = ',';
*cptr++ = '\n';
*cptr++ = ' ';
*cptr++ = '"';
b = 0;
}
}
len = (len + 3) & ~3;
for(; i < len; i++)
{
*cptr++ = '\\';
*cptr++ = 'x';
*cptr++ = '0';
*cptr++ = '0';
}
*cptr++ = '"';
*cptr = '\0';
free(tmp);
}
return str;
}
static void write_rcinline(FILE *fp)
{
lan_blk_t *lbp;
int i;
int j;
for(lbp = lanblockhead; lbp; lbp = lbp->next)
{
unsigned offs = 4 * (lbp->nblk * 3 + 1);
fprintf(fp, "\n1 MESSAGETABLE\n");
fprintf(fp, "LANGUAGE 0x%x, 0x%x\n", lbp->lan & 0x3ff, lbp->lan >> 10);
fprintf(fp, "{\n");
fprintf(fp, " /* NBlocks */ 0x%08xL,\n", lbp->nblk);
for(i = 0; i < lbp->nblk; i++)
{
fprintf(fp, " /* Lo,Hi,Offs */ 0x%08xL, 0x%08xL, 0x%08xL,\n",
lbp->blks[i].idlo,
lbp->blks[i].idhi,
offs);
offs += lbp->blks[i].size;
}
for(i = 0; i < lbp->nblk; i++)
{
block_t *blk = &lbp->blks[i];
for(j = 0; j < blk->nmsg; j++)
{
char *cptr;
int l = blk->msgs[j]->len;
const char *comma = j == blk->nmsg-1 && i == lbp->nblk-1 ? "" : ",";
cptr = make_string(blk->msgs[j]->msg, l, unicodeout ? 0 : blk->msgs[j]->cp);
fprintf(fp, "\n /* Msg 0x%08x */ 0x%04x, 0x000%c,\n",
blk->idlo + j,
(unicodeout ? (l*2+3)&~3 : (l+3)&~3) + 4,
unicodeout ? '1' : '0');
fprintf(fp, "%s%s\n", cptr, comma);
free(cptr);
}
}
fprintf(fp, "}\n");
}
}
void write_rc_file(const char *fname)
{
FILE *fp;
char *cptr;
fp = fopen(fname, "w");
if(!fp)
{
perror(fname);
exit(1);
}
cptr = ctime(&now);
killnl(cptr, 0);
fprintf(fp, str_header, input_name ? input_name : "<stdin>", cmdline, cptr);
if(rcinline)
write_rcinline(fp);
else
write_rcbin(fp);
fclose(fp);
}
void write_bin_files(void)
{
assert(rcinline == 0);
}

27
reactos/tools/wmc/write.h Normal file
View file

@ -0,0 +1,27 @@
/*
* Wine Message Compiler outpur generation
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WMC_WRITE_H
#define __WMC_WRITE_H
void write_h_file(const char *fname);
void write_rc_file(const char *fname);
void write_bin_files(void);
#endif