1214571Sdim/* windmc.c -- a program to compile Windows message files. 2214571Sdim Copyright 2007 3214571Sdim Free Software Foundation, Inc. 4214571Sdim Written by Kai Tietz, Onevision. 5214571Sdim 6214571Sdim This file is part of GNU Binutils. 7214571Sdim 8214571Sdim This program is free software; you can redistribute it and/or modify 9214571Sdim it under the terms of the GNU General Public License as published by 10214571Sdim the Free Software Foundation; either version 2 of the License, or 11214571Sdim (at your option) any later version. 12214571Sdim 13214571Sdim This program is distributed in the hope that it will be useful, 14214571Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 15214571Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16214571Sdim GNU General Public License for more details. 17214571Sdim 18214571Sdim You should have received a copy of the GNU General Public License 19214571Sdim along with this program; if not, write to the Free Software 20214571Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 21214571Sdim 02110-1301, USA. */ 22214571Sdim 23214571Sdim/* This program can read and comile Windows message format. 24214571Sdim 25214571Sdim It is based on information taken from the following sources: 26214571Sdim 27214571Sdim * Microsoft documentation. 28214571Sdim 29214571Sdim * The wmc program, written by Bertho A. Stultiens (BS). */ 30214571Sdim 31214571Sdim#include "sysdep.h" 32214571Sdim#include <assert.h> 33214571Sdim#include <time.h> 34214571Sdim#include "bfd.h" 35214571Sdim#include "getopt.h" 36214571Sdim#include "bucomm.h" 37214571Sdim#include "libiberty.h" 38214571Sdim#include "safe-ctype.h" 39214571Sdim#include "obstack.h" 40214571Sdim 41214571Sdim#include "windmc.h" 42214571Sdim#include "windint.h" 43214571Sdim 44214571Sdim/* Defines a message compiler element item with length and offset 45214571Sdim information. */ 46214571Sdimtypedef struct mc_msg_item 47214571Sdim{ 48214571Sdim rc_uint_type res_len; 49214571Sdim rc_uint_type res_off; 50214571Sdim struct bin_messagetable_item *res; 51214571Sdim} mc_msg_item; 52214571Sdim 53214571Sdim/* Defined in bfd/binary.c. Used to set architecture and machine of input 54214571Sdim binary files. */ 55214571Sdimextern enum bfd_architecture bfd_external_binary_architecture; 56214571Sdimextern unsigned long bfd_external_machine; 57214571Sdim 58214571Sdimint target_is_bigendian = 0; 59214571Sdimconst char *def_target_arch; 60214571Sdim 61214571Sdim/* Globals and static variable definitions. */ 62214571Sdim 63214571Sdim/* bfd global helper struct variable. */ 64214571Sdimstatic struct 65214571Sdim{ 66214571Sdim bfd *abfd; 67214571Sdim asection *sec; 68214571Sdim} mc_bfd; 69214571Sdim 70214571Sdim/* Memory list. */ 71214571Sdimmc_node *mc_nodes = NULL; 72214571Sdimstatic mc_node_lang **mc_nodes_lang = NULL; 73214571Sdimstatic int mc_nodes_lang_count = 0; 74214571Sdimstatic mc_keyword **mc_severity_codes = NULL; 75214571Sdimstatic int mc_severity_codes_count = 0; 76214571Sdimstatic mc_keyword **mc_facility_codes = NULL; 77214571Sdimstatic int mc_facility_codes_count = 0; 78214571Sdim 79214571Sdim/* When we are building a resource tree, we allocate everything onto 80214571Sdim an obstack, so that we can free it all at once if we want. */ 81214571Sdim#define obstack_chunk_alloc xmalloc 82214571Sdim#define obstack_chunk_free free 83214571Sdim 84214571Sdim/* The resource building obstack. */ 85214571Sdimstatic struct obstack res_obstack; 86214571Sdim 87214571Sdim/* Flag variables. */ 88214571Sdim/* Set by -C. Set the default code page to be used for input text file. */ 89214571Sdimstatic rc_uint_type mcset_codepage_in = 0; 90214571Sdim 91214571Sdim/* Set by -O. Set the default code page to be used for output text files. */ 92214571Sdimstatic rc_uint_type mcset_codepage_out = 0; 93214571Sdim 94214571Sdim/* Set by -b. .BIN filename should have .mc filename_ included for uniqueness. */ 95214571Sdimstatic int mcset_prefix_bin = 0; 96214571Sdim 97214571Sdim/* The base name of the .mc file. */ 98214571Sdimstatic const char *mcset_mc_basename = "unknown"; 99214571Sdim 100214571Sdim/* Set by -e <ext>. Specify the extension for the header file. */ 101214571Sdimstatic const char *mcset_header_ext = ".h"; 102214571Sdim 103214571Sdim/* Set by -h <path>. Gives the path of where to create the C include file. */ 104214571Sdimstatic const char *mcset_header_dir = "./"; 105214571Sdim 106214571Sdim/* Set by -r <path>. Gives the path of where to create the RC include file 107214571Sdim and the binary message resource files it includes. */ 108214571Sdimstatic const char *mcset_rc_dir = "./"; 109214571Sdim 110214571Sdim/* Modified by -a & -u. By -u input file is unicode, by -a is ASCII (default). */ 111214571Sdimstatic int mcset_text_in_is_unicode = 0; 112214571Sdim 113214571Sdim/* Modified by -A & -U. By -U bin file is unicode (default), by -A is ASCII. */ 114214571Sdimstatic int mcset_bin_out_is_unicode = 1; 115214571Sdim 116214571Sdim/* Set by -c. Sets the Customer bit in all the message ID's. */ 117214571Sdimint mcset_custom_bit = 0; 118214571Sdim 119214571Sdim/* Set by -o. Generate OLE2 header file. Use HRESULT definition instead of 120214571Sdim status code definition. */ 121214571Sdimstatic int mcset_use_hresult = 0; 122214571Sdim 123214571Sdim/* Set by -m <msglen>. Generate a warning if the size of any message exceeds 124214571Sdim maxmsglen characters. */ 125214571Sdimrc_uint_type mcset_max_message_length = 0; 126214571Sdim 127214571Sdim/* Set by -d. Sets message values in header to decimal initially. */ 128214571Sdimint mcset_out_values_are_decimal = 0; 129214571Sdim 130214571Sdim/* Set by -n. terminates all strings with null's in the message tables. */ 131214571Sdimstatic int mcset_automatic_null_termination = 0; 132214571Sdim 133214571Sdim/* The type used for message id output in header. */ 134214571Sdimunichar *mcset_msg_id_typedef = NULL; 135214571Sdim 136214571Sdim/* Set by -x path. Geberated debug C file for mapping ID's to text. */ 137214571Sdimstatic const char *mcset_dbg_dir = NULL; 138214571Sdim 139214571Sdim/* getopt long name definitions. */ 140214571Sdimstatic const struct option long_options[] = 141214571Sdim{ 142214571Sdim {"binprefix", no_argument, 0, 'b'}, 143214571Sdim {"target", required_argument, 0, 'F'}, 144214571Sdim {"extension", required_argument, 0, 'e'}, 145214571Sdim {"headerdir", required_argument, 0, 'h'}, 146214571Sdim {"rcdir", required_argument, 0, 'r'}, 147214571Sdim {"verbose", no_argument, 0, 'v'}, 148214571Sdim {"codepage_in", required_argument, 0, 'C'}, 149214571Sdim {"codepage_out", required_argument, 0, 'O'}, 150214571Sdim {"maxlength", required_argument, 0, 'm'}, 151214571Sdim {"ascii_in", no_argument, 0, 'a'}, 152214571Sdim {"ascii_out", no_argument, 0, 'A'}, 153214571Sdim {"unicode_in", no_argument, 0, 'u'}, 154214571Sdim {"unicode_out", no_argument, 0, 'U'}, 155214571Sdim {"customflag", no_argument, 0, 'c'}, 156214571Sdim {"decimal_values", no_argument, 0, 'd'}, 157214571Sdim {"hresult_use", no_argument, 0, 'o'}, 158214571Sdim {"nullterminate", no_argument, 0, 'n'}, 159214571Sdim {"xdbg", required_argument, 0, 'x'}, 160214571Sdim {"version", no_argument, 0, 'V'}, 161214571Sdim {"help", no_argument, 0, 'H'}, 162214571Sdim {0, no_argument, 0, 0} 163214571Sdim}; 164214571Sdim 165214571Sdim 166214571Sdim/* Initialize the resource building obstack. */ 167214571Sdimstatic void 168214571Sdimres_init (void) 169214571Sdim{ 170214571Sdim obstack_init (&res_obstack); 171214571Sdim} 172214571Sdim 173214571Sdim/* Allocate space on the resource building obstack. */ 174214571Sdimvoid * 175214571Sdimres_alloc (rc_uint_type bytes) 176214571Sdim{ 177214571Sdim return (void *) obstack_alloc (&res_obstack, (size_t) bytes); 178214571Sdim} 179214571Sdim 180214571Sdimstatic FILE * 181214571Sdimmc_create_path_text_file (const char *path, const char *ext) 182214571Sdim{ 183214571Sdim FILE *ret; 184214571Sdim size_t len = 1; 185214571Sdim char *hsz; 186214571Sdim 187214571Sdim len += (path != NULL ? strlen (path) : 0); 188214571Sdim len += strlen (mcset_mc_basename); 189214571Sdim len += (ext != NULL ? strlen (ext) : 0); 190214571Sdim hsz = xmalloc (len); 191214571Sdim sprintf (hsz, "%s%s%s", (path != NULL ? path : ""), mcset_mc_basename, 192214571Sdim (ext != NULL ? ext : "")); 193214571Sdim if ((ret = fopen (hsz, "wb")) == NULL) 194214571Sdim fatal (_("can't create %s file ,%s' for output.\n"), (ext ? ext : "text"), hsz); 195214571Sdim free (hsz); 196214571Sdim return ret; 197214571Sdim} 198214571Sdim 199214571Sdimstatic void 200214571Sdimusage (FILE *stream, int status) 201214571Sdim{ 202214571Sdim fprintf (stream, _("Usage: %s [option(s)] [input-file]\n"), 203214571Sdim program_name); 204214571Sdim fprintf (stream, _(" The options are:\n\ 205214571Sdim -a --ascii_in Read input file as ASCII file\n\ 206214571Sdim -A --ascii_out Write binary messages as ASCII\n\ 207214571Sdim -b --binprefix .bin filename is prefixed by .mc filename_ for uniqueness.\n\ 208214571Sdim -c --customflag Set custom flags for messages\n\ 209214571Sdim -C --codepage_in=<val> Set codepage when reading mc text file\n\ 210214571Sdim -d --decimal_values Print values to text files decimal\n\ 211214571Sdim -e --extension=<extension> Set header extension used on export header file\n\ 212214571Sdim -F --target <target> Specify output target for endianess.\n\ 213214571Sdim -h --headerdir=<directory> Set the export directory for headers\n\ 214214571Sdim -u --unicode_in Read input file as UTF16 file\n\ 215214571Sdim -U --unicode_out Write binary messages as UFT16\n\ 216214571Sdim -m --maxlength=<val> Set the maximal allowed message length\n\ 217214571Sdim -n --nullterminate Automatic add a zero termination to strings\n\ 218214571Sdim -o --hresult_use Use HRESULT definition instead of status code definition\n\ 219214571Sdim -O --codepage_out=<val> Set codepage used for writing text file\n\ 220214571Sdim -r --rcdir=<directory> Set the export directory for rc files\n\ 221214571Sdim -x --xdbg=<directory> Where to create the .dbg C include file\n\ 222214571Sdim that maps message ID's to their symbolic name.\n\ 223214571Sdim")); 224214571Sdim fprintf (stream, _("\ 225214571Sdim -H --help Print this help message\n\ 226214571Sdim -v --verbose Verbose - tells you what it's doing\n\ 227214571Sdim -V --version Print version information\n")); 228214571Sdim 229214571Sdim list_supported_targets (program_name, stream); 230214571Sdim 231214571Sdim if (REPORT_BUGS_TO[0] && status == 0) 232214571Sdim fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); 233214571Sdim 234214571Sdim exit (status); 235214571Sdim} 236214571Sdim 237214571Sdimstatic void 238214571Sdimset_endianess (bfd *abfd, const char *target) 239214571Sdim{ 240214571Sdim const bfd_target *target_vec; 241214571Sdim 242214571Sdim def_target_arch = NULL; 243214571Sdim target_vec = bfd_find_target (target, abfd); 244214571Sdim if (! target_vec) 245214571Sdim fatal ("Can't detect target endianess and architecture."); 246214571Sdim target_is_bigendian = ((target_vec->byteorder == BFD_ENDIAN_BIG) ? 1 : 0); 247214571Sdim { 248214571Sdim const char *tname = target_vec->name; 249214571Sdim const char **arch = bfd_arch_list (); 250214571Sdim 251214571Sdim if (arch && tname) 252214571Sdim { 253214571Sdim if (strchr (tname, '-') != NULL) 254214571Sdim tname = strchr (tname, '-') + 1; 255214571Sdim while (*arch != NULL) 256214571Sdim { 257214571Sdim const char *in_a = strstr (*arch, tname); 258214571Sdim char end_ch = (in_a ? in_a[strlen (tname)] : 0); 259214571Sdim if (in_a && (in_a == *arch || in_a[-1] == ':') 260214571Sdim && end_ch == 0) 261214571Sdim { 262214571Sdim def_target_arch = *arch; 263214571Sdim break; 264214571Sdim } 265214571Sdim arch++; 266214571Sdim } 267214571Sdim } 268214571Sdim if (! def_target_arch) 269214571Sdim fatal ("Can't detect architecture."); 270214571Sdim } 271214571Sdim} 272214571Sdim 273214571Sdimstatic int 274214571Sdimprobe_codepage (rc_uint_type *cp, int *is_uni, const char *pswitch, int defmode) 275214571Sdim{ 276214571Sdim if (*is_uni == -1) 277214571Sdim { 278214571Sdim if (*cp != CP_UTF16) 279214571Sdim *is_uni = defmode; 280214571Sdim else 281214571Sdim *is_uni = 1; 282214571Sdim } 283214571Sdim if (*is_uni) 284214571Sdim { 285214571Sdim if (*cp != 0 && *cp != CP_UTF16) 286214571Sdim { 287214571Sdim fprintf (stderr, _("%s: warning: "), program_name); 288214571Sdim fprintf (stderr, _("A codepage was specified switch ,%s' and UTF16.\n"), pswitch); 289214571Sdim fprintf (stderr, _("\tcodepage settings are ignored.\n")); 290214571Sdim } 291214571Sdim *cp = CP_UTF16; 292214571Sdim return 1; 293214571Sdim } 294214571Sdim if (*cp == CP_UTF16) 295214571Sdim { 296214571Sdim *is_uni = 1; 297214571Sdim return 1; 298214571Sdim } 299214571Sdim if (*cp == 0) 300214571Sdim *cp = 1252; 301214571Sdim if (! unicode_is_valid_codepage (*cp)) 302214571Sdim fatal ("Code page 0x%x is unknown.", (unsigned int) *cp); 303214571Sdim *is_uni = 0; 304214571Sdim return 1; 305214571Sdim} 306214571Sdim 307214571Sdimmc_node * 308214571Sdimmc_add_node (void) 309214571Sdim{ 310214571Sdim mc_node *ret; 311214571Sdim 312214571Sdim ret = res_alloc (sizeof (mc_node)); 313214571Sdim memset (ret, 0, sizeof (mc_node)); 314214571Sdim if (! mc_nodes) 315214571Sdim mc_nodes = ret; 316214571Sdim else 317214571Sdim { 318214571Sdim mc_node *h = mc_nodes; 319214571Sdim 320214571Sdim while (h->next != NULL) 321214571Sdim h = h->next; 322214571Sdim h->next = ret; 323214571Sdim } 324214571Sdim return ret; 325214571Sdim} 326214571Sdim 327214571Sdimmc_node_lang * 328214571Sdimmc_add_node_lang (mc_node *root, const mc_keyword *lang, rc_uint_type vid) 329214571Sdim{ 330214571Sdim mc_node_lang *ret, *h, *p; 331214571Sdim 332214571Sdim if (! lang || ! root) 333214571Sdim fatal (_("try to add a ill language.")); 334214571Sdim ret = res_alloc (sizeof (mc_node_lang)); 335214571Sdim memset (ret, 0, sizeof (mc_node_lang)); 336214571Sdim ret->lang = lang; 337214571Sdim ret->vid = vid; 338214571Sdim if ((h = root->sub) == NULL) 339214571Sdim root->sub = ret; 340214571Sdim else 341214571Sdim { 342214571Sdim p = NULL; 343214571Sdim while (h != NULL) 344214571Sdim { 345214571Sdim if (h->lang->nval > lang->nval) 346214571Sdim break; 347214571Sdim if (h->lang->nval == lang->nval) 348214571Sdim { 349214571Sdim if (h->vid > vid) 350214571Sdim break; 351214571Sdim if (h->vid == vid) 352214571Sdim fatal ("double defined message id %ld.\n", (long) vid); 353214571Sdim } 354214571Sdim h = (p = h)->next; 355214571Sdim } 356214571Sdim ret->next = h; 357214571Sdim if (! p) 358214571Sdim root->sub = ret; 359214571Sdim else 360214571Sdim p->next = ret; 361214571Sdim } 362214571Sdim return ret; 363214571Sdim} 364214571Sdim 365214571Sdimstatic char * 366214571Sdimconvert_unicode_to_ACP (const unichar *usz) 367214571Sdim{ 368214571Sdim char *s; 369214571Sdim rc_uint_type l; 370214571Sdim 371214571Sdim if (! usz) 372214571Sdim return NULL; 373214571Sdim codepage_from_unicode (&l, usz, &s, mcset_codepage_out); 374214571Sdim if (! s) 375214571Sdim fatal ("unicode string not mappable to ASCII codepage 0x%lx.\n", (long) mcset_codepage_out); 376214571Sdim return s; 377214571Sdim} 378214571Sdim 379214571Sdimstatic void 380214571Sdimwrite_dbg_define (FILE *fp, const unichar *sym_name, const unichar *typecast) 381214571Sdim{ 382214571Sdim char *sym; 383214571Sdim 384214571Sdim if (!sym_name || sym_name[0] == 0) 385214571Sdim return; 386214571Sdim sym = convert_unicode_to_ACP (sym_name); 387214571Sdim fprintf (fp, " {("); 388214571Sdim if (typecast) 389214571Sdim unicode_print (fp, typecast, unichar_len (typecast)); 390214571Sdim else 391214571Sdim fprintf (fp, "DWORD"); 392214571Sdim fprintf (fp, ") %s, \"%s\" },\n", sym, sym); 393214571Sdim} 394214571Sdim 395214571Sdimstatic void 396214571Sdimwrite_header_define (FILE *fp, const unichar *sym_name, rc_uint_type vid, const unichar *typecast, mc_node_lang *nl) 397214571Sdim{ 398214571Sdim char *sym; 399214571Sdim char *tdef = NULL; 400214571Sdim 401214571Sdim if (!sym_name || sym_name[0] == 0) 402214571Sdim { 403214571Sdim if (nl != NULL) 404214571Sdim { 405214571Sdim if (mcset_out_values_are_decimal) 406214571Sdim fprintf (fp, "//\n// MessageId: 0x%lu\n//\n", (unsigned long) vid); 407214571Sdim else 408214571Sdim fprintf (fp, "//\n// MessageId: 0x%lx\n//\n", (unsigned long) vid); 409214571Sdim } 410214571Sdim return; 411214571Sdim } 412214571Sdim sym = convert_unicode_to_ACP (sym_name); 413214571Sdim if (typecast && typecast[0] != 0) 414214571Sdim tdef = convert_unicode_to_ACP (typecast); 415214571Sdim fprintf (fp, "//\n// MessageId: %s\n//\n", sym); 416214571Sdim if (! mcset_out_values_are_decimal) 417214571Sdim fprintf (fp, "#define %s %s%s%s 0x%lx\n\n", sym, 418214571Sdim (tdef ? "(" : ""), (tdef ? tdef : ""), (tdef ? ")" : ""), 419214571Sdim (unsigned long) vid); 420214571Sdim else 421214571Sdim fprintf (fp, "#define %s %s%s%s 0x%lu\n\n", sym, 422214571Sdim (tdef ? "(" : ""), (tdef ? tdef : ""), (tdef ? ")" : ""), 423214571Sdim (unsigned long) vid); 424214571Sdim} 425214571Sdim 426214571Sdimstatic int 427214571Sdimsort_mc_node_lang (const void *l, const void *r) 428214571Sdim{ 429214571Sdim const mc_node_lang *l1 = *((const mc_node_lang **)l); 430214571Sdim const mc_node_lang *r1 = *((const mc_node_lang **)r); 431214571Sdim 432214571Sdim if (l == r) 433214571Sdim return 0; 434214571Sdim if (l1->lang != r1->lang) 435214571Sdim { 436214571Sdim if (l1->lang->nval < r1->lang->nval) 437214571Sdim return -1; 438214571Sdim return 1; 439214571Sdim } 440214571Sdim if (l1->vid == r1->vid) 441214571Sdim return 0; 442214571Sdim if (l1->vid < r1->vid) 443214571Sdim return -1; 444214571Sdim return 1; 445214571Sdim} 446214571Sdim 447214571Sdimstatic int 448214571Sdimsort_keyword_by_nval (const void *l, const void *r) 449214571Sdim{ 450214571Sdim const mc_keyword *l1 = *((const mc_keyword **)l); 451214571Sdim const mc_keyword *r1 = *((const mc_keyword **)r); 452214571Sdim rc_uint_type len1, len2; 453214571Sdim int e; 454214571Sdim 455214571Sdim if (l == r) 456214571Sdim return 0; 457214571Sdim if (l1->nval != r1->nval) 458214571Sdim { 459214571Sdim if (l1->nval < r1->nval) 460214571Sdim return -1; 461214571Sdim return 1; 462214571Sdim } 463214571Sdim len1 = unichar_len (l1->usz); 464214571Sdim len2 = unichar_len (r1->usz); 465214571Sdim if (len1 <= len2) 466214571Sdim e = memcmp (l1->usz, r1->usz, sizeof (unichar) * len1); 467214571Sdim else 468214571Sdim e = memcmp (l1->usz, r1->usz, sizeof (unichar) * len2); 469214571Sdim if (e) 470214571Sdim return e; 471214571Sdim if (len1 < len2) 472214571Sdim return -1; 473214571Sdim else if (len1 > len2) 474214571Sdim return 1; 475214571Sdim return 0; 476214571Sdim} 477214571Sdim 478214571Sdimstatic void 479214571Sdimdo_sorts (void) 480214571Sdim{ 481214571Sdim mc_node *h; 482214571Sdim mc_node_lang *n; 483214571Sdim const mc_keyword *k; 484214571Sdim int i; 485214571Sdim 486214571Sdim /* Sort message by their language and id ascending. */ 487214571Sdim mc_nodes_lang_count = 0; 488214571Sdim 489214571Sdim h = mc_nodes; 490214571Sdim while (h != NULL) 491214571Sdim { 492214571Sdim n = h->sub; 493214571Sdim while (n != NULL) 494214571Sdim { 495214571Sdim mc_nodes_lang_count +=1; 496214571Sdim n = n->next; 497214571Sdim } 498214571Sdim h = h->next; 499214571Sdim } 500214571Sdim 501214571Sdim if (mc_nodes_lang_count != 0) 502214571Sdim { 503214571Sdim h = mc_nodes; 504214571Sdim i = 0; 505214571Sdim mc_nodes_lang = xmalloc (sizeof (mc_node_lang *) * mc_nodes_lang_count); 506214571Sdim 507214571Sdim while (h != NULL) 508214571Sdim { 509214571Sdim n = h->sub; 510214571Sdim while (n != NULL) 511214571Sdim { 512214571Sdim mc_nodes_lang[i++] = n; 513214571Sdim n = n->next; 514214571Sdim } 515214571Sdim h = h->next; 516214571Sdim } 517214571Sdim qsort (mc_nodes_lang, (size_t) mc_nodes_lang_count, sizeof (mc_node_lang *), sort_mc_node_lang); 518214571Sdim } 519214571Sdim /* Sort facility code definitions by there id ascending. */ 520214571Sdim i = 0; 521214571Sdim while ((k = enum_facility (i)) != NULL) 522214571Sdim ++i; 523214571Sdim mc_facility_codes_count = i; 524214571Sdim if (i != 0) 525214571Sdim { 526214571Sdim mc_facility_codes = xmalloc (sizeof (mc_keyword *) * i); 527214571Sdim i = 0; 528214571Sdim while ((k = enum_facility (i)) != NULL) 529214571Sdim mc_facility_codes[i++] = (mc_keyword *) k; 530214571Sdim qsort (mc_facility_codes, (size_t) mc_facility_codes_count, sizeof (mc_keyword *), sort_keyword_by_nval); 531214571Sdim } 532214571Sdim 533214571Sdim /* Sort severity code definitions by there id ascending. */ 534214571Sdim i = 0; 535214571Sdim while ((k = enum_severity (i)) != NULL) 536214571Sdim ++i; 537214571Sdim mc_severity_codes_count = i; 538214571Sdim if (i != 0) 539214571Sdim { 540214571Sdim mc_severity_codes = xmalloc (sizeof (mc_keyword *) * i); 541214571Sdim i = 0; 542214571Sdim while ((k = enum_severity (i)) != NULL) 543214571Sdim mc_severity_codes[i++] = (mc_keyword *) k; 544214571Sdim qsort (mc_severity_codes, (size_t) mc_severity_codes_count, sizeof (mc_keyword *), sort_keyword_by_nval); 545214571Sdim } 546214571Sdim} 547214571Sdim 548214571Sdimstatic int 549214571Sdimmc_get_block_count (mc_node_lang **nl, int elems) 550214571Sdim{ 551214571Sdim rc_uint_type exid; 552214571Sdim int i, ret; 553214571Sdim 554214571Sdim if (! nl) 555214571Sdim return 0; 556214571Sdim i = 0; 557214571Sdim ret = 0; 558214571Sdim while (i < elems) 559214571Sdim { 560214571Sdim ret++; 561214571Sdim exid = nl[i++]->vid; 562214571Sdim while (i < elems && nl[i]->vid == exid + 1) 563214571Sdim exid = nl[i++]->vid; 564214571Sdim } 565214571Sdim return ret; 566214571Sdim} 567214571Sdim 568214571Sdimstatic bfd * 569214571Sdimwindmc_open_as_binary (const char *filename) 570214571Sdim{ 571214571Sdim bfd *abfd; 572214571Sdim 573214571Sdim abfd = bfd_openw (filename, "binary"); 574214571Sdim if (! abfd) 575214571Sdim fatal ("can't open `%s' for output", filename); 576214571Sdim 577214571Sdim return abfd; 578214571Sdim} 579214571Sdim 580214571Sdimstatic void 581214571Sdimtarget_put_16 (void *p, rc_uint_type value) 582214571Sdim{ 583214571Sdim assert (!! p); 584214571Sdim 585214571Sdim if (target_is_bigendian) 586214571Sdim bfd_putb16 (value, p); 587214571Sdim else 588214571Sdim bfd_putl16 (value, p); 589214571Sdim} 590214571Sdim 591214571Sdimstatic void 592214571Sdimtarget_put_32 (void *p, rc_uint_type value) 593214571Sdim{ 594214571Sdim assert (!! p); 595214571Sdim 596214571Sdim if (target_is_bigendian) 597214571Sdim bfd_putb32 (value, p); 598214571Sdim else 599214571Sdim bfd_putl32 (value, p); 600214571Sdim} 601214571Sdim 602214571Sdimstatic struct bin_messagetable_item * 603214571Sdimmc_generate_bin_item (mc_node_lang *n, rc_uint_type *res_len) 604214571Sdim{ 605214571Sdim struct bin_messagetable_item *ret = NULL; 606214571Sdim rc_uint_type len; 607214571Sdim 608214571Sdim *res_len = 0; 609214571Sdim if (mcset_bin_out_is_unicode == 1) 610214571Sdim { 611214571Sdim unichar *ht = n->message; 612214571Sdim rc_uint_type txt_len; 613214571Sdim 614214571Sdim txt_len = unichar_len (n->message); 615214571Sdim if (mcset_automatic_null_termination && txt_len != 0) 616214571Sdim { 617214571Sdim while (txt_len > 0 && ht[txt_len - 1] > 0 && ht[txt_len - 1] < 0x20) 618214571Sdim ht[--txt_len] = 0; 619214571Sdim } 620214571Sdim txt_len *= sizeof (unichar); 621214571Sdim len = BIN_MESSAGETABLE_ITEM_SIZE + txt_len + sizeof (unichar); 622214571Sdim ret = res_alloc ((len + 3) & ~3); 623214571Sdim memset (ret, 0, (len + 3) & ~3); 624214571Sdim target_put_16 (ret->length, (len + 3) & ~3); 625214571Sdim target_put_16 (ret->flags, MESSAGE_RESOURCE_UNICODE); 626214571Sdim txt_len = 0; 627214571Sdim while (*ht != 0) 628214571Sdim { 629214571Sdim target_put_16 (ret->data + txt_len, *ht++); 630214571Sdim txt_len += 2; 631214571Sdim } 632214571Sdim } 633214571Sdim else 634214571Sdim { 635214571Sdim rc_uint_type txt_len, l; 636214571Sdim char *cvt_txt; 637214571Sdim 638214571Sdim codepage_from_unicode( &l, n->message, &cvt_txt, n->lang->lang_info.wincp); 639214571Sdim if (! cvt_txt) 640214571Sdim fatal ("Failed to convert message to language codepage.\n"); 641214571Sdim txt_len = strlen (cvt_txt); 642214571Sdim if (mcset_automatic_null_termination && txt_len > 0) 643214571Sdim { 644214571Sdim while (txt_len > 0 && cvt_txt[txt_len - 1] > 0 && cvt_txt[txt_len - 1] < 0x20) 645214571Sdim cvt_txt[--txt_len] = 0; 646214571Sdim } 647214571Sdim len = BIN_MESSAGETABLE_ITEM_SIZE + txt_len + 1; 648214571Sdim ret = res_alloc ((len + 3) & ~3); 649214571Sdim memset (ret, 0, (len + 3) & ~3); 650214571Sdim target_put_16 (ret->length, (len + 3) & ~3); 651214571Sdim target_put_16 (ret->flags, 0); 652214571Sdim strcpy ((char *) ret->data, cvt_txt); 653214571Sdim } 654214571Sdim *res_len = (len + 3) & ~3; 655214571Sdim return ret; 656214571Sdim} 657214571Sdim 658214571Sdimstatic void 659214571Sdimmc_write_blocks (struct bin_messagetable *mtbl, mc_node_lang **nl, mc_msg_item *ml, int elems) 660214571Sdim{ 661214571Sdim int i, idx = 0; 662214571Sdim rc_uint_type exid; 663214571Sdim 664214571Sdim if (! nl) 665214571Sdim return; 666214571Sdim i = 0; 667214571Sdim while (i < elems) 668214571Sdim { 669214571Sdim target_put_32 (mtbl->items[idx].lowid, nl[i]->vid); 670214571Sdim target_put_32 (mtbl->items[idx].highid, nl[i]->vid); 671214571Sdim target_put_32 (mtbl->items[idx].offset, ml[i].res_off); 672214571Sdim exid = nl[i++]->vid; 673214571Sdim while (i < elems && nl[i]->vid == exid + 1) 674214571Sdim { 675214571Sdim target_put_32 (mtbl->items[idx].highid, nl[i]->vid); 676214571Sdim exid = nl[i++]->vid; 677214571Sdim } 678214571Sdim ++idx; 679214571Sdim } 680214571Sdim} 681214571Sdim 682214571Sdimstatic void 683214571Sdimset_windmc_bfd_content (const void *data, rc_uint_type off, rc_uint_type length) 684214571Sdim{ 685214571Sdim if (! bfd_set_section_contents (mc_bfd.abfd, mc_bfd.sec, data, off, length)) 686214571Sdim bfd_fatal ("bfd_set_section_contents"); 687214571Sdim} 688214571Sdim 689214571Sdimstatic void 690214571Sdimwindmc_write_bin (const char *filename, mc_node_lang **nl, int elems) 691214571Sdim{ 692214571Sdim unsigned long sec_length = 1; 693214571Sdim int block_count, i; 694214571Sdim mc_msg_item *mi; 695214571Sdim struct bin_messagetable *mtbl; 696214571Sdim rc_uint_type dta_off, dta_start; 697214571Sdim 698214571Sdim if (elems <= 0) 699214571Sdim return; 700214571Sdim mc_bfd.abfd = windmc_open_as_binary (filename); 701214571Sdim mc_bfd.sec = bfd_make_section (mc_bfd.abfd, ".data"); 702214571Sdim if (mc_bfd.sec == NULL) 703214571Sdim bfd_fatal ("bfd_make_section"); 704214571Sdim if (! bfd_set_section_flags (mc_bfd.abfd, mc_bfd.sec, 705214571Sdim (SEC_HAS_CONTENTS | SEC_ALLOC 706214571Sdim | SEC_LOAD | SEC_DATA))) 707214571Sdim bfd_fatal ("bfd_set_section_flags"); 708214571Sdim /* Requiring this is probably a bug in BFD. */ 709214571Sdim mc_bfd.sec->output_section = mc_bfd.sec; 710214571Sdim 711214571Sdim block_count = mc_get_block_count (nl, elems); 712214571Sdim 713214571Sdim dta_off = (rc_uint_type) ((BIN_MESSAGETABLE_BLOCK_SIZE * block_count) + BIN_MESSAGETABLE_SIZE - 4); 714214571Sdim dta_start = dta_off = (dta_off + 3) & ~3; 715214571Sdim mi = xmalloc (sizeof (mc_msg_item) * elems); 716214571Sdim mtbl = xmalloc (dta_start); 717214571Sdim 718214571Sdim /* Clear header region. */ 719214571Sdim memset (mtbl, 0, dta_start); 720214571Sdim target_put_32 (mtbl->cblocks, block_count); 721214571Sdim /* Prepare items section for output. */ 722214571Sdim for (i = 0; i < elems; i++) 723214571Sdim { 724214571Sdim mi[i].res_off = dta_off; 725214571Sdim mi[i].res = mc_generate_bin_item (nl[i], &mi[i].res_len); 726214571Sdim dta_off += mi[i].res_len; 727214571Sdim } 728214571Sdim sec_length = (dta_off + 3) & ~3; 729214571Sdim if (! bfd_set_section_size (mc_bfd.abfd, mc_bfd.sec, sec_length)) 730214571Sdim bfd_fatal ("bfd_set_section_size"); 731214571Sdim /* Make sure we write the complete block. */ 732214571Sdim set_windmc_bfd_content ("\0", sec_length - 1, 1); 733214571Sdim 734214571Sdim /* Write block information. */ 735214571Sdim mc_write_blocks (mtbl, nl, mi, elems); 736214571Sdim 737214571Sdim set_windmc_bfd_content (mtbl, 0, dta_start); 738214571Sdim 739214571Sdim /* Write items. */ 740214571Sdim for (i = 0; i < elems; i++) 741214571Sdim set_windmc_bfd_content (mi[i].res, mi[i].res_off, mi[i].res_len); 742214571Sdim 743214571Sdim free (mtbl); 744214571Sdim free (mi); 745214571Sdim bfd_close (mc_bfd.abfd); 746214571Sdim mc_bfd.abfd = NULL; 747214571Sdim mc_bfd.sec = NULL; 748214571Sdim} 749214571Sdim 750214571Sdimstatic void 751214571Sdimwrite_bin (void) 752214571Sdim{ 753214571Sdim mc_node_lang *n = NULL; 754214571Sdim int i, c; 755214571Sdim 756214571Sdim if (! mc_nodes_lang_count) 757214571Sdim return; 758214571Sdim 759214571Sdim i = 0; 760214571Sdim while (i < mc_nodes_lang_count) 761214571Sdim { 762214571Sdim char *nd; 763214571Sdim char *filename; 764214571Sdim 765214571Sdim if (n && n->lang == mc_nodes_lang[i]->lang) 766214571Sdim { 767214571Sdim i++; 768214571Sdim continue; 769214571Sdim } 770214571Sdim n = mc_nodes_lang[i]; 771214571Sdim c = i + 1; 772214571Sdim while (c < mc_nodes_lang_count && n->lang == mc_nodes_lang[c]->lang) 773214571Sdim c++; 774214571Sdim nd = convert_unicode_to_ACP (n->lang->sval); 775214571Sdim 776214571Sdim /* Prepare filename for binary output. */ 777214571Sdim filename = xmalloc (strlen (nd) + 4 + 1 + strlen (mcset_mc_basename) + 1 + strlen (mcset_rc_dir)); 778214571Sdim strcpy (filename, mcset_rc_dir); 779214571Sdim if (mcset_prefix_bin) 780214571Sdim sprintf (filename + strlen (filename), "%s_", mcset_mc_basename); 781214571Sdim strcat (filename, nd); 782214571Sdim strcat (filename, ".bin"); 783214571Sdim 784214571Sdim /* Write message file. */ 785214571Sdim windmc_write_bin (filename, &mc_nodes_lang[i], (c - i)); 786214571Sdim 787214571Sdim free (filename); 788214571Sdim i = c; 789214571Sdim } 790214571Sdim} 791214571Sdim 792214571Sdimstatic void 793214571Sdimwrite_rc (FILE *fp) 794214571Sdim{ 795214571Sdim mc_node_lang *n; 796214571Sdim int i, l; 797214571Sdim 798214571Sdim fprintf (fp, 799214571Sdim "/* Do not edit this file manually.\n" 800214571Sdim " This file is autogenerated by windmc. */\n\n"); 801214571Sdim if (! mc_nodes_lang_count) 802214571Sdim return; 803214571Sdim n = NULL; 804214571Sdim i = 0; 805214571Sdim for (l = 0; l < mc_nodes_lang_count; l++) 806214571Sdim { 807214571Sdim if (n && n->lang == mc_nodes_lang[l]->lang) 808214571Sdim continue; 809214571Sdim ++i; 810214571Sdim n = mc_nodes_lang[l]; 811214571Sdim fprintf (fp, "\n// Country: %s\n// Language: %s\n#pragma code_page(%u)\n", 812214571Sdim n->lang->lang_info.country, n->lang->lang_info.name, 813214571Sdim (unsigned) n->lang->lang_info.wincp); 814214571Sdim fprintf (fp, "LANGUAGE 0x%lx, 0x%lx\n", (long) (n->lang->nval & 0x3ff), 815214571Sdim (long) ((n->lang->nval & 0xffff) >> 10)); 816214571Sdim fprintf (fp, "1 MESSAGETABLE \""); 817214571Sdim if (mcset_prefix_bin) 818214571Sdim fprintf (fp, "%s_", mcset_mc_basename); 819214571Sdim unicode_print (fp, n->lang->sval, unichar_len (n->lang->sval)); 820214571Sdim fprintf (fp, ".bin\"\n"); 821214571Sdim } 822214571Sdim} 823214571Sdim 824214571Sdimstatic void 825214571Sdimwrite_dbg (FILE *fp) 826214571Sdim{ 827214571Sdim mc_node *h; 828214571Sdim 829214571Sdim fprintf (fp, 830214571Sdim "/* Do not edit this file manually.\n" 831214571Sdim " This file is autogenerated by windmc.\n\n" 832214571Sdim " This file maps each message ID value in to a text string that contains\n" 833214571Sdim " the symbolic name used for it. */\n\n"); 834214571Sdim 835214571Sdim fprintf (fp, 836214571Sdim "struct %sSymbolicName\n" 837214571Sdim "{\n ", mcset_mc_basename); 838214571Sdim if (mcset_msg_id_typedef) 839214571Sdim unicode_print (fp, mcset_msg_id_typedef, unichar_len (mcset_msg_id_typedef)); 840214571Sdim else 841214571Sdim fprintf (fp, "DWORD"); 842214571Sdim fprintf (fp, 843214571Sdim " MessageId;\n" 844214571Sdim " char *SymbolicName;\n" 845214571Sdim "} %sSymbolicNames[] =\n" 846214571Sdim "{\n", mcset_mc_basename); 847214571Sdim h = mc_nodes; 848214571Sdim while (h != NULL) 849214571Sdim { 850214571Sdim if (h->symbol) 851214571Sdim write_dbg_define (fp, h->symbol, mcset_msg_id_typedef); 852214571Sdim h = h->next; 853214571Sdim } 854214571Sdim fprintf (fp, " { ("); 855214571Sdim if (mcset_msg_id_typedef) 856214571Sdim unicode_print (fp, mcset_msg_id_typedef, unichar_len (mcset_msg_id_typedef)); 857214571Sdim else 858214571Sdim fprintf (fp, "DWORD"); 859214571Sdim fprintf (fp, 860214571Sdim ") 0xffffffff, NULL }\n" 861214571Sdim "};\n"); 862214571Sdim} 863214571Sdim 864214571Sdimstatic void 865214571Sdimwrite_header (FILE *fp) 866214571Sdim{ 867214571Sdim char *s; 868214571Sdim int i; 869214571Sdim const mc_keyword *key; 870214571Sdim mc_node *h; 871214571Sdim 872214571Sdim fprintf (fp, 873214571Sdim "/* Do not edit this file manually.\n" 874214571Sdim " This file is autogenerated by windmc. */\n\n" 875214571Sdim "//\n// The values are 32 bit layed out as follows:\n//\n" 876214571Sdim "// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\n" 877214571Sdim "// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\n" 878214571Sdim "// +---+-+-+-----------------------+-------------------------------+\n" 879214571Sdim "// |Sev|C|R| Facility | Code |\n" 880214571Sdim "// +---+-+-+-----------------------+-------------------------------+\n//\n" 881214571Sdim "// where\n//\n" 882214571Sdim "// C - is the Customer code flag\n//\n" 883214571Sdim "// R - is a reserved bit\n//\n" 884214571Sdim "// Code - is the facility's status code\n//\n"); 885214571Sdim 886214571Sdim h = mc_nodes; 887214571Sdim 888214571Sdim fprintf (fp, "// Sev - is the severity code\n//\n"); 889214571Sdim if (mc_severity_codes_count != 0) 890214571Sdim { 891214571Sdim for (i = 0; i < mc_severity_codes_count; i++) 892214571Sdim { 893214571Sdim key = mc_severity_codes[i]; 894214571Sdim fprintf (fp, "// %s - %02lx\n", convert_unicode_to_ACP (key->usz), 895214571Sdim (unsigned long) key->nval); 896214571Sdim if (key->sval && key->sval[0] != 0) 897214571Sdim { 898214571Sdim if (! mcset_out_values_are_decimal) 899214571Sdim fprintf (fp, "#define %s 0x%lx\n", convert_unicode_to_ACP (key->sval), 900214571Sdim (unsigned long) key->nval); 901214571Sdim else 902214571Sdim fprintf (fp, "#define %s 0x%lu\n", convert_unicode_to_ACP (key->sval), 903214571Sdim (unsigned long) key->nval); 904214571Sdim } 905214571Sdim } 906214571Sdim fprintf (fp, "//\n"); 907214571Sdim } 908214571Sdim fprintf (fp, "// Facility - is the facility code\n//\n"); 909214571Sdim if (mc_facility_codes_count != 0) 910214571Sdim { 911214571Sdim for (i = 0; i < mc_facility_codes_count; i++) 912214571Sdim { 913214571Sdim key = mc_facility_codes[i]; 914214571Sdim fprintf (fp, "// %s - %04lx\n", convert_unicode_to_ACP (key->usz), 915214571Sdim (unsigned long) key->nval); 916214571Sdim if (key->sval && key->sval[0] != 0) 917214571Sdim { 918214571Sdim if (! mcset_out_values_are_decimal) 919214571Sdim fprintf (fp, "#define %s 0x%lx\n", convert_unicode_to_ACP (key->sval), 920214571Sdim (unsigned long) key->nval); 921214571Sdim else 922214571Sdim fprintf (fp, "#define %s 0x%lu\n", convert_unicode_to_ACP (key->sval), 923214571Sdim (unsigned long) key->nval); 924214571Sdim } 925214571Sdim } 926214571Sdim fprintf (fp, "//\n"); 927214571Sdim } 928214571Sdim fprintf (fp, "\n"); 929214571Sdim while (h != NULL) 930214571Sdim { 931214571Sdim if (h->user_text) 932214571Sdim { 933214571Sdim s = convert_unicode_to_ACP (h->user_text); 934214571Sdim if (s) 935214571Sdim fprintf (fp, "%s", s); 936214571Sdim } 937214571Sdim if (h->symbol) 938214571Sdim write_header_define (fp, h->symbol, h->vid, mcset_msg_id_typedef, h->sub); 939214571Sdim h = h->next; 940214571Sdim } 941214571Sdim} 942214571Sdim 943214571Sdimstatic const char * 944214571Sdimmc_unify_path (const char *path) 945214571Sdim{ 946214571Sdim char *end; 947214571Sdim char *hsz; 948214571Sdim 949214571Sdim if (! path || *path == 0) 950214571Sdim return "./"; 951214571Sdim hsz = xmalloc (strlen (path) + 2); 952214571Sdim strcpy (hsz, path); 953214571Sdim end = hsz + strlen (hsz); 954214571Sdim if (hsz[-1] != '/' && hsz[-1] != '\\') 955214571Sdim strcpy (end, "/"); 956214571Sdim while ((end = strchr (hsz, '\\')) != NULL) 957214571Sdim *end = '/'; 958214571Sdim return hsz; 959214571Sdim} 960214571Sdim 961214571Sdimint main (int, char **); 962214571Sdim 963214571Sdimint 964214571Sdimmain (int argc, char **argv) 965214571Sdim{ 966214571Sdim FILE *h_fp; 967214571Sdim int c; 968214571Sdim char *target, *input_filename; 969214571Sdim int verbose; 970214571Sdim 971214571Sdim#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 972214571Sdim setlocale (LC_MESSAGES, ""); 973214571Sdim#endif 974214571Sdim#if defined (HAVE_SETLOCALE) 975214571Sdim setlocale (LC_CTYPE, ""); 976214571Sdim#endif 977214571Sdim bindtextdomain (PACKAGE, LOCALEDIR); 978214571Sdim textdomain (PACKAGE); 979214571Sdim 980214571Sdim program_name = argv[0]; 981214571Sdim xmalloc_set_program_name (program_name); 982214571Sdim 983214571Sdim expandargv (&argc, &argv); 984214571Sdim 985214571Sdim bfd_init (); 986214571Sdim set_default_bfd_target (); 987214571Sdim 988214571Sdim target = NULL; 989214571Sdim verbose = 0; 990214571Sdim input_filename = NULL; 991214571Sdim 992214571Sdim res_init (); 993214571Sdim 994214571Sdim while ((c = getopt_long (argc, argv, "C:F:O:h:e:m:r:x:aAbcdHunoUvV", long_options, 995214571Sdim (int *) 0)) != EOF) 996214571Sdim { 997214571Sdim switch (c) 998214571Sdim { 999214571Sdim case 'b': 1000214571Sdim mcset_prefix_bin = 1; 1001214571Sdim break; 1002214571Sdim case 'e': 1003214571Sdim { 1004214571Sdim mcset_header_ext = optarg; 1005214571Sdim if (mcset_header_ext[0] != '.' && mcset_header_ext[0] != 0) 1006214571Sdim { 1007214571Sdim char *hsz = xmalloc (strlen (mcset_header_ext) + 2); 1008214571Sdim 1009214571Sdim sprintf (hsz, ".%s", mcset_header_ext); 1010214571Sdim mcset_header_ext = hsz; 1011214571Sdim } 1012214571Sdim } 1013214571Sdim break; 1014214571Sdim case 'h': 1015214571Sdim mcset_header_dir = mc_unify_path (optarg); 1016214571Sdim break; 1017214571Sdim case 'r': 1018214571Sdim mcset_rc_dir = mc_unify_path (optarg); 1019214571Sdim break; 1020214571Sdim case 'a': 1021214571Sdim mcset_text_in_is_unicode = 0; 1022214571Sdim break; 1023214571Sdim case 'x': 1024214571Sdim if (*optarg != 0) 1025214571Sdim mcset_dbg_dir = mc_unify_path (optarg); 1026214571Sdim break; 1027214571Sdim case 'A': 1028214571Sdim mcset_bin_out_is_unicode = 0; 1029214571Sdim break; 1030214571Sdim case 'd': 1031214571Sdim mcset_out_values_are_decimal = 1; 1032214571Sdim break; 1033214571Sdim case 'u': 1034214571Sdim mcset_text_in_is_unicode = 1; 1035214571Sdim break; 1036214571Sdim case 'U': 1037214571Sdim mcset_bin_out_is_unicode = 1; 1038214571Sdim break; 1039214571Sdim case 'c': 1040214571Sdim mcset_custom_bit = 1; 1041214571Sdim break; 1042214571Sdim case 'n': 1043214571Sdim mcset_automatic_null_termination = 1; 1044214571Sdim break; 1045214571Sdim case 'o': 1046214571Sdim mcset_use_hresult = 1; 1047214571Sdim fatal ("option -o is not implemented until yet.\n"); 1048214571Sdim break; 1049214571Sdim case 'F': 1050214571Sdim target = optarg; 1051214571Sdim break; 1052214571Sdim case 'v': 1053214571Sdim verbose ++; 1054214571Sdim break; 1055214571Sdim case 'm': 1056214571Sdim mcset_max_message_length = strtol (optarg, (char **) NULL, 10); 1057214571Sdim break; 1058214571Sdim case 'C': 1059214571Sdim mcset_codepage_in = strtol (optarg, (char **) NULL, 10); 1060214571Sdim break; 1061214571Sdim case 'O': 1062214571Sdim mcset_codepage_out = strtol (optarg, (char **) NULL, 10); 1063214571Sdim break; 1064214571Sdim case '?': 1065214571Sdim case 'H': 1066214571Sdim usage (stdout, 0); 1067214571Sdim break; 1068214571Sdim case 'V': 1069214571Sdim print_version ("windmc"); 1070214571Sdim break; 1071214571Sdim 1072214571Sdim default: 1073214571Sdim usage (stderr, 1); 1074214571Sdim break; 1075214571Sdim } 1076214571Sdim } 1077214571Sdim if (input_filename == NULL && optind < argc) 1078214571Sdim { 1079214571Sdim input_filename = argv[optind]; 1080214571Sdim ++optind; 1081214571Sdim } 1082214571Sdim 1083214571Sdim set_endianess (NULL, target); 1084214571Sdim 1085214571Sdim if (input_filename == NULL) 1086214571Sdim { 1087214571Sdim fprintf (stderr, "Error: No input file was specified.\n"); 1088214571Sdim usage (stderr, 1); 1089214571Sdim } 1090214571Sdim mc_set_inputfile (input_filename); 1091214571Sdim 1092214571Sdim if (!probe_codepage (&mcset_codepage_in, &mcset_text_in_is_unicode, "codepage_in", 0)) 1093214571Sdim usage (stderr, 1); 1094214571Sdim if (mcset_codepage_out == 0) 1095214571Sdim mcset_codepage_out = 1252; 1096214571Sdim if (! unicode_is_valid_codepage (mcset_codepage_out)) 1097214571Sdim fatal ("Code page 0x%x is unknown.", (unsigned int) mcset_codepage_out); 1098214571Sdim if (mcset_codepage_out == CP_UTF16) 1099214571Sdim fatal ("UTF16 is no valid text output code page."); 1100214571Sdim if (verbose) 1101214571Sdim { 1102214571Sdim fprintf (stderr, "// Default target is %s and it is %s endian.\n", 1103214571Sdim def_target_arch, (target_is_bigendian ? "big" : "little")); 1104214571Sdim fprintf (stderr, "// Input codepage: 0x%x\n", (unsigned int) mcset_codepage_in); 1105214571Sdim fprintf (stderr, "// Output codepage: 0x%x\n", (unsigned int) mcset_codepage_out); 1106214571Sdim } 1107214571Sdim 1108214571Sdim if (argc != optind) 1109214571Sdim usage (stderr, 1); 1110214571Sdim 1111214571Sdim /* Initialize mcset_mc_basename. */ 1112214571Sdim { 1113214571Sdim const char *bn, *bn2; 1114214571Sdim char *hsz; 1115214571Sdim 1116214571Sdim bn = strrchr (input_filename, '/'); 1117214571Sdim bn2 = strrchr (input_filename, '\\'); 1118214571Sdim if (! bn) 1119214571Sdim bn = bn2; 1120214571Sdim if (bn && bn2 && bn < bn2) 1121214571Sdim bn = bn2; 1122214571Sdim if (! bn) 1123214571Sdim bn = input_filename; 1124214571Sdim else 1125214571Sdim bn++; 1126214571Sdim mcset_mc_basename = hsz = xstrdup (bn); 1127214571Sdim 1128214571Sdim /* Cut of right-hand extension. */ 1129214571Sdim if ((hsz = strrchr (hsz, '.')) != NULL) 1130214571Sdim *hsz = 0; 1131214571Sdim } 1132214571Sdim 1133214571Sdim /* Load the input file and do code page transformations to UTF16. */ 1134214571Sdim { 1135214571Sdim unichar *u; 1136214571Sdim rc_uint_type ul; 1137214571Sdim char *buff; 1138214571Sdim long flen; 1139214571Sdim FILE *fp = fopen (input_filename, "rb"); 1140214571Sdim 1141214571Sdim if (!fp) 1142214571Sdim fatal (_("unable to open file ,%s' for input.\n"), input_filename); 1143214571Sdim 1144214571Sdim fseek (fp, 0, SEEK_END); 1145214571Sdim flen = ftell (fp); 1146214571Sdim fseek (fp, 0, SEEK_SET); 1147214571Sdim buff = malloc (flen + 3); 1148214571Sdim memset (buff, 0, flen + 3); 1149214571Sdim fread (buff, 1, flen, fp); 1150214571Sdim fclose (fp); 1151214571Sdim if (mcset_text_in_is_unicode != 1) 1152214571Sdim { 1153214571Sdim unicode_from_codepage (&ul, &u, buff, mcset_codepage_in); 1154214571Sdim if (! u) 1155214571Sdim fatal ("Failed to convert input to UFT16\n"); 1156214571Sdim mc_set_content (u); 1157214571Sdim } 1158214571Sdim else 1159214571Sdim { 1160214571Sdim if ((flen & 1) != 0) 1161214571Sdim fatal (_("input file does not seems to be UFT16.\n")); 1162214571Sdim mc_set_content ((unichar *) buff); 1163214571Sdim } 1164214571Sdim free (buff); 1165214571Sdim } 1166214571Sdim 1167214571Sdim while (yyparse ()) 1168214571Sdim ; 1169214571Sdim 1170214571Sdim do_sorts (); 1171214571Sdim 1172214571Sdim h_fp = mc_create_path_text_file (mcset_header_dir, mcset_header_ext); 1173214571Sdim write_header (h_fp); 1174214571Sdim fclose (h_fp); 1175214571Sdim 1176214571Sdim h_fp = mc_create_path_text_file (mcset_rc_dir, ".rc"); 1177214571Sdim write_rc (h_fp); 1178214571Sdim fclose (h_fp); 1179214571Sdim 1180214571Sdim if (mcset_dbg_dir != NULL) 1181214571Sdim { 1182214571Sdim h_fp = mc_create_path_text_file (mcset_dbg_dir, ".dbg"); 1183214571Sdim write_dbg (h_fp); 1184214571Sdim fclose (h_fp); 1185214571Sdim } 1186214571Sdim write_bin (); 1187214571Sdim 1188214571Sdim if (mc_nodes_lang) 1189214571Sdim free (mc_nodes_lang); 1190214571Sdim if (mc_severity_codes) 1191214571Sdim free (mc_severity_codes); 1192214571Sdim if (mc_facility_codes) 1193214571Sdim free (mc_facility_codes); 1194214571Sdim 1195214571Sdim xexit (0); 1196214571Sdim return 0; 1197214571Sdim} 1198