Hi folks, Things have been a bit quiet lately, so I figured we need a bit of controversy to spice things up :) This problem has been discussed before indirectly, but please bear with me for a second. Now, this patch removes wrc's ability to generate assembly output, and here is why: -- It makes things a _lot_ simpler for the user. For anyone looking at wrc, it seems they have two choice: compile either to .res or .s. Which is not the case, the entire build system supports only .res output. Then they have to worry about things like -s (generate resource directory). What is that? I, for one, don't know! And even if they ignore all that, how does one use the output? It's nowhere documented. All this frustration for no purpose. -- We are approaching 0.9 (hopefully). Getting interfaces right is very improtant at this point IMO. Having a too large/powerful interface is just as bad (or maybe worse) than having a too restrictive one. A small one can be enlarged at anytime without upsetting anyone (but making some people happy), a large one you're stuck with forever, which means support, maintenance, documentation, etc. Wasted energy, and it's not like we have too much time on our hands. :) -- The only reason wrc generates asm output is that the old wrc was generating .s output. Wine has evolved since then, and uses the proper .res output. Which means this is unused code. A lot of it, and like any unused code, it will bitrot. It's just waiting in the shadows to bite us. -- As a principle, we've tried hard to not provide superfluous extensions to the Windows API, and for good reason! Every time we do that, we regret it, because our little extensions provide fertile ground for gratuitous incompatibilities. They lead people down a path they need not take, just to realize down the road they made the wrong decision. It seems to me this very principle applies here loud and clear. -- It simplifies the code by a lot. Most of the code in wrc's output was dealing with asm output. And it is difficult and obscure. The .res output code is a *trivial* 60-line function, whereas the .s output code is over 800-line of tricky code! -- It cleans up wrc's options by removing 4 switches (-b,-g,-p,-s) All in all, the code will forever be available in CVS history. If we ever need it, we can always retrieve it with a few keystrokes. But for now, we are much better off with the simplifications this patch is bringing to the table. Just to show the amount of simplification, here is a quick diffstat: [dimi@dimi wine.src]$ diffstat diffs/wrc-no-asm.diff wrc.c | 180 +------------ wrc.h | 4 wrc.man | 53 --- writeres.c | 829 ------------------------------------------------------------- writeres.h | 31 -- 5 files changed, 38 insertions(+), 1059 deletions(-) Please consider it for inclusion. The patch also gets rid of writeres.h, so please do a cvs rm -f tools/wrc/writeres.h before committing. ChangeLog Remove assembly generation from wrc. Index: tools/wrc/wrc.c =================================================================== RCS file: /var/cvs/wine/tools/wrc/wrc.c,v retrieving revision 1.28 diff -u -r1.28 wrc.c --- tools/wrc/wrc.c 11 Feb 2003 21:58:46 -0000 1.28 +++ tools/wrc/wrc.c 21 Feb 2003 05:00:40 -0000 @@ -65,7 +65,6 @@ #include "wrc.h" #include "utils.h" -#include "writeres.h" #include "readres.h" #include "dumpres.h" #include "genres.h" @@ -86,7 +85,6 @@ static char usage[] = "Usage: wrc [options...] [infile[.rc|.res]] [outfile]\n" " -a n Alignment of resource (win16 only, default is 4)\n" - " -b Create an assembly array from a binary .res file\n" " -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n" " (win32 only; default is " ENDIAN "-endian)\n" " -C cp Set the resource's codepage to cp (default is 0)\n" @@ -95,18 +93,15 @@ " -e Disable recognition of win32 keywords in 16bit compile\n" " -E Preprocess only\n" " -F target Ignored for compatibility with windres\n" - " -g Add symbols to the global c namespace\n" " -h Prints this summary.\n" " -i file The name of the input file.\n" " -I path Set include search dir to path (multiple -I allowed)\n" " -J Do not search the standard include path\n" " -l lan Set default language to lan (default is neutral {0, 0})\n" " -m Do not remap numerical resource IDs\n" - " -o file Output to file (default is infile.[res|s]\n" - " -O format The output format: one of `res', 'asm'.\n" - " -p prefix Give a prefix for the generated names\n" + " -o file Output to file (default is infile.res\n" + " -O format The output format (must be `res').\n" " -P program Specifies the preprocessor to use, including arguments.\n" - " -s Add structure with win32/16 (PE/NE) resource directory\n" " -v Enable verbose mode.\n" " -V Print version and exit\n" " -w 16|32 Select win16 or win32 output (default is win32)\n" @@ -136,7 +131,7 @@ " * 0x10 Preprocessor lex messages\n" " * 0x20 Preprocessor yacc trace\n" "If no input filename is given and the output name is not overridden\n" - "with -o, then the output is written to \"wrc.tab.{s,res}\"\n" + "with -o, then the output is written to \"wrc.tab.res\"\n" ; char version_string[] = "Wine Resource Compiler Version " WRC_FULLVERSION "\n" @@ -144,10 +139,9 @@ " 1994 Martin von Loewis\n"; /* - * Default prefix for resource names used in the C array. - * Option '-p name' sets it to 'name' + * External functions */ -char *prefix = __ASM_NAME("_Resource"); +void write_resfile(char *outname, resource_t *top); /* * Set if compiling in 32bit mode (default). @@ -155,11 +149,6 @@ int win32 = 1; /* - * Output type (default res) - */ -enum output_t { output_def, output_res, output_asm } output_type = output_def; - -/* * debuglevel == DEBUGLEVEL_NONE Don't bother * debuglevel & DEBUGLEVEL_CHAT Say whats done * debuglevel & DEBUGLEVEL_DUMP Dump internal structures @@ -177,22 +166,6 @@ int extensions = 1; /* - * Set when creating C array from .res file (-b option). - */ -int binary = 0; - -/* - * Set when the NE/PE resource directory should be dumped into - * the output file. - */ -int create_dir = 0; - -/* - * Set when all symbols should be added to the global namespace (-g option) - */ -int global = 0; - -/* * NE segment resource aligment (-a option) */ int alignment = 4; @@ -250,7 +223,7 @@ static void segvhandler(int sig); static const char* short_options = - "a:AbB:cC:d:D:eEF:ghH:i:I:Jl:LmnNo:O:p:P:rstTvVw:W"; + "a:AB:cC:d:D:eEF:hH:i:I:Jl:LmnNo:O:P:rtTvVw:W"; #ifdef HAVE_GETOPT_LONG static struct option long_options[] = { { "input", 1, 0, 'i' }, @@ -320,9 +293,6 @@ case 'a': alignment = atoi(optarg); break; - case 'b': - binary = 1; - break; case 'B': switch(optarg[0]) { @@ -361,9 +331,6 @@ case 'F': /* ignored for compatibility with windres */ break; - case 'g': - global = 1; - break; case 'h': printf(usage); exit(0); @@ -394,20 +361,13 @@ else error("Too many output files.\n"); break; case 'O': - if (strcmp(optarg, "res") == 0) output_type = output_res; - else if (strcmp(optarg, "asm") == 0) output_type = output_asm; - else error("Output format %s not supported.", optarg); - break; - case 'p': - prefix = xstrdup(optarg); + if (strcmp(optarg, "res")) + error("Output format %s not supported.", optarg); break; case 'P': if (strcmp(optarg, "cat") == 0) no_preprocess = 1; else fprintf(stderr, "-P option not yet supported, ignored.\n"); break; - case 's': - create_dir = 1; - break; case 'v': debuglevel = DEBUGLEVEL_CHAT; break; @@ -460,19 +420,6 @@ else error("Too many output files.\n"); } - /* Try to guess the output format based on output name */ - if (output_type == output_def) - { - char *dotstr = output_name ? strrchr(output_name, '.') : 0; - - output_type = output_res; /* by default generate .res files */ - if (dotstr) - { - if (strcmp(dotstr+1, "s") == 0) output_type = output_asm; - } - } - - /* Check the command line options for invalid combinations */ if(win32) { @@ -483,51 +430,6 @@ } } - if(output_type == output_res) - { - if(global) - { - warning("Option -g ignored with compile to .res\n"); - global = 0; - } - - if(create_dir) - { - error("Option -r and -s cannot be used together\n"); - } - - if(binary) - { - error("Option -r and -b cannot be used together\n"); - } - } - - if(byteorder != WRC_BO_NATIVE) - { - if(binary) - error("Forced byteordering not supported for binary resources\n"); - } - - if(preprocess_only) - { - if(global) - { - warning("Option -g ignored with preprocess only\n"); - global = 0; - } - - if(create_dir) - { - warning("Option -s ignored with preprocess only\n"); - create_dir = 0; - } - - if(binary) - { - error("Option -E and -b cannot be used together\n"); - } - } - /* Set alignment power */ a = alignment; for(alignment_pwr = 0; alignment_pwr < 10 && a > 1; alignment_pwr++) @@ -575,21 +477,15 @@ if(!currentlanguage) currentlanguage = new_language(0, 0); - if(binary && !input_name) - { - error("Binary mode requires .res file as input\n"); - } - /* Generate appropriate outfile names */ if(!output_name && !preprocess_only) { - output_name = dup_basename(input_name, binary ? ".res" : ".rc"); - if (output_type == output_res) strcat(output_name, ".res"); - else if (output_type == output_asm) strcat(output_name, ".s"); + output_name = dup_basename(input_name, ".rc"); + strcat(output_name, ".res"); } /* Run the preprocessor on the input */ - if(!no_preprocess && !binary) + if(!no_preprocess) { /* * Preprocess the input to a temp-file, or stdout if @@ -626,54 +522,26 @@ input_name = temp_name; } - if(!binary) - { - /* Go from .rc to .res or .s */ - chat("Starting parse"); - - if(!(yyin = fopen(input_name, "rb"))) - error("Could not open %s for input\n", input_name); + /* Go from .rc to .res */ + chat("Starting parse"); - ret = yyparse(); + if(!(yyin = fopen(input_name, "rb"))) + error("Could not open %s for input\n", input_name); - if(input_name) - fclose(yyin); + ret = yyparse(); - if(ret) - { - /* Error during parse */ - exit(1); - } + if(input_name) fclose(yyin); - if(debuglevel & DEBUGLEVEL_DUMP) - dump_resources(resource_top); + if(ret) exit(1); /* Error during parse */ - /* Convert the internal lists to binary data */ - resources2res(resource_top); + if(debuglevel & DEBUGLEVEL_DUMP) + dump_resources(resource_top); - if(output_type == output_res) - { - chat("Writing .res-file"); - write_resfile(output_name, resource_top); - } - else if(output_type == output_asm) - { - chat("Writing .s-file"); - write_s_file(output_name, resource_top); - } + /* Convert the internal lists to binary data */ + resources2res(resource_top); - } - else - { - /* Go from .res to .s */ - chat("Reading .res-file"); - resource_top = read_resfile(input_name); - if(output_type == output_asm) - { - chat("Writing .s-file"); - write_s_file(output_name, resource_top); - } - } + chat("Writing .res-file"); + write_resfile(output_name, resource_top); return 0; } Index: tools/wrc/wrc.h =================================================================== RCS file: /var/cvs/wine/tools/wrc/wrc.h,v retrieving revision 1.27 diff -u -r1.27 wrc.h --- tools/wrc/wrc.h 31 Jan 2003 03:20:49 -0000 1.27 +++ tools/wrc/wrc.h 21 Feb 2003 04:50:26 -0000 @@ -51,9 +51,6 @@ extern int win32; extern int create_res; extern int extensions; -extern int binary; -extern int create_dir; -extern int global; extern int alignment; extern int alignment_pwr; extern int create_s; @@ -64,7 +61,6 @@ extern int no_preprocess; extern int remap; -extern char *prefix; extern char *output_name; extern char *input_name; extern char *cmdline; Index: tools/wrc/wrc.man =================================================================== RCS file: /var/cvs/wine/tools/wrc/wrc.man,v retrieving revision 1.14 diff -u -r1.14 wrc.man --- tools/wrc/wrc.man 11 Feb 2003 21:58:46 -0000 1.14 +++ tools/wrc/wrc.man 21 Feb 2003 05:08:26 -0000 @@ -5,39 +5,25 @@ .BI "wrc " "[options] " "[inputfile]" .SH DESCRIPTION .B wrc -compiles resources from -.I inputfile -into win16 and win32 compatible -binary format. -.B wrc -outputs the binary data either in a standard \fB.res\fR formatted binary -file, or an assembly file. -.B wrc -is also capable of reading \fB.res\fR formatted files and convert them -into an assembly file. +compiles resources from \fBinputfile\fR +into win16 and win32 compatible binary format. .PP The source\-file is preprocessed with a builtin ANSI\-C compatible preprocessor before the resources are compiled. See \fBPREPROCESSOR\fR below. .PP .B wrc -takes only one \fBinputfile\fR as argument. The \fBinputfile\fR has -extension \fB.rc\fR for resources in source form and \fB.res\fR for -binary resources. The resources are read from standard input if no -inputfile is given. If the outputfile is not specified with \fI-o\fR, -then \fBwrc\fR will write the output to \fBinputfile.{s,res}\fR -with \fB.rc\fR stripped, depending on the mode of compilation. -The outputfile is named \fBwrc.tab.{s,res}\fR if no inputfile was -given. +takes only one \fBinputfile\fR as argument. The resources are read from +standard input if no inputfile is given. If the output file is not +specified with \fI-o\fR, then \fBwrc\fR will write the output to +\fBinputfile.res\fR with \fB.rc\fR stripped, or to \fBwrc.tab.res\fR if +no inputfile was given. .SH OPTIONS .TP .I \-a n Win16 only; set the alignment between resources n. The alignment must be a power of 2. The default is 4. .TP -.I \-b -Create an assembly file from a binary \fB.res\fR file. -.TP .I \-B x Win32 only; set output byte\-ordering, where \fIx\fR is one of n[ative], l[ittle] or b[ig]. Only resources in source-form can be reorderd. Native @@ -68,10 +54,6 @@ outputfile was selected. The output is compatible with what gcc would generate. .TP -.I \-g -Add symbols to the global C namespace. This makes all symbols available -for linking by other modules. -.TP .I \-h Prints a summary message and exits. .TP @@ -106,28 +88,19 @@ resource is not 100% compliant. .TP .I \-o file -Write output to \fIfile\fR. Default is \fBinputfile.{res,s,h}\fR -with \fB.rc\fR stripped or \fBwrc.tab.{s,h,res}\fR, depending on the -compilation mode. +Write output to \fIfile\fR. Default is \fBinputfile.res\fR +with \fB.rc\fR stripped or \fBwrc.tab.res\fR if input is read +from standard input. .TP .I \-O format -Sets the output format. \fformat\fR can one either 'res' or 'asm' -to generate a \fB.res\fR or \fB.s\fR file respectively. -If not specified, \fBwrc\fR assumes 'res'. -.TP -.I \-p prefix -Prefix all generated names with \fIprefix\fR. This is only relevant for -names in the assembly code and header file. Resource names are not -affected. +Sets the output format. The only supported \fformat\fR is 'res', which +is also the default format if this option is not specified. The option +exists mainly for compatibility with \fBwindres\fR. .TP .I \-P program This option may be used to specify the preprocessor to use, including any leading arguments. If not specified, \fBwrc\fR uses its builtin processor. To disable preprocessing, use \fB-P cat\fR. -.TP -.I \-s -Add structure with win32/16 (PE/NE) resource directory to outputfile. -This directory is always in native byteorder. .TP .I \-v Turns on verbose mode (equivalent to -d 1). Index: tools/wrc/writeres.c =================================================================== RCS file: /var/cvs/wine/tools/wrc/writeres.c,v retrieving revision 1.26 diff -u -r1.26 writeres.c --- tools/wrc/writeres.c 31 Jan 2003 03:20:49 -0000 1.26 +++ tools/wrc/writeres.c 21 Feb 2003 04:49:40 -0000 @@ -1,5 +1,5 @@ /* - * Write .res, .s and .h file(s) from a resource-tree + * Write .res file from a resource-tree * * Copyright 1998 Bertho A. Stultiens * @@ -28,38 +28,10 @@ #include "wine/unicode.h" #include "wrc.h" -#include "writeres.h" #include "genres.h" #include "newstruc.h" #include "utils.h" -static char s_file_head_str[] = - "/* This file is generated with wrc version " WRC_FULLVERSION ". Do not edit! */\n" - "/* Source : %s */\n" - "/* Cmdline: %s */\n" - "/* Date : %s */\n" - "\n" - "\t.data\n" - "\n" - ; - -static char s_file_tail_str[] = - "/* <eof> */\n" - "\n" - ; - -char _NEResTab[] = "_NEResTab"; -char _PEResTab[] = "_PEResTab"; -char _ResTable[] = "_ResTable"; - -/* Variables used for resource sorting */ -res_count_t *rcarray = NULL; /* Type-level count array */ -int rccount = 0; /* Nr of entries in the type-level array */ -int n_id_entries = 0; /* win32 only: Nr of unique ids in the type-level array */ -int n_name_entries = 0; /* win32 only: Nr of unique namess in the type-level array */ - -static int direntries; /* win32 only: Total number of unique resources */ - /* ***************************************************************************** * Function : write_resfile @@ -133,802 +105,3 @@ fclose(fo); } -/* - ***************************************************************************** - * Function : write_s_res - * Syntax : void write_s_res(FILE *fp, res_t *res) - * Input : - * Output : - * Description : - * Remarks : - ***************************************************************************** -*/ -#define BYTESPERLINE 8 -static void write_s_res(FILE *fp, res_t *res) -{ - int idx = res->dataidx; - int end = res->size; - int rest = (end - idx) % BYTESPERLINE; - int lines = (end - idx) / BYTESPERLINE; - int i, j; - - for(i = 0 ; i < lines; i++) - { - fprintf(fp, "\t.byte\t"); - for(j = 0; j < BYTESPERLINE; j++, idx++) - { - fprintf(fp, "0x%02x%s", res->data[idx] & 0xff, - j == BYTESPERLINE-1 ? "" : ", "); - } - fprintf(fp, "\n"); - } - if(rest) - { - fprintf(fp, "\t.byte\t"); - for(j = 0; j < rest; j++, idx++) - { - fprintf(fp, "0x%02x%s", res->data[idx] & 0xff, - j == rest-1 ? "" : ", "); - } - fprintf(fp, "\n"); - } -} -#undef BYTESPERLINE - -/* - ***************************************************************************** - * Function : write_name_str - * Syntax : void write_name_str(FILE *fp, name_id_t *nid) - * Input : - * Output : - * Description : - * Remarks : One level self recursive for string type conversion - ***************************************************************************** -*/ -static void write_name_str(FILE *fp, name_id_t *nid) -{ - res_t res; - assert(nid->type == name_str); - - if(!win32 && nid->name.s_name->type == str_char) - { - res.size = strlen(nid->name.s_name->str.cstr); - if(res.size > 254) - error("Can't write strings larger than 254 bytes"); - if(res.size == 0) - internal_error(__FILE__, __LINE__, "Attempt to write empty string"); - res.dataidx = 0; - res.data = (char *)xmalloc(1 + res.size + 1); - res.data[0] = (char)res.size; - res.size++; /* We need to write the length byte as well */ - strcpy(res.data+1, nid->name.s_name->str.cstr); - write_s_res(fp, &res); - free(res.data); - } - else if(!win32 && nid->name.s_name->type == str_unicode) - { - name_id_t lnid; - - lnid.type = name_str; - lnid.name.s_name = convert_string( nid->name.s_name, str_char, - get_language_codepage(0,0) ); - write_name_str(fp, &lnid); - free_string( lnid.name.s_name ); - } - else if(win32 && nid->name.s_name->type == str_char) - { - name_id_t lnid; - - lnid.type = name_str; - lnid.name.s_name = convert_string( nid->name.s_name, str_unicode, - get_language_codepage(0,0) ); - write_name_str(fp, &lnid); - free_string( lnid.name.s_name ); - } - else if(win32 && nid->name.s_name->type == str_unicode) - { - res.size = strlenW(nid->name.s_name->str.wstr); - if(res.size > 65534) - error("Can't write strings larger than 65534 characters"); - if(res.size == 0) - internal_error(__FILE__, __LINE__, "Attempt to write empty string"); - res.dataidx = 0; - res.data = (char *)xmalloc(2 + (res.size + 1) * 2); - ((short *)res.data)[0] = (short)res.size; - strcpyW((WCHAR *)(res.data+2), nid->name.s_name->str.wstr); - res.size *= 2; /* Function writes bytes, not shorts... */ - res.size += 2; /* We need to write the length word as well */ - write_s_res(fp, &res); - free(res.data); - } - else - { - internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d", - nid->name.s_name->type); - } -} - -/* - ***************************************************************************** - * Function : find_counter - * Syntax : res_count_t *find_counter(name_id_t *type) - * Input : - * Output : - * Description : - * Remarks : - ***************************************************************************** -*/ -static res_count_t *find_counter(name_id_t *type) -{ - int i; - for(i = 0; i < rccount; i++) - { - if(!compare_name_id(type, &(rcarray[i].type))) - return &rcarray[i]; - } - return NULL; -} - -/* - ***************************************************************************** - * Function : count_resources - * Syntax : res_count_t *count_resources(resource_t *top) - * Input : - * Output : - * Description : - * Remarks : The whole lot is converted into arrays because they are - * easy sortable. Makes the lot almost unreadable, but it - * works (I hope). Basically you have to keep in mind that - * the lot is a three-dimensional structure for win32 and a - * two-dimensional structure for win16. - ***************************************************************************** -*/ -#define RCT(v) (*((resource_t **)(v))) -/* qsort sorting function */ -static int sort_name_id(const void *e1, const void *e2) -{ - return compare_name_id(RCT(e1)->name, RCT(e2)->name); -} - -static int sort_language(const void *e1, const void *e2) -{ - assert((RCT(e1)->lan) != NULL); - assert((RCT(e2)->lan) != NULL); - - return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub) - - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub); -} -#undef RCT -#define RCT(v) ((res_count_t *)(v)) -static int sort_type(const void *e1, const void *e2) -{ - return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type)); -} -#undef RCT - -static void count_resources(resource_t *top) -{ - resource_t *rsc; - res_count_t *rcp; - name_id_t nid; - int i, j; - - for(rsc = top; rsc; rsc = rsc->next) - { - if(!rsc->binres) - continue; - switch(rsc->type) - { - case res_dlgex: - nid.name.i_name = WRC_RT_DIALOG; - nid.type = name_ord; - break; - case res_menex: - nid.name.i_name = WRC_RT_MENU; - nid.type = name_ord; - break; - case res_usr: - nid = *(rsc->res.usr->type); - break; - default: - nid.name.i_name = rsc->type; - nid.type = name_ord; - } - - if((rcp = find_counter(&nid)) == NULL) - { - /* Count the number of uniq ids and names */ - - if(nid.type == name_ord) - n_id_entries++; - else - n_name_entries++; - - if(!rcarray) - { - rcarray = (res_count_t *)xmalloc(sizeof(res_count_t)); - rccount = 1; - rcarray[0].count = 1; - rcarray[0].type = nid; - rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *)); - rcarray[0].rscarray[0] = rsc; - } - else - { - rccount++; - rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t)); - rcarray[rccount-1].count = 1; - rcarray[rccount-1].type = nid; - rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *)); - rcarray[rccount-1].rscarray[0] = rsc; - } - } - else - { - rcp->count++; - rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *)); - rcp->rscarray[rcp->count-1] = rsc; - } - } - - if(!win32) - { - /* We're done, win16 requires no special sorting */ - return; - } - - /* We now have a unsorted list of types with an array of res_count_t - * in rcarray[0..rccount-1]. And we have names of one type in the - * rcarray[x].rsc[0..rcarray[x].count-1] arrays. - * The list needs to be sorted for win32's top level tree structure. - */ - - /* Sort the types */ - if(rccount > 1) - qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type); - - /* Now sort the name-id arrays */ - for(i = 0; i < rccount; i++) - { - if(rcarray[i].count > 1) - qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id); - } - - /* Now split the name-id arrays into name/language - * subs. Don't look at the awfull expressions... - * We do this by taking the array elements out of rscarray and putting - * together a new array in rsc32array. - */ - for(i = 0; i < rccount; i++) - { - res_count_t *rcap; - - assert(rcarray[i].count >= 1); - - /* rcap points to the current type we are dealing with */ - rcap = &(rcarray[i]); - - /* Insert the first name-id */ - rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t)); - rcap->count32 = 1; - rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *)); - rcap->rsc32array[0].count = 1; - rcap->rsc32array[0].rsc[0] = rcap->rscarray[0]; - if(rcap->rscarray[0]->name->type == name_ord) - { - rcap->n_id_entries = 1; - rcap->n_name_entries = 0; - } - else - { - rcap->n_id_entries = 0; - rcap->n_name_entries = 1; - } - - /* Now loop over the resting resources of the current type - * to find duplicate names (which should have different - * languages). - */ - for(j = 1; j < rcap->count; j++) - { - res32_count_t *r32cp; - - /* r32cp points to the current res32_count structure - * that holds the resource name we are processing. - */ - r32cp = &(rcap->rsc32array[rcap->count32-1]); - - if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name)) - { - /* Names are the same, add to list */ - r32cp->count++; - r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *)); - r32cp->rsc[r32cp->count-1] = rcap->rscarray[j]; - } - else - { - /* New name-id, sort the old one by - * language and create new list - */ - if(r32cp->count > 1) - qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language); - rcap->count32++; - rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t)); - rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *)); - rcap->rsc32array[rcap->count32-1].count = 1; - rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j]; - - if(rcap->rscarray[j]->name->type == name_ord) - rcap->n_id_entries++; - else - rcap->n_name_entries++; - } - } - /* Also sort the languages of the last name group */ - if(rcap->rsc32array[rcap->count32-1].count > 1) - qsort(rcap->rsc32array[rcap->count32-1].rsc, - rcap->rsc32array[rcap->count32-1].count, - sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]), - sort_language); - } -} - -/* - ***************************************************************************** - * Function : write_pe_segment - * Syntax : void write_pe_segment(FILE *fp) - * Input : - * Output : - * Description : - * Remarks : - ***************************************************************************** -*/ -static void write_pe_segment(FILE *fp) -{ - int i; - - fprintf(fp, "\t.align\t4\n"); - fprintf(fp, __ASM_NAME("%s%s") ":\n", prefix, _PEResTab); - fprintf(fp, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, _PEResTab); - /* Flags */ - fprintf(fp, "\t.long\t0\n"); - /* Time/Date stamp */ - fprintf(fp, "\t.long\t0x%08lx\n", (long)now); - /* Version */ - fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */ - /* # of id entries, # of name entries */ - fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries); - - /* Write the type level of the tree */ - for(i = 0; i < rccount; i++) - { - res_count_t *rcp; - char *label; - - rcp = &rcarray[i]; - - /* TypeId */ - if(rcp->type.type == name_ord) - fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name); - else - { - char *name = prep_nid_for_label(&(rcp->type)); - fprintf(fp, "\t.long\t(" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") ") | 0x80000000\n", - prefix, - name, - prefix, - _PEResTab); - } - /* Offset */ - label = prep_nid_for_label(&(rcp->type)); - fprintf(fp, "\t.long\t(.L%s - " __ASM_NAME("%s%s") ") | 0x80000000\n", - label, - prefix, - _PEResTab); - } - - /* Write the name level of the tree */ - - for(i = 0; i < rccount; i++) - { - res_count_t *rcp; - char *typelabel; - char *namelabel; - int j; - - rcp = &rcarray[i]; - - typelabel = xstrdup(prep_nid_for_label(&(rcp->type))); - fprintf(fp, ".L%s:\n", typelabel); - - fprintf(fp, "\t.long\t0\n"); /* Flags */ - fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */ - fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */ - fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries); - for(j = 0; j < rcp->count32; j++) - { - resource_t *rsc = rcp->rsc32array[j].rsc[0]; - /* NameId */ - if(rsc->name->type == name_ord) - fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name); - else - { - fprintf(fp, "\t.long\t(" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") ") | 0x80000000\n", - prefix, - rsc->c_name, - prefix, - _PEResTab); - } - /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and - * put the offset to the resource data entry. - * ?? Is unescaping worth while ?? - */ - /* Offset */ - namelabel = prep_nid_for_label(rsc->name); - fprintf(fp, "\t.long\t(.L%s_%s - " __ASM_NAME("%s%s") ") | 0x80000000\n", - typelabel, - namelabel, - prefix, - _PEResTab); - } - free(typelabel); - } - - /* Write the language level of the tree */ - - for(i = 0; i < rccount; i++) - { - res_count_t *rcp; - char *namelabel; - char *typelabel; - int j; - - rcp = &rcarray[i]; - typelabel = xstrdup(prep_nid_for_label(&(rcp->type))); - - for(j = 0; j < rcp->count32; j++) - { - res32_count_t *r32cp = &(rcp->rsc32array[j]); - int k; - - namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name)); - fprintf(fp, ".L%s_%s:\n", typelabel, namelabel); - - fprintf(fp, "\t.long\t0\n"); /* Flags */ - fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */ - fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */ - fprintf(fp, "\t.short\t0, %d\n", r32cp->count); - - for(k = 0; k < r32cp->count; k++) - { - resource_t *rsc = r32cp->rsc[k]; - assert(rsc->lan != NULL); - /* LanguageId */ - fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0); - /* Offset */ - fprintf(fp, "\t.long\t.L%s_%s_%d - " __ASM_NAME("%s%s") "\n", - typelabel, - namelabel, - rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0, - prefix, - _PEResTab); - } - free(namelabel); - } - free(typelabel); - } - - /* Write the resource table itself */ - fprintf(fp, __ASM_NAME("%s_ResourceDirectory") ":\n", prefix); - fprintf(fp, "\t.globl\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix); - direntries = 0; - - for(i = 0; i < rccount; i++) - { - res_count_t *rcp; - char *namelabel; - char *typelabel; - int j; - - rcp = &rcarray[i]; - typelabel = xstrdup(prep_nid_for_label(&(rcp->type))); - - for(j = 0; j < rcp->count32; j++) - { - res32_count_t *r32cp = &(rcp->rsc32array[j]); - int k; - - namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name)); - - for(k = 0; k < r32cp->count; k++) - { - resource_t *rsc = r32cp->rsc[k]; - - assert(rsc->lan != NULL); - - fprintf(fp, ".L%s_%s_%d:\n", - typelabel, - namelabel, - rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0); - - /* Data RVA */ - fprintf(fp, "\t.long\t" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") "\n", - prefix, - rsc->c_name, - prefix, - _PEResTab); - /* Size */ - fprintf(fp, "\t.long\t%d\n", - rsc->binres->size - rsc->binres->dataidx); - /* CodePage */ - fprintf(fp, "\t.long\t%ld\n", codepage); - /* Reserved */ - fprintf(fp, "\t.long\t0\n"); - - direntries++; - } - free(namelabel); - } - free(typelabel); - } -} - -/* - ***************************************************************************** - * Function : write_ne_segment - * Syntax : void write_ne_segment(FILE *fp) - * Input : - * Output : - * Description : - * Remarks : - ***************************************************************************** -*/ -static void write_ne_segment(FILE *fp) -{ - int i, j; - - fprintf(fp, "\t.align\t4\n"); - fprintf(fp, __ASM_NAME("%s%s") ":\n", prefix, _NEResTab); - fprintf(fp, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, _NEResTab); - - /* AlignmentShift */ - fprintf(fp, "\t.short\t%d\n", alignment_pwr); - - /* TypeInfo */ - for(i = 0; i < rccount; i++) - { - res_count_t *rcp = &rcarray[i]; - - /* TypeId */ - if(rcp->type.type == name_ord) - fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000); - else - fprintf(fp, "\t.short\t" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") "\n", - prefix, - rcp->type.name.s_name->str.cstr, - prefix, - _NEResTab); - /* ResourceCount */ - fprintf(fp, "\t.short\t%d\n", rcp->count); - /* Reserved */ - fprintf(fp, "\t.long\t0\n"); - /* NameInfo */ - for(j = 0; j < rcp->count; j++) - { -/* - * VERY IMPORTANT: - * The offset is relative to the beginning of the NE resource segment - * and _NOT_ to the file-beginning. This is because we do not have a - * file based resource, but a simulated NE segment. The offset _is_ - * scaled by the AlignShift field. - * All other things are as the MS doc describes (alignment etc.) - */ - /* Offset */ - fprintf(fp, "\t.short\t(" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") ") >> %d\n", - prefix, - rcp->rscarray[j]->c_name, - prefix, - _NEResTab, - alignment_pwr); - /* Length */ - fprintf(fp, "\t.short\t%d\n", - (rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx + alignment - 1) >> alignment_pwr); - /* Flags */ - fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt); - /* Id */ - if(rcp->rscarray[j]->name->type == name_ord) - fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000); - else - fprintf(fp, "\t.short\t" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") "\n", - prefix, - rcp->rscarray[j]->c_name, - prefix, - _NEResTab); - /* Handle and Usage */ - fprintf(fp, "\t.short\t0, 0\n"); - } - } - /* EndTypes */ - fprintf(fp, "\t.short\t0\n"); -} - -/* - ***************************************************************************** - * Function : write_rsc_names - * Syntax : void write_rsc_names(FILE *fp) - * Input : - * Output : - * Description : - * Remarks : - ***************************************************************************** -*/ -static void write_rsc_names(FILE *fp) -{ - int i, j; - - if(win32) - { - /* Write the names */ - - for(i = 0; i < rccount; i++) - { - res_count_t *rcp; - - rcp = &rcarray[i]; - - if(rcp->type.type == name_str) - { - char *name = prep_nid_for_label(&(rcp->type)); - fprintf(fp, __ASM_NAME("%s_%s_typename") ":\n", - prefix, - name); - write_name_str(fp, &(rcp->type)); - } - - for(j = 0; j < rcp->count32; j++) - { - resource_t *rsc = rcp->rsc32array[j].rsc[0]; - - if(rsc->name->type == name_str) - { - fprintf(fp, __ASM_NAME("%s%s_name") ":\n", - prefix, - rsc->c_name); - write_name_str(fp, rsc->name); - } - } - } - } - else - { - /* ResourceNames */ - for(i = 0; i < rccount; i++) - { - res_count_t *rcp = &rcarray[i]; - - if(rcp->type.type == name_str) - { - fprintf(fp, __ASM_NAME("%s_%s_typename") ":\n", - prefix, - rcp->type.name.s_name->str.cstr); - write_name_str(fp, &(rcp->type)); - } - for(j = 0; j < rcp->count; j++) - { - if(rcp->rscarray[j]->name->type == name_str) - { - fprintf(fp, __ASM_NAME("%s%s_name") ":\n", - prefix, - rcp->rscarray[j]->c_name); - write_name_str(fp, rcp->rscarray[j]->name); - } - } - } - /* EndNames */ - - /* This is to end the NE resource table */ - if(create_dir) - fprintf(fp, "\t.byte\t0\n"); - } - - fprintf(fp, "\n"); -} - -/* - ***************************************************************************** - * Function : write_s_file - * Syntax : void write_s_file(char *outname, resource_t *top) - * Input : - * outname - Filename to write to - * top - The resource-tree to convert - * Output : - * Description : - * Remarks : - ***************************************************************************** -*/ -void write_s_file(char *outname, resource_t *top) -{ - FILE *fo; - resource_t *rsc; - - fo = fopen(outname, "wt"); - if(!fo) - { - error("Could not open %s\n", outname); - return; - } - - { - char *s, *p; - s = ctime(&now); - p = strchr(s, '\n'); - if(p) *p = '\0'; - fprintf(fo, s_file_head_str, input_name ? input_name : "stdin", - cmdline, s); - } - - /* Get an idea how many we have and restructure the tables */ - count_resources(top); - - /* First write the segment tables */ - if(create_dir) - { - if(win32) - write_pe_segment(fo); - else - write_ne_segment(fo); - } - - /* Dump the names */ - write_rsc_names(fo); - - if(create_dir) - fprintf(fo, ".LResTabEnd:\n"); - - /* Write the resource data */ - fprintf(fo, "\n/* Resource binary data */\n\n"); - for(rsc = top; rsc; rsc = rsc->next) - { - if(!rsc->binres) - continue; - - fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment); - fprintf(fo, __ASM_NAME("%s%s_data") ":\n", prefix, rsc->c_name); - if(global) - fprintf(fo, "\t.globl\t" __ASM_NAME("%s%s_data") "\n", prefix, rsc->c_name); - - write_s_res(fo, rsc->binres); - - fprintf(fo, "\n"); - } - - if(create_dir) - { - /* Add a resource descriptor for built-in and elf-dlls */ - fprintf(fo, "\t.align\t4\n"); - fprintf(fo, __ASM_NAME("%s_ResourceDescriptor") ":\n", prefix); - fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceDescriptor") "\n", prefix); - fprintf(fo, __ASM_NAME("%s_ResourceTable") ":\n", prefix); - if(global) - fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceTable") "\n", prefix); - fprintf(fo, "\t.long\t" __ASM_NAME("%s%s") "\n", prefix, win32 ? _PEResTab : _NEResTab); - fprintf(fo, __ASM_NAME("%s_NumberOfResources") ":\n", prefix); - if(global) - fprintf(fo, "\t.globl\t" __ASM_NAME("%s_NumberOfResources") "\n", prefix); - fprintf(fo, "\t.long\t%d\n", direntries); - fprintf(fo, __ASM_NAME("%s_ResourceSectionSize") ":\n", prefix); - if(global) - fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceSectionSize") "\n", prefix); - fprintf(fo, "\t.long\t.LResTabEnd - " __ASM_NAME("%s%s") "\n", prefix, win32 ? _PEResTab : _NEResTab); - if(win32) - { - fprintf(fo, __ASM_NAME("%s_ResourcesEntries") ":\n", prefix); - if(global) - fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourcesEntries") "\n", prefix); - fprintf(fo, "\t.long\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix); - } - } - - fprintf(fo, s_file_tail_str); - fclose(fo); -} Index: tools/wrc/writeres.h =================================================================== RCS file: /var/cvs/wine/tools/wrc/writeres.h,v retrieving revision 1.3 diff -u -r1.3 writeres.h --- tools/wrc/writeres.h 31 Jan 2003 03:20:49 -0000 1.3 +++ tools/wrc/writeres.h 21 Feb 2003 05:10:41 -0000 @@ -1,31 +0,0 @@ -/* - * Write resource prototypes - * - * Copyright 1998 Bertho A. Stultiens (BS) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WRC_WRITERES_H -#define __WRC_WRITERES_H - -#ifndef __WRC_WRCTYPES_H -#include "wrctypes.h" -#endif - -void write_resfile(char *outname, resource_t *top); -void write_s_file(char *outname, resource_t *top); - -#endif -- Dimi.