Re-import wmc from Wine
authorGé van Geldorp <ge@gse.nl>
Mon, 28 Nov 2005 22:03:22 +0000 (22:03 +0000)
committerGé van Geldorp <ge@gse.nl>
Mon, 28 Nov 2005 22:03:22 +0000 (22:03 +0000)
svn path=/trunk/; revision=19728

17 files changed:
reactos/Makefile
reactos/media/doc/README.WINE
reactos/tools/wmc/CHANGES [new file with mode: 0644]
reactos/tools/wmc/lang.c [new file with mode: 0644]
reactos/tools/wmc/lang.h [new file with mode: 0644]
reactos/tools/wmc/mcl.c [new file with mode: 0644]
reactos/tools/wmc/mcy.tab.c [new file with mode: 0644]
reactos/tools/wmc/mcy.tab.h [new file with mode: 0644]
reactos/tools/wmc/mcy.y [new file with mode: 0644]
reactos/tools/wmc/utils.c [new file with mode: 0644]
reactos/tools/wmc/utils.h [new file with mode: 0644]
reactos/tools/wmc/wmc.c [new file with mode: 0644]
reactos/tools/wmc/wmc.h [new file with mode: 0644]
reactos/tools/wmc/wmc.mak [new file with mode: 0644]
reactos/tools/wmc/wmctypes.h [new file with mode: 0644]
reactos/tools/wmc/write.c [new file with mode: 0644]
reactos/tools/wmc/write.h [new file with mode: 0644]

index 8b80e5c..18da205 100644 (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)
index 79fc8d5..b352e41 100644 (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
 
diff --git a/reactos/tools/wmc/CHANGES b/reactos/tools/wmc/CHANGES
new file mode 100644 (file)
index 0000000..bec49ca
--- /dev/null
@@ -0,0 +1,5 @@
+---------------------------------------------------------------------------
+Version 1.0.0 (12-Jun-2000)
+
+Bertho Stultiens <bertho@akhphd.au.dk>
+- Initial release
diff --git a/reactos/tools/wmc/lang.c b/reactos/tools/wmc/lang.c
new file mode 100644 (file)
index 0000000..d14ad3b
--- /dev/null
@@ -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);
+}
diff --git a/reactos/tools/wmc/lang.h b/reactos/tools/wmc/lang.h
new file mode 100644 (file)
index 0000000..12350f5
--- /dev/null
@@ -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
diff --git a/reactos/tools/wmc/mcl.c b/reactos/tools/wmc/mcl.c
new file mode 100644 (file)
index 0000000..61710a2
--- /dev/null
@@ -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);
+               }
+       }
+}
diff --git a/reactos/tools/wmc/mcy.tab.c b/reactos/tools/wmc/mcy.tab.c
new file mode 100644 (file)
index 0000000..e2929ec
--- /dev/null
@@ -0,0 +1,2266 @@
+/* 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.  */
+
+/* Written by Richard Stallman by simplifying the original so called
+   ``semantic'' parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* 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
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 39 "tools/wmc/mcy.y"
+
+
+#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);
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#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 191 of yacc.c.  */
+#line 186 "tools/wmc/mcy.tab.c"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 214 of yacc.c.  */
+#line 198 "tools/wmc/mcy.tab.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+# ifndef YYFREE
+#  define YYFREE free
+# endif
+# ifndef YYMALLOC
+#  define YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   define YYSTACK_ALLOC alloca
+#  endif
+# else
+#  if defined (alloca) || defined (_ALLOCA_H)
+#   define YYSTACK_ALLOC alloca
+#  else
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+        || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined (__GNUC__) && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         register YYSIZE_T yyi;                \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)                                       \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+   typedef signed char yysigned_char;
+#else
+   typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL  30
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   165
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS  27
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS  32
+/* YYNRULES -- Number of rules. */
+#define YYNRULES  104
+/* YYNRULES -- Number of states. */
+#define YYNSTATES  155
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   276
+
+#define YYTRANSLATE(YYX)                                               \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const unsigned char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+      23,    24,     2,    26,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    25,     2,
+       2,    22,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const unsigned short yyprhs[] =
+{
+       0,     0,     3,     5,     7,    10,    12,    14,    16,    18,
+      24,    30,    34,    37,    43,    49,    53,    56,    62,    68,
+      72,    75,    81,    87,    91,    94,    98,   102,   105,   109,
+     113,   116,   118,   121,   123,   128,   132,   135,   137,   140,
+     142,   147,   151,   154,   155,   158,   161,   163,   166,   168,
+     176,   183,   188,   192,   195,   196,   199,   202,   204,   207,
+     209,   215,   221,   226,   230,   233,   235,   237,   238,   243,
+     247,   250,   251,   253,   256,   259,   260,   263,   266,   269,
+     273,   277,   280,   284,   288,   291,   295,   299,   302,   304,
+     307,   309,   314,   320,   326,   331,   334,   336,   339,   341,
+     344,   346,   348,   349,   350
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+      28,     0,    -1,    29,    -1,    30,    -1,    29,    30,    -1,
+      31,    -1,    43,    -1,    19,    -1,     1,    -1,     3,    22,
+      23,    32,    24,    -1,     3,    22,    23,    32,     1,    -1,
+       3,    22,     1,    -1,     3,     1,    -1,     4,    22,    23,
+      34,    24,    -1,     4,    22,    23,    34,     1,    -1,     4,
+      22,     1,    -1,     4,     1,    -1,     5,    22,    23,    37,
+      24,    -1,     5,    22,    23,    37,     1,    -1,     5,    22,
+       1,    -1,     5,     1,    -1,     7,    22,    23,    40,    24,
+      -1,     7,    22,    23,    40,     1,    -1,     7,    22,     1,
+      -1,     7,     1,    -1,     8,    22,    16,    -1,     8,    22,
+       1,    -1,     8,     1,    -1,     6,    22,    20,    -1,     6,
+      22,     1,    -1,     6,     1,    -1,    33,    -1,    32,    33,
+      -1,     1,    -1,    55,    22,    20,    36,    -1,    55,    22,
+       1,    -1,    55,     1,    -1,    35,    -1,    34,    35,    -1,
+       1,    -1,    55,    22,    20,    36,    -1,    55,    22,     1,
+      -1,    55,     1,    -1,    -1,    25,    16,    -1,    25,     1,
+      -1,    38,    -1,    37,    38,    -1,     1,    -1,    55,    22,
+      20,    58,    25,    18,    39,    -1,    55,    22,    20,    58,
+      25,     1,    -1,    55,    22,    20,     1,    -1,    55,    22,
+       1,    -1,    55,     1,    -1,    -1,    25,    20,    -1,    25,
+       1,    -1,    41,    -1,    40,    41,    -1,     1,    -1,    42,
+      22,    20,    25,    20,    -1,    42,    22,    20,    25,     1,
+      -1,    42,    22,    20,     1,    -1,    42,    22,     1,    -1,
+      42,     1,    -1,    20,    -1,    21,    -1,    -1,    45,    47,
+      44,    51,    -1,    15,    22,    46,    -1,    15,     1,    -1,
+      -1,    20,    -1,    26,    20,    -1,    26,     1,    -1,    -1,
+      47,    49,    -1,    47,    50,    -1,    47,    48,    -1,    10,
+      22,    16,    -1,    10,    22,     1,    -1,    10,     1,    -1,
+      12,    22,    55,    -1,    12,    22,     1,    -1,    12,     1,
+      -1,    13,    22,    55,    -1,    13,    22,     1,    -1,    13,
+       1,    -1,    52,    -1,    51,    52,    -1,     1,    -1,    53,
+      57,    54,    11,    -1,    14,    56,    22,    55,     9,    -1,
+      14,    56,    22,    55,     1,    -1,    14,    56,    22,     1,
+      -1,    14,     1,    -1,    17,    -1,    54,    17,    -1,     1,
+      -1,    54,     1,    -1,    16,    -1,    21,    -1,    -1,    -1,
+      -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const unsigned short yyrline[] =
+{
+       0,   124,   124,   131,   132,   135,   136,   137,   138,   141,
+     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
+     152,   153,   154,   155,   156,   157,   158,   159,   160,   172,
+     173,   179,   180,   181,   184,   191,   192,   198,   199,   200,
+     203,   210,   211,   214,   215,   216,   222,   223,   224,   227,
+     235,   236,   237,   238,   241,   242,   243,   249,   250,   251,
+     254,   264,   265,   266,   267,   270,   271,   281,   281,   284,
+     289,   292,   293,   294,   295,   298,   299,   300,   301,   304,
+     305,   306,   309,   317,   318,   321,   329,   330,   336,   337,
+     338,   341,   349,   378,   379,   380,   383,   384,   385,   386,
+     392,   393,   396,   399,   402
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "tSEVNAMES", "tFACNAMES", "tLANNAMES",
+  "tBASE", "tCODEPAGE", "tTYPEDEF", "tNL", "tSYMNAME", "tMSGEND",
+  "tSEVERITY", "tFACILITY", "tLANGUAGE", "tMSGID", "tIDENT", "tLINE",
+  "tFILE", "tCOMMENT", "tNUMBER", "tTOKEN", "'='", "'('", "')'", "':'",
+  "'+'", "$accept", "file", "items", "decl", "global", "smaps", "smap",
+  "fmaps", "fmap", "alias", "lmaps", "lmap", "optcp", "cmaps", "cmap",
+  "clan", "msg", "@1", "msgid", "id", "sevfacsym", "sym", "sev", "fac",
+  "bodies", "body", "lang", "lines", "token", "setnl", "setline",
+  "setfile", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const unsigned short yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,    61,    40,    41,    58,    43
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const unsigned char yyr1[] =
+{
+       0,    27,    28,    29,    29,    30,    30,    30,    30,    31,
+      31,    31,    31,    31,    31,    31,    31,    31,    31,    31,
+      31,    31,    31,    31,    31,    31,    31,    31,    31,    31,
+      31,    32,    32,    32,    33,    33,    33,    34,    34,    34,
+      35,    35,    35,    36,    36,    36,    37,    37,    37,    38,
+      38,    38,    38,    38,    39,    39,    39,    40,    40,    40,
+      41,    41,    41,    41,    41,    42,    42,    44,    43,    45,
+      45,    46,    46,    46,    46,    47,    47,    47,    47,    48,
+      48,    48,    49,    49,    49,    50,    50,    50,    51,    51,
+      51,    52,    53,    53,    53,    53,    54,    54,    54,    54,
+      55,    55,    56,    57,    58
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const unsigned char yyr2[] =
+{
+       0,     2,     1,     1,     2,     1,     1,     1,     1,     5,
+       5,     3,     2,     5,     5,     3,     2,     5,     5,     3,
+       2,     5,     5,     3,     2,     3,     3,     2,     3,     3,
+       2,     1,     2,     1,     4,     3,     2,     1,     2,     1,
+       4,     3,     2,     0,     2,     2,     1,     2,     1,     7,
+       6,     4,     3,     2,     0,     2,     2,     1,     2,     1,
+       5,     5,     4,     3,     2,     1,     1,     0,     4,     3,
+       2,     0,     1,     2,     2,     0,     2,     2,     2,     3,
+       3,     2,     3,     3,     2,     3,     3,     2,     1,     2,
+       1,     4,     5,     5,     4,     2,     1,     2,     1,     2,
+       1,     1,     0,     0,     0
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const unsigned char yydefact[] =
+{
+       0,     8,     0,     0,     0,     0,     0,     0,     0,     7,
+       0,     0,     3,     5,     6,    75,    12,     0,    16,     0,
+      20,     0,    30,     0,    24,     0,    27,     0,    70,    71,
+       1,     4,    67,    11,     0,    15,     0,    19,     0,    29,
+      28,    23,     0,    26,    25,    72,     0,    69,     0,     0,
+       0,     0,    78,    76,    77,    33,   100,   101,     0,    31,
+       0,    39,     0,    37,     0,    48,     0,    46,     0,    59,
+      65,    66,     0,    57,     0,    74,    73,    81,     0,    84,
+       0,    87,     0,    90,     0,    68,    88,   103,    10,     9,
+      32,    36,     0,    14,    13,    38,    42,     0,    18,    17,
+      47,    53,     0,    22,    21,    58,    64,     0,    80,    79,
+      83,    82,    86,    85,    95,     0,    89,     0,    35,    43,
+      41,    43,    52,     0,    63,     0,     0,    98,    96,     0,
+       0,    34,    40,    51,     0,    62,     0,    94,     0,    99,
+      91,    97,    45,    44,     0,    61,    60,    93,    92,    50,
+      54,     0,    49,    56,    55
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short yydefgoto[] =
+{
+      -1,    10,    11,    12,    13,    58,    59,    62,    63,   131,
+      66,    67,   152,    72,    73,    74,    14,    51,    15,    47,
+      32,    52,    53,    54,    85,    86,    87,   129,    60,   115,
+     117,   134
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -37
+static const short yypact[] =
+{
+     132,   -37,    18,    44,    46,    47,    48,    49,    50,   -37,
+      10,   113,   -37,   -37,   -37,   -37,   -37,    11,   -37,    14,
+     -37,    19,   -37,    85,   -37,    20,   -37,   147,   -37,   -13,
+     -37,   -37,    87,   -37,    66,   -37,    80,   -37,    82,   -37,
+     -37,   -37,    64,   -37,   -37,   -37,   107,   -37,    51,    52,
+      53,     3,   -37,   -37,   -37,   -37,   -37,   -37,     7,   -37,
+      54,   -37,     8,   -37,    55,   -37,    17,   -37,    56,   -37,
+     -37,   -37,    15,   -37,    57,   -37,   -37,   -37,   148,   -37,
+      88,   -37,    90,   -37,    58,    -3,   -37,   -37,   -37,   -37,
+     -37,   -37,   109,   -37,   -37,   -37,   -37,   114,   -37,   -37,
+     -37,   -37,   121,   -37,   -37,   -37,   -37,   122,   -37,   -37,
+     -37,   -37,   -37,   -37,   -37,    38,   -37,   129,   -37,    36,
+     -37,    36,   -37,     0,   -37,     2,    91,   -37,   -37,   144,
+     149,   -37,   -37,   -37,    37,   -37,   123,   -37,     5,   -37,
+     -37,   -37,   -37,   -37,     4,   -37,   -37,   -37,   -37,   -37,
+      39,   124,   -37,   -37,   -37
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yysigned_char yypgoto[] =
+{
+     -37,   -37,   -37,    77,   -37,   -37,    35,   -37,     1,   -27,
+     -37,    29,   -37,   -37,    30,   -37,   -37,   -37,   -37,   -37,
+     -37,   -37,   -37,   -37,   -37,    41,   -37,   -37,   -36,   -37,
+     -37,   -37
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -105
+static const short yytable[] =
+{
+      64,   133,    68,   135,    83,   149,   147,    45,    88,    93,
+      30,    84,    33,    46,   148,    35,   103,    84,    98,    16,
+      37,    41,   150,    56,    56,  -104,    64,   136,    57,    57,
+      68,    89,    94,    56,    34,    70,    71,    36,    57,   104,
+      17,    99,    38,    42,   111,    18,   113,    20,    22,    24,
+      26,    28,    77,    79,    81,    91,    96,   101,   106,   114,
+     126,   130,   144,    95,   151,    69,    19,    55,    21,    23,
+      25,    27,    29,    78,    80,    82,    92,    97,   102,   107,
+    -102,    61,    56,    65,    70,    71,    39,    57,    31,   110,
+     138,   112,   137,    90,   132,   100,    56,    48,    56,    49,
+      50,    57,   105,    57,    56,    40,    56,    56,    75,    57,
+     118,    57,    57,    -2,     1,   120,     2,     3,     4,     5,
+       6,     7,   122,   124,   145,   153,   116,    76,     8,   119,
+     127,     0,     9,     1,   121,     2,     3,     4,     5,     6,
+       7,   123,   125,   146,   154,   139,   128,     8,    43,   108,
+     142,     9,     0,     0,     0,   140,     0,     0,     0,     0,
+       0,   141,     0,    44,   109,   143
+};
+
+static const yysigned_char yycheck[] =
+{
+      36,     1,    38,     1,     1,     1,     1,    20,     1,     1,
+       0,    14,     1,    26,     9,     1,     1,    14,     1,     1,
+       1,     1,    18,    16,    16,    25,    62,    25,    21,    21,
+      66,    24,    24,    16,    23,    20,    21,    23,    21,    24,
+      22,    24,    23,    23,    80,     1,    82,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+      22,    25,    25,    62,    25,     1,    22,     1,    22,    22,
+      22,    22,    22,    22,    22,    22,    22,    22,    22,    22,
+      22,     1,    16,     1,    20,    21,     1,    21,    11,     1,
+     126,     1,     1,    58,   121,    66,    16,    10,    16,    12,
+      13,    21,    72,    21,    16,    20,    16,    16,     1,    21,
+       1,    21,    21,     0,     1,     1,     3,     4,     5,     6,
+       7,     8,     1,     1,     1,     1,    85,    20,    15,    20,
+       1,    -1,    19,     1,    20,     3,     4,     5,     6,     7,
+       8,    20,    20,    20,    20,     1,    17,    15,     1,     1,
+       1,    19,    -1,    -1,    -1,    11,    -1,    -1,    -1,    -1,
+      -1,    17,    -1,    16,    16,    16
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const unsigned char yystos[] =
+{
+       0,     1,     3,     4,     5,     6,     7,     8,    15,    19,
+      28,    29,    30,    31,    43,    45,     1,    22,     1,    22,
+       1,    22,     1,    22,     1,    22,     1,    22,     1,    22,
+       0,    30,    47,     1,    23,     1,    23,     1,    23,     1,
+      20,     1,    23,     1,    16,    20,    26,    46,    10,    12,
+      13,    44,    48,    49,    50,     1,    16,    21,    32,    33,
+      55,     1,    34,    35,    55,     1,    37,    38,    55,     1,
+      20,    21,    40,    41,    42,     1,    20,     1,    22,     1,
+      22,     1,    22,     1,    14,    51,    52,    53,     1,    24,
+      33,     1,    22,     1,    24,    35,     1,    22,     1,    24,
+      38,     1,    22,     1,    24,    41,     1,    22,     1,    16,
+       1,    55,     1,    55,     1,    56,    52,    57,     1,    20,
+       1,    20,     1,    20,     1,    20,    22,     1,    17,    54,
+      25,    36,    36,     1,    58,     1,    25,     1,    55,     1,
+      11,    17,     1,    16,    25,     1,    20,     1,     9,     1,
+      18,    25,    39,     1,    20
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                (-2)
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL         goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yytoken = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");\
+      YYERROR;                                                 \
+    }                                                          \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)               \
+   ((Current).first_line   = (Rhs)[1].first_line,      \
+    (Current).first_column = (Rhs)[1].first_column,    \
+    (Current).last_line    = (Rhs)[N].last_line,       \
+    (Current).last_column  = (Rhs)[N].last_column)
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+
+# define YYDSYMPRINT(Args)                     \
+do {                                           \
+  if (yydebug)                                 \
+    yysymprint Args;                           \
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location)           \
+do {                                                           \
+  if (yydebug)                                                 \
+    {                                                          \
+      YYFPRINTF (stderr, "%s ", Title);                                \
+      yysymprint (stderr,                                      \
+                  Token, Value);       \
+      YYFPRINTF (stderr, "\n");                                        \
+    }                                                          \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short *bottom, short *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    short *bottom;
+    short *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (/* Nothing. */; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                           \
+do {                                                           \
+  if (yydebug)                                                 \
+    yy_stack_print ((Bottom), (Top));                          \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+    int yyrule;
+#endif
+{
+  int yyi;
+  unsigned int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+             yyrule - 1, yylno);
+  /* Print the symbols being reduced, and their result.  */
+  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule)         \
+do {                                   \
+  if (yydebug)                         \
+    yy_reduce_print (Rule);            \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+\f
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  if (yytype < YYNTOKENS)
+    {
+      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+    }
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+  YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  switch (yytype)
+    {
+
+      default:
+        break;
+    }
+}
+\f
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+  void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  short        yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule.  */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack. Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       short *yyss1 = yyss;
+
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  This used to be a
+          conditional around just the two extra args, but that might
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+
+                   &yystacksize);
+
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+       goto yyoverflowlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       short *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 124 "tools/wmc/mcy.y"
+    {
+               if(!check_languages(nodehead))
+                       xyyerror("No messages defined");
+               lanblockhead = block_messages(nodehead);
+       ;}
+    break;
+
+  case 6:
+#line 136 "tools/wmc/mcy.y"
+    { add_node(nd_msg, yyvsp[0].msg); ;}
+    break;
+
+  case 7:
+#line 137 "tools/wmc/mcy.y"
+    { add_node(nd_comment, yyvsp[0].str); ;}
+    break;
+
+  case 8:
+#line 138 "tools/wmc/mcy.y"
+    { xyyerror(err_syntax); /* `Catch all' error */ ;}
+    break;
+
+  case 10:
+#line 142 "tools/wmc/mcy.y"
+    { xyyerror(err_pclose); ;}
+    break;
+
+  case 11:
+#line 143 "tools/wmc/mcy.y"
+    { xyyerror(err_popen); ;}
+    break;
+
+  case 12:
+#line 144 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 14:
+#line 146 "tools/wmc/mcy.y"
+    { xyyerror(err_pclose); ;}
+    break;
+
+  case 15:
+#line 147 "tools/wmc/mcy.y"
+    { xyyerror(err_popen); ;}
+    break;
+
+  case 16:
+#line 148 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 18:
+#line 150 "tools/wmc/mcy.y"
+    { xyyerror(err_pclose); ;}
+    break;
+
+  case 19:
+#line 151 "tools/wmc/mcy.y"
+    { xyyerror(err_popen); ;}
+    break;
+
+  case 20:
+#line 152 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 22:
+#line 154 "tools/wmc/mcy.y"
+    { xyyerror(err_pclose); ;}
+    break;
+
+  case 23:
+#line 155 "tools/wmc/mcy.y"
+    { xyyerror(err_popen); ;}
+    break;
+
+  case 24:
+#line 156 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 25:
+#line 157 "tools/wmc/mcy.y"
+    { cast = yyvsp[0].str; ;}
+    break;
+
+  case 26:
+#line 158 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 27:
+#line 159 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 28:
+#line 160 "tools/wmc/mcy.y"
+    {
+               switch(base)
+               {
+               case 8:
+               case 10:
+               case 16:
+                       base = yyvsp[0].num;
+                       break;
+               default:
+                       xyyerror("Numberbase must be 8, 10 or 16");
+               }
+       ;}
+    break;
+
+  case 29:
+#line 172 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 30:
+#line 173 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 33:
+#line 181 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 34:
+#line 184 "tools/wmc/mcy.y"
+    {
+               yyvsp[-3].tok->token = yyvsp[-1].num;
+               yyvsp[-3].tok->alias = yyvsp[0].str;
+               if(yyvsp[-1].num & (~0x3))
+                       xyyerror("Severity value out of range (0x%08x > 0x3)", yyvsp[-1].num);
+               do_add_token(tok_severity, yyvsp[-3].tok, "severity");
+       ;}
+    break;
+
+  case 35:
+#line 191 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 36:
+#line 192 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 39:
+#line 200 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 40:
+#line 203 "tools/wmc/mcy.y"
+    {
+               yyvsp[-3].tok->token = yyvsp[-1].num;
+               yyvsp[-3].tok->alias = yyvsp[0].str;
+               if(yyvsp[-1].num & (~0xfff))
+                       xyyerror("Facility value out of range (0x%08x > 0xfff)", yyvsp[-1].num);
+               do_add_token(tok_facility, yyvsp[-3].tok, "facility");
+       ;}
+    break;
+
+  case 41:
+#line 210 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 42:
+#line 211 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 43:
+#line 214 "tools/wmc/mcy.y"
+    { yyval.str = NULL; ;}
+    break;
+
+  case 44:
+#line 215 "tools/wmc/mcy.y"
+    { yyval.str = yyvsp[0].str; ;}
+    break;
+
+  case 45:
+#line 216 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 48:
+#line 224 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 49:
+#line 227 "tools/wmc/mcy.y"
+    {
+               yyvsp[-6].tok->token = yyvsp[-4].num;
+               yyvsp[-6].tok->alias = yyvsp[-1].str;
+               yyvsp[-6].tok->codepage = yyvsp[0].num;
+               do_add_token(tok_language, yyvsp[-6].tok, "language");
+               if(!find_language(yyvsp[-4].num) && !find_cpxlat(yyvsp[-4].num))
+                       yywarning("Language 0x%x not built-in, using codepage %d; use explicit codepage to override", yyvsp[-4].num, WMC_DEFAULT_CODEPAGE);
+       ;}
+    break;
+
+  case 50:
+#line 235 "tools/wmc/mcy.y"
+    { xyyerror("Filename expected"); ;}
+    break;
+
+  case 51:
+#line 236 "tools/wmc/mcy.y"
+    { xyyerror(err_colon); ;}
+    break;
+
+  case 52:
+#line 237 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 53:
+#line 238 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 54:
+#line 241 "tools/wmc/mcy.y"
+    { yyval.num = 0; ;}
+    break;
+
+  case 55:
+#line 242 "tools/wmc/mcy.y"
+    { yyval.num = yyvsp[0].num; ;}
+    break;
+
+  case 56:
+#line 243 "tools/wmc/mcy.y"
+    { xyyerror("Codepage-number expected"); ;}
+    break;
+
+  case 59:
+#line 251 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 60:
+#line 254 "tools/wmc/mcy.y"
+    {
+               static const char err_nocp[] = "Codepage %d not builtin; cannot convert";
+               if(find_cpxlat(yyvsp[-4].num))
+                       xyyerror("Codepage translation already defined for language 0x%x", yyvsp[-4].num);
+               if(yyvsp[-2].num && !find_codepage(yyvsp[-2].num))
+                       xyyerror(err_nocp, yyvsp[-2].num);
+               if(yyvsp[0].num && !find_codepage(yyvsp[0].num))
+                       xyyerror(err_nocp, yyvsp[0].num);
+               add_cpxlat(yyvsp[-4].num, yyvsp[-2].num, yyvsp[0].num);
+       ;}
+    break;
+
+  case 61:
+#line 264 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 62:
+#line 265 "tools/wmc/mcy.y"
+    { xyyerror(err_colon); ;}
+    break;
+
+  case 63:
+#line 266 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 64:
+#line 267 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 65:
+#line 270 "tools/wmc/mcy.y"
+    { yyval.num = yyvsp[0].num; ;}
+    break;
+
+  case 66:
+#line 271 "tools/wmc/mcy.y"
+    {
+               if(yyvsp[0].tok->type != tok_language)
+                       xyyerror("Language name or code expected");
+               yyval.num = yyvsp[0].tok->token;
+       ;}
+    break;
+
+  case 67:
+#line 281 "tools/wmc/mcy.y"
+    { test_id(yyvsp[-1].num); ;}
+    break;
+
+  case 68:
+#line 281 "tools/wmc/mcy.y"
+    { yyval.msg = complete_msg(yyvsp[0].msg, yyvsp[-3].num); ;}
+    break;
+
+  case 69:
+#line 284 "tools/wmc/mcy.y"
+    {
+               if(yyvsp[0].num & (~0xffff))
+                       xyyerror("Message ID value out of range (0x%08x > 0xffff)", yyvsp[0].num);
+               yyval.num = yyvsp[0].num;
+       ;}
+    break;
+
+  case 70:
+#line 289 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 71:
+#line 292 "tools/wmc/mcy.y"
+    { yyval.num = ++last_id; ;}
+    break;
+
+  case 72:
+#line 293 "tools/wmc/mcy.y"
+    { yyval.num = last_id = yyvsp[0].num; ;}
+    break;
+
+  case 73:
+#line 294 "tools/wmc/mcy.y"
+    { yyval.num = last_id += yyvsp[0].num; ;}
+    break;
+
+  case 74:
+#line 295 "tools/wmc/mcy.y"
+    { xyyerror(err_number); ;}
+    break;
+
+  case 75:
+#line 298 "tools/wmc/mcy.y"
+    { have_sev = have_fac = have_sym = 0; ;}
+    break;
+
+  case 76:
+#line 299 "tools/wmc/mcy.y"
+    { if(have_sev) xyyerror("Severity already defined"); have_sev = 1; ;}
+    break;
+
+  case 77:
+#line 300 "tools/wmc/mcy.y"
+    { if(have_fac) xyyerror("Facility already defined"); have_fac = 1; ;}
+    break;
+
+  case 78:
+#line 301 "tools/wmc/mcy.y"
+    { if(have_sym) xyyerror("Symbolname already defined"); have_sym = 1; ;}
+    break;
+
+  case 79:
+#line 304 "tools/wmc/mcy.y"
+    { last_sym = yyvsp[0].str; ;}
+    break;
+
+  case 80:
+#line 305 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 81:
+#line 306 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 82:
+#line 309 "tools/wmc/mcy.y"
+    {
+               token_t *tok = lookup_token(yyvsp[0].tok->name);
+               if(!tok)
+                       xyyerror("Undefined severityname");
+               if(tok->type != tok_severity)
+                       xyyerror("Identifier is not of class 'severity'");
+               last_sev = tok->token;
+       ;}
+    break;
+
+  case 83:
+#line 317 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 84:
+#line 318 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 85:
+#line 321 "tools/wmc/mcy.y"
+    {
+               token_t *tok = lookup_token(yyvsp[0].tok->name);
+               if(!tok)
+                       xyyerror("Undefined facilityname");
+               if(tok->type != tok_facility)
+                       xyyerror("Identifier is not of class 'facility'");
+               last_fac = tok->token;
+       ;}
+    break;
+
+  case 86:
+#line 329 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 87:
+#line 330 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 88:
+#line 336 "tools/wmc/mcy.y"
+    { yyval.msg = add_lanmsg(NULL, yyvsp[0].lmp); ;}
+    break;
+
+  case 89:
+#line 337 "tools/wmc/mcy.y"
+    { yyval.msg = add_lanmsg(yyvsp[-1].msg, yyvsp[0].lmp); ;}
+    break;
+
+  case 90:
+#line 338 "tools/wmc/mcy.y"
+    { xyyerror("'Language=...' (start of message text-definition) expected"); ;}
+    break;
+
+  case 91:
+#line 341 "tools/wmc/mcy.y"
+    { yyval.lmp = new_lanmsg(&yyvsp[-3].lcp, yyvsp[-1].str); ;}
+    break;
+
+  case 92:
+#line 349 "tools/wmc/mcy.y"
+    {
+               token_t *tok = lookup_token(yyvsp[-1].tok->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(yyval.lcp.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(yyval.lcp.codepage = WMC_DEFAULT_CODEPAGE);
+                       }
+                       else
+                       {
+                               /* The default seems to be to use the DOS codepage... */
+                               set_codepage(yyval.lcp.codepage = lan->doscp);
+                       }
+               }
+               else
+                       set_codepage(yyval.lcp.codepage = tok->codepage);
+               yyval.lcp.language = tok->token;
+       ;}
+    break;
+
+  case 93:
+#line 378 "tools/wmc/mcy.y"
+    { xyyerror("Missing newline"); ;}
+    break;
+
+  case 94:
+#line 379 "tools/wmc/mcy.y"
+    { xyyerror(err_ident); ;}
+    break;
+
+  case 95:
+#line 380 "tools/wmc/mcy.y"
+    { xyyerror(err_assign); ;}
+    break;
+
+  case 96:
+#line 383 "tools/wmc/mcy.y"
+    { yyval.str = yyvsp[0].str; ;}
+    break;
+
+  case 97:
+#line 384 "tools/wmc/mcy.y"
+    { yyval.str = merge(yyvsp[-1].str, yyvsp[0].str); ;}
+    break;
+
+  case 98:
+#line 385 "tools/wmc/mcy.y"
+    { xyyerror(err_msg); ;}
+    break;
+
+  case 99:
+#line 386 "tools/wmc/mcy.y"
+    { xyyerror(err_msg); ;}
+    break;
+
+  case 100:
+#line 392 "tools/wmc/mcy.y"
+    { yyval.tok = xmalloc(sizeof(token_t)); yyval.tok->name = yyvsp[0].str; ;}
+    break;
+
+  case 101:
+#line 393 "tools/wmc/mcy.y"
+    { yyval.tok = yyvsp[0].tok; ;}
+    break;
+
+  case 102:
+#line 396 "tools/wmc/mcy.y"
+    { want_nl = 1; ;}
+    break;
+
+  case 103:
+#line 399 "tools/wmc/mcy.y"
+    { want_line = 1; ;}
+    break;
+
+  case 104:
+#line 402 "tools/wmc/mcy.y"
+    { want_file = 1; ;}
+    break;
+
+
+    }
+
+/* Line 1000 of yacc.c.  */
+#line 1768 "tools/wmc/mcy.tab.c"
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+
+
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (YYPACT_NINF < yyn && yyn < YYLAST)
+       {
+         YYSIZE_T yysize = 0;
+         int yytype = YYTRANSLATE (yychar);
+         const char* yyprefix;
+         char *yymsg;
+         int yyx;
+
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         int yyxbegin = yyn < 0 ? -yyn : 0;
+
+         /* Stay within bounds of both yycheck and yytname.  */
+         int yychecklim = YYLAST - yyn;
+         int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+         int yycount = 0;
+
+         yyprefix = ", expecting ";
+         for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+           if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+             {
+               yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+               yycount += 1;
+               if (yycount == 5)
+                 {
+                   yysize = 0;
+                   break;
+                 }
+             }
+         yysize += (sizeof ("syntax error, unexpected ")
+                    + yystrlen (yytname[yytype]));
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
+           {
+             char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[yytype]);
+
+             if (yycount < 5)
+               {
+                 yyprefix = ", expecting ";
+                 for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+                   if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+                     {
+                       yyp = yystpcpy (yyp, yyprefix);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yyprefix = " or ";
+                     }
+               }
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
+           }
+         else
+           yyerror ("syntax error; also virtual memory exhausted");
+       }
+      else
+#endif /* YYERROR_VERBOSE */
+       yyerror ("syntax error");
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* If at end of input, pop the error token,
+            then the rest of the stack, then return failure.  */
+         if (yychar == YYEOF)
+            for (;;)
+              {
+                YYPOPSTACK;
+                if (yyssp == yyss)
+                  YYABORT;
+                YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+                yydestruct (yystos[*yyssp], yyvsp);
+              }
+        }
+      else
+       {
+         YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+         yydestruct (yytoken, &yylval);
+         yychar = YYEMPTY;
+
+       }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+  /* Pacify GCC when the user code never invokes YYERROR and the label
+     yyerrorlab therefore never appears in user code.  */
+  if (0)
+     goto yyerrorlab;
+#endif
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+      yydestruct (yystos[yystate], yyvsp);
+      YYPOPSTACK;
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here.  |
+`----------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+
+
+#line 405 "tools/wmc/mcy.y"
+
+
+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);
+}
+
diff --git a/reactos/tools/wmc/mcy.tab.h b/reactos/tools/wmc/mcy.tab.h
new file mode 100644 (file)
index 0000000..2900568
--- /dev/null
@@ -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;
+
+
+
diff --git a/reactos/tools/wmc/mcy.y b/reactos/tools/wmc/mcy.y
new file mode 100644 (file)
index 0000000..3b99e34
--- /dev/null
@@ -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);
+}
diff --git a/reactos/tools/wmc/utils.c b/reactos/tools/wmc/utils.c
new file mode 100644 (file)
index 0000000..14739bb
--- /dev/null
@@ -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;
+}
diff --git a/reactos/tools/wmc/utils.h b/reactos/tools/wmc/utils.h
new file mode 100644 (file)
index 0000000..b666bd9
--- /dev/null
@@ -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
diff --git a/reactos/tools/wmc/wmc.c b/reactos/tools/wmc/wmc.c
new file mode 100644 (file)
index 0000000..5faab41
--- /dev/null
@@ -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();
+}
diff --git a/reactos/tools/wmc/wmc.h b/reactos/tools/wmc/wmc.h
new file mode 100644 (file)
index 0000000..aa37656
--- /dev/null
@@ -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
diff --git a/reactos/tools/wmc/wmc.mak b/reactos/tools/wmc/wmc.mak
new file mode 100644 (file)
index 0000000..a417dae
--- /dev/null
@@ -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
diff --git a/reactos/tools/wmc/wmctypes.h b/reactos/tools/wmc/wmctypes.h
new file mode 100644 (file)
index 0000000..2f8e02a
--- /dev/null
@@ -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
diff --git a/reactos/tools/wmc/write.c b/reactos/tools/wmc/write.c
new file mode 100644 (file)
index 0000000..0d65938
--- /dev/null
@@ -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);
+}
diff --git a/reactos/tools/wmc/write.h b/reactos/tools/wmc/write.h
new file mode 100644 (file)
index 0000000..8169348
--- /dev/null
@@ -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