/* * Wine Message Compiler main program * * Copyright 2000 Bertho A. Stultiens (BS) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include "wine/port.h" #include #include #include #include #include "wmc.h" #include "utils.h" #include "lang.h" #include "write.h" static const 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" " -O fmt Set output format (rc, res, pot)\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 const char version_string[] = "Wine Message Compiler version " PACKAGE_VERSION "\n" "Copyright 2000 Bertho A. Stultiens\n" ; /* * The output byte-order of resources (set with -B) */ int byteorder = WMC_BO_NATIVE; /* * Custom bit (bit 29) in output values must be set (-c option) */ int custombit = 0; /* * Output decimal values (-d option) */ int decimal = 0; /* * Enable pedantic warnings; check arg references (-W option) */ int pedantic = 0; /* * Unicode input (-u option) */ int unicodein = 0; /* * Unicode output (-U option) */ int unicodeout = 0; /* * Inline the messagetables (don't write *.bin files; -i option) */ int rcinline = 0; /* * Debugging flag (-D option) */ static 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 mcy_debug; FILE *yyin; static enum { FORMAT_RC, FORMAT_RES, FORMAT_POT } output_format; int getopt (int argc, char *const *argv, const char *optstring); static void segvhandler(int sig); static void cleanup_files(void) { if (output_name) unlink( output_name ); if (header_name) unlink( header_name ); } static void exit_on_signal( int sig ) { exit(1); /* this will call the atexit functions */ } int main(int argc,char *argv[]) { extern char* optarg; extern int optind; int optc; int lose = 0; int ret; int i; int cmdlen; atexit( cleanup_files ); signal(SIGSEGV, segvhandler); signal( SIGTERM, exit_on_signal ); signal( SIGINT, exit_on_signal ); #ifdef SIGHUP signal( SIGHUP, exit_on_signal ); #endif 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 = 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:O: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 'O': if (!strcmp( optarg, "rc" )) output_format = FORMAT_RC; else if (!strcmp( optarg, "res" )) output_format = FORMAT_RES; else if (!strcmp( optarg, "pot" )) output_format = FORMAT_POT; else { fprintf(stderr, "Output format must be rc or res\n" ); lose++; } 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; } mcy_debug = dodebug; if(dodebug) { setbuf(stdout, NULL); setbuf(stderr, NULL); } /* 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 = mcy_parse(); if(input_name) fclose(yyin); if(ret) { /* Error during parse */ exit(1); } #ifdef WORDS_BIGENDIAN byte_swapped = (byteorder == WMC_BO_LITTLE); #else byte_swapped = (byteorder == WMC_BO_BIG); #endif switch (output_format) { case FORMAT_RC: write_h_file(header_name); write_rc_file(output_name); if(!rcinline) write_bin_files(); break; case FORMAT_RES: write_res_file( output_name ); break; case FORMAT_POT: write_pot_file( output_name ); break; } output_name = NULL; header_name = NULL; 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(); }