| /* | |
| * 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 <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <signal.h> | |
| #ifdef HAVE_GETOPT_H | |
| # include <getopt.h> | |
| #endif | |
| #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, --help Print this message\n" | |
| " -H FILE Write header file to FILE (default is inputfile.h)\n" | |
| " -i Inline messagetable(s)\n" | |
| " -o, --output=FILE Output to FILE (default is infile.rc)\n" | |
| " -O, --output-format=FORMAT The output format (`rc', `res', or `pot')\n" | |
| " -P, --po-dir=DIR Directory containing po files for translations\n" | |
| " -u Input file is in unicode\n" | |
| " -U Output unicode messagetable(s)\n" | |
| " -v Show supported codepages and languages\n" | |
| " -V, --version Print version end exit\n" | |
| " -W, --pedantic 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; | |
| static char *po_dir; | |
| 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; | |
| static const char short_options[] = "B:cdDhH:io:O:P:uUvVW"; | |
| static const struct option long_options[] = | |
| { | |
| { "help", 0, NULL, 'h' }, | |
| { "output", 1, NULL, 'o' }, | |
| { "output-format", 1, NULL, 'O' }, | |
| { "pedantic", 0, NULL, 'W' }, | |
| { "po-dir", 1, NULL, 'P' }, | |
| { "version", 0, NULL, 'v' } | |
| }; | |
| 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[]) | |
| { | |
| int optc; | |
| int opti = 0; | |
| 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 | |
| /* First rebuild the commandline to put in destination */ | |
| /* Could be done through env[], but not all OS-es support it */ | |
| cmdlen = 5; /* for "wmc " and \0 */ | |
| 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_long(argc, argv, short_options, long_options, &opti)) != 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 'P': | |
| po_dir = 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; | |
| } | |
| 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: | |
| add_translations( po_dir ); | |
| 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(); | |
| } |