Added message compiler.

svn path=/trunk/; revision=2362
This commit is contained in:
Eric Kohl 2001-11-09 12:27:02 +00:00
parent af8dfb404f
commit 51f2c2d3d0
20 changed files with 6689 additions and 0 deletions

454
reactos/tools/wmc/config.h Normal file
View file

@ -0,0 +1,454 @@
/* include/config.h. Generated automatically by configure. */
/* include/config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define if you have alloca, as a function or macro. */
#define HAVE_ALLOCA 1
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define as __inline if that's what the C compiler calls it. */
/* #undef inline */
/* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
/* #undef STAT_MACROS_BROKEN */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
/* #undef WORDS_BIGENDIAN */
/* Define if the X Window System is missing or not being used. */
/* #undef X_DISPLAY_MISSING */
/* Define if lex declares yytext as a char * by default, not a char[]. */
#define YYTEXT_POINTER 1
/* Define if symbols declared in assembly code need an underscore prefix */
/* #undef NEED_UNDERSCORE_PREFIX */
/* Define to use .string instead of .ascii */
#define HAVE_ASM_STRING 1
/* Define if struct msghdr contains msg_accrights */
/* #undef HAVE_MSGHDR_ACCRIGHTS */
/* Define if struct sockaddr_un contains sun_len */
/* #undef HAVE_SOCKADDR_SUN_LEN */
/* Define if you have the Xxf86dga library (-lXxf86dga). */
#define HAVE_LIBXXF86DGA 1
/* Define if you have the Xxf86dga library version 2.0 (-lXxf86dga). */
/* #undef HAVE_LIBXXF86DGA2 */
/* Define if you have the X Shm extension */
#define HAVE_LIBXXSHM 1
/* Define if you have the X Shape extension */
#define HAVE_LIBXSHAPE 1
/* Define if you have the Xxf86vm library */
#define HAVE_LIBXXF86VM 1
/* Define if you have the Xpm library */
#define HAVE_LIBXXPM 1
/* Define if you have the Open Sound system. */
#define HAVE_OSS 1
/* Define if you have the Open Sound system (MIDI interface). */
#define HAVE_OSS_MIDI 1
/* Define if X libraries are not reentrant (compiled without -D_REENTRANT). */
/* #undef NO_REENTRANT_X11 */
/* Define if libc is not reentrant */
/* #undef NO_REENTRANT_LIBC */
/* Define if libc uses __errno_location for reentrant errno */
#define HAVE__ERRNO_LOCATION 1
/* Define if libc uses __error for reentrant errno */
/* #undef HAVE__ERROR */
/* Define if libc uses ___errno for reentrant errno */
/* #undef HAVE___ERRNO */
/* Define if libc uses __thr_errno for reentrant errno */
/* #undef HAVE__THR_ERRNO */
/* Define if all debug messages are to be compiled out */
/* #undef NO_DEBUG_MSGS */
/* Define if TRACE messages are to be compiled out */
/* #undef NO_TRACE_MSGS */
/* Define if the struct statfs has the member bavail */
#define STATFS_HAS_BAVAIL 1
/* Define if the struct statfs has the member bfree */
#define STATFS_HAS_BFREE 1
/* Define if the struct statfs is defined by <sys/vfs.h> */
#define STATFS_DEFINED_BY_SYS_VFS 1
/* Define if the struct statfs is defined by <sys/statfs.h> */
#define STATFS_DEFINED_BY_SYS_STATFS 1
/* Define if the struct statfs is defined by <sys/mount.h> */
/* #undef STATFS_DEFINED_BY_SYS_MOUNT */
/* Define if ncurses have the new resizeterm function */
#define HAVE_RESIZETERM 1
/* Define if ncurses have the new getbkgd function */
#define HAVE_GETBKGD 1
/* Define if IPX should use netipx/ipx.h from libc */
#define HAVE_IPX_GNU 1
/* Define if IPX includes are taken from Linux kernel */
/* #undef HAVE_IPX_LINUX */
/* Define if OpenGL is present on the system or not */
#define HAVE_OPENGL 1
/* Define if the system has dynamic link library support with the dl* API */
#define HAVE_DL_API 1
/* Define if <linux/joystick.h> defines the Linux 2.2 joystick API */
#define HAVE_LINUX_22_JOYSTICK_API 1
/* Define if the OpenGL library supports the glXGetProcAddressARB call */
/* #undef HAVE_GLX_GETPROCADDRESS */
/* Define if the OpenGL headers define extension typedefs */
/* #undef HAVE_GLEXT_PROTOTYPES */
/* The number of bytes in a long long. */
#define SIZEOF_LONG_LONG 8
/* Define if you have the __libc_fork function. */
/* #undef HAVE___LIBC_FORK */
/* Define if you have the _lwp_create function. */
/* #undef HAVE__LWP_CREATE */
/* Define if you have the clone function. */
#define HAVE_CLONE 1
/* Define if you have the connect function. */
#define HAVE_CONNECT 1
/* Define if you have the dlopen function. */
/* #undef HAVE_DLOPEN */
/* Define if you have the gethostbyname function. */
#define HAVE_GETHOSTBYNAME 1
/* Define if you have the getnetbyaddr function. */
#define HAVE_GETNETBYADDR 1
/* Define if you have the getnetbyname function. */
#define HAVE_GETNETBYNAME 1
/* Define if you have the getpagesize function. */
#define HAVE_GETPAGESIZE 1
/* Define if you have the getprotobyname function. */
#define HAVE_GETPROTOBYNAME 1
/* Define if you have the getprotobynumber function. */
#define HAVE_GETPROTOBYNUMBER 1
/* Define if you have the getservbyport function. */
#define HAVE_GETSERVBYPORT 1
/* Define if you have the getsockopt function. */
#define HAVE_GETSOCKOPT 1
/* Define if you have the inet_network function. */
#define HAVE_INET_NETWORK 1
/* Define if you have the memmove function. */
#define HAVE_MEMMOVE 1
/* Define if you have the openpty function. */
#define HAVE_OPENPTY 1
/* Define if you have the rfork function. */
/* #undef HAVE_RFORK */
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the sendmsg function. */
#define HAVE_SENDMSG 1
/* Define if you have the settimeofday function. */
#define HAVE_SETTIMEOFDAY 1
/* Define if you have the sigaltstack function. */
/* #undef HAVE_SIGALTSTACK */
/* Define if you have the statfs function. */
#define HAVE_STATFS 1
/* Define if you have the strcasecmp function. */
#define HAVE_STRCASECMP 1
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the strncasecmp function. */
#define HAVE_STRNCASECMP 1
/* Define if you have the tcgetattr function. */
#define HAVE_TCGETATTR 1
/* Define if you have the timegm function. */
#define HAVE_TIMEGM 1
/* Define if you have the usleep function. */
#define HAVE_USLEEP 1
/* Define if you have the vfscanf function. */
#define HAVE_VFSCANF 1
/* Define if you have the wait4 function. */
#define HAVE_WAIT4 1
/* Define if you have the waitpid function. */
#define HAVE_WAITPID 1
/* Define if you have the <GL/gl.h> header file. */
#define HAVE_GL_GL_H 1
/* Define if you have the <GL/glext.h> header file. */
/* #undef HAVE_GL_GLEXT_H */
/* Define if you have the <GL/glx.h> header file. */
#define HAVE_GL_GLX_H 1
/* Define if you have the <X11/Xlib.h> header file. */
#define HAVE_X11_XLIB_H 1
/* Define if you have the <X11/extensions/XShm.h> header file. */
#define HAVE_X11_EXTENSIONS_XSHM_H 1
/* Define if you have the <X11/extensions/shape.h> header file. */
#define HAVE_X11_EXTENSIONS_SHAPE_H 1
/* Define if you have the <X11/extensions/xf86dga.h> header file. */
#define HAVE_X11_EXTENSIONS_XF86DGA_H 1
/* Define if you have the <X11/extensions/xf86vmode.h> header file. */
#define HAVE_X11_EXTENSIONS_XF86VMODE_H 1
/* Define if you have the <X11/xpm.h> header file. */
#define HAVE_X11_XPM_H 1
/* Define if you have the <a.out.h> header file. */
#define HAVE_A_OUT_H 1
/* Define if you have the <a_out.h> header file. */
#define HAVE_A_OUT_H 1
/* Define if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define if you have the <arpa/nameser.h> header file. */
#define HAVE_ARPA_NAMESER_H 1
/* Define if you have the <curses.h> header file. */
/* #undef HAVE_CURSES_H */
/* Define if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define if you have the <elf.h> header file. */
#define HAVE_ELF_H 1
/* Define if you have the <float.h> header file. */
#define HAVE_FLOAT_H 1
/* Define if you have the <libio.h> header file. */
#define HAVE_LIBIO_H 1
/* Define if you have the <libutil.h> header file. */
/* #undef HAVE_LIBUTIL_H */
/* Define if you have the <link.h> header file. */
#define HAVE_LINK_H 1
/* Define if you have the <linux/cdrom.h> header file. */
#define HAVE_LINUX_CDROM_H 1
/* Define if you have the <linux/joystick.h> header file. */
#define HAVE_LINUX_JOYSTICK_H 1
/* Define if you have the <linux/ucdrom.h> header file. */
/* #undef HAVE_LINUX_UCDROM_H */
/* Define if you have the <machine/soundcard.h> header file. */
/* #undef HAVE_MACHINE_SOUNDCARD_H */
/* Define if you have the <ncurses.h> header file. */
#define HAVE_NCURSES_H 1
/* Define if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H 1
/* Define if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define if you have the <netinet/tcp.h> header file. */
#define HAVE_NETINET_TCP_H 1
/* Define if you have the <pty.h> header file. */
#define HAVE_PTY_H 1
/* Define if you have the <resolv.h> header file. */
#define HAVE_RESOLV_H 1
/* Define if you have the <sched.h> header file. */
#define HAVE_SCHED_H 1
/* Define if you have the <socket.h> header file. */
/* #undef HAVE_SOCKET_H */
/* Define if you have the <soundcard.h> header file. */
/* #undef HAVE_SOUNDCARD_H */
/* Define if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define if you have the <sys/cdio.h> header file. */
/* #undef HAVE_SYS_CDIO_H */
/* Define if you have the <sys/errno.h> header file. */
#define HAVE_SYS_ERRNO_H 1
/* Define if you have the <sys/file.h> header file. */
#define HAVE_SYS_FILE_H 1
/* Define if you have the <sys/filio.h> header file. */
/* #undef HAVE_SYS_FILIO_H */
/* Define if you have the <sys/ipc.h> header file. */
#define HAVE_SYS_IPC_H 1
/* Define if you have the <sys/lwp.h> header file. */
/* #undef HAVE_SYS_LWP_H */
/* Define if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define if you have the <sys/modem.h> header file. */
/* #undef HAVE_SYS_MODEM_H */
/* Define if you have the <sys/mount.h> header file. */
#define HAVE_SYS_MOUNT_H 1
/* Define if you have the <sys/msg.h> header file. */
#define HAVE_SYS_MSG_H 1
/* Define if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define if you have the <sys/reg.h> header file. */
#define HAVE_SYS_REG_H 1
/* Define if you have the <sys/shm.h> header file. */
#define HAVE_SYS_SHM_H 1
/* Define if you have the <sys/signal.h> header file. */
#define HAVE_SYS_SIGNAL_H 1
/* Define if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define if you have the <sys/sockio.h> header file. */
/* #undef HAVE_SYS_SOCKIO_H */
/* Define if you have the <sys/soundcard.h> header file. */
#define HAVE_SYS_SOUNDCARD_H 1
/* Define if you have the <sys/statfs.h> header file. */
#define HAVE_SYS_STATFS_H 1
/* Define if you have the <sys/strtio.h> header file. */
/* #undef HAVE_SYS_STRTIO_H */
/* Define if you have the <sys/syscall.h> header file. */
#define HAVE_SYS_SYSCALL_H 1
/* Define if you have the <sys/v86.h> header file. */
/* #undef HAVE_SYS_V86_H */
/* Define if you have the <sys/v86intr.h> header file. */
/* #undef HAVE_SYS_V86INTR_H */
/* Define if you have the <sys/vfs.h> header file. */
#define HAVE_SYS_VFS_H 1
/* Define if you have the <sys/vm86.h> header file. */
#define HAVE_SYS_VM86_H 1
/* Define if you have the <sys/wait.h> header file. */
#define HAVE_SYS_WAIT_H 1
/* Define if you have the <syscall.h> header file. */
#define HAVE_SYSCALL_H 1
/* Define if you have the <ucontext.h> header file. */
/* #undef HAVE_UCONTEXT_H */
/* Define if you have the curses library (-lcurses). */
/* #undef HAVE_LIBCURSES */
/* Define if you have the i386 library (-li386). */
/* #undef HAVE_LIBI386 */
/* Define if you have the m library (-lm). */
#define HAVE_LIBM 1
/* Define if you have the mmap library (-lmmap). */
/* #undef HAVE_LIBMMAP */
/* Define if you have the ncurses library (-lncurses). */
#define HAVE_LIBNCURSES 1
/* Define if you have the ossaudio library (-lossaudio). */
/* #undef HAVE_LIBOSSAUDIO */
/* Define if you have the w library (-lw). */
/* #undef HAVE_LIBW */
/* Define if you have the xpg4 library (-lxpg4). */
/* #undef HAVE_LIBXPG4 */

1050
reactos/tools/wmc/getopt.c Normal file

File diff suppressed because it is too large Load diff

131
reactos/tools/wmc/getopt.h Normal file
View file

@ -0,0 +1,131 @@
/* Declarations for getopt.
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if defined (__STDC__) && __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if defined (__STDC__) && __STDC__
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

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

@ -0,0 +1,155 @@
/*
* Wine Message Compiler language and codepage support
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#include <windows.h>
#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[] = {
{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"},
/* {0x048F, ?, ?, "Esperanto", "<none>"},*/
/* {0x0804, ?, ?, "Chinese (People's replublic 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)
{
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 *(unsigned *)p1 - ((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)
{
#if 0
unsigned i;
const union cptable *cpp;
printf("Codepages:\n");
for(i = 0; (cpp = cp_enum_table(i)); i++)
{
printf("%-5d %s\n", cpp->info.codepage, cpp->info.name);
}
#endif
}
#if 0
const union cptable *find_codepage(int id)
{
return cp_get_table(id);
}
#endif

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

@ -0,0 +1,26 @@
/*
* Wine Message Compiler language and codepage support
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#ifndef __WMC_LANG_H
#define __WMC_LANG_H
//#include "wine/unicode.h"
typedef struct language {
unsigned id;
unsigned doscp;
unsigned wincp;
char *name;
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

View file

@ -0,0 +1,107 @@
{"South Africa", 0x0436, 1252},
{"Saudi Arabia", 0x0401, 1256},
{"Lebanon", 0x0401, 1256},
{"Egypt", 0x0401, 1256},
{"Algeria", 0x0401, 1256},
{"Iraq", 0x0401, 1256},
{"Kuwait", 0x0401, 1256},
{"Marocco", 0x0401, 1256},
{"Oman", 0x0401, 1256},
{"Quatar", 0x0401, 1256},
{"Syria", 0x0401, 1256},
{"Tunisia", 0x0401, 1256},
{"United Arab Emirates",0x0401, 1256},
{"Belaruss", 0x0423, 1251},
{"Bulgaria", 0x0402
{"France", 0x040c, 1252},
{"Spain", 0x0403, 1252},
{"China (Taiwan)", 0x0404
{"United Kingdom", 0x0409, 1252},
{"Wales", 0x0409, 1252}, /* FIXME */
{"Czech Republic", 0x0405, 1250},
{"Denmark", 0x0406, 1252},
{"Austria", 0x0407, 1252},
{"Liechtenstein", 0x0407, 1252},
{"Luxemburg", 0x0407, 1252},
{"Switzerland", 0x0807, 1252},
{"Germany", 0x0407, 1252},
{"Australia", 0x0c09, 1252},
{"Caribbean", 0x2409, 1252},
{"Canada", 0x1009, 1252},
{"United Kingdom", 0x0809, 1252},
{"Ireland", 0x1809, 1252},
{"Jamaica", 0x2009, 1252},
{"Belize", 0x2809, 1252},
{"South Africa", 0x1c09, 1252},
{"Trinidad & Tobago", 0x2c09, 1252},
{"United States", 0x0409, 1252},
{"New Zealand", 0x1409, 1252},
{"Panama", 0x040a, 1252},
{"Bolivia", 0x040a, 1252},
{"Costa Rica", 0x140a, 1252},
{"Dominican Republic", 0x040a, 1252},
{"El Salvador", 0x040a, 1252},
{"Ecuador", 0x040a, 1252},
{"Guatemala", 0x040a, 1252},
{"Honduras", 0x040a, 1252},
{"Nicaragua", 0x040a, 1252},
{"Chile", 0x040a, 1252},
{"Mexico", 0x040a, 1252},
{"Spain", 0x040a, 1252},
{"Colombia", 0x040a, 1252},
{"Spain", 0x040a, 1252},
{"Peru", 0x040a, 1252},
{"Argentina", 0x040a, 1252},
{"Estonia", 0x0425, 1252},
{"Puerto Rico", 0x040a, 1252},
{"Venezuela", 0x040a, 1252},
{"Uruguay", 0x380a, 1252},
{"Paraguay", 0x040a, 1252},
{"Spain (Basque)", 0x04d2, 1252},
{"Finland", 0x040b, 1252},
{"Faroe Islands", 0x0438, 1252},
{"France", 0x040c, 1252},
{"Belgium", 0x040c, 1252},
{"Canada", 0x040c, 1252},
{"Luxemburg", 0x040c, 1252},
{"Switzerland", 0x040c, 1252},
{"Ireland", 0x0000, 1252},
{"United Kingdom", 0x0409, 1252},
{"Isle of Man", 0x0409, 1252},
{"Greece", 0x0408, 1253},
{"Croatia", 0x041a, 1250},
{"Hungary", 0x040e, 1250},
{"Indonesia", 0x0421, 1252},
{"Iceland", 0x040f, 1252},
{"Italy", 0x0410, 1252},
{"Switzerand", 0x0410, 1252},
{"Japan", 0x0411, 0},
{"Korea", 0x0000, 0},
{"Korea (South)", 0x0412, 0},
{"Lithuania", 0x0427, 1257},
{"Latvia", 0x0426, 1257},
{"Belgium", 0x0413, 1252},
{"Netherlands", 0x0413, 1252},
{"Suriname", 0x0413, 1252},
{"Norway", 0x0814, 1252},
{"Norway", 0x0414, 1252},
{"Poland", 0x0415, 1250},
{"Brazil", 0x0416, 1252},
{"Portugal", 0x0416, 1252},
{"Romania", 0x0418, 1250},
{"Russia", 0x0000, 1251},
{"Slovakia", 0x041b, 1250},
{"Slovenia", 0x0424, 1250},
{"Albania", 0x041c, 0},
{"Yugoslavia", 0x0c1a, 0},
{"Yugoslavia", 0x081a, 1250},
{"Sweden", 0x041d, 1252},
{"Finland", 0x081d, 1252},
{"Thailand", 0x041e, 0},
{"Turkey", 0x041f, 1254},
{"Ukrainia", 0x0422, 1251},
{"Vietnam", 0x042a, 0},
{"Belgium", 0x0490, 1252},
{"Hong Kong", 0x0404, 0},
{"People's republic of China", 0x0804, 0},
{"Singapore", 0x0404, 0}

View file

@ -0,0 +1,32 @@
#
# ReactOS/Wine message compiler
#
PATH_TO_TOP = ../..
TARGET=wmc$(EXE_POSTFIX)
all: $(TARGET)
OBJECTS = getopt.o lang.o mcl.o utils.o wmc.o write.o y_tab.o
CLEAN_FILES = *.o wmc$(EXE_POSTFIX)
wmc$(EXE_POSTFIX): $(OBJECTS)
$(HOST_CC) $(OBJECTS) -lkernel32 -lcrtdll -luser32 -o wmc$(EXE_POSTFIX)
ifeq ($(HOST),mingw32-linux)
clean:
rm *.o
rm wmc$(EXE_POSTFIX)
endif
ifeq ($(HOST),mingw32-windows)
clean:
del *.o
del wmc$(EXE_POSTFIX)
endif
.phony: clean
include $(PATH_TO_TOP)/rules.mak
# EOF

View file

@ -0,0 +1,49 @@
DEFS = -D__WINE__
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
YACCOPT = #-v
LIBEXT = @LIBEXT@
PROGRAMS = wmc
MODULE = none
C_SRCS = \
lang.c \
mcl.c \
utils.c \
wmc.c \
write.c
EXTRA_SRCS = mcy.y
EXTRA_OBJS = y.tab.o
all: $(PROGRAMS)
depend mcl.o: y.tab.h
@MAKE_RULES@
wmc: $(OBJS) $(TOPOBJDIR)/libwine_unicode.$(LIBEXT)
$(CC) $(CFLAGS) -o wmc $(OBJS) -L$(TOPOBJDIR) -lwine_unicode $(LEXLIB)
$(TOPOBJDIR)/libwine_unicode.$(LIBEXT):
cd $(TOPOBJDIR) && $(MAKE) libwine_unicode.$(LIBEXT)
y.tab.c y.tab.h: mcy.y
$(YACC) $(YACCOPT) -d -t $(SRCDIR)/mcy.y
clean::
$(RM) y.tab.c y.tab.h y.output
install:: $(PROGRAMS)
[ -d $(bindir) ] || $(MKDIR) $(bindir)
[ -d $(mandir)/man$(prog_manext) ] || $(MKDIR) $(mandir)/man$(prog_manext)
$(INSTALL_DATA) $(SRCDIR)/wmc.man $(mandir)/man$(prog_manext)/wmc.$(prog_manext)
$(INSTALL_PROGRAM) wmc $(bindir)/wmc
uninstall::
$(RM) $(bindir)/wmc $(mandir)/man$(prog_manext)/wmc.$(prog_manext)
### Dependencies:

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

@ -0,0 +1,736 @@
/*
* Wine Message Compiler lexical scanner
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include "config.h"
#include "utils.h"
#include "wmc.h"
#include "lang.h"
#include "y_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;
#if 0
codepage_def = find_codepage(codepage);
if(!codepage_def)
xyyerror("Codepage %d not found; cannot process", codepage);
#endif
}
/*
* 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 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 = cp_mbstowcs(codepage_def, 0, xlatebuffer, strlen(xlatebuffer)+1, inputbuffer, INPUTBUFFER_SIZE);
n = MultiByteToWideChar(codepage, 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(((token_t *)p1)->name, ((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 WCHAR ustr_dot1[] = { '.', '\n', 0 };
static 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);
}
}
}

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

@ -0,0 +1,662 @@
/*
* Wine Message Compiler parser
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
* 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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "config.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($1->token) && !find_cpxlat($1->token))
yywarning("Language 0x%x not built-in, using codepage %d; use explicit codepage to override", $1->token, 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 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);
}

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

@ -0,0 +1,242 @@
/*
* Utility routines
*
* Copyright 1998,2000 Bertho A. Stultiens
*
*/
#include "config.h"
#include <windows.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(!stricmp(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 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;
}

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

@ -0,0 +1,44 @@
/*
* Utility routines' prototypes etc.
*
* Copyright 1998,2000 Bertho A. Stultiens (BS)
*
*/
#ifndef __WMC_UTILS_H
#define __WMC_UTILS_H
#ifndef __WMC_WMCTYPES_H
#include "wmctypes.h"
#endif
#include <stddef.h> /* size_t */
void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(const char *str);
#if 0
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)));
#endif
int yyerror(const char *s, ...);
int xyyerror(const char *s, ...);
int yywarning(const char *s, ...);
void internal_error(const char *file, int line, const char *s, ...);
void error(const char *s, ...);
void warning(const char *s, ...);
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

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

@ -0,0 +1,269 @@
/*
* Wine Message Compiler main program
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "config.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 " WMC_FULLVERSION "\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();
}

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

@ -0,0 +1,74 @@
/*
* Main definitions and externals
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#ifndef __WMC_WMC_H
#define __WMC_WMC_H
#ifndef __WMC_WMCTYPES_H
#include "wmctypes.h"
#endif
#include <time.h> /* For time_t */
#define WMC_MAJOR_VERSION 1
#define WMC_MINOR_VERSION 0
#define WMC_MICRO_VERSION 0
#define WMC_RELEASEDATE "(12-Jun-2000)"
#define WMC_STRINGIZE(a) #a
#define WMC_VERSIONIZE(a,b,c) WMC_STRINGIZE(a) "." WMC_STRINGIZE(b) "." WMC_STRINGIZE(c)
#define WMC_VERSION WMC_VERSIONIZE(WMC_MAJOR_VERSION, WMC_MINOR_VERSION, WMC_MICRO_VERSION)
#define WMC_FULLVERSION WMC_VERSION " " WMC_RELEASEDATE
/*
* 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

103
reactos/tools/wmc/wmc.man Normal file
View file

@ -0,0 +1,103 @@
.TH WMC 1 "June 12, 2000" "Version 1.0.0" "Wine Message Compiler"
.SH NAME
wrc \- Wine Message Compiler
.SH SYNOPSIS
.BI "wmc " "[options] " "[inputfile]"
.SH DESCRIPTION
.B wmc
compiles messages from
.B inputfile
into FormatMessage[AW] compatible format encapsulated in a resourcescript
format.
.B wmc
outputs the data either in a standard \fB.bin\fR formatted binary
file, or can generated inline resource data.
.PP
.B wmc
takes only one \fBinputfile\fR as argument (see \fBBUGS\fR). The
\fBinputfile\fR normally has extension \fB.mc\fR. The messages are read from
standard input if no inputfile is given. If the outputfile is not specified
with \fI-o\fR, then \fBwmc\fR will write the output to \fBinputfile.{rc,h}\fR.
The outputfile is named \fBwmc.tab.{rc,h}\fR if no inputfile was given.
.SH OPTIONS
.TP
.I \-B x
Set output byte-order x={n[ative], l[ittle], b[ig]}. Default is n[ative].
.TP
.I \-c
Set 'custom-bit' in message-code values.
.TP
.I \-d
NON-FUNCTIONAL; Use decimal values in output
.TP
.I \-D
Set debug flag. This results is a parser trace and a lot of extra messages.
.TP
.I \-h
Print an informative usage message.
.TP
.I \-H file
Write headerfile to \fIfile\fR. Default is \fIinputfile.h\fR.
.TP
.I \-i
Inline messagetable(s). This option skips the generation of all \fI.bin\fR files
and writes all output into the \fI.rc\fR file. This encoding is parsable with
wrc(1).
.TP
.I \-o file
Output to \fIfile\fR. Default is \fIinputfile.rc\fR.
.TP
.I \-u
Assume that the inputfile is in unicode.
.TP
.I \-U
Write resource output in unicode formatted messagetable(s).
.TP
.I \-v
Show all supported codepages and languages.
.TP
.I \-V
Print version end exit.
.TP
.I \-W
Enable pedantic warnings.
.SH EXTENSIONS
The original syntax is extended to support codepages more smoothly. Normally,
codepages are based on the DOS\-codepage from the language setting. The
original syntax only allows the destination codepage to be set. However, this
is not enough for non\-DOS systems which do not use unicode source-files.
.PP
A new keyword \fICodepages\fR is introduced to set both input and output
codepages to anything one wants for each language. The syntax is similar to
the other constructs:
.PP
Codepages '=' '(' language '=' cpin ':' cpout ... ')'
.PP
The \fIlanguage\fR is the numerical language\-ID or the alias set with
LanguageNames. The input\-codepage \fIcpin\fR and output\-codepage
\fIcpout\fR are the numerical codepage\-IDs. There can be multiple mapping
within the definition and the definition may occur more than once.
.SH AUTHORS
.B wmc
was written by Bertho A. Stultiens.
.SH BUGS
The message compiler should be able to have multiple inputfiles and combine
them into one outputfile. This would enable the splitting of languages into
separate files.
.PP
Unicode detection of the input is suboptimal, to say the least. It should
recognize byte\-order\-marks (BOM) and decide what to do.
.PP
Decimal output is completely lacking. Don't know whether it should be
implemented because it is a, well, non-informative format change. It is
recognized on the commandline for some form of compatibility.
.SH AVAILABILITY
.B wmc
is part of the wine distribution, which is available through
WineHQ, the
.B wine
development headquarters, at
.I http://www.winehq.com/.
.SH "SEE ALSO"
.BR wine (1),
.BR wrc (1)

View file

@ -0,0 +1,106 @@
/*
* Main definitions and externals
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#ifndef __WMC_WMCTYPES_H
#define __WMC_WMCTYPES_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

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

@ -0,0 +1,631 @@
/*
* Wine Message Compiler output generation
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#include <windows.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 " WMC_FULLVERSION ". 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 = unistrlen(uc);
char *cptr = xmalloc(len+1);
// const union cptable *cpdef = find_codepage(cp);
// if(!cpdef)
// internal_error(__FILE__, __LINE__, "Codepage %d not found (vanished?)", cp);
// if((len = cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, cptr, len+1, NULL, NULL)) < 0)
if((len = WideCharToMultiByte(cp, 0, uc, unistrlen(uc)+1, cptr, len+1, 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", now);
fprintf(fp, "#define __WMCGENERATED_%08lx_H\n", 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++)
{
int n;
if(*uc < 0x100)
{
if(isprint(*uc))
{
*cptr++ = (char)*uc;
b++;
}
else
{
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:
n = sprintf(cptr, "\\x%04x", *uc & 0xffff);
cptr += n;
b += n;
}
}
}
else
{
n = sprintf(cptr, "\\x%04x", *uc & 0xffff);
cptr += n;
b += n;
}
if(i < len-1 && b >= 72)
{
*cptr++ = '"';
*cptr++ = ',';
*cptr++ = '\n';
*cptr++ = ' ';
*cptr++ = 'L';
*cptr++ = '"';
b = 0;
}
}
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 = xmalloc(2*len+1);
char *cc = tmp;
// const union cptable *cpdef = find_codepage(codepage);
// assert(cpdef != NULL);
// if((i = cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0)
if((i = WideCharToMultiByte(codepage, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0)
internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", i);
*cptr++ = ' ';
*cptr++ = '"';
for(i = b = 0; i < len; i++, cc++)
{
int n;
if(isprint(*cc))
{
*cptr++ = *cc;
b++;
}
else
{
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:
n = sprintf(cptr, "\\x%02x", *cc & 0xff);
cptr += n;
b += n;
}
}
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 char *make_bin_string(WCHAR *uc, int len, int *retlen, int codepage)
{
char *str = xmalloc(7 * len + 1);
int i;
int b;
if(!codepage)
{
WCHAR *cptr = (WCHAR*)str;
for(i = b = 0; i < len; i++, uc++)
{
*cptr++ = *uc;
}
len = (len + 1) & ~1;
for(; i < len; i++)
{
*cptr++ = 0;
}
*retlen = len * 2;
}
else
{
char *tmp = xmalloc(2*len+1);
char *cc = tmp;
char *cptr = str;
// const union cptable *cpdef = find_codepage(codepage);
// assert(cpdef != NULL);
// if((i = cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0)
if((i = WideCharToMultiByte(codepage, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0)
internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", i);
for(i = b = 0; i < len; i++, cc++)
{
*cptr++ = *cc;
b++;
}
len = (len + 3) & ~3;
for(; i < len; i++)
{
*cptr++ = 0;
}
free(tmp);
*retlen = len;
}
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;
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)
{
lan_blk_t *lbp;
token_t *ttab;
int ntab;
int i;
int j;
char fname[16];
FILE *fp;
get_tokentable(&ttab, &ntab);
for (lbp = lanblockhead; lbp; lbp = lbp->next)
{
unsigned offs = 4 * (lbp->nblk * 3 + 1);
char *cptr = NULL;
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);
sprintf(fname, "%s.bin", cptr);
free(cptr);
fp = fopen(fname, "wb");
if (!fp)
{
perror(fname);
exit(1);
}
/* NBlocks */
fwrite(&lbp->nblk, sizeof(unsigned long), 1, fp);
for(i = 0; i < lbp->nblk; i++)
{
/* Lo */
fwrite(&lbp->blks[i].idlo, sizeof(unsigned long), 1, fp);
/* Hi */
fwrite(&lbp->blks[i].idhi, sizeof(unsigned long), 1, fp);
/* Offs */
fwrite(&offs, sizeof(unsigned long), 1, fp);
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;
int retlen = 0;
unsigned short length = (unicodeout ? (l*2+3)&~3 : (l+3)&~3)+4;
unsigned short flags = unicodeout ? 1 : 0;
/* Lo */
fwrite(&length, sizeof(unsigned short), 1, fp);
/* Hi */
fwrite(&flags, sizeof(unsigned short), 1, fp);
/* message text */
cptr = make_bin_string(blk->msgs[j]->msg, l, &retlen, unicodeout ? 0 : blk->msgs[j]->cp);
fwrite(cptr, retlen, 1, fp);
free(cptr);
}
}
fclose(fp);
}
}
/* EOF */

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

@ -0,0 +1,14 @@
/*
* Wine Message Compiler output generation
*
* Copyright 2000 Bertho A. Stultiens (BS)
*
*/
#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

1774
reactos/tools/wmc/y_tab.c Normal file

File diff suppressed because it is too large Load diff

30
reactos/tools/wmc/y_tab.h Normal file
View file

@ -0,0 +1,30 @@
typedef union {
WCHAR *str;
unsigned num;
token_t *tok;
lanmsg_t *lmp;
msg_t *msg;
lan_cp_t lcp;
} YYSTYPE;
#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
extern YYSTYPE yylval;