mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 09:50:07 +00:00
Re-import wmc from Wine
svn path=/trunk/; revision=19728
This commit is contained in:
parent
512b5dad2c
commit
0586868b52
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
5
reactos/tools/wmc/CHANGES
Normal file
5
reactos/tools/wmc/CHANGES
Normal file
|
@ -0,0 +1,5 @@
|
|||
---------------------------------------------------------------------------
|
||||
Version 1.0.0 (12-Jun-2000)
|
||||
|
||||
Bertho Stultiens <bertho@akhphd.au.dk>
|
||||
- Initial release
|
165
reactos/tools/wmc/lang.c
Normal file
165
reactos/tools/wmc/lang.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Wine Message Compiler language and codepage support
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "wmc.h"
|
||||
#include "lang.h"
|
||||
|
||||
|
||||
/*
|
||||
* Languages supported
|
||||
*
|
||||
* MUST be sorting ascending on language ID
|
||||
*/
|
||||
static const language_t languages[] = {
|
||||
|
||||
{0x0000, 437, 1252, "Neutral", "Neutral"},
|
||||
{0x0402, 866, 1251, "Bulgarian", "Bulgaria"},
|
||||
{0x0403, 850, 1252, "Catalan", "Spain"},
|
||||
{0x0405, 852, 1250, "Czech", "Czech Republic"},
|
||||
{0x0406, 850, 1252, "Danish", "Denmark"},
|
||||
{0x0407, 850, 1252, "German", "Germany"},
|
||||
{0x0408, 737, 1253, "Greek", "Greece"},
|
||||
{0x0409, 437, 1252, "English", "United States"},
|
||||
{0x040A, 850, 1252, "Spanish - Traditional Sort", "Spain"},
|
||||
{0x040B, 850, 1252, "Finnish", "Finland"},
|
||||
{0x040C, 850, 1252, "French", "France"},
|
||||
{0x040E, 852, 1250, "Hungarian", "Hungary"},
|
||||
{0x040F, 850, 1252, "Icelandic", "Iceland"},
|
||||
{0x0410, 850, 1252, "Italian", "Italy"},
|
||||
{0x0411, 932, 932, "Japanese", "Japan"},
|
||||
{0x0412, 949, 949, "Korean", "Korea (south)"},
|
||||
{0x0413, 850, 1252, "Dutch", "Netherlands"},
|
||||
{0x0414, 850, 1252, "Norwegian (Bokmål)", "Norway"},
|
||||
{0x0415, 852, 1250, "Polish", "Poland"},
|
||||
{0x0416, 850, 1252, "Portuguese", "Brazil"},
|
||||
{0x0418, 852, 1250, "Romanian", "Romania"},
|
||||
{0x0419, 866, 1251, "Russian", "Russia"},
|
||||
{0x041A, 852, 1250, "Croatian", "Croatia"},
|
||||
{0x041B, 852, 1250, "Slovak", "Slovakia"},
|
||||
{0x041C, 852, 1250, "Albanian", "Albania"},
|
||||
{0x041D, 850, 1252, "Swedish", "Sweden"},
|
||||
{0x041F, 857, 1254, "Turkish", "Turkey"},
|
||||
{0x0421, 850, 1252, "Indonesian", "Indonesia"},
|
||||
{0x0422, 866, 1251, "Ukrainian", "Ukraine"},
|
||||
{0x0423, 866, 1251, "Belarusian", "Belarus"},
|
||||
{0x0424, 852, 1250, "Slovene", "Slovenia"},
|
||||
{0x0425, 775, 1257, "Estonian", "Estonia"},
|
||||
{0x0426, 775, 1257, "Latvian", "Latvia"},
|
||||
{0x0427, 775, 1257, "Lithuanian", "Lithuania"},
|
||||
/* {0x042A, ?, ?, "Vietnamese", "Vietnam"},*/
|
||||
{0x042D, 850, 1252, "Basque", "Spain"},
|
||||
{0x042F, 866, 1251, "Macedonian", "Former Yugoslav Republic of Macedonia"},
|
||||
{0x0436, 850, 1252, "Afrikaans", "South Africa"},
|
||||
/* {0x0438, 852, 1252, "Faroese", "Faroe Islands"}, FIXME: Not sure about codepages */
|
||||
{0x043C, 437, 1252, "Irish", "Ireland"},
|
||||
{0x043E, 850, 1252, "Malay", "Malaysia"},
|
||||
/* {0x048F, ?, ?, "Esperanto", "<none>"},*/
|
||||
{0x0804, 936, 936, "Chinese (People's republic of China)", "People's republic of China"},
|
||||
{0x0807, 850, 1252, "German", "Switzerland"},
|
||||
{0x0809, 850, 1252, "English", "United Kingdom"},
|
||||
{0x080A, 850, 1252, "Spanish", "Mexico"},
|
||||
{0x080C, 850, 1252, "French", "Belgium"},
|
||||
{0x0810, 850, 1252, "Italian", "Switzerland"},
|
||||
{0x0813, 850, 1252, "Dutch", "Belgium"},
|
||||
{0x0814, 850, 1252, "Norwegian (Nynorsk)", "Norway"},
|
||||
{0x0816, 850, 1252, "Portuguese", "Portugal"},
|
||||
/* {0x081A, ?, ?, "Serbian (latin)", "Yugoslavia"},*/
|
||||
{0x081D, 850, 1252, "Swedish (Finland)", "Finland"},
|
||||
{0x0C07, 850, 1252, "German", "Austria"},
|
||||
{0x0C09, 850, 1252, "English", "Australia"},
|
||||
{0x0C0A, 850, 1252, "Spanish - International Sort", "Spain"},
|
||||
{0x0C0C, 850, 1252, "French", "Canada"},
|
||||
{0x0C1A, 855, 1251, "Serbian (Cyrillic)", "Serbia"},
|
||||
{0x1007, 850, 1252, "German", "Luxembourg"},
|
||||
{0x1009, 850, 1252, "English", "Canada"},
|
||||
{0x100A, 850, 1252, "Spanish", "Guatemala"},
|
||||
{0x100C, 850, 1252, "French", "Switzerland"},
|
||||
{0x1407, 850, 1252, "German", "Liechtenstein"},
|
||||
{0x1409, 850, 1252, "English", "New Zealand"},
|
||||
{0x140A, 850, 1252, "Spanish", "Costa Rica"},
|
||||
{0x140C, 850, 1252, "French", "Luxembourg"},
|
||||
{0x1809, 850, 1252, "English", "Ireland"},
|
||||
{0x180A, 850, 1252, "Spanish", "Panama"},
|
||||
{0x1C09, 437, 1252, "English", "South Africa"},
|
||||
{0x1C0A, 850, 1252, "Spanish", "Dominican Republic"},
|
||||
{0x2009, 850, 1252, "English", "Jamaica"},
|
||||
{0x200A, 850, 1252, "Spanish", "Venezuela"},
|
||||
{0x2409, 850, 1252, "English", "Caribbean"},
|
||||
{0x240A, 850, 1252, "Spanish", "Colombia"},
|
||||
{0x2809, 850, 1252, "English", "Belize"},
|
||||
{0x280A, 850, 1252, "Spanish", "Peru"},
|
||||
{0x2C09, 437, 1252, "English", "Trinidad & Tobago"},
|
||||
{0x2C0A, 850, 1252, "Spanish", "Argentina"},
|
||||
{0x300A, 850, 1252, "Spanish", "Ecuador"},
|
||||
{0x340A, 850, 1252, "Spanish", "Chile"},
|
||||
{0x380A, 850, 1252, "Spanish", "Uruguay"},
|
||||
{0x3C0A, 850, 1252, "Spanish", "Paraguay"},
|
||||
{0x400A, 850, 1252, "Spanish", "Bolivia"},
|
||||
{0x440A, 850, 1252, "Spanish", "El Salvador"},
|
||||
{0x480A, 850, 1252, "Spanish", "Honduras"},
|
||||
{0x4C0A, 850, 1252, "Spanish", "Nicaragua"},
|
||||
{0x500A, 850, 1252, "Spanish", "Puerto Rico"}
|
||||
};
|
||||
|
||||
#define NLAN (sizeof(languages)/sizeof(languages[0]))
|
||||
|
||||
void show_languages(void)
|
||||
{
|
||||
unsigned int i;
|
||||
printf(" Code | DOS-cp | WIN-cp | Language | Country\n");
|
||||
printf("-------+--------+--------+--------------+---------\n");
|
||||
for(i = 0; i < NLAN; i++)
|
||||
printf("0x%04x | %5d | %5d | %-12s | %s\n",
|
||||
languages[i].id,
|
||||
languages[i].doscp,
|
||||
languages[i].wincp,
|
||||
languages[i].name,
|
||||
languages[i].country);
|
||||
}
|
||||
|
||||
static int langcmp(const void *p1, const void *p2)
|
||||
{
|
||||
return *(const unsigned *)p1 - ((const language_t *)p2)->id;
|
||||
}
|
||||
|
||||
const language_t *find_language(unsigned id)
|
||||
{
|
||||
return (const language_t *)bsearch(&id, languages, NLAN, sizeof(languages[0]), langcmp);
|
||||
}
|
||||
|
||||
void show_codepages(void)
|
||||
{
|
||||
unsigned i;
|
||||
const union cptable *cpp;
|
||||
printf("Codepages:\n");
|
||||
for(i = 0; (cpp = wine_cp_enum_table(i)); i++)
|
||||
{
|
||||
printf("%-5d %s\n", cpp->info.codepage, cpp->info.name);
|
||||
}
|
||||
}
|
||||
|
||||
const union cptable *find_codepage(int id)
|
||||
{
|
||||
return wine_cp_get_table(id);
|
||||
}
|
39
reactos/tools/wmc/lang.h
Normal file
39
reactos/tools/wmc/lang.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Wine Message Compiler language and codepage support
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WMC_LANG_H
|
||||
#define __WMC_LANG_H
|
||||
|
||||
#include "wine/unicode.h"
|
||||
|
||||
typedef struct language {
|
||||
unsigned id;
|
||||
unsigned doscp;
|
||||
unsigned wincp;
|
||||
const char *name;
|
||||
const char *country;
|
||||
} language_t;
|
||||
|
||||
void show_languages(void);
|
||||
const language_t *find_language(unsigned id);
|
||||
void show_codepages(void);
|
||||
const union cptable *find_codepage(int id);
|
||||
|
||||
#endif
|
747
reactos/tools/wmc/mcl.c
Normal file
747
reactos/tools/wmc/mcl.c
Normal file
|
@ -0,0 +1,747 @@
|
|||
/*
|
||||
* Wine Message Compiler lexical scanner
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "wmc.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "mcy.tab.h"
|
||||
|
||||
/*
|
||||
* Keywords are case insenitive. All normal input is treated as
|
||||
* being in codepage iso-8859-1 for ascii input files (unicode
|
||||
* page 0) and as equivalent unicode if unicode input is selected.
|
||||
* All normal input, which is not part of a message text, is
|
||||
* enforced to be unicode page 0. Otherwise an error will be
|
||||
* generated. The normal file data should only be ASCII because
|
||||
* that is the basic definition of the grammar.
|
||||
*
|
||||
* Byteorder or unicode input is determined automatically by
|
||||
* reading the first 8 bytes and checking them against unicode
|
||||
* page 0 byteorder (hibyte must be 0).
|
||||
* -- FIXME --
|
||||
* Alternatively, the input is checked against a special byte
|
||||
* sequence to identify the file.
|
||||
* -- FIXME --
|
||||
*
|
||||
*
|
||||
* Keywords:
|
||||
* Codepages
|
||||
* Facility
|
||||
* FacilityNames
|
||||
* LanguageNames
|
||||
* MessageId
|
||||
* MessageIdTypedef
|
||||
* Severity
|
||||
* SeverityNames
|
||||
* SymbolicName
|
||||
*
|
||||
* Default added identifiers for classes:
|
||||
* SeverityNames:
|
||||
* Success = 0x0
|
||||
* Informational = 0x1
|
||||
* Warning = 0x2
|
||||
* Error = 0x3
|
||||
* FacilityNames:
|
||||
* System = 0x0FF
|
||||
* Application = 0xFFF
|
||||
*
|
||||
* The 'Codepages' keyword is a wmc extension.
|
||||
*/
|
||||
|
||||
static WCHAR ustr_application[] = { 'A', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', 0 };
|
||||
static WCHAR ustr_codepages[] = { 'C', 'o', 'd', 'e', 'p', 'a', 'g', 'e', 's', 0 };
|
||||
static WCHAR ustr_english[] = { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 };
|
||||
static WCHAR ustr_error[] = { 'E', 'r', 'r', 'o', 'r', 0 };
|
||||
static WCHAR ustr_facility[] = { 'F', 'a', 'c', 'i', 'l', 'i', 't', 'y', 0 };
|
||||
static WCHAR ustr_facilitynames[] = { 'F', 'a', 'c', 'i', 'l', 'i', 't', 'y', 'N', 'a', 'm', 'e', 's', 0 };
|
||||
static WCHAR ustr_informational[] = { 'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'a', 'l', 0 };
|
||||
static WCHAR ustr_language[] = { 'L', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 0};
|
||||
static WCHAR ustr_languagenames[] = { 'L', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 'N', 'a', 'm', 'e', 's', 0};
|
||||
static WCHAR ustr_messageid[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'I', 'd', 0 };
|
||||
static WCHAR ustr_messageidtypedef[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'I', 'd', 'T', 'y', 'p', 'e', 'd', 'e', 'f', 0 };
|
||||
static WCHAR ustr_outputbase[] = { 'O', 'u', 't', 'p', 'u', 't', 'B', 'a', 's', 'e', 0 };
|
||||
static WCHAR ustr_severity[] = { 'S', 'e', 'v', 'e', 'r', 'i', 't', 'y', 0 };
|
||||
static WCHAR ustr_severitynames[] = { 'S', 'e', 'v', 'e', 'r', 'i', 't', 'y', 'N', 'a', 'm', 'e', 's', 0 };
|
||||
static WCHAR ustr_success[] = { 'S', 'u', 'c', 'c', 'e', 's', 's', 0 };
|
||||
static WCHAR ustr_symbolicname[] = { 'S', 'y', 'm', 'b', 'o', 'l', 'i', 'c', 'N', 'a', 'm', 'e', 0 };
|
||||
static WCHAR ustr_system[] = { 'S', 'y', 's', 't', 'e', 'm', 0 };
|
||||
static WCHAR ustr_warning[] = { 'W', 'a', 'r', 'n', 'i', 'n', 'g', 0 };
|
||||
static WCHAR ustr_msg00001[] = { 'm', 's', 'g', '0', '0', '0', '0', '1', 0 };
|
||||
/*
|
||||
* This table is to beat any form of "expression building" to check for
|
||||
* correct filename characters. It is also used for ident checks.
|
||||
* FIXME: use it more consistently.
|
||||
*/
|
||||
|
||||
#define CH_SHORTNAME 0x01
|
||||
#define CH_LONGNAME 0x02
|
||||
#define CH_IDENT 0x04
|
||||
#define CH_NUMBER 0x08
|
||||
/*#define CH_WILDCARD 0x10*/
|
||||
/*#define CH_DOT 0x20*/
|
||||
#define CH_PUNCT 0x40
|
||||
#define CH_INVALID 0x80
|
||||
|
||||
static const char char_table[256] = {
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x00 - 0x07 */
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x08 - 0x0F */
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x10 - 0x17 */
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x18 - 0x1F */
|
||||
0x80, 0x03, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, /* 0x20 - 0x27 " !"#$%&'" */
|
||||
0x43, 0x43, 0x10, 0x80, 0x03, 0x03, 0x22, 0x80, /* 0x28 - 0x2F "()*+,-./" */
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, /* 0x30 - 0x37 "01234567" */
|
||||
0x0b, 0x0b, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x10, /* 0x38 - 0x3F "89:;<=>?" */
|
||||
0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x40 - 0x47 "@ABCDEFG" */
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x48 - 0x4F "HIJKLMNO" */
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x50 - 0x57 "PQRSTUVW" */
|
||||
0x07, 0x07, 0x07, 0x80, 0x80, 0x80, 0x80, 0x07, /* 0x58 - 0x5F "XYZ[\]^_" */
|
||||
0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x60 - 0x67 "`abcdefg" */
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x68 - 0x6F "hijklmno" */
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x70 - 0x77 "pqrstuvw" */
|
||||
0x07, 0x07, 0x07, 0x03, 0x80, 0x03, 0x03, 0x80, /* 0x78 - 0x7F "xyz{|}~ " */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x80 - 0x87 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x88 - 0x8F */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x90 - 0x97 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x98 - 0x9F */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xA0 - 0xA7 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xA8 - 0xAF */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xB0 - 0xB7 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xB8 - 0xBF */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xC0 - 0xC7 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xC8 - 0xCF */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xD0 - 0xD7 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xD8 - 0xDF */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xE0 - 0xE7 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xE8 - 0xEF */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xF0 - 0xF7 */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x80, /* 0xF8 - 0xFF */
|
||||
};
|
||||
|
||||
static int isisochar(int ch)
|
||||
{
|
||||
return !(ch & (~0xff));
|
||||
}
|
||||
|
||||
static int codepage;
|
||||
static const union cptable *codepage_def;
|
||||
|
||||
void set_codepage(int cp)
|
||||
{
|
||||
codepage = cp;
|
||||
codepage_def = find_codepage(codepage);
|
||||
if(!codepage_def)
|
||||
xyyerror("Codepage %d not found; cannot process", codepage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Input functions
|
||||
*/
|
||||
static int nungetstack = 0;
|
||||
static int allocungetstack = 0;
|
||||
static char *ungetstack = NULL;
|
||||
static int ninputbuffer = 0;
|
||||
static WCHAR *inputbuffer = NULL;
|
||||
static char *xlatebuffer = NULL;
|
||||
|
||||
#define INPUTBUFFER_SIZE 2048 /* Must be larger than 4 and approx. large enough to hold a line */
|
||||
|
||||
/*
|
||||
* Fill the input buffer with *one* line of input.
|
||||
* The line is '\n' terminated so that scanning
|
||||
* messages with translation works as expected
|
||||
* (otherwise we cannot pre-translate because the
|
||||
* language is first known one line before the
|
||||
* actual message).
|
||||
*/
|
||||
static int fill_inputbuffer(void)
|
||||
{
|
||||
int n;
|
||||
static const char err_fatalread[] = "Fatal: reading input failed";
|
||||
static int endian = -1;
|
||||
|
||||
if(!inputbuffer)
|
||||
{
|
||||
inputbuffer = xmalloc(INPUTBUFFER_SIZE);
|
||||
xlatebuffer = xmalloc(INPUTBUFFER_SIZE);
|
||||
}
|
||||
|
||||
try_again:
|
||||
if(!unicodein)
|
||||
{
|
||||
char *cptr;
|
||||
cptr = fgets(xlatebuffer, INPUTBUFFER_SIZE, yyin);
|
||||
if(!cptr && ferror(yyin))
|
||||
xyyerror(err_fatalread);
|
||||
else if(!cptr)
|
||||
return 0;
|
||||
assert(codepage_def != NULL);
|
||||
n = wine_cp_mbstowcs(codepage_def, 0, xlatebuffer, strlen(xlatebuffer)+1, inputbuffer, INPUTBUFFER_SIZE);
|
||||
if(n < 0)
|
||||
internal_error(__FILE__, __LINE__, "Could not translate to unicode (%d)", n);
|
||||
if(n <= 1)
|
||||
goto try_again; /* Should not hapen */
|
||||
n--; /* Strip added conversion '\0' from input length */
|
||||
/*
|
||||
* FIXME:
|
||||
* Detect UTF-8 in the first time we read some bytes by
|
||||
* checking the special sequence "FE..." or something like
|
||||
* that. I need to check www.unicode.org for details.
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if(endian == -1)
|
||||
{
|
||||
n = fread(inputbuffer, 1, 8, yyin);
|
||||
if(n != 8)
|
||||
{
|
||||
if(!n && ferror(yyin))
|
||||
xyyerror(err_fatalread);
|
||||
else
|
||||
xyyerror("Fatal: file to short to determine byteorder (should never happen)");
|
||||
}
|
||||
if(isisochar(inputbuffer[0]) &&
|
||||
isisochar(inputbuffer[1]) &&
|
||||
isisochar(inputbuffer[2]) &&
|
||||
isisochar(inputbuffer[3]))
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
endian = WMC_BO_BIG;
|
||||
#else
|
||||
endian = WMC_BO_LITTLE;
|
||||
#endif
|
||||
}
|
||||
else if(isisochar(BYTESWAP_WORD(inputbuffer[0])) &&
|
||||
isisochar(BYTESWAP_WORD(inputbuffer[1])) &&
|
||||
isisochar(BYTESWAP_WORD(inputbuffer[2])) &&
|
||||
isisochar(BYTESWAP_WORD(inputbuffer[3])))
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
endian = WMC_BO_LITTLE;
|
||||
#else
|
||||
endian = WMC_BO_BIG;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
xyyerror("Fatal: cannot determine file's byteorder");
|
||||
/* FIXME:
|
||||
* Determine the file-endian with the leader-bytes
|
||||
* "FF FE..."; can't remember the exact sequence.
|
||||
*/
|
||||
n /= 2;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if(endian == WMC_BO_LITTLE)
|
||||
#else
|
||||
if(endian == WMC_BO_BIG)
|
||||
#endif
|
||||
{
|
||||
inputbuffer[0] = BYTESWAP_WORD(inputbuffer[0]);
|
||||
inputbuffer[1] = BYTESWAP_WORD(inputbuffer[1]);
|
||||
inputbuffer[2] = BYTESWAP_WORD(inputbuffer[2]);
|
||||
inputbuffer[3] = BYTESWAP_WORD(inputbuffer[3]);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
n = 0;
|
||||
for(i = 0; i < INPUTBUFFER_SIZE; i++)
|
||||
{
|
||||
int t;
|
||||
t = fread(&inputbuffer[i], 2, 1, yyin);
|
||||
if(!t && ferror(yyin))
|
||||
xyyerror(err_fatalread);
|
||||
else if(!t && n)
|
||||
break;
|
||||
n++;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if(endian == WMC_BO_LITTLE)
|
||||
#else
|
||||
if(endian == WMC_BO_BIG)
|
||||
#endif
|
||||
{
|
||||
if((inputbuffer[i] = BYTESWAP_WORD(inputbuffer[i])) == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(inputbuffer[i] == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!n)
|
||||
{
|
||||
yywarning("Re-read line (input was or converted to zilch)");
|
||||
goto try_again; /* Should not happen, but could be due to stdin reading and a signal */
|
||||
}
|
||||
|
||||
ninputbuffer += n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_unichar(void)
|
||||
{
|
||||
static WCHAR *b = NULL;
|
||||
char_number++;
|
||||
|
||||
if(nungetstack)
|
||||
return ungetstack[--nungetstack];
|
||||
|
||||
if(!ninputbuffer)
|
||||
{
|
||||
if(!fill_inputbuffer())
|
||||
return EOF;
|
||||
b = inputbuffer;
|
||||
}
|
||||
|
||||
ninputbuffer--;
|
||||
return (int)(*b++ & 0xffff);
|
||||
}
|
||||
|
||||
static void unget_unichar(int ch)
|
||||
{
|
||||
if(ch == EOF)
|
||||
return;
|
||||
|
||||
char_number--;
|
||||
|
||||
if(nungetstack == allocungetstack)
|
||||
{
|
||||
allocungetstack += 32;
|
||||
ungetstack = xrealloc(ungetstack, allocungetstack * sizeof(*ungetstack));
|
||||
}
|
||||
|
||||
ungetstack[nungetstack++] = (WCHAR)ch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Normal character stack.
|
||||
* Used for number scanning.
|
||||
*/
|
||||
static int ncharstack = 0;
|
||||
static int alloccharstack = 0;
|
||||
static char *charstack = NULL;
|
||||
|
||||
static void empty_char_stack(void)
|
||||
{
|
||||
ncharstack = 0;
|
||||
}
|
||||
|
||||
static void push_char(int ch)
|
||||
{
|
||||
if(ncharstack == alloccharstack)
|
||||
{
|
||||
alloccharstack += 32;
|
||||
charstack = xrealloc(charstack, alloccharstack * sizeof(*charstack));
|
||||
}
|
||||
charstack[ncharstack++] = (char)ch;
|
||||
}
|
||||
|
||||
static int tos_char_stack(void)
|
||||
{
|
||||
if(!ncharstack)
|
||||
return 0;
|
||||
else
|
||||
return (int)(charstack[ncharstack-1] & 0xff);
|
||||
}
|
||||
|
||||
static char *get_char_stack(void)
|
||||
{
|
||||
return charstack;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unicode character stack.
|
||||
* Used for general scanner.
|
||||
*/
|
||||
static int nunicharstack = 0;
|
||||
static int allocunicharstack = 0;
|
||||
static WCHAR *unicharstack = NULL;
|
||||
|
||||
static void empty_unichar_stack(void)
|
||||
{
|
||||
nunicharstack = 0;
|
||||
}
|
||||
|
||||
static void push_unichar(int ch)
|
||||
{
|
||||
if(nunicharstack == allocunicharstack)
|
||||
{
|
||||
allocunicharstack += 128;
|
||||
unicharstack = xrealloc(unicharstack, allocunicharstack * sizeof(*unicharstack));
|
||||
}
|
||||
unicharstack[nunicharstack++] = (WCHAR)ch;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int tos_unichar_stack(void)
|
||||
{
|
||||
if(!nunicharstack)
|
||||
return 0;
|
||||
else
|
||||
return (int)(unicharstack[nunicharstack-1] & 0xffff);
|
||||
}
|
||||
#endif
|
||||
|
||||
static WCHAR *get_unichar_stack(void)
|
||||
{
|
||||
return unicharstack;
|
||||
}
|
||||
|
||||
/*
|
||||
* Number scanner
|
||||
*
|
||||
* state | ch | next state
|
||||
* ------+-----------------+--------------------------
|
||||
* 0 | [0] | 1
|
||||
* 0 | [1-9] | 4
|
||||
* 0 | . | error (should never occur)
|
||||
* 1 | [xX] | 2
|
||||
* 1 | [0-7] | 3
|
||||
* 1 | [89a-wyzA-WYZ_] | error invalid digit
|
||||
* 1 | . | return 0
|
||||
* 2 | [0-9a-fA-F] | 2
|
||||
* 2 | [g-zG-Z_] | error invalid hex digit
|
||||
* 2 | . | return (hex-number) if TOS != [xX] else error
|
||||
* 3 | [0-7] | 3
|
||||
* 3 | [89a-zA-Z_] | error invalid octal digit
|
||||
* 3 | . | return (octal-number)
|
||||
* 4 | [0-9] | 4
|
||||
* 4 | [a-zA-Z_] | error invalid decimal digit
|
||||
* 4 | . | return (decimal-number)
|
||||
*
|
||||
* All non-identifier characters [^a-zA-Z_0-9] terminate the scan
|
||||
* and return the value. This is not entirely correct, but close
|
||||
* enough (should check punctuators as trailing context, but the
|
||||
* char_table is not adapted to that and it is questionable whether
|
||||
* it is worth the trouble).
|
||||
* All non-iso-8859-1 characters are an error.
|
||||
*/
|
||||
static int scan_number(int ch)
|
||||
{
|
||||
int state = 0;
|
||||
int base = 10;
|
||||
empty_char_stack();
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(!isisochar(ch))
|
||||
xyyerror("Invalid digit");
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case 0:
|
||||
if(isdigit(ch))
|
||||
{
|
||||
push_char(ch);
|
||||
if(ch == '0')
|
||||
state = 1;
|
||||
else
|
||||
state = 4;
|
||||
}
|
||||
else
|
||||
internal_error(__FILE__, __LINE__, "Non-digit in first number-scanner state");
|
||||
break;
|
||||
case 1:
|
||||
if(ch == 'x' || ch == 'X')
|
||||
{
|
||||
push_char(ch);
|
||||
state = 2;
|
||||
}
|
||||
else if(ch >= '0' && ch <= '7')
|
||||
{
|
||||
push_char(ch);
|
||||
state = 3;
|
||||
}
|
||||
else if(isalpha(ch) || ch == '_')
|
||||
xyyerror("Invalid number digit");
|
||||
else
|
||||
{
|
||||
unget_unichar(ch);
|
||||
yylval.num = 0;
|
||||
return tNUMBER;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(isxdigit(ch))
|
||||
push_char(ch);
|
||||
else if(isalpha(ch) || ch == '_' || !isxdigit(tos_char_stack()))
|
||||
xyyerror("Invalid hex digit");
|
||||
else
|
||||
{
|
||||
base = 16;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(ch >= '0' && ch <= '7')
|
||||
push_char(ch);
|
||||
else if(isalnum(ch) || ch == '_')
|
||||
xyyerror("Invalid octal digit");
|
||||
else
|
||||
{
|
||||
base = 8;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(isdigit(ch))
|
||||
push_char(ch);
|
||||
else if(isalnum(ch) || ch == '_')
|
||||
xyyerror("Invalid decimal digit");
|
||||
else
|
||||
{
|
||||
base = 10;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
internal_error(__FILE__, __LINE__, "Invalid state in number-scanner");
|
||||
}
|
||||
ch = get_unichar();
|
||||
}
|
||||
finish:
|
||||
unget_unichar(ch);
|
||||
push_char(0);
|
||||
yylval.num = strtoul(get_char_stack(), NULL, base);
|
||||
return tNUMBER;
|
||||
}
|
||||
|
||||
static void newline(void)
|
||||
{
|
||||
line_number++;
|
||||
char_number = 1;
|
||||
}
|
||||
|
||||
static int unisort(const void *p1, const void *p2)
|
||||
{
|
||||
return unistricmp(((const token_t *)p1)->name, ((const token_t *)p2)->name);
|
||||
}
|
||||
|
||||
static token_t *tokentable = NULL;
|
||||
static int ntokentable = 0;
|
||||
|
||||
token_t *lookup_token(const WCHAR *s)
|
||||
{
|
||||
token_t tok;
|
||||
|
||||
tok.name = s;
|
||||
return (token_t *)bsearch(&tok, tokentable, ntokentable, sizeof(*tokentable), unisort);
|
||||
}
|
||||
|
||||
void add_token(tok_e type, const WCHAR *name, int tok, int cp, const WCHAR *alias, int fix)
|
||||
{
|
||||
ntokentable++;
|
||||
tokentable = xrealloc(tokentable, ntokentable * sizeof(*tokentable));
|
||||
tokentable[ntokentable-1].type = type;
|
||||
tokentable[ntokentable-1].name = name;
|
||||
tokentable[ntokentable-1].token = tok;
|
||||
tokentable[ntokentable-1].codepage = cp;
|
||||
tokentable[ntokentable-1].alias = alias;
|
||||
tokentable[ntokentable-1].fixed = fix;
|
||||
qsort(tokentable, ntokentable, sizeof(*tokentable), unisort);
|
||||
}
|
||||
|
||||
void get_tokentable(token_t **tab, int *len)
|
||||
{
|
||||
assert(tab != NULL);
|
||||
assert(len != NULL);
|
||||
*tab = tokentable;
|
||||
*len = ntokentable;
|
||||
}
|
||||
|
||||
/*
|
||||
* The scanner
|
||||
*
|
||||
*/
|
||||
int yylex(void)
|
||||
{
|
||||
static const WCHAR ustr_dot1[] = { '.', '\n', 0 };
|
||||
static const WCHAR ustr_dot2[] = { '.', '\r', '\n', 0 };
|
||||
static int isinit = 0;
|
||||
int ch;
|
||||
|
||||
if(!isinit)
|
||||
{
|
||||
isinit++;
|
||||
set_codepage(WMC_DEFAULT_CODEPAGE);
|
||||
add_token(tok_keyword, ustr_codepages, tCODEPAGE, 0, NULL, 0);
|
||||
add_token(tok_keyword, ustr_facility, tFACILITY, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_facilitynames, tFACNAMES, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_language, tLANGUAGE, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_languagenames, tLANNAMES, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_messageid, tMSGID, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_messageidtypedef, tTYPEDEF, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_outputbase, tBASE, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_severity, tSEVERITY, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_severitynames, tSEVNAMES, 0, NULL, 1);
|
||||
add_token(tok_keyword, ustr_symbolicname, tSYMNAME, 0, NULL, 1);
|
||||
add_token(tok_severity, ustr_error, 0x03, 0, NULL, 0);
|
||||
add_token(tok_severity, ustr_warning, 0x02, 0, NULL, 0);
|
||||
add_token(tok_severity, ustr_informational, 0x01, 0, NULL, 0);
|
||||
add_token(tok_severity, ustr_success, 0x00, 0, NULL, 0);
|
||||
add_token(tok_facility, ustr_application, 0xFFF, 0, NULL, 0);
|
||||
add_token(tok_facility, ustr_system, 0x0FF, 0, NULL, 0);
|
||||
add_token(tok_language, ustr_english, 0x409, 437, ustr_msg00001, 0);
|
||||
}
|
||||
|
||||
empty_unichar_stack();
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(want_line)
|
||||
{
|
||||
while((ch = get_unichar()) != '\n')
|
||||
{
|
||||
if(ch == EOF)
|
||||
xyyerror("Unexpected EOF");
|
||||
push_unichar(ch);
|
||||
}
|
||||
newline();
|
||||
push_unichar(ch);
|
||||
push_unichar(0);
|
||||
if(!unistrcmp(ustr_dot1, get_unichar_stack()) || !unistrcmp(ustr_dot2, get_unichar_stack()))
|
||||
{
|
||||
want_line = 0;
|
||||
/* Reset the codepage to our default after each message */
|
||||
set_codepage(WMC_DEFAULT_CODEPAGE);
|
||||
return tMSGEND;
|
||||
}
|
||||
yylval.str = xunistrdup(get_unichar_stack());
|
||||
return tLINE;
|
||||
}
|
||||
|
||||
ch = get_unichar();
|
||||
|
||||
if(ch == EOF)
|
||||
return EOF;
|
||||
|
||||
if(ch == '\n')
|
||||
{
|
||||
newline();
|
||||
if(want_nl)
|
||||
{
|
||||
want_nl = 0;
|
||||
return tNL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isisochar(ch))
|
||||
{
|
||||
if(want_file)
|
||||
{
|
||||
int n = 0;
|
||||
while(n < 8 && isisochar(ch))
|
||||
{
|
||||
int t = char_table[ch];
|
||||
if((t & CH_PUNCT) || !(t & CH_SHORTNAME))
|
||||
break;
|
||||
|
||||
push_unichar(ch);
|
||||
n++;
|
||||
ch = get_unichar();
|
||||
}
|
||||
unget_unichar(ch);
|
||||
push_unichar(0);
|
||||
want_file = 0;
|
||||
yylval.str = xunistrdup(get_unichar_stack());
|
||||
return tFILE;
|
||||
}
|
||||
|
||||
if(char_table[ch] & CH_IDENT)
|
||||
{
|
||||
token_t *tok;
|
||||
while(isisochar(ch) && (char_table[ch] & (CH_IDENT|CH_NUMBER)))
|
||||
{
|
||||
push_unichar(ch);
|
||||
ch = get_unichar();
|
||||
}
|
||||
unget_unichar(ch);
|
||||
push_unichar(0);
|
||||
if(!(tok = lookup_token(get_unichar_stack())))
|
||||
{
|
||||
yylval.str = xunistrdup(get_unichar_stack());
|
||||
return tIDENT;
|
||||
}
|
||||
switch(tok->type)
|
||||
{
|
||||
case tok_keyword:
|
||||
return tok->token;
|
||||
|
||||
case tok_language:
|
||||
codepage = tok->codepage;
|
||||
/* Fall through */
|
||||
case tok_severity:
|
||||
case tok_facility:
|
||||
yylval.tok = tok;
|
||||
return tTOKEN;
|
||||
|
||||
default:
|
||||
internal_error(__FILE__, __LINE__, "Invalid token type encountered");
|
||||
}
|
||||
}
|
||||
|
||||
if(isspace(ch)) /* Ignore space */
|
||||
continue;
|
||||
|
||||
if(isdigit(ch))
|
||||
return scan_number(ch);
|
||||
}
|
||||
|
||||
switch(ch)
|
||||
{
|
||||
case ':':
|
||||
case '=':
|
||||
case '+':
|
||||
case '(':
|
||||
case ')':
|
||||
return ch;
|
||||
case ';':
|
||||
while(ch != '\n' && ch != EOF)
|
||||
{
|
||||
push_unichar(ch);
|
||||
ch = get_unichar();
|
||||
}
|
||||
newline();
|
||||
push_unichar(ch); /* Include the newline */
|
||||
push_unichar(0);
|
||||
yylval.str = xunistrdup(get_unichar_stack());
|
||||
return tCOMMENT;
|
||||
default:
|
||||
xyyerror("Invalid character '%c' (0x%04x)", isisochar(ch) && isprint(ch) ? ch : '.', ch);
|
||||
}
|
||||
}
|
||||
}
|
2266
reactos/tools/wmc/mcy.tab.c
Normal file
2266
reactos/tools/wmc/mcy.tab.c
Normal file
File diff suppressed because it is too large
Load diff
96
reactos/tools/wmc/mcy.tab.h
Normal file
96
reactos/tools/wmc/mcy.tab.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* A Bison parser, made by GNU Bison 1.875c. */
|
||||
|
||||
/* Skeleton parser for Yacc-like parsing with Bison,
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, when this file is copied by Bison into a
|
||||
Bison output file, you may use that output file without restriction.
|
||||
This special exception was added by the Free Software Foundation
|
||||
in version 1.24 of Bison. */
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
tSEVNAMES = 258,
|
||||
tFACNAMES = 259,
|
||||
tLANNAMES = 260,
|
||||
tBASE = 261,
|
||||
tCODEPAGE = 262,
|
||||
tTYPEDEF = 263,
|
||||
tNL = 264,
|
||||
tSYMNAME = 265,
|
||||
tMSGEND = 266,
|
||||
tSEVERITY = 267,
|
||||
tFACILITY = 268,
|
||||
tLANGUAGE = 269,
|
||||
tMSGID = 270,
|
||||
tIDENT = 271,
|
||||
tLINE = 272,
|
||||
tFILE = 273,
|
||||
tCOMMENT = 274,
|
||||
tNUMBER = 275,
|
||||
tTOKEN = 276
|
||||
};
|
||||
#endif
|
||||
#define tSEVNAMES 258
|
||||
#define tFACNAMES 259
|
||||
#define tLANNAMES 260
|
||||
#define tBASE 261
|
||||
#define tCODEPAGE 262
|
||||
#define tTYPEDEF 263
|
||||
#define tNL 264
|
||||
#define tSYMNAME 265
|
||||
#define tMSGEND 266
|
||||
#define tSEVERITY 267
|
||||
#define tFACILITY 268
|
||||
#define tLANGUAGE 269
|
||||
#define tMSGID 270
|
||||
#define tIDENT 271
|
||||
#define tLINE 272
|
||||
#define tFILE 273
|
||||
#define tCOMMENT 274
|
||||
#define tNUMBER 275
|
||||
#define tTOKEN 276
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
|
||||
#line 99 "tools/wmc/mcy.y"
|
||||
typedef union YYSTYPE {
|
||||
WCHAR *str;
|
||||
unsigned num;
|
||||
token_t *tok;
|
||||
lanmsg_t *lmp;
|
||||
msg_t *msg;
|
||||
lan_cp_t lcp;
|
||||
} YYSTYPE;
|
||||
/* Line 1275 of yacc.c. */
|
||||
#line 88 "tools/wmc/mcy.tab.h"
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
||||
|
677
reactos/tools/wmc/mcy.y
Normal file
677
reactos/tools/wmc/mcy.y
Normal file
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* Wine Message Compiler parser
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
* The basic grammar of the file is yet another example of, humpf,
|
||||
* design. There is is mix of context-insensitive and -sentitive
|
||||
* stuff, which makes it rather complicated.
|
||||
* The header definitions are all context-insensitive because they have
|
||||
* delimited arguments, whereas the message headers are (semi-) context-
|
||||
* sensitive and the messages themselves are, well, RFC82[12] delimited.
|
||||
* This mixture seems to originate from the time that ms and ibm were
|
||||
* good friends and developing os/2 according to the "compatibility"
|
||||
* switch and reading some comments here and there.
|
||||
*
|
||||
* I'll ignore most of the complications and concentrate on the concept
|
||||
* which allows me to use yacc. Basically, everything is context-
|
||||
* insensitive now, with the exception of the message-text itself and
|
||||
* the preceding language declaration.
|
||||
*
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "wmc.h"
|
||||
#include "lang.h"
|
||||
|
||||
static const char err_syntax[] = "Syntax error";
|
||||
static const char err_number[] = "Number expected";
|
||||
static const char err_ident[] = "Identifier expected";
|
||||
static const char err_assign[] = "'=' expected";
|
||||
static const char err_popen[] = "'(' expected";
|
||||
static const char err_pclose[] = "')' expected";
|
||||
static const char err_colon[] = "':' expected";
|
||||
static const char err_msg[] = "Message expected";
|
||||
|
||||
/* Scanner switches */
|
||||
int want_nl = 0; /* Request next newlinw */
|
||||
int want_line = 0; /* Request next complete line */
|
||||
int want_file = 0; /* Request next ident as filename */
|
||||
|
||||
node_t *nodehead = NULL; /* The list of all parsed elements */
|
||||
static node_t *nodetail = NULL;
|
||||
lan_blk_t *lanblockhead; /* List of parsed elements transposed */
|
||||
|
||||
static int base = 16; /* Current printout base to use (8, 10 or 16) */
|
||||
static WCHAR *cast = NULL; /* Current typecast to use */
|
||||
|
||||
static int last_id = 0; /* The last message ID parsed */
|
||||
static int last_sev = 0; /* Last severity code parsed */
|
||||
static int last_fac = 0; /* Last facility code parsed */
|
||||
static WCHAR *last_sym = NULL;/* Last alias symbol parsed */
|
||||
static int have_sev; /* Set if severity parsed for current message */
|
||||
static int have_fac; /* Set if facility parsed for current message */
|
||||
static int have_sym; /* Set is symbol parsed for current message */
|
||||
|
||||
static cp_xlat_t *cpxlattab = NULL; /* Codepage translation table */
|
||||
static int ncpxlattab = 0;
|
||||
|
||||
/* Prototypes */
|
||||
static WCHAR *merge(WCHAR *s1, WCHAR *s2);
|
||||
static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg);
|
||||
static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg);
|
||||
static msg_t *complete_msg(msg_t *msg, int id);
|
||||
static void add_node(node_e type, void *p);
|
||||
static void do_add_token(tok_e type, token_t *tok, const char *code);
|
||||
static void test_id(int id);
|
||||
static int check_languages(node_t *head);
|
||||
static lan_blk_t *block_messages(node_t *head);
|
||||
static void add_cpxlat(int lan, int cpin, int cpout);
|
||||
static cp_xlat_t *find_cpxlat(int lan);
|
||||
|
||||
%}
|
||||
|
||||
|
||||
%union {
|
||||
WCHAR *str;
|
||||
unsigned num;
|
||||
token_t *tok;
|
||||
lanmsg_t *lmp;
|
||||
msg_t *msg;
|
||||
lan_cp_t lcp;
|
||||
}
|
||||
|
||||
|
||||
%token tSEVNAMES tFACNAMES tLANNAMES tBASE tCODEPAGE
|
||||
%token tTYPEDEF tNL tSYMNAME tMSGEND
|
||||
%token tSEVERITY tFACILITY tLANGUAGE tMSGID
|
||||
%token <str> tIDENT tLINE tFILE tCOMMENT
|
||||
%token <num> tNUMBER
|
||||
%token <tok> tTOKEN
|
||||
|
||||
%type <str> alias lines
|
||||
%type <num> optcp id msgid clan
|
||||
%type <tok> token
|
||||
%type <lmp> body
|
||||
%type <msg> bodies msg
|
||||
%type <lcp> lang
|
||||
|
||||
%%
|
||||
file : items {
|
||||
if(!check_languages(nodehead))
|
||||
xyyerror("No messages defined");
|
||||
lanblockhead = block_messages(nodehead);
|
||||
}
|
||||
;
|
||||
|
||||
items : decl
|
||||
| items decl
|
||||
;
|
||||
|
||||
decl : global
|
||||
| msg { add_node(nd_msg, $1); }
|
||||
| tCOMMENT { add_node(nd_comment, $1); }
|
||||
| error { xyyerror(err_syntax); /* `Catch all' error */ }
|
||||
;
|
||||
|
||||
global : tSEVNAMES '=' '(' smaps ')'
|
||||
| tSEVNAMES '=' '(' smaps error { xyyerror(err_pclose); }
|
||||
| tSEVNAMES '=' error { xyyerror(err_popen); }
|
||||
| tSEVNAMES error { xyyerror(err_assign); }
|
||||
| tFACNAMES '=' '(' fmaps ')'
|
||||
| tFACNAMES '=' '(' fmaps error { xyyerror(err_pclose); }
|
||||
| tFACNAMES '=' error { xyyerror(err_popen); }
|
||||
| tFACNAMES error { xyyerror(err_assign); }
|
||||
| tLANNAMES '=' '(' lmaps ')'
|
||||
| tLANNAMES '=' '(' lmaps error { xyyerror(err_pclose); }
|
||||
| tLANNAMES '=' error { xyyerror(err_popen); }
|
||||
| tLANNAMES error { xyyerror(err_assign); }
|
||||
| tCODEPAGE '=' '(' cmaps ')'
|
||||
| tCODEPAGE '=' '(' cmaps error { xyyerror(err_pclose); }
|
||||
| tCODEPAGE '=' error { xyyerror(err_popen); }
|
||||
| tCODEPAGE error { xyyerror(err_assign); }
|
||||
| tTYPEDEF '=' tIDENT { cast = $3; }
|
||||
| tTYPEDEF '=' error { xyyerror(err_number); }
|
||||
| tTYPEDEF error { xyyerror(err_assign); }
|
||||
| tBASE '=' tNUMBER {
|
||||
switch(base)
|
||||
{
|
||||
case 8:
|
||||
case 10:
|
||||
case 16:
|
||||
base = $3;
|
||||
break;
|
||||
default:
|
||||
xyyerror("Numberbase must be 8, 10 or 16");
|
||||
}
|
||||
}
|
||||
| tBASE '=' error { xyyerror(err_number); }
|
||||
| tBASE error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* SeverityNames mapping
|
||||
*/
|
||||
smaps : smap
|
||||
| smaps smap
|
||||
| error { xyyerror(err_ident); }
|
||||
;
|
||||
|
||||
smap : token '=' tNUMBER alias {
|
||||
$1->token = $3;
|
||||
$1->alias = $4;
|
||||
if($3 & (~0x3))
|
||||
xyyerror("Severity value out of range (0x%08x > 0x3)", $3);
|
||||
do_add_token(tok_severity, $1, "severity");
|
||||
}
|
||||
| token '=' error { xyyerror(err_number); }
|
||||
| token error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* FacilityNames mapping
|
||||
*/
|
||||
fmaps : fmap
|
||||
| fmaps fmap
|
||||
| error { xyyerror(err_ident); }
|
||||
;
|
||||
|
||||
fmap : token '=' tNUMBER alias {
|
||||
$1->token = $3;
|
||||
$1->alias = $4;
|
||||
if($3 & (~0xfff))
|
||||
xyyerror("Facility value out of range (0x%08x > 0xfff)", $3);
|
||||
do_add_token(tok_facility, $1, "facility");
|
||||
}
|
||||
| token '=' error { xyyerror(err_number); }
|
||||
| token error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
alias : /* Empty */ { $$ = NULL; }
|
||||
| ':' tIDENT { $$ = $2; }
|
||||
| ':' error { xyyerror(err_ident); }
|
||||
;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* LanguageNames mapping
|
||||
*/
|
||||
lmaps : lmap
|
||||
| lmaps lmap
|
||||
| error { xyyerror(err_ident); }
|
||||
;
|
||||
|
||||
lmap : token '=' tNUMBER setfile ':' tFILE optcp {
|
||||
$1->token = $3;
|
||||
$1->alias = $6;
|
||||
$1->codepage = $7;
|
||||
do_add_token(tok_language, $1, "language");
|
||||
if(!find_language($3) && !find_cpxlat($3))
|
||||
yywarning("Language 0x%x not built-in, using codepage %d; use explicit codepage to override", $3, WMC_DEFAULT_CODEPAGE);
|
||||
}
|
||||
| token '=' tNUMBER setfile ':' error { xyyerror("Filename expected"); }
|
||||
| token '=' tNUMBER error { xyyerror(err_colon); }
|
||||
| token '=' error { xyyerror(err_number); }
|
||||
| token error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
optcp : /* Empty */ { $$ = 0; }
|
||||
| ':' tNUMBER { $$ = $2; }
|
||||
| ':' error { xyyerror("Codepage-number expected"); }
|
||||
;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Codepages mapping
|
||||
*/
|
||||
cmaps : cmap
|
||||
| cmaps cmap
|
||||
| error { xyyerror(err_ident); }
|
||||
;
|
||||
|
||||
cmap : clan '=' tNUMBER ':' tNUMBER {
|
||||
static const char err_nocp[] = "Codepage %d not builtin; cannot convert";
|
||||
if(find_cpxlat($1))
|
||||
xyyerror("Codepage translation already defined for language 0x%x", $1);
|
||||
if($3 && !find_codepage($3))
|
||||
xyyerror(err_nocp, $3);
|
||||
if($5 && !find_codepage($5))
|
||||
xyyerror(err_nocp, $5);
|
||||
add_cpxlat($1, $3, $5);
|
||||
}
|
||||
| clan '=' tNUMBER ':' error { xyyerror(err_number); }
|
||||
| clan '=' tNUMBER error { xyyerror(err_colon); }
|
||||
| clan '=' error { xyyerror(err_number); }
|
||||
| clan error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
clan : tNUMBER { $$ = $1; }
|
||||
| tTOKEN {
|
||||
if($1->type != tok_language)
|
||||
xyyerror("Language name or code expected");
|
||||
$$ = $1->token;
|
||||
}
|
||||
;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Message-definition parsing
|
||||
*/
|
||||
msg : msgid sevfacsym { test_id($1); } bodies { $$ = complete_msg($4, $1); }
|
||||
;
|
||||
|
||||
msgid : tMSGID '=' id {
|
||||
if($3 & (~0xffff))
|
||||
xyyerror("Message ID value out of range (0x%08x > 0xffff)", $3);
|
||||
$$ = $3;
|
||||
}
|
||||
| tMSGID error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
id : /* Empty */ { $$ = ++last_id; }
|
||||
| tNUMBER { $$ = last_id = $1; }
|
||||
| '+' tNUMBER { $$ = last_id += $2; }
|
||||
| '+' error { xyyerror(err_number); }
|
||||
;
|
||||
|
||||
sevfacsym: /* Empty */ { have_sev = have_fac = have_sym = 0; }
|
||||
| sevfacsym sev { if(have_sev) xyyerror("Severity already defined"); have_sev = 1; }
|
||||
| sevfacsym fac { if(have_fac) xyyerror("Facility already defined"); have_fac = 1; }
|
||||
| sevfacsym sym { if(have_sym) xyyerror("Symbolname already defined"); have_sym = 1; }
|
||||
;
|
||||
|
||||
sym : tSYMNAME '=' tIDENT { last_sym = $3; }
|
||||
| tSYMNAME '=' error { xyyerror(err_ident); }
|
||||
| tSYMNAME error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
sev : tSEVERITY '=' token {
|
||||
token_t *tok = lookup_token($3->name);
|
||||
if(!tok)
|
||||
xyyerror("Undefined severityname");
|
||||
if(tok->type != tok_severity)
|
||||
xyyerror("Identifier is not of class 'severity'");
|
||||
last_sev = tok->token;
|
||||
}
|
||||
| tSEVERITY '=' error { xyyerror(err_ident); }
|
||||
| tSEVERITY error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
fac : tFACILITY '=' token {
|
||||
token_t *tok = lookup_token($3->name);
|
||||
if(!tok)
|
||||
xyyerror("Undefined facilityname");
|
||||
if(tok->type != tok_facility)
|
||||
xyyerror("Identifier is not of class 'facility'");
|
||||
last_fac = tok->token;
|
||||
}
|
||||
| tFACILITY '=' error { xyyerror(err_ident); }
|
||||
| tFACILITY error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Message-text parsing
|
||||
*/
|
||||
bodies : body { $$ = add_lanmsg(NULL, $1); }
|
||||
| bodies body { $$ = add_lanmsg($1, $2); }
|
||||
| error { xyyerror("'Language=...' (start of message text-definition) expected"); }
|
||||
;
|
||||
|
||||
body : lang setline lines tMSGEND { $$ = new_lanmsg(&$1, $3); }
|
||||
;
|
||||
|
||||
/*
|
||||
* The newline is to be able to set the codepage
|
||||
* to the language based codepage for the next
|
||||
* message to be parsed.
|
||||
*/
|
||||
lang : tLANGUAGE setnl '=' token tNL {
|
||||
token_t *tok = lookup_token($4->name);
|
||||
cp_xlat_t *cpx;
|
||||
if(!tok)
|
||||
xyyerror("Undefined language");
|
||||
if(tok->type != tok_language)
|
||||
xyyerror("Identifier is not of class 'language'");
|
||||
if((cpx = find_cpxlat(tok->token)))
|
||||
{
|
||||
set_codepage($$.codepage = cpx->cpin);
|
||||
}
|
||||
else if(!tok->codepage)
|
||||
{
|
||||
const language_t *lan = find_language(tok->token);
|
||||
if(!lan)
|
||||
{
|
||||
/* Just set default; warning was given while parsing languagenames */
|
||||
set_codepage($$.codepage = WMC_DEFAULT_CODEPAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The default seems to be to use the DOS codepage... */
|
||||
set_codepage($$.codepage = lan->doscp);
|
||||
}
|
||||
}
|
||||
else
|
||||
set_codepage($$.codepage = tok->codepage);
|
||||
$$.language = tok->token;
|
||||
}
|
||||
| tLANGUAGE setnl '=' token error { xyyerror("Missing newline"); }
|
||||
| tLANGUAGE setnl '=' error { xyyerror(err_ident); }
|
||||
| tLANGUAGE error { xyyerror(err_assign); }
|
||||
;
|
||||
|
||||
lines : tLINE { $$ = $1; }
|
||||
| lines tLINE { $$ = merge($1, $2); }
|
||||
| error { xyyerror(err_msg); }
|
||||
| lines error { xyyerror(err_msg); }
|
||||
;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Helper rules
|
||||
*/
|
||||
token : tIDENT { $$ = xmalloc(sizeof(token_t)); $$->name = $1; }
|
||||
| tTOKEN { $$ = $1; }
|
||||
;
|
||||
|
||||
setnl : /* Empty */ { want_nl = 1; }
|
||||
;
|
||||
|
||||
setline : /* Empty */ { want_line = 1; }
|
||||
;
|
||||
|
||||
setfile : /* Empty */ { want_file = 1; }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
static WCHAR *merge(WCHAR *s1, WCHAR *s2)
|
||||
{
|
||||
int l1 = unistrlen(s1);
|
||||
int l2 = unistrlen(s2);
|
||||
s1 = xrealloc(s1, (l1 + l2 + 1) * sizeof(*s1));
|
||||
unistrcpy(s1+l1, s2);
|
||||
free(s2);
|
||||
return s1;
|
||||
}
|
||||
|
||||
static void do_add_token(tok_e type, token_t *tok, const char *code)
|
||||
{
|
||||
token_t *tp = lookup_token(tok->name);
|
||||
if(tp)
|
||||
{
|
||||
if(tok->type != type)
|
||||
yywarning("Type change in token");
|
||||
if(tp != tok)
|
||||
xyyerror("Overlapping token not the same");
|
||||
/* else its already defined and changed */
|
||||
if(tok->fixed)
|
||||
xyyerror("Redefinition of %s", code);
|
||||
tok->fixed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_token(type, tok->name, tok->token, tok->codepage, tok->alias, 1);
|
||||
free(tok);
|
||||
}
|
||||
}
|
||||
|
||||
static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg)
|
||||
{
|
||||
lanmsg_t *lmp = (lanmsg_t *)xmalloc(sizeof(lanmsg_t));
|
||||
lmp->lan = lcp->language;
|
||||
lmp->cp = lcp->codepage;
|
||||
lmp->msg = msg;
|
||||
lmp->len = unistrlen(msg) + 1; /* Include termination */
|
||||
if(lmp->len > 4096)
|
||||
yywarning("Message exceptionally long; might be a missing termination");
|
||||
return lmp;
|
||||
}
|
||||
|
||||
static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg)
|
||||
{
|
||||
int i;
|
||||
if(!msg)
|
||||
msg = xmalloc(sizeof(msg_t));
|
||||
msg->msgs = xrealloc(msg->msgs, (msg->nmsgs+1) * sizeof(*(msg->msgs)));
|
||||
msg->msgs[msg->nmsgs] = lanmsg;
|
||||
msg->nmsgs++;
|
||||
for(i = 0; i < msg->nmsgs-1; i++)
|
||||
{
|
||||
if(msg->msgs[i]->lan == lanmsg->lan)
|
||||
xyyerror("Message for language 0x%x already defined", lanmsg->lan);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
static int sort_lanmsg(const void *p1, const void *p2)
|
||||
{
|
||||
return (*(lanmsg_t **)p1)->lan - (*(lanmsg_t **)p2)->lan;
|
||||
}
|
||||
|
||||
static msg_t *complete_msg(msg_t *mp, int id)
|
||||
{
|
||||
assert(mp != NULL);
|
||||
mp->id = id;
|
||||
if(have_sym)
|
||||
mp->sym = last_sym;
|
||||
else
|
||||
xyyerror("No symbolic name defined for message id %d", id);
|
||||
mp->sev = last_sev;
|
||||
mp->fac = last_fac;
|
||||
qsort(mp->msgs, mp->nmsgs, sizeof(*(mp->msgs)), sort_lanmsg);
|
||||
mp->realid = id | (last_sev << 30) | (last_fac << 16);
|
||||
if(custombit)
|
||||
mp->realid |= 1 << 29;
|
||||
mp->base = base;
|
||||
mp->cast = cast;
|
||||
return mp;
|
||||
}
|
||||
|
||||
static void add_node(node_e type, void *p)
|
||||
{
|
||||
node_t *ndp = (node_t *)xmalloc(sizeof(node_t));
|
||||
ndp->type = type;
|
||||
ndp->u.all = p;
|
||||
|
||||
if(nodetail)
|
||||
{
|
||||
ndp->prev = nodetail;
|
||||
nodetail->next = ndp;
|
||||
nodetail = ndp;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodehead = nodetail = ndp;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_id(int id)
|
||||
{
|
||||
node_t *ndp;
|
||||
for(ndp = nodehead; ndp; ndp = ndp->next)
|
||||
{
|
||||
if(ndp->type != nd_msg)
|
||||
continue;
|
||||
if(ndp->u.msg->id == id && ndp->u.msg->sev == last_sev && ndp->u.msg->fac == last_fac)
|
||||
xyyerror("MessageId %d with facility 0x%x and severity 0x%x already defined", id, last_fac, last_sev);
|
||||
}
|
||||
}
|
||||
|
||||
static int check_languages(node_t *head)
|
||||
{
|
||||
static const char err_missing[] = "Missing definition for language 0x%x; MessageID %d, facility 0x%x, severity 0x%x";
|
||||
node_t *ndp;
|
||||
int nm = 0;
|
||||
msg_t *msg = NULL;
|
||||
|
||||
for(ndp = head; ndp; ndp = ndp->next)
|
||||
{
|
||||
if(ndp->type != nd_msg)
|
||||
continue;
|
||||
if(!nm)
|
||||
{
|
||||
msg = ndp->u.msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
msg_t *m1;
|
||||
msg_t *m2;
|
||||
if(ndp->u.msg->nmsgs > msg->nmsgs)
|
||||
{
|
||||
m1 = ndp->u.msg;
|
||||
m2 = msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
m1 = msg;
|
||||
m2 = ndp->u.msg;
|
||||
}
|
||||
|
||||
for(i = 0; i < m1->nmsgs; i++)
|
||||
{
|
||||
if(i > m2->nmsgs)
|
||||
error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev);
|
||||
else if(m1->msgs[i]->lan < m2->msgs[i]->lan)
|
||||
error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev);
|
||||
else if(m1->msgs[i]->lan > m2->msgs[i]->lan)
|
||||
error(err_missing, m2->msgs[i]->lan, m1->id, m1->fac, m1->sev);
|
||||
}
|
||||
}
|
||||
nm++;
|
||||
}
|
||||
return nm;
|
||||
}
|
||||
|
||||
#define MSGRID(x) ((*(msg_t **)(x))->realid)
|
||||
static int sort_msg(const void *p1, const void *p2)
|
||||
{
|
||||
return MSGRID(p1) > MSGRID(p2) ? 1 : (MSGRID(p1) == MSGRID(p2) ? 0 : -1);
|
||||
/* return (*(msg_t **)p1)->realid - (*(msg_t **)p1)->realid; */
|
||||
}
|
||||
|
||||
/*
|
||||
* block_messages() basically transposes the messages
|
||||
* from ID/language based list to a language/ID
|
||||
* based list.
|
||||
*/
|
||||
static lan_blk_t *block_messages(node_t *head)
|
||||
{
|
||||
lan_blk_t *lbp;
|
||||
lan_blk_t *lblktail = NULL;
|
||||
lan_blk_t *lblkhead = NULL;
|
||||
msg_t **msgtab = NULL;
|
||||
node_t *ndp;
|
||||
int nmsg = 0;
|
||||
int i;
|
||||
int nl;
|
||||
int factor = unicodeout ? 2 : 1;
|
||||
|
||||
for(ndp = head; ndp; ndp = ndp->next)
|
||||
{
|
||||
if(ndp->type != nd_msg)
|
||||
continue;
|
||||
msgtab = xrealloc(msgtab, (nmsg+1) * sizeof(*msgtab));
|
||||
msgtab[nmsg++] = ndp->u.msg;
|
||||
}
|
||||
|
||||
assert(nmsg != 0);
|
||||
qsort(msgtab, nmsg, sizeof(*msgtab), sort_msg);
|
||||
|
||||
for(nl = 0; nl < msgtab[0]->nmsgs; nl++) /* This should be equal for all after check_languages() */
|
||||
{
|
||||
lbp = xmalloc(sizeof(lan_blk_t));
|
||||
|
||||
if(!lblktail)
|
||||
{
|
||||
lblkhead = lblktail = lbp;
|
||||
}
|
||||
else
|
||||
{
|
||||
lblktail->next = lbp;
|
||||
lbp->prev = lblktail;
|
||||
lblktail = lbp;
|
||||
}
|
||||
lbp->nblk = 1;
|
||||
lbp->blks = xmalloc(sizeof(*lbp->blks));
|
||||
lbp->blks[0].idlo = msgtab[0]->realid;
|
||||
lbp->blks[0].idhi = msgtab[0]->realid;
|
||||
/* The plus 4 is the entry header; (+3)&~3 is DWORD alignment */
|
||||
lbp->blks[0].size = ((factor * msgtab[0]->msgs[nl]->len + 3) & ~3) + 4;
|
||||
lbp->blks[0].msgs = xmalloc(sizeof(*lbp->blks[0].msgs));
|
||||
lbp->blks[0].nmsg = 1;
|
||||
lbp->blks[0].msgs[0] = msgtab[0]->msgs[nl];
|
||||
lbp->lan = msgtab[0]->msgs[nl]->lan;
|
||||
|
||||
for(i = 1; i < nmsg; i++)
|
||||
{
|
||||
block_t *blk = &(lbp->blks[lbp->nblk-1]);
|
||||
if(msgtab[i]->realid == blk->idhi+1)
|
||||
{
|
||||
blk->size += ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4;
|
||||
blk->idhi++;
|
||||
blk->msgs = xrealloc(blk->msgs, (blk->nmsg+1) * sizeof(*blk->msgs));
|
||||
blk->msgs[blk->nmsg++] = msgtab[i]->msgs[nl];
|
||||
}
|
||||
else
|
||||
{
|
||||
lbp->nblk++;
|
||||
lbp->blks = xrealloc(lbp->blks, lbp->nblk * sizeof(*lbp->blks));
|
||||
blk = &(lbp->blks[lbp->nblk-1]);
|
||||
blk->idlo = msgtab[i]->realid;
|
||||
blk->idhi = msgtab[i]->realid;
|
||||
blk->size = ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4;
|
||||
blk->msgs = xmalloc(sizeof(*blk->msgs));
|
||||
blk->nmsg = 1;
|
||||
blk->msgs[0] = msgtab[i]->msgs[nl];
|
||||
}
|
||||
}
|
||||
}
|
||||
free(msgtab);
|
||||
return lblkhead;
|
||||
}
|
||||
|
||||
static int sc_xlat(const void *p1, const void *p2)
|
||||
{
|
||||
return ((cp_xlat_t *)p1)->lan - ((cp_xlat_t *)p2)->lan;
|
||||
}
|
||||
|
||||
static void add_cpxlat(int lan, int cpin, int cpout)
|
||||
{
|
||||
cpxlattab = xrealloc(cpxlattab, (ncpxlattab+1) * sizeof(*cpxlattab));
|
||||
cpxlattab[ncpxlattab].lan = lan;
|
||||
cpxlattab[ncpxlattab].cpin = cpin;
|
||||
cpxlattab[ncpxlattab].cpout = cpout;
|
||||
ncpxlattab++;
|
||||
qsort(cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat);
|
||||
}
|
||||
|
||||
static cp_xlat_t *find_cpxlat(int lan)
|
||||
{
|
||||
cp_xlat_t t;
|
||||
|
||||
if(!cpxlattab) return NULL;
|
||||
|
||||
t.lan = lan;
|
||||
return (cp_xlat_t *)bsearch(&t, cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat);
|
||||
}
|
254
reactos/tools/wmc/utils.c
Normal file
254
reactos/tools/wmc/utils.c
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Utility routines
|
||||
*
|
||||
* Copyright 1998,2000 Bertho A. Stultiens
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "wmctypes.h"
|
||||
#include "utils.h"
|
||||
#include "wmc.h"
|
||||
|
||||
#define SUPPRESS_YACC_ERROR_MESSAGE
|
||||
|
||||
static void generic_msg(const char *s, const char *t, va_list ap)
|
||||
{
|
||||
fprintf(stderr, "%s %s: %d, %d: ", t, input_name ? input_name : "stdin", line_number, char_number);
|
||||
vfprintf(stderr, s, ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* The yyerror routine should not exit because we use the error-token
|
||||
* to determine the syntactic error in the source. However, YACC
|
||||
* uses the same routine to print an error just before the error
|
||||
* token is reduced.
|
||||
* The extra routine 'xyyerror' is used to exit after giving a real
|
||||
* message.
|
||||
*/
|
||||
int yyerror(const char *s, ...)
|
||||
{
|
||||
#ifndef SUPPRESS_YACC_ERROR_MESSAGE
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
generic_msg(s, "Yacc error", ap);
|
||||
va_end(ap);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xyyerror(const char *s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
generic_msg(s, "Error", ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int yywarning(const char *s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
generic_msg(s, "Warning", ap);
|
||||
va_end(ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void internal_error(const char *file, int line, const char *s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
|
||||
vfprintf(stderr, s, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
void error(const char *s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
fprintf(stderr, "Error: ");
|
||||
vfprintf(stderr, s, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void warning(const char *s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
fprintf(stderr, "Warning: ");
|
||||
vfprintf(stderr, s, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
char *dup_basename(const char *name, const char *ext)
|
||||
{
|
||||
int namelen;
|
||||
int extlen = strlen(ext);
|
||||
char *base;
|
||||
char *slash;
|
||||
|
||||
if(!name)
|
||||
name = "wmc.tab";
|
||||
|
||||
slash = strrchr(name, '/');
|
||||
if (slash)
|
||||
name = slash + 1;
|
||||
|
||||
namelen = strlen(name);
|
||||
|
||||
/* +4 for later extension and +1 for '\0' */
|
||||
base = (char *)xmalloc(namelen +4 +1);
|
||||
strcpy(base, name);
|
||||
if(!strcasecmp(name + namelen-extlen, ext))
|
||||
{
|
||||
base[namelen - extlen] = '\0';
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
void *xmalloc(size_t size)
|
||||
{
|
||||
void *res;
|
||||
|
||||
assert(size > 0);
|
||||
assert(size < 102400);
|
||||
res = malloc(size);
|
||||
if(res == NULL)
|
||||
{
|
||||
error("Virtual memory exhausted.\n");
|
||||
}
|
||||
/*
|
||||
* We set it to 0.
|
||||
* This is *paramount* because we depend on it
|
||||
* just about everywhere in the rest of the code.
|
||||
*/
|
||||
memset(res, 0, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void *xrealloc(void *p, size_t size)
|
||||
{
|
||||
void *res;
|
||||
|
||||
assert(size > 0);
|
||||
assert(size < 102400);
|
||||
res = realloc(p, size);
|
||||
if(res == NULL)
|
||||
{
|
||||
error("Virtual memory exhausted.\n");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
char *xstrdup(const char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
assert(str != NULL);
|
||||
s = (char *)xmalloc(strlen(str)+1);
|
||||
return strcpy(s, str);
|
||||
}
|
||||
|
||||
int unistrlen(const WCHAR *s)
|
||||
{
|
||||
int n;
|
||||
for(n = 0; *s; n++, s++)
|
||||
;
|
||||
return n;
|
||||
}
|
||||
|
||||
WCHAR *unistrcpy(WCHAR *dst, const WCHAR *src)
|
||||
{
|
||||
WCHAR *t = dst;
|
||||
while(*src)
|
||||
*t++ = *src++;
|
||||
*t = 0;
|
||||
return dst;
|
||||
}
|
||||
|
||||
WCHAR *xunistrdup(const WCHAR * str)
|
||||
{
|
||||
WCHAR *s;
|
||||
|
||||
assert(str != NULL);
|
||||
s = (WCHAR *)xmalloc((unistrlen(str)+1) * sizeof(WCHAR));
|
||||
return unistrcpy(s, str);
|
||||
}
|
||||
|
||||
int unistricmp(const WCHAR *s1, const WCHAR *s2)
|
||||
{
|
||||
int i;
|
||||
int once = 0;
|
||||
static const char warn[] = "Don't know the uppercase equivalent of non acsii characters;"
|
||||
"comparison might yield wrong results";
|
||||
while(*s1 && *s2)
|
||||
{
|
||||
if((*s1 & 0xffff) > 0x7f || (*s2 & 0xffff) > 0x7f)
|
||||
{
|
||||
if(!once)
|
||||
{
|
||||
once++;
|
||||
yywarning(warn);
|
||||
}
|
||||
i = *s1++ - *s2++;
|
||||
}
|
||||
else
|
||||
i = toupper(*s1++) - toupper(*s2++);
|
||||
if(i)
|
||||
return i;
|
||||
}
|
||||
|
||||
if((*s1 & 0xffff) > 0x7f || (*s2 & 0xffff) > 0x7f)
|
||||
{
|
||||
if(!once)
|
||||
yywarning(warn);
|
||||
return *s1 - *s2;
|
||||
}
|
||||
else
|
||||
return toupper(*s1) - toupper(*s2);
|
||||
}
|
||||
|
||||
int unistrcmp(const WCHAR *s1, const WCHAR *s2)
|
||||
{
|
||||
int i;
|
||||
while(*s1 && *s2)
|
||||
{
|
||||
i = *s1++ - *s2++;
|
||||
if(i)
|
||||
return i;
|
||||
}
|
||||
|
||||
return *s1 - *s2;
|
||||
}
|
51
reactos/tools/wmc/utils.h
Normal file
51
reactos/tools/wmc/utils.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Utility routines' prototypes etc.
|
||||
*
|
||||
* Copyright 1998,2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WMC_UTILS_H
|
||||
#define __WMC_UTILS_H
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
#include "wmctypes.h"
|
||||
|
||||
void *xmalloc(size_t);
|
||||
void *xrealloc(void *, size_t);
|
||||
char *xstrdup(const char *str);
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __attribute__(X)
|
||||
#endif
|
||||
|
||||
int yyerror(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
int xyyerror(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
int yywarning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4)));
|
||||
void error(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
|
||||
|
||||
char *dup_basename(const char *name, const char *ext);
|
||||
|
||||
WCHAR *xunistrdup(const WCHAR * str);
|
||||
WCHAR *unistrcpy(WCHAR *dst, const WCHAR *src);
|
||||
int unistrlen(const WCHAR *s);
|
||||
int unistricmp(const WCHAR *s1, const WCHAR *s2);
|
||||
int unistrcmp(const WCHAR *s1, const WCHAR *s2);
|
||||
|
||||
#endif
|
282
reactos/tools/wmc/wmc.c
Normal file
282
reactos/tools/wmc/wmc.c
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Wine Message Compiler main program
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "wmc.h"
|
||||
#include "utils.h"
|
||||
#include "lang.h"
|
||||
#include "write.h"
|
||||
|
||||
static char usage[] =
|
||||
"Usage: wmc [options...] [inputfile.mc]\n"
|
||||
" -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n"
|
||||
" (default is n[ative] which equals "
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
"big"
|
||||
#else
|
||||
"little"
|
||||
#endif
|
||||
"-endian)\n"
|
||||
" -c Set 'custom-bit' in values\n"
|
||||
" -d Use decimal values in output\n"
|
||||
" -D Set debug flag\n"
|
||||
" -h This message\n"
|
||||
" -H file Write headerfile to file (default is inputfile.h)\n"
|
||||
" -i Inline messagetable(s)\n"
|
||||
" -o file Output to file (default is inputfile.rc)\n"
|
||||
" -u Inputfile is in unicode\n"
|
||||
" -U Output unicode messagetable(s)\n"
|
||||
" -v Show supported codepages and languages\n"
|
||||
" -V Print version end exit\n"
|
||||
" -W Enable pedantic warnings\n"
|
||||
"Input is taken from stdin if no inputfile is specified.\n"
|
||||
"Byteorder of unicode input is based upon the first couple of\n"
|
||||
"bytes read, which should be 0x0000..0x00ff.\n"
|
||||
;
|
||||
|
||||
static char version_string[] =
|
||||
"Wine Message Compiler version " PACKAGE_VERSION "\n"
|
||||
"Copyright 2000 Bertho A. Stultiens\n"
|
||||
;
|
||||
|
||||
/*
|
||||
* The output byte-order of resources (set with -B)
|
||||
*/
|
||||
int byteorder = WMC_BO_NATIVE;
|
||||
|
||||
/*
|
||||
* Custom bit (bit 29) in output values must be set (-c option)
|
||||
*/
|
||||
int custombit = 0;
|
||||
|
||||
/*
|
||||
* Output decimal values (-d option)
|
||||
*/
|
||||
int decimal = 0;
|
||||
|
||||
/*
|
||||
* Enable pedantic warnings; check arg references (-W option)
|
||||
*/
|
||||
int pedantic = 0;
|
||||
|
||||
/*
|
||||
* Unicode input (-u option)
|
||||
*/
|
||||
int unicodein = 0;
|
||||
|
||||
/*
|
||||
* Unicode output (-U option)
|
||||
*/
|
||||
int unicodeout = 0;
|
||||
|
||||
/*
|
||||
* Inline the messagetables (don't write *.bin files; -i option)
|
||||
*/
|
||||
int rcinline = 0;
|
||||
|
||||
/*
|
||||
* Debugging flag (-D option)
|
||||
*/
|
||||
int dodebug = 0;
|
||||
|
||||
char *output_name = NULL; /* The name given by the -o option */
|
||||
char *input_name = NULL; /* The name given on the command-line */
|
||||
char *header_name = NULL; /* The name given by the -H option */
|
||||
|
||||
int line_number = 1; /* The current line */
|
||||
int char_number = 1; /* The current char pos within the line */
|
||||
|
||||
char *cmdline; /* The entire commandline */
|
||||
time_t now; /* The time of start of wmc */
|
||||
|
||||
int getopt (int argc, char *const *argv, const char *optstring);
|
||||
static void segvhandler(int sig);
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
extern char* optarg;
|
||||
extern int optind;
|
||||
int optc;
|
||||
int lose = 0;
|
||||
int ret;
|
||||
int i;
|
||||
int cmdlen;
|
||||
|
||||
signal(SIGSEGV, segvhandler);
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
/* First rebuild the commandline to put in destination */
|
||||
/* Could be done through env[], but not all OS-es support it */
|
||||
cmdlen = 4; /* for "wmc " */
|
||||
for(i = 1; i < argc; i++)
|
||||
cmdlen += strlen(argv[i]) + 1;
|
||||
cmdline = (char *)xmalloc(cmdlen);
|
||||
strcpy(cmdline, "wmc ");
|
||||
for(i = 1; i < argc; i++)
|
||||
{
|
||||
strcat(cmdline, argv[i]);
|
||||
if(i < argc-1)
|
||||
strcat(cmdline, " ");
|
||||
}
|
||||
|
||||
while((optc = getopt(argc, argv, "B:cdDhH:io:p:uUvVW")) != EOF)
|
||||
{
|
||||
switch(optc)
|
||||
{
|
||||
case 'B':
|
||||
switch(optarg[0])
|
||||
{
|
||||
case 'n':
|
||||
case 'N':
|
||||
byteorder = WMC_BO_NATIVE;
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
byteorder = WMC_BO_LITTLE;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
byteorder = WMC_BO_BIG;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n");
|
||||
lose++;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
custombit = 1;
|
||||
break;
|
||||
case 'd':
|
||||
decimal = 1;
|
||||
break;
|
||||
case 'D':
|
||||
dodebug = 1;
|
||||
break;
|
||||
case 'h':
|
||||
printf("%s", usage);
|
||||
exit(0);
|
||||
/* No return */
|
||||
case 'H':
|
||||
header_name = xstrdup(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
rcinline = 1;
|
||||
break;
|
||||
case 'o':
|
||||
output_name = xstrdup(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
unicodein = 1;
|
||||
break;
|
||||
case 'U':
|
||||
unicodeout = 1;
|
||||
break;
|
||||
case 'v':
|
||||
show_languages();
|
||||
show_codepages();
|
||||
exit(0);
|
||||
/* No return */
|
||||
case 'V':
|
||||
printf(version_string);
|
||||
exit(0);
|
||||
/* No return */
|
||||
case 'W':
|
||||
pedantic = 1;
|
||||
break;
|
||||
default:
|
||||
lose++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(lose)
|
||||
{
|
||||
fprintf(stderr, "%s", usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
yydebug = dodebug;
|
||||
if(dodebug)
|
||||
{
|
||||
setbuf(stdout, 0);
|
||||
setbuf(stderr, 0);
|
||||
}
|
||||
|
||||
/* Check for input file on command-line */
|
||||
if(optind < argc)
|
||||
{
|
||||
input_name = argv[optind];
|
||||
}
|
||||
|
||||
/* Generate appropriate outfile names */
|
||||
if(!output_name)
|
||||
{
|
||||
output_name = dup_basename(input_name, ".mc");
|
||||
strcat(output_name, ".rc");
|
||||
}
|
||||
|
||||
if(!header_name)
|
||||
{
|
||||
header_name = dup_basename(input_name, ".mc");
|
||||
strcat(header_name, ".h");
|
||||
}
|
||||
|
||||
if(input_name)
|
||||
{
|
||||
if(!(yyin = fopen(input_name, "rb")))
|
||||
error("Could not open %s for input\n", input_name);
|
||||
}
|
||||
else
|
||||
yyin = stdin;
|
||||
|
||||
ret = yyparse();
|
||||
|
||||
if(input_name)
|
||||
fclose(yyin);
|
||||
|
||||
if(ret)
|
||||
{
|
||||
/* Error during parse */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
write_h_file(header_name);
|
||||
write_rc_file(output_name);
|
||||
if(!rcinline)
|
||||
write_bin_files();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void segvhandler(int sig)
|
||||
{
|
||||
fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
75
reactos/tools/wmc/wmc.h
Normal file
75
reactos/tools/wmc/wmc.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Main definitions and externals
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WMC_WMC_H
|
||||
#define __WMC_WMC_H
|
||||
|
||||
#include <time.h> /* For time_t */
|
||||
|
||||
#include "wmctypes.h"
|
||||
|
||||
/*
|
||||
* The default codepage setting is only to
|
||||
* read and convert input which is non-message
|
||||
* text. It doesn't really matter that much because
|
||||
* all codepages map 0x00-0x7f to 0x0000-0x007f from
|
||||
* char to unicode and all non-message text should
|
||||
* be plain ASCII.
|
||||
* However, we do implement iso-8859-1 for 1-to-1
|
||||
* mapping for all other chars, so this is very close
|
||||
* to what we really want.
|
||||
*/
|
||||
#define WMC_DEFAULT_CODEPAGE 28591
|
||||
|
||||
extern int pedantic;
|
||||
extern int leave_case;
|
||||
extern int byteorder;
|
||||
extern int decimal;
|
||||
extern int custombit;
|
||||
extern int unicodein;
|
||||
extern int unicodeout;
|
||||
extern int rcinline;
|
||||
|
||||
extern char *output_name;
|
||||
extern char *input_name;
|
||||
extern char *header_name;
|
||||
extern char *cmdline;
|
||||
extern time_t now;
|
||||
|
||||
extern int line_number;
|
||||
extern int char_number;
|
||||
|
||||
int yyparse(void);
|
||||
extern int yydebug;
|
||||
extern int want_nl;
|
||||
extern int want_line;
|
||||
extern int want_file;
|
||||
extern node_t *nodehead;
|
||||
extern lan_blk_t *lanblockhead;
|
||||
|
||||
int yylex(void);
|
||||
FILE *yyin;
|
||||
void set_codepage(int cp);
|
||||
|
||||
void add_token(tok_e type, const WCHAR *name, int tok, int cp, const WCHAR *alias, int fix);
|
||||
token_t *lookup_token(const WCHAR *s);
|
||||
void get_tokentable(token_t **tab, int *len);
|
||||
|
||||
#endif
|
79
reactos/tools/wmc/wmc.mak
Normal file
79
reactos/tools/wmc/wmc.mak
Normal file
|
@ -0,0 +1,79 @@
|
|||
WMC_BASE = $(TOOLS_BASE_)wmc
|
||||
WMC_BASE_ = $(WMC_BASE)$(SEP)
|
||||
WMC_INT = $(INTERMEDIATE_)$(WMC_BASE)
|
||||
WMC_INT_ = $(WMC_INT)$(SEP)
|
||||
WMC_OUT = $(OUTPUT_)$(WMC_BASE)
|
||||
WMC_OUT_ = $(WMC_OUT)$(SEP)
|
||||
|
||||
$(WMC_INT): | $(TOOLS_INT)
|
||||
$(ECHO_MKDIR)
|
||||
${mkdir} $@
|
||||
|
||||
ifneq ($(INTERMEDIATE),$(OUTPUT))
|
||||
$(WMC_OUT): | $(TOOLS_OUT)
|
||||
$(ECHO_MKDIR)
|
||||
${mkdir} $@
|
||||
endif
|
||||
|
||||
WMC_TARGET = \
|
||||
$(EXEPREFIX)$(WMC_OUT_)wmc$(EXEPOSTFIX)
|
||||
|
||||
WMC_SOURCES = $(addprefix $(WMC_BASE_), \
|
||||
lang.c \
|
||||
mcl.c \
|
||||
utils.c \
|
||||
wmc.c \
|
||||
write.c \
|
||||
mcy.tab.c \
|
||||
)
|
||||
|
||||
WMC_OBJECTS = \
|
||||
$(addprefix $(INTERMEDIATE_), $(WMC_SOURCES:.c=.o))
|
||||
|
||||
WMC_HOST_CFLAGS = -I$(WMC_BASE) $(TOOLS_CFLAGS) \
|
||||
-D__USE_W32API -DWINE_UNICODE_API= -I$(UNICODE_BASE) \
|
||||
-DDWORD="unsigned int" -DDWORD_DEFINED \
|
||||
-DLONG="int" -DULONG="unsigned int" \
|
||||
-DPULONG="unsigned int *" -DLONG_DEFINED \
|
||||
-Dwchar_t="unsigned short" -D_WCHAR_T_DEFINED \
|
||||
-Iinclude/wine -Iinclude -Iw32api/include
|
||||
|
||||
WMC_HOST_LFLAGS = $(TOOLS_LFLAGS)
|
||||
|
||||
WMC_LIBS = $(UNICODE_TARGET)
|
||||
|
||||
.PHONY: wmc
|
||||
wmc: $(WMC_TARGET)
|
||||
|
||||
$(WMC_TARGET): $(WMC_OBJECTS) $(WMC_LIBS) | $(WMC_OUT)
|
||||
$(ECHO_LD)
|
||||
${host_gcc} $(WMC_OBJECTS) $(WMC_LIBS) $(WMC_HOST_LFLAGS) -o $@
|
||||
|
||||
$(WMC_INT_)lang.o: $(WMC_BASE_)lang.c | $(WMC_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
$(WMC_INT_)mcl.o: $(WMC_BASE_)mcl.c | $(WMC_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
$(WMC_INT_)utils.o: $(WMC_BASE_)utils.c | $(WMC_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
$(WMC_INT_)wmc.o: $(WMC_BASE_)wmc.c | $(WMC_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
$(WMC_INT_)write.o: $(WMC_BASE_)write.c | $(WMC_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
$(WMC_INT_)mcy.tab.o: $(WMC_BASE_)mcy.tab.c | $(WMC_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gcc} $(WMC_HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
.PHONY: wmc_clean
|
||||
wmc_clean:
|
||||
-@$(rm) $(WMC_TARGET) $(WMC_OBJECTS) 2>$(NUL)
|
||||
clean: wmc_clean
|
122
reactos/tools/wmc/wmctypes.h
Normal file
122
reactos/tools/wmc/wmctypes.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Main definitions and externals
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WMC_WMCTYPES_H
|
||||
#define __WMC_WMCTYPES_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
||||
/* Byteordering defines */
|
||||
#define WMC_BO_NATIVE 0x00
|
||||
#define WMC_BO_LITTLE 0x01
|
||||
#define WMC_BO_BIG 0x02
|
||||
|
||||
#define WMC_LOBYTE(w) ((WORD)(w) & 0xff)
|
||||
#define WMC_HIBYTE(w) (((WORD)(w) >> 8) & 0xff)
|
||||
#define WMC_LOWORD(d) ((DWORD)(d) & 0xffff)
|
||||
#define WMC_HIWORD(d) (((DWORD)(d) >> 16) & 0xffff)
|
||||
#define BYTESWAP_WORD(w) ((WORD)(((WORD)WMC_LOBYTE(w) << 8) + (WORD)WMC_HIBYTE(w)))
|
||||
#define BYTESWAP_DWORD(d) ((DWORD)(((DWORD)BYTESWAP_WORD(WMC_LOWORD(d)) << 16) + ((DWORD)BYTESWAP_WORD(WMC_HIWORD(d)))))
|
||||
|
||||
/*
|
||||
* Tokenizer types
|
||||
*/
|
||||
typedef enum tok_enum {
|
||||
tok_null = 0,
|
||||
tok_keyword,
|
||||
tok_severity,
|
||||
tok_facility,
|
||||
tok_language
|
||||
} tok_e;
|
||||
|
||||
typedef struct token {
|
||||
tok_e type;
|
||||
const WCHAR *name; /* Parsed name of token */
|
||||
int token; /* Tokenvalue or language code */
|
||||
int codepage;
|
||||
const WCHAR *alias; /* Alias or filename */
|
||||
int fixed; /* Cleared if token may change */
|
||||
} token_t;
|
||||
|
||||
typedef struct lan_cp {
|
||||
int language;
|
||||
int codepage;
|
||||
} lan_cp_t;
|
||||
|
||||
typedef struct cp_xlat {
|
||||
int lan;
|
||||
int cpin;
|
||||
int cpout;
|
||||
} cp_xlat_t;
|
||||
|
||||
typedef struct lanmsg {
|
||||
int lan; /* Language code of message */
|
||||
int cp; /* Codepage of message */
|
||||
WCHAR *msg; /* Message text */
|
||||
int len; /* Message length including trailing '\0' */
|
||||
} lanmsg_t;
|
||||
|
||||
typedef struct msg {
|
||||
int id; /* Message ID */
|
||||
unsigned realid; /* Combined message ID */
|
||||
WCHAR *sym; /* Symbolic name */
|
||||
int sev; /* Severity code */
|
||||
int fac; /* Facility code */
|
||||
lanmsg_t **msgs; /* Array message texts */
|
||||
int nmsgs; /* Number of message texts in array */
|
||||
int base; /* Base of number to print */
|
||||
WCHAR *cast; /* Typecase to use */
|
||||
} msg_t;
|
||||
|
||||
typedef enum {
|
||||
nd_msg,
|
||||
nd_comment
|
||||
} node_e;
|
||||
|
||||
typedef struct node {
|
||||
struct node *next;
|
||||
struct node *prev;
|
||||
node_e type;
|
||||
union {
|
||||
void *all;
|
||||
WCHAR *comment;
|
||||
msg_t *msg;
|
||||
} u;
|
||||
} node_t;
|
||||
|
||||
typedef struct block {
|
||||
unsigned idlo; /* Lowest ID in this set */
|
||||
unsigned idhi; /* Highest ID in this set */
|
||||
int size; /* Size of this set */
|
||||
lanmsg_t **msgs; /* Array of messages in this set */
|
||||
int nmsg; /* Number of array entries */
|
||||
} block_t;
|
||||
|
||||
typedef struct lan_blk {
|
||||
struct lan_blk *next; /* Linkage for languages */
|
||||
struct lan_blk *prev;
|
||||
int lan; /* The language of this block */
|
||||
block_t *blks; /* Array of blocks for this language */
|
||||
int nblk; /* Nr of blocks in array */
|
||||
} lan_blk_t;
|
||||
|
||||
#endif
|
515
reactos/tools/wmc/write.c
Normal file
515
reactos/tools/wmc/write.c
Normal file
|
@ -0,0 +1,515 @@
|
|||
/*
|
||||
* Wine Message Compiler output generation
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "wmc.h"
|
||||
#include "utils.h"
|
||||
#include "lang.h"
|
||||
#include "write.h"
|
||||
|
||||
/*
|
||||
* The binary resource layout is as follows:
|
||||
*
|
||||
* +===============+
|
||||
* Header | NBlocks |
|
||||
* +===============+
|
||||
* Block 0 | Low ID |
|
||||
* +---------------+
|
||||
* | High ID |
|
||||
* +---------------+
|
||||
* | Offset |---+
|
||||
* +===============+ |
|
||||
* Block 1 | Low ID | |
|
||||
* +---------------+ |
|
||||
* | High ID | |
|
||||
* +---------------+ |
|
||||
* | Offset |------+
|
||||
* +===============+ | |
|
||||
* | | | |
|
||||
* ... ... | |
|
||||
* | | | |
|
||||
* +===============+ <-+ |
|
||||
* B0 LoID | Len | Flags | |
|
||||
* +---+---+---+---+ |
|
||||
* | b | l | a | b | |
|
||||
* +---+---+---+---+ |
|
||||
* | l | a | \0| \0| |
|
||||
* +===============+ |
|
||||
* | | |
|
||||
* ... ... |
|
||||
* | | |
|
||||
* +===============+ |
|
||||
* B0 HiID | Len | Flags | |
|
||||
* +---+---+---+---+ |
|
||||
* | M | o | r | e | |
|
||||
* +---+---+---+---+ |
|
||||
* | b | l | a | \0| |
|
||||
* +===============+ <----+
|
||||
* B1 LoID | Len | Flags |
|
||||
* +---+---+---+---+
|
||||
* | J | u | n | k |
|
||||
* +---+---+---+---+
|
||||
* | \0| \0| \0| \0|
|
||||
* +===============+
|
||||
* | |
|
||||
* ... ...
|
||||
* | |
|
||||
* +===============+
|
||||
*
|
||||
* All Fields are aligned on their natural boundaries. The length
|
||||
* field (Len) covers both the length of the string and the header
|
||||
* fields (Len and Flags). Strings are '\0' terminated. Flags is 0
|
||||
* for normal character strings and 1 for unicode strings.
|
||||
*/
|
||||
|
||||
static char str_header[] =
|
||||
"/* This file is generated with wmc version " PACKAGE_VERSION ". Do not edit! */\n"
|
||||
"/* Source : %s */\n"
|
||||
"/* Cmdline: %s */\n"
|
||||
"/* Date : %s */\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
static char *dup_u2c(int cp, const WCHAR *uc)
|
||||
{
|
||||
int len;
|
||||
char *cptr;
|
||||
const union cptable *cpdef = find_codepage(cp);
|
||||
if(!cpdef)
|
||||
internal_error(__FILE__, __LINE__, "Codepage %d not found (vanished?)", cp);
|
||||
len = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, NULL, 0, NULL, NULL);
|
||||
cptr = xmalloc(len);
|
||||
if((len = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, cptr, len, NULL, NULL)) < 0)
|
||||
internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", len);
|
||||
return cptr;
|
||||
}
|
||||
|
||||
static void killnl(char *s, int ddd)
|
||||
{
|
||||
char *tmp;
|
||||
tmp = strstr(s, "\r\n");
|
||||
if(tmp)
|
||||
{
|
||||
if(ddd && tmp - s > 3)
|
||||
{
|
||||
tmp[0] = tmp[1] = tmp[2] = '.';
|
||||
tmp[3] = '\0';
|
||||
}
|
||||
else
|
||||
*tmp = '\0';
|
||||
}
|
||||
tmp = strchr(s, '\n');
|
||||
if(tmp)
|
||||
{
|
||||
if(ddd && tmp - s > 3)
|
||||
{
|
||||
tmp[0] = tmp[1] = tmp[2] = '.';
|
||||
tmp[3] = '\0';
|
||||
}
|
||||
else
|
||||
*tmp = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static int killcomment(char *s)
|
||||
{
|
||||
char *tmp = s;
|
||||
int b = 0;
|
||||
while((tmp = strstr(tmp, "/*")))
|
||||
{
|
||||
tmp[1] = 'x';
|
||||
b++;
|
||||
}
|
||||
tmp = s;
|
||||
while((tmp = strstr(tmp, "*/")))
|
||||
{
|
||||
tmp[0] = 'x';
|
||||
b++;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
void write_h_file(const char *fname)
|
||||
{
|
||||
node_t *ndp;
|
||||
char *cptr;
|
||||
char *cast;
|
||||
FILE *fp;
|
||||
token_t *ttab;
|
||||
int ntab;
|
||||
int i;
|
||||
int once = 0;
|
||||
int idx_en = 0;
|
||||
|
||||
fp = fopen(fname, "w");
|
||||
if(!fp)
|
||||
{
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
cptr = ctime(&now);
|
||||
killnl(cptr, 0);
|
||||
fprintf(fp, str_header, input_name ? input_name : "<stdin>", cmdline, cptr);
|
||||
fprintf(fp, "#ifndef __WMCGENERATED_%08lx_H\n", (long)now);
|
||||
fprintf(fp, "#define __WMCGENERATED_%08lx_H\n", (long)now);
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* Write severity and facility aliases */
|
||||
get_tokentable(&ttab, &ntab);
|
||||
fprintf(fp, "/* Severity codes */\n");
|
||||
for(i = 0; i < ntab; i++)
|
||||
{
|
||||
if(ttab[i].type == tok_severity && ttab[i].alias)
|
||||
{
|
||||
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias);
|
||||
fprintf(fp, "#define %s\t0x%x\n", cptr, ttab[i].token);
|
||||
free(cptr);
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
fprintf(fp, "/* Facility codes */\n");
|
||||
for(i = 0; i < ntab; i++)
|
||||
{
|
||||
if(ttab[i].type == tok_facility && ttab[i].alias)
|
||||
{
|
||||
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias);
|
||||
fprintf(fp, "#define %s\t0x%x\n", cptr, ttab[i].token);
|
||||
free(cptr);
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* Write the message codes */
|
||||
fprintf(fp, "/* Message definitions */\n");
|
||||
for(ndp = nodehead; ndp; ndp = ndp->next)
|
||||
{
|
||||
switch(ndp->type)
|
||||
{
|
||||
case nd_comment:
|
||||
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.comment+1);
|
||||
killnl(cptr, 0);
|
||||
killcomment(cptr);
|
||||
if(*cptr)
|
||||
fprintf(fp, "/* %s */\n", cptr);
|
||||
else
|
||||
fprintf(fp, "\n");
|
||||
free(cptr);
|
||||
break;
|
||||
case nd_msg:
|
||||
if(!once)
|
||||
{
|
||||
/*
|
||||
* Search for an english text.
|
||||
* If not found, then use the first in the list
|
||||
*/
|
||||
once++;
|
||||
for(i = 0; i < ndp->u.msg->nmsgs; i++)
|
||||
{
|
||||
if(ndp->u.msg->msgs[i]->lan == 0x409)
|
||||
{
|
||||
idx_en = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fprintf(fp, "/* MessageId : 0x%08x */\n", ndp->u.msg->realid);
|
||||
cptr = dup_u2c(ndp->u.msg->msgs[idx_en]->cp, ndp->u.msg->msgs[idx_en]->msg);
|
||||
killnl(cptr, 0);
|
||||
killcomment(cptr);
|
||||
fprintf(fp, "/* Approx. msg: %s */\n", cptr);
|
||||
free(cptr);
|
||||
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.msg->sym);
|
||||
if(ndp->u.msg->cast)
|
||||
cast = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.msg->cast);
|
||||
else
|
||||
cast = NULL;
|
||||
switch(ndp->u.msg->base)
|
||||
{
|
||||
case 8:
|
||||
if(cast)
|
||||
fprintf(fp, "#define %s\t((%s)0%oL)\n\n", cptr, cast, ndp->u.msg->realid);
|
||||
else
|
||||
fprintf(fp, "#define %s\t0%oL\n\n", cptr, ndp->u.msg->realid);
|
||||
break;
|
||||
case 10:
|
||||
if(cast)
|
||||
fprintf(fp, "#define %s\t((%s)%dL)\n\n", cptr, cast, ndp->u.msg->realid);
|
||||
else
|
||||
fprintf(fp, "#define %s\t%dL\n\n", cptr, ndp->u.msg->realid);
|
||||
break;
|
||||
case 16:
|
||||
if(cast)
|
||||
fprintf(fp, "#define %s\t((%s)0x%08xL)\n\n", cptr, cast, ndp->u.msg->realid);
|
||||
else
|
||||
fprintf(fp, "#define %s\t0x%08xL\n\n", cptr, ndp->u.msg->realid);
|
||||
break;
|
||||
default:
|
||||
internal_error(__FILE__, __LINE__, "Invalid base for number print");
|
||||
}
|
||||
free(cptr);
|
||||
if(cast)
|
||||
free(cast);
|
||||
break;
|
||||
default:
|
||||
internal_error(__FILE__, __LINE__, "Invalid node type %d", ndp->type);
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n#endif\n");
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void write_rcbin(FILE *fp)
|
||||
{
|
||||
lan_blk_t *lbp;
|
||||
token_t *ttab;
|
||||
int ntab;
|
||||
int i;
|
||||
|
||||
get_tokentable(&ttab, &ntab);
|
||||
|
||||
for(lbp = lanblockhead; lbp; lbp = lbp->next)
|
||||
{
|
||||
char *cptr = NULL;
|
||||
fprintf(fp, "LANGUAGE 0x%x, 0x%x\n", lbp->lan & 0x3ff, lbp->lan >> 10);
|
||||
for(i = 0; i < ntab; i++)
|
||||
{
|
||||
if(ttab[i].type == tok_language && ttab[i].token == lbp->lan)
|
||||
{
|
||||
if(ttab[i].alias)
|
||||
cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!cptr)
|
||||
internal_error(__FILE__, __LINE__, "Filename vanished for language 0x%0x", lbp->lan);
|
||||
fprintf(fp, "1 MESSAGETABLE \"%s.bin\"\n", cptr);
|
||||
free(cptr);
|
||||
}
|
||||
}
|
||||
|
||||
static char *make_string(WCHAR *uc, int len, int codepage)
|
||||
{
|
||||
char *str = xmalloc(7*len + 1);
|
||||
char *cptr = str;
|
||||
int i;
|
||||
int b;
|
||||
|
||||
if(!codepage)
|
||||
{
|
||||
*cptr++ = ' ';
|
||||
*cptr++ = 'L';
|
||||
*cptr++ = '"';
|
||||
for(i = b = 0; i < len; i++, uc++)
|
||||
{
|
||||
switch(*uc)
|
||||
{
|
||||
case '\a': *cptr++ = '\\'; *cptr++ = 'a'; b += 2; break;
|
||||
case '\b': *cptr++ = '\\'; *cptr++ = 'b'; b += 2; break;
|
||||
case '\f': *cptr++ = '\\'; *cptr++ = 'f'; b += 2; break;
|
||||
case '\n': *cptr++ = '\\'; *cptr++ = 'n'; b += 2; break;
|
||||
case '\r': *cptr++ = '\\'; *cptr++ = 'r'; b += 2; break;
|
||||
case '\t': *cptr++ = '\\'; *cptr++ = 't'; b += 2; break;
|
||||
case '\v': *cptr++ = '\\'; *cptr++ = 'v'; b += 2; break;
|
||||
case '\\': *cptr++ = '\\'; *cptr++ = '\\'; b += 2; break;
|
||||
case '"': *cptr++ = '\\'; *cptr++ = '"'; b += 2; break;
|
||||
default:
|
||||
if (*uc < 0x100 && isprint(*uc))
|
||||
{
|
||||
*cptr++ = *uc;
|
||||
b++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = sprintf(cptr, "\\x%04x", *uc & 0xffff);
|
||||
cptr += n;
|
||||
b += n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(i < len-1 && b >= 72)
|
||||
{
|
||||
*cptr++ = '"';
|
||||
*cptr++ = ',';
|
||||
*cptr++ = '\n';
|
||||
*cptr++ = ' ';
|
||||
*cptr++ = 'L';
|
||||
*cptr++ = '"';
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
if (unicodeout)
|
||||
len = (len + 1) & ~1;
|
||||
else
|
||||
len = (len + 3) & ~3;
|
||||
for(; i < len; i++)
|
||||
{
|
||||
*cptr++ = '\\';
|
||||
*cptr++ = 'x';
|
||||
*cptr++ = '0';
|
||||
*cptr++ = '0';
|
||||
*cptr++ = '0';
|
||||
*cptr++ = '0';
|
||||
}
|
||||
*cptr++ = '"';
|
||||
*cptr = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
char *tmp, *cc;
|
||||
int mlen;
|
||||
const union cptable *cpdef = find_codepage(codepage);
|
||||
|
||||
assert(cpdef != NULL);
|
||||
mlen = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, NULL, 0, NULL, NULL);
|
||||
cc = tmp = xmalloc(mlen);
|
||||
if((i = wine_cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, tmp, mlen, NULL, NULL)) < 0)
|
||||
internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", i);
|
||||
*cptr++ = ' ';
|
||||
*cptr++ = '"';
|
||||
for(i = b = 0; i < len; i++, cc++)
|
||||
{
|
||||
switch(*cc)
|
||||
{
|
||||
case '\a': *cptr++ = '\\'; *cptr++ = 'a'; b += 2; break;
|
||||
case '\b': *cptr++ = '\\'; *cptr++ = 'b'; b += 2; break;
|
||||
case '\f': *cptr++ = '\\'; *cptr++ = 'f'; b += 2; break;
|
||||
case '\n': *cptr++ = '\\'; *cptr++ = 'n'; b += 2; break;
|
||||
case '\r': *cptr++ = '\\'; *cptr++ = 'r'; b += 2; break;
|
||||
case '\t': *cptr++ = '\\'; *cptr++ = 't'; b += 2; break;
|
||||
case '\v': *cptr++ = '\\'; *cptr++ = 'v'; b += 2; break;
|
||||
case '\\': *cptr++ = '\\'; *cptr++ = '\\'; b += 2; break;
|
||||
case '"': *cptr++ = '\\'; *cptr++ = '"'; b += 2; break;
|
||||
default:
|
||||
if(isprint(*cc))
|
||||
{
|
||||
*cptr++ = *cc;
|
||||
b++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = sprintf(cptr, "\\x%02x", *cc & 0xff);
|
||||
cptr += n;
|
||||
b += n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(i < len-1 && b >= 72)
|
||||
{
|
||||
*cptr++ = '"';
|
||||
*cptr++ = ',';
|
||||
*cptr++ = '\n';
|
||||
*cptr++ = ' ';
|
||||
*cptr++ = '"';
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
len = (len + 3) & ~3;
|
||||
for(; i < len; i++)
|
||||
{
|
||||
*cptr++ = '\\';
|
||||
*cptr++ = 'x';
|
||||
*cptr++ = '0';
|
||||
*cptr++ = '0';
|
||||
}
|
||||
*cptr++ = '"';
|
||||
*cptr = '\0';
|
||||
free(tmp);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static void write_rcinline(FILE *fp)
|
||||
{
|
||||
lan_blk_t *lbp;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for(lbp = lanblockhead; lbp; lbp = lbp->next)
|
||||
{
|
||||
unsigned offs = 4 * (lbp->nblk * 3 + 1);
|
||||
fprintf(fp, "\n1 MESSAGETABLE\n");
|
||||
fprintf(fp, "LANGUAGE 0x%x, 0x%x\n", lbp->lan & 0x3ff, lbp->lan >> 10);
|
||||
fprintf(fp, "{\n");
|
||||
fprintf(fp, " /* NBlocks */ 0x%08xL,\n", lbp->nblk);
|
||||
for(i = 0; i < lbp->nblk; i++)
|
||||
{
|
||||
fprintf(fp, " /* Lo,Hi,Offs */ 0x%08xL, 0x%08xL, 0x%08xL,\n",
|
||||
lbp->blks[i].idlo,
|
||||
lbp->blks[i].idhi,
|
||||
offs);
|
||||
offs += lbp->blks[i].size;
|
||||
}
|
||||
for(i = 0; i < lbp->nblk; i++)
|
||||
{
|
||||
block_t *blk = &lbp->blks[i];
|
||||
for(j = 0; j < blk->nmsg; j++)
|
||||
{
|
||||
char *cptr;
|
||||
int l = blk->msgs[j]->len;
|
||||
const char *comma = j == blk->nmsg-1 && i == lbp->nblk-1 ? "" : ",";
|
||||
cptr = make_string(blk->msgs[j]->msg, l, unicodeout ? 0 : blk->msgs[j]->cp);
|
||||
fprintf(fp, "\n /* Msg 0x%08x */ 0x%04x, 0x000%c,\n",
|
||||
blk->idlo + j,
|
||||
(unicodeout ? (l*2+3)&~3 : (l+3)&~3) + 4,
|
||||
unicodeout ? '1' : '0');
|
||||
fprintf(fp, "%s%s\n", cptr, comma);
|
||||
free(cptr);
|
||||
}
|
||||
}
|
||||
fprintf(fp, "}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void write_rc_file(const char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
char *cptr;
|
||||
|
||||
fp = fopen(fname, "w");
|
||||
if(!fp)
|
||||
{
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
cptr = ctime(&now);
|
||||
killnl(cptr, 0);
|
||||
fprintf(fp, str_header, input_name ? input_name : "<stdin>", cmdline, cptr);
|
||||
|
||||
if(rcinline)
|
||||
write_rcinline(fp);
|
||||
else
|
||||
write_rcbin(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void write_bin_files(void)
|
||||
{
|
||||
assert(rcinline == 0);
|
||||
}
|
27
reactos/tools/wmc/write.h
Normal file
27
reactos/tools/wmc/write.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Wine Message Compiler outpur generation
|
||||
*
|
||||
* Copyright 2000 Bertho A. Stultiens (BS)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef __WMC_WRITE_H
|
||||
#define __WMC_WRITE_H
|
||||
|
||||
void write_h_file(const char *fname);
|
||||
void write_rc_file(const char *fname);
|
||||
void write_bin_files(void);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue