diff --git a/dlls/user/Makefile.in b/dlls/user/Makefile.in index 2c64b382175..f3668a5fe8b 100644 --- a/dlls/user/Makefile.in +++ b/dlls/user/Makefile.in @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = user32 SOVERSION = 1.0 -WRCEXTRA = -w16 +WRCEXTRA = -w16 -m ALTNAMES = user keyboard ddeml display mouse SPEC_SRCS = \ diff --git a/tools/wrc/CHANGES b/tools/wrc/CHANGES index bc0aa7a1015..1a9ffc6ea38 100644 --- a/tools/wrc/CHANGES +++ b/tools/wrc/CHANGES @@ -1,3 +1,18 @@ +--------------------------------------------------------------------------- +Version 1.1.5 (12-Jun-2000) + +Bertho Stultiens +- Bugfix: Corrected "off by one" error in the linenumber while parsing + resource. +- Bugfix: A segfault would occur if messagetables were parsed without + memory options attached. Also added buffer-overflow safeguard while + converting between byteorders. +- Finished remapping usertype resources onto standars types by tricking + the parser into accepting a different token. The remapping can be + disabled with a new commandline option '-m'. +- Resolved some warning about chars used as index on SGI O2 machine + (the ctype isXXX() routines are macros there). + --------------------------------------------------------------------------- Version 1.1.4 (07-Jun-2000) diff --git a/tools/wrc/README.wrc b/tools/wrc/README.wrc index 9074f858751..c787d5b8e3a 100644 --- a/tools/wrc/README.wrc +++ b/tools/wrc/README.wrc @@ -1,4 +1,4 @@ -Release 1.1.4 of wrc (07-Jun-2000), the wine resource compiler. +Release 1.1.5 of wrc (12-Jun-2000), the wine resource compiler. See the file CHANGES for differences between the version and what has been corrected in the current version. @@ -42,6 +42,7 @@ Usage: wrc [options...] [infile[.rc|.res]] -I path Set include search dir to path (multiple -I allowed) -l lan Set default language to lan (default is neutral {0, 0}) -L Leave case of embedded filenames as is + -m Do not remap numerical resource IDs -n Do not generate .s file -N Do not preprocess input -o file Output to file (default is infile.[res|s|h] @@ -283,8 +284,6 @@ though): different action for win32 and win16 - PUSHBOX control is unsupported. The MS docs use it plenty, but neither MS' nor Borland's compiler supports it. -- Usertype resources with a type-clash are not handled correctly. These - should map onto other resources. Reporting bugs and patches -------------------------- diff --git a/tools/wrc/dumpres.c b/tools/wrc/dumpres.c index 56185fecfa7..f5caba68b7d 100644 --- a/tools/wrc/dumpres.c +++ b/tools/wrc/dumpres.c @@ -237,7 +237,7 @@ static void dump_raw_data(raw_data_t *d) { printf("- "); for(i = 0; i < 16; i++) - printf("%c", isprint(d->data[n-16+i]) ? d->data[n-16+i] : '.'); + printf("%c", isprint(d->data[n-16+i] & 0xff) ? d->data[n-16+i] : '.'); printf("\n%08x: ", n); } else @@ -250,7 +250,7 @@ static void dump_raw_data(raw_data_t *d) if(!j) j = 16; for(i = 0; i < j; i++) - printf("%c", isprint(d->data[n-j+i]) ? d->data[n-j+i] : '.'); + printf("%c", isprint(d->data[n-j+i] & 0xff) ? d->data[n-j+i] : '.'); printf("\n"); } diff --git a/tools/wrc/genres.c b/tools/wrc/genres.c index 6ab36ccc9a1..c544c7cf335 100644 --- a/tools/wrc/genres.c +++ b/tools/wrc/genres.c @@ -1746,7 +1746,7 @@ char *prep_nid_for_label(name_id_t *nid) buf[0] = '\0'; for(i = 0; *sptr && i < MAXNAMELEN; i++) { - if((unsigned)*sptr < 0x80 && isprint((char)*sptr)) + if((unsigned)*sptr < 0x80 && isprint(*sptr & 0xff)) buf[i] = *sptr++; else warning("Resourcename (str_unicode) contain unprintable characters or invalid translation, ignored"); @@ -1761,7 +1761,7 @@ char *prep_nid_for_label(name_id_t *nid) buf[0] = '\0'; for(i = 0; *cptr && i < MAXNAMELEN; i++) { - if((unsigned)*cptr < 0x80 && isprint(*cptr)) + if((unsigned)*cptr < 0x80 && isprint(*cptr & 0xff)) buf[i] = *cptr++; else warning("Resourcename (str_char) contain unprintable characters, ignored"); diff --git a/tools/wrc/newstruc.c b/tools/wrc/newstruc.c index 7584d8008ed..cc5a4262b5e 100644 --- a/tools/wrc/newstruc.c +++ b/tools/wrc/newstruc.c @@ -903,6 +903,7 @@ ver_words_t *add_ver_words(ver_words_t *w, int i) return w; } +#define MSGTAB_BAD_PTR(p, b, l, r) (((l) - ((char *)(p) - (char *)(b))) > (r)) messagetable_t *new_messagetable(raw_data_t *rd, int *memopt) { messagetable_t *msg = (messagetable_t *)xmalloc(sizeof(messagetable_t)); @@ -912,8 +913,17 @@ messagetable_t *new_messagetable(raw_data_t *rd, int *memopt) WORD hi; msg->data = rd; - msg->memopt = *memopt; - free(memopt); + if(memopt) + { + msg->memopt = *memopt; + free(memopt); + } + else + msg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; + + if(rd->size < sizeof(DWORD)) + yyerror("Invalid messagetable, size too small"); + nblk = *(DWORD *)rd->data; lo = WRC_LOWORD(nblk); hi = WRC_HIWORD(nblk); @@ -939,6 +949,8 @@ messagetable_t *new_messagetable(raw_data_t *rd, int *memopt) { msgtab_block_t *mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]); nblk = BYTESWAP_DWORD(nblk); + if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp))) + yyerror("Messagetable's blocks are outside of defined data"); for(i = 0; i < nblk; i++) { msgtab_entry_t *mep; @@ -952,7 +964,9 @@ messagetable_t *new_messagetable(raw_data_t *rd, int *memopt) { mep->length = BYTESWAP_WORD(mep->length); mep->flags = BYTESWAP_WORD(mep->flags); - if(mep->flags & 1) + if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length)) + yyerror("Messagetable's data for block %d, ID 0x%08lx is outside of defined data", (int)i, id); + if(mep->flags == 1) /* Docu says 'flags == 0x0001' for unicode */ { WORD *wp = (WORD *)&mep[1]; int l = mep->length/2 - 2; /* Length included header */ @@ -971,6 +985,7 @@ messagetable_t *new_messagetable(raw_data_t *rd, int *memopt) return msg; } +#undef MSGTAB_BAD_PTR void copy_raw_data(raw_data_t *dst, raw_data_t *src, int offs, int len) { diff --git a/tools/wrc/parser.l b/tools/wrc/parser.l index 0f531b33da8..1d7b4341bcf 100644 --- a/tools/wrc/parser.l +++ b/tools/wrc/parser.l @@ -518,7 +518,7 @@ L\" { char_number = 1; } yywarning("Unmatched text '%c' (0x%02x) YY_START=%d stripslevel=%d", - isprint(*yytext) ? *yytext : '.', *yytext, YY_START,stripslevel); + isprint(*yytext & 0xff) ? *yytext : '.', *yytext, YY_START,stripslevel); } %% diff --git a/tools/wrc/parser.y b/tools/wrc/parser.y index 1c6c9732600..4215982fdae 100644 --- a/tools/wrc/parser.y +++ b/tools/wrc/parser.y @@ -188,6 +188,7 @@ static toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); static string_t *make_filename(string_t *s); static resource_t *build_fontdirs(resource_t *tail); static resource_t *build_fontdir(resource_t **fnt, int nfnt); +static int rsrcid_to_token(int lookahead); %} %union{ @@ -411,7 +412,7 @@ resources */ preprocessor : '#' { want_nl = 1; } tNUMBER tSTRING any_nums tNL { - line_number = $3 - 1; + line_number = $3; input_name = $4->str.cstr; /* fprintf(stderr, "Now at %s:%d\n", input_name, line_number); */ } @@ -437,18 +438,18 @@ cjunk : tTYPEDEF { strip_til_semicolon(); } /* Parse top level resource definitions etc. */ resource - : nameid resource_definition { - $$ = $2; + : nameid usrcvt resource_definition { + $$ = $3; if($$) { $$->name = $1; if($1->type == name_ord) { - chat("Got %s (%d)",get_typename($2),$1->name.i_name); + chat("Got %s (%d)",get_typename($3),$1->name.i_name); } else if($1->type == name_str) { - chat("Got %s (%s)",get_typename($2),$1->name.s_name->str.cstr); + chat("Got %s (%s)",get_typename($3),$1->name.s_name->str.cstr); } } } @@ -474,6 +475,13 @@ resource } ; +/* + * Remapping of numerical resource types + * (see also comment of called function below) + */ +usrcvt : /* Empty */ { yychar = rsrcid_to_token(yychar); } + ; + /* * Get a valid name/id */ @@ -662,48 +670,6 @@ dlginit : tDLGINIT loadmemopts file_raw { $$ = new_dlginit($3, $2); } /* ------------------------------ UserType ------------------------------ */ userres : usertype loadmemopts file_raw { - if($1->type == name_ord) - { - switch($1->name.i_name) - { - case WRC_RT_CURSOR: /* Bad idea; cursors should generate directories */ - case WRC_RT_ANICURSOR: - case WRC_RT_ICON: - case WRC_RT_ANIICON: /* Bad idea; icons should generate directories */ - case WRC_RT_BITMAP: - case WRC_RT_FONT: /* Bad idea; fonts should generate directories */ - case WRC_RT_FONTDIR: - case WRC_RT_RCDATA: /* This cannot be interpreted anyway */ - case WRC_RT_MESSAGETABLE: /* This case is involked by mc.exe */ - case WRC_RT_DLGINIT: /* No real layout available */ - - /* These should never be invoked because they have their own layout */ - case WRC_RT_ACCELERATOR: - case WRC_RT_MENU: - case WRC_RT_DIALOG: - case WRC_RT_STRING: - case WRC_RT_TOOLBAR: - case WRC_RT_VERSION: - yywarning("Usertype uses special type-ID %d (wrc cannot yet re-interpret the data)", $1->name.i_name); - goto douser; - - case WRC_RT_GROUP_CURSOR: - case WRC_RT_GROUP_ICON: - yywarning("Usertype uses reserved type-ID %d, which is auto-generated", $1->name.i_name); - goto douser; - - case WRC_RT_DLGINCLUDE: - case WRC_RT_PLUGPLAY: - case WRC_RT_VXD: - case WRC_RT_HTML: - yywarning("Usertype uses reserved type-ID %d, which is not supported by wrc", $1->name.i_name); - default: - goto douser; - } - } - else - { - douser: #ifdef WORDS_BIGENDIAN if(pedantic && byteorder != WRC_BO_LITTLE) #else @@ -712,7 +678,6 @@ userres : usertype loadmemopts file_raw { yywarning("Byteordering is not little-endian and type cannot be interpreted"); $$ = new_user($1, $3, $2); } - } ; usertype: tNUMBER { @@ -2041,7 +2006,7 @@ byebye: static name_id_t *convert_ctlclass(name_id_t *cls) { - char *cc; + char *cc = NULL; int iclass; if(cls->type == name_ord) @@ -2213,7 +2178,7 @@ static event_t *add_string_event(string_t *key, int id, int flags, event_t *prev if(key->type != str_char) yyerror("Key code must be an ascii string"); - if((flags & WRC_AF_VIRTKEY) && (!isupper(key->str.cstr[0]) && !isdigit(key->str.cstr[0]))) + if((flags & WRC_AF_VIRTKEY) && (!isupper(key->str.cstr[0] & 0xff) && !isdigit(key->str.cstr[0] & 0xff))) yyerror("VIRTKEY code is not equal to ascii value"); if(key->str.cstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0) @@ -2821,3 +2786,131 @@ clean: return lst; } +/* + * This gets invoked to determine whether the next resource + * is to be of a standard-type (e.g. bitmaps etc.), or should + * be a user-type resource. This function is required because + * there is the _possibility_ of a lookahead token in the + * parser, which is generated from the "expr" state in the + * "nameid" parsing. + * + * The general resource format is: + * + * + * The can either be tIDENT or "expr". The latter + * will always generate a lookahead, which is the of the + * resource to parse. Otherwise, we need to get a new token from + * the scanner to determine the next step. + * + * The problem arrises when is numerical. This case should + * map onto default resource-types and be parsed as such instead + * of being mapped onto user-type resources. + * + * The trick lies in the fact that yacc (bison) doesn't care about + * intermediate changes of the lookahead while reducing a rule. We + * simply replace the lookahead with a token that will result in + * a shift to the appropriate rule for the specific resource-type. + */ +static int rsrcid_to_token(int lookahead) +{ + int token; + char *type = "?"; + + /* Get a token if we don't have one yet */ + if(lookahead == YYEMPTY) + lookahead = YYLEX; + + /* Only numbers are possibly interesting */ + switch(lookahead) + { + case tNUMBER: + case tLNUMBER: + break; + default: + return lookahead; + } + + token = lookahead; + + switch(yylval.num) + { + case WRC_RT_CURSOR: + type = "CURSOR"; + token = tCURSOR; + break; + case WRC_RT_ICON: + type = "ICON"; + token = tICON; + break; + case WRC_RT_BITMAP: + type = "BITMAP"; + token = tBITMAP; + break; + case WRC_RT_FONT: + type = "FONT"; + token = tFONT; + break; + case WRC_RT_FONTDIR: + type = "FONTDIR"; + token = tFONTDIR; + break; + case WRC_RT_RCDATA: + type = "RCDATA"; + token = tRCDATA; + break; + case WRC_RT_MESSAGETABLE: + type = "MESSAGETABLE"; + token = tMESSAGETABLE; + break; + case WRC_RT_DLGINIT: + type = "DLGINIT"; + token = tDLGINIT; + break; + case WRC_RT_ACCELERATOR: + type = "ACCELERATOR"; + token = tACCELERATORS; + break; + case WRC_RT_MENU: + type = "MENU"; + token = tMENU; + break; + case WRC_RT_DIALOG: + type = "DIALOG"; + token = tDIALOG; + break; + case WRC_RT_VERSION: + type = "VERSION"; + token = tVERSIONINFO; + break; + case WRC_RT_TOOLBAR: + type = "TOOLBAR"; + token = tTOOLBAR; + break; + + case WRC_RT_STRING: + type = "STRINGTABLE"; + break; + + case WRC_RT_ANICURSOR: + case WRC_RT_ANIICON: + case WRC_RT_GROUP_CURSOR: + case WRC_RT_GROUP_ICON: + yywarning("Usertype uses reserved type-ID %d, which is auto-generated", yylval.num); + return lookahead; + + case WRC_RT_DLGINCLUDE: + case WRC_RT_PLUGPLAY: + case WRC_RT_VXD: + case WRC_RT_HTML: + yywarning("Usertype uses reserved type-ID %d, which is not supported by wrc", yylval.num); + default: + return lookahead; + } + + if(remap) + return token; + else + yywarning("Usertype uses reserved type-ID %d, which is used by %s", yylval.num, type); + return lookahead; +} + diff --git a/tools/wrc/ppl.l b/tools/wrc/ppl.l index 4cf7716dc02..004fa9ed1b3 100644 --- a/tools/wrc/ppl.l +++ b/tools/wrc/ppl.l @@ -656,7 +656,7 @@ includelogicentry_t *includelogiclist = NULL; * This is a 'catch-all' rule to discover errors in the scanner * in an orderly manner. */ -<*>. seen_junk++; ppwarning("Unmatched text '%c' (0x%02x); please report\n", isprint(*pptext) ? *pptext : ' ', *pptext); +<*>. seen_junk++; ppwarning("Unmatched text '%c' (0x%02x); please report\n", isprint(*pptext & 0xff) ? *pptext : ' ', *pptext); <> { YY_BUFFER_STATE b = YY_CURRENT_BUFFER; @@ -954,7 +954,7 @@ static mtext_t *add_expand_text(mtext_t *mtp, macexpstackentry_t *mep, int *nnl) /* Remove trailing whitespace from current expansion text */ while(curdef_idx) { - if(isspace(curdef_text[curdef_idx-1])) + if(isspace(curdef_text[curdef_idx-1] & 0xff)) curdef_idx--; else break; @@ -968,7 +968,7 @@ static mtext_t *add_expand_text(mtext_t *mtp, macexpstackentry_t *mep, int *nnl) n = curdef_idx - tag; while(n) { - if(isspace(*cptr)) + if(isspace(*cptr & 0xff)) { cptr++; n--; @@ -1054,7 +1054,7 @@ static void expand_macro(macexpstackentry_t *mep) /* Strip trailing whitespace from expansion */ for(k = curdef_idx, cptr = &curdef_text[curdef_idx-1]; k > 0; k--, cptr--) { - if(!isspace(*cptr)) + if(!isspace(*cptr & 0xff)) break; } @@ -1069,7 +1069,7 @@ static void expand_macro(macexpstackentry_t *mep) /* Strip leading whitespace from expansion */ for(n = 0, cptr = curdef_text; n < k; n++, cptr++) { - if(!isspace(*cptr)) + if(!isspace(*cptr & 0xff)) break; } diff --git a/tools/wrc/ppy.y b/tools/wrc/ppy.y index a4c5b5a23b2..9acbb7542e3 100644 --- a/tools/wrc/ppy.y +++ b/tools/wrc/ppy.y @@ -569,7 +569,7 @@ static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp) while(len) { /* FIXME: should delete space from head of string */ - if(isspace(mtp->subst.text[len-1])) + if(isspace(mtp->subst.text[len-1] & 0xff)) mtp->subst.text[--len] = '\0'; else break; @@ -588,7 +588,7 @@ static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp) int len = strlen(tail->subst.text); while(len) { - if(isspace(tail->subst.text[len-1])) + if(isspace(tail->subst.text[len-1] & 0xff)) tail->subst.text[--len] = '\0'; else break; diff --git a/tools/wrc/wrc.c b/tools/wrc/wrc.c index 7255eaafa29..eea657cc73b 100644 --- a/tools/wrc/wrc.c +++ b/tools/wrc/wrc.c @@ -78,6 +78,7 @@ static char usage[] = " -I path Set include search dir to path (multiple -I allowed)\n" " -l lan Set default language to lan (default is neutral {0, 0})\n" " -L Leave case of embedded filenames as is\n" + " -m Do not remap numerical resource IDs\n" " -n Do not generate .s file\n" " -N Do not preprocess input\n" " -o file Output to file (default is infile.[res|s|h]\n" @@ -233,6 +234,11 @@ int preprocess_only = 0; */ int no_preprocess = 0; +/* + * Cleared when _not_ to remap resource types (-m option) + */ +int remap = 1; + char *output_name; /* The name given by the -o option */ char *input_name; /* The name given on the command-line */ char *header_name; /* The name given by the -H option */ @@ -279,7 +285,7 @@ int main(int argc,char *argv[]) strcat(cmdline, " "); } - while((optc = getopt(argc, argv, "a:AbB:cC:d:D:eEghH:I:l:LnNo:p:rstTVw:W")) != EOF) + while((optc = getopt(argc, argv, "a:AbB:cC:d:D:eEghH:I:l:LmnNo:p:rstTVw:W")) != EOF) { switch(optc) { @@ -352,6 +358,9 @@ int main(int argc,char *argv[]) case 'L': leave_case = 1; break; + case 'm': + remap = 0; + break; case 'n': create_s = 0; break; diff --git a/tools/wrc/wrc.h b/tools/wrc/wrc.h index cf4b3f3382d..b16b2cabea4 100644 --- a/tools/wrc/wrc.h +++ b/tools/wrc/wrc.h @@ -16,8 +16,8 @@ #define WRC_MAJOR_VERSION 1 #define WRC_MINOR_VERSION 1 -#define WRC_MICRO_VERSION 4 -#define WRC_RELEASEDATE "(07-Jun-2000)" +#define WRC_MICRO_VERSION 5 +#define WRC_RELEASEDATE "(09-Jun-2000)" #define WRC_STRINGIZE(a) #a #define WRC_VERSIONIZE(a,b,c) WRC_STRINGIZE(a) "." WRC_STRINGIZE(b) "." WRC_STRINGIZE(c) @@ -55,6 +55,7 @@ extern int leave_case; extern int byteorder; extern int preprocess_only; extern int no_preprocess; +extern int remap; extern char *prefix; extern char *output_name; diff --git a/tools/wrc/wrc.man b/tools/wrc/wrc.man index 81c25561f8f..f05175a0dd2 100644 --- a/tools/wrc/wrc.man +++ b/tools/wrc/wrc.man @@ -1,4 +1,4 @@ -.TH WRC 1 "June 07, 2000" "Version 1.1.4" "Wine Resource Compiler" +.TH WRC 1 "June 12, 2000" "Version 1.1.5" "Wine Resource Compiler" .SH NAME wrc \- Wine Resource Compiler .SH SYNOPSIS @@ -105,6 +105,17 @@ Set default language to \fIlan\fR. Default is the neutral language 0 Leave case of embedded filenames as is. All filenames are converted to lower case before they are attemped to be opened without this option. .TP +.I \-m +Do not remap numerical resource type-IDs onto standard resources. This will +cause all numerical resource type\-IDs to be treated as user\-type resources +and will not be checked nor byte\-reversed. Without this option, resources +with, for example, type\-ID 2 are parsed as bitmaps and other type\-IDs will +map onto their respective standard type. +Use this option with caution because it can create problems when compiling for, +for example, big\-endian platforms. The \fI\-m\fR option is usefull for +source\-files that contain overlapping type\-IDs, or when the format of the +resource is not 100% compliant. +.TP .I \-n Do not generate an assembly outputfile (suppress generation of \fB.s\fR file). Usefull if you are interested in a header file only. @@ -195,11 +206,6 @@ Fonts are parsed and generated, but there is no support for the generation of the FONTDIR yet. The user must supply the FONTDIR resource in the source to match the FONT resources. .PP -Usertype resources that have a type-clash with other resources are not -handled correctly. These should map onto the builtin resources as much -as possible (especially icons, cursors and fonts because of directory -generation and everything else that would require byte-order swapping). -.PP See the CHANGES and README.wrc files in the distribution for more comments on bugs and fixes across the versions. .SH AVAILABILITY