From 0586868b526e52f4d0b81601b5aa4e9af6dd0dd8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 28 Nov 2005 22:03:22 +0000 Subject: [PATCH] Re-import wmc from Wine svn path=/trunk/; revision=19728 --- reactos/Makefile | 2 +- reactos/media/doc/README.WINE | 2 +- reactos/tools/wmc/CHANGES | 5 + reactos/tools/wmc/lang.c | 165 +++ reactos/tools/wmc/lang.h | 39 + reactos/tools/wmc/mcl.c | 747 +++++++++++ reactos/tools/wmc/mcy.tab.c | 2266 +++++++++++++++++++++++++++++++++ reactos/tools/wmc/mcy.tab.h | 96 ++ reactos/tools/wmc/mcy.y | 677 ++++++++++ reactos/tools/wmc/utils.c | 254 ++++ reactos/tools/wmc/utils.h | 51 + reactos/tools/wmc/wmc.c | 282 ++++ reactos/tools/wmc/wmc.h | 75 ++ reactos/tools/wmc/wmc.mak | 79 ++ reactos/tools/wmc/wmctypes.h | 122 ++ reactos/tools/wmc/write.c | 515 ++++++++ reactos/tools/wmc/write.h | 27 + 17 files changed, 5402 insertions(+), 2 deletions(-) create mode 100644 reactos/tools/wmc/CHANGES create mode 100644 reactos/tools/wmc/lang.c create mode 100644 reactos/tools/wmc/lang.h create mode 100644 reactos/tools/wmc/mcl.c create mode 100644 reactos/tools/wmc/mcy.tab.c create mode 100644 reactos/tools/wmc/mcy.tab.h create mode 100644 reactos/tools/wmc/mcy.y create mode 100644 reactos/tools/wmc/utils.c create mode 100644 reactos/tools/wmc/utils.h create mode 100644 reactos/tools/wmc/wmc.c create mode 100644 reactos/tools/wmc/wmc.h create mode 100644 reactos/tools/wmc/wmc.mak create mode 100644 reactos/tools/wmc/wmctypes.h create mode 100644 reactos/tools/wmc/write.c create mode 100644 reactos/tools/wmc/write.h diff --git a/reactos/Makefile b/reactos/Makefile index 8b80e5c0eaa..18da2053c64 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -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) diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 79fc8d5bcd6..b352e412a92 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -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 index 00000000000..bec49ca4521 --- /dev/null +++ b/reactos/tools/wmc/CHANGES @@ -0,0 +1,5 @@ +--------------------------------------------------------------------------- +Version 1.0.0 (12-Jun-2000) + +Bertho Stultiens +- Initial release diff --git a/reactos/tools/wmc/lang.c b/reactos/tools/wmc/lang.c new file mode 100644 index 00000000000..d14ad3b1cbc --- /dev/null +++ b/reactos/tools/wmc/lang.c @@ -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 +#include +#include +#include + +#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", ""},*/ + {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 index 00000000000..12350f50eab --- /dev/null +++ b/reactos/tools/wmc/lang.h @@ -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 index 00000000000..61710a2d03c --- /dev/null +++ b/reactos/tools/wmc/mcl.c @@ -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 +#include +#include +#include +#include + +#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 index 00000000000..e2929ec6432 --- /dev/null +++ b/reactos/tools/wmc/mcy.tab.c @@ -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 +#include +#include + +#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 /* 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 /* 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 /* 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 + + + +#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 */ + + + +#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; + } +} + + +/* 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" + + 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 index 00000000000..2900568415a --- /dev/null +++ b/reactos/tools/wmc/mcy.tab.h @@ -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 index 00000000000..3b99e347110 --- /dev/null +++ b/reactos/tools/wmc/mcy.y @@ -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 +#include +#include + +#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 tIDENT tLINE tFILE tCOMMENT +%token tNUMBER +%token tTOKEN + +%type alias lines +%type optcp id msgid clan +%type token +%type body +%type bodies msg +%type 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 index 00000000000..14739bb0b8f --- /dev/null +++ b/reactos/tools/wmc/utils.c @@ -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 +#include +#include +#include +#include +#include + +#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 index 00000000000..b666bd9f31b --- /dev/null +++ b/reactos/tools/wmc/utils.h @@ -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 /* 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 index 00000000000..5faab412a49 --- /dev/null +++ b/reactos/tools/wmc/wmc.c @@ -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 +#include +#include +#include + +#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 index 00000000000..aa376568603 --- /dev/null +++ b/reactos/tools/wmc/wmc.h @@ -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 /* 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 index 00000000000..a417dae659f --- /dev/null +++ b/reactos/tools/wmc/wmc.mak @@ -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 index 00000000000..2f8e02a08ee --- /dev/null +++ b/reactos/tools/wmc/wmctypes.h @@ -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 +#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 index 00000000000..0d65938bbbb --- /dev/null +++ b/reactos/tools/wmc/write.c @@ -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 +#include +#include +#include +#include + +#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 : "", 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 : "", 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 index 00000000000..8169348b0ab --- /dev/null +++ b/reactos/tools/wmc/write.h @@ -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 -- 2.17.1