X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fresrc.c;h=59f182837563135246686f5852f8e8f12e87122b;hb=1d29ab86cb5145cac5045c1a4113d8b8fbd4d9c6;hp=24b423d93e98f82056ba1912073c89d712dad74f;hpb=4a594fce16683232bbb2e239d3e3ebcfcde16d1a;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/resrc.c b/binutils/resrc.c index 24b423d93e..59f1828375 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -1,6 +1,5 @@ /* resrc.c -- read and write Windows rc files. - Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007 - Free Software Foundation, Inc. + Copyright (C) 1997-2019 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. Rewritten by Kai Tietz, Onevision. @@ -8,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -32,11 +31,6 @@ #include "windres.h" #include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif #ifdef HAVE_SYS_WAIT_H #include @@ -221,7 +215,7 @@ run_cmd (char *cmd, const char *redir) i++; i++; - argv = alloca (sizeof (char *) * (i + 3)); + argv = xmalloc (sizeof (char *) * (i + 3)); i = 0; s = cmd; @@ -272,6 +266,7 @@ run_cmd (char *cmd, const char *redir) pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); + free (argv); /* Restore stdout to its previous setting. */ dup2 (stdout_save, STDOUT_FILENO); @@ -281,7 +276,7 @@ run_cmd (char *cmd, const char *redir) if (pid == -1) { - fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno)); + fatal ("%s %s: %s", errmsg_fmt, errmsg_arg, strerror (errno)); return 1; } @@ -328,7 +323,7 @@ open_input_stream (char *cmd) if (run_cmd (cmd, cpp_temp_file)) fatal (_("can't execute `%s': %s"), cmd, strerror (errno)); - cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);; + cpp_pipe = fopen (cpp_temp_file, FOPEN_RT); if (cpp_pipe == NULL) fatal (_("can't open temporary file `%s': %s"), cpp_temp_file, strerror (errno)); @@ -351,7 +346,33 @@ open_input_stream (char *cmd) return cpp_pipe; } -/* look for the preprocessor program */ +/* Determine if FILENAME contains special characters that + can cause problems unless the entire filename is quoted. */ + +static int +filename_need_quotes (const char *filename) +{ + if (filename == NULL || (filename[0] == '-' && filename[1] == 0)) + return 0; + + while (*filename != 0) + { + switch (*filename) + { + case '&': + case ' ': + case '<': + case '>': + case '|': + case '%': + return 1; + } + ++filename; + } + return 0; +} + +/* Look for the preprocessor program. */ static FILE * look_for_default (char *cmd, const char *prefix, int end_prefix, @@ -360,6 +381,7 @@ look_for_default (char *cmd, const char *prefix, int end_prefix, char *space; int found; struct stat s; + const char *fnquotes = (filename_need_quotes (filename) ? "\"" : ""); strcpy (cmd, prefix); @@ -390,8 +412,8 @@ look_for_default (char *cmd, const char *prefix, int end_prefix, strcpy (cmd, prefix); - sprintf (cmd + end_prefix, "%s %s %s", - DEFAULT_PREPROCESSOR, preprocargs, filename); + sprintf (cmd + end_prefix, "%s %s %s%s%s", + DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes); if (verbose) fprintf (stderr, _("Using `%s'\n"), cmd); @@ -407,21 +429,60 @@ read_rc_file (const char *filename, const char *preprocessor, const char *preprocargs, int language, int use_temp_file) { char *cmd; + const char *fnquotes = (filename_need_quotes (filename) ? "\"" : ""); + + if (filename == NULL) + filename = "-"; + /* Setup the default resource import path taken from input file. */ + else if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL) + { + char *edit, *dir; + + if (filename[0] == '/' + || filename[0] == '\\' + || filename[1] == ':') + /* Absolute path. */ + edit = dir = xstrdup (filename); + else + { + /* Relative path. */ + edit = dir = xmalloc (strlen (filename) + 3); + sprintf (dir, "./%s", filename); + } + + /* Walk dir backwards stopping at the first directory separator. */ + edit += strlen (dir); + while (edit > dir && (edit[-1] != '\\' && edit[-1] != '/')) + { + --edit; + edit[0] = 0; + } + + /* Cut off trailing slash. */ + --edit; + edit[0] = 0; + + /* Convert all back slashes to forward slashes. */ + while ((edit = strchr (dir, '\\')) != NULL) + *edit = '/'; + + windres_add_include_dir (dir); + } istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE; if (preprocargs == NULL) preprocargs = ""; - if (filename == NULL) - filename = "-"; if (preprocessor) { cmd = xmalloc (strlen (preprocessor) + strlen (preprocargs) + strlen (filename) + + strlen (fnquotes) * 2 + 10); - sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename); + sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs, + fnquotes, filename, fnquotes); cpp_pipe = open_input_stream (cmd); } @@ -435,6 +496,7 @@ read_rc_file (const char *filename, const char *preprocessor, + strlen (preprocessor) + strlen (preprocargs) + strlen (filename) + + strlen (fnquotes) * 2 #ifdef HAVE_EXECUTABLE_SUFFIX + strlen (EXECUTABLE_SUFFIX) #endif @@ -528,7 +590,19 @@ close_input_stream (void) else { if (cpp_pipe != NULL) - pclose (cpp_pipe); + { + int err; + err = pclose (cpp_pipe); + /* We are reading from a pipe, therefore we don't + know if cpp failed or succeeded until pclose. */ + if (err != 0 || errno == ECHILD) + { + /* Since this is also run via xatexit, safeguard. */ + cpp_pipe = NULL; + cpp_temp_file = NULL; + fatal (_("preprocessing failed.")); + } + } } /* Since this is also run via xatexit, safeguard. */ @@ -549,7 +623,7 @@ yyerror (const char *msg) void rcparse_warning (const char *msg) { - fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg); + fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg); } /* Die if we get an unexpected end of file. */ @@ -606,7 +680,8 @@ get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg) if (got == c) return; - fatal (_("%s: read of %lu returned %lu"), msg, (long) c, (long) got); + fatal (_("%s: read of %lu returned %lu"), + msg, (unsigned long) c, (unsigned long) got); } /* Define an accelerator resource. */ @@ -1511,8 +1586,9 @@ define_rcdata_number (rc_uint_type val, int dword) void define_stringtable (const rc_res_res_info *resinfo, - rc_uint_type stringid, const unichar *string) + rc_uint_type stringid, const unichar *string, int len) { + unichar *h; rc_res_id id; rc_res_resource *r; @@ -1536,9 +1612,12 @@ define_stringtable (const rc_res_res_info *resinfo, r->res_info = *resinfo; } - - r->u.stringtable->strings[stringid & 0xf].length = unichar_len (string); - r->u.stringtable->strings[stringid & 0xf].string = unichar_dup (string); + h = (unichar *) res_alloc ((len + 1) * sizeof (unichar)); + if (len) + memcpy (h, string, len * sizeof (unichar)); + h[len] = 0; + r->u.stringtable->strings[stringid & 0xf].length = (rc_uint_type) len; + r->u.stringtable->strings[stringid & 0xf].string = h; } void @@ -1723,16 +1802,15 @@ define_versioninfo (rc_res_id id, rc_uint_type language, /* Add string version info to a list of version information. */ rc_ver_info * -append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language, - rc_ver_stringinfo *strings) +append_ver_stringfileinfo (rc_ver_info *verinfo, + rc_ver_stringtable *stringtables) { rc_ver_info *vi, **pp; vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); vi->next = NULL; vi->type = VERINFO_STRING; - unicode_from_ascii ((rc_uint_type *) NULL, &vi->u.string.language, language); - vi->u.string.strings = strings; + vi->u.string.stringtables = stringtables; for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) ; @@ -1741,6 +1819,25 @@ append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language, return verinfo; } +rc_ver_stringtable * +append_ver_stringtable (rc_ver_stringtable *stringtable, + const char *language, + rc_ver_stringinfo *strings) +{ + rc_ver_stringtable *vst, **pp; + + vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable)); + vst->next = NULL; + unicode_from_ascii ((rc_uint_type *) NULL, &vst->language, language); + vst->strings = strings; + + for (pp = &stringtable; *pp != NULL; pp = &(*pp)->next) + ; + *pp = vst; + + return stringtable; +} + /* Add variable version info to a list of version information. */ rc_ver_info * @@ -1846,7 +1943,7 @@ indent (FILE *e, int c) without the need to store it somewhere externally. */ void -write_rc_file (const char *filename, const rc_res_directory *resources) +write_rc_file (const char *filename, const rc_res_directory *res_dir) { FILE *e; rc_uint_type language; @@ -1861,7 +1958,7 @@ write_rc_file (const char *filename, const rc_res_directory *resources) } language = (rc_uint_type) ((bfd_signed_vma) -1); - write_rc_directory (e, resources, (const rc_res_id *) NULL, + write_rc_directory (e, res_dir, (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); } @@ -2179,7 +2276,7 @@ write_rc_resource (FILE *e, const rc_res_id *type, default: res_id_print (e, *type, 0); break; - + PRINT_RT_NAME(RT_MANIFEST); PRINT_RT_NAME(RT_ANICURSOR); PRINT_RT_NAME(RT_ANIICON); @@ -2553,7 +2650,13 @@ write_rc_dialog_control (FILE *e, const rc_dialog_control *control) ci = NULL; } - if (control->text.named || control->text.u.id != 0) + /* For EDITTEXT, COMBOBOX, LISTBOX, and SCROLLBAR don't dump text. */ + if ((control->text.named || control->text.u.id != 0) + && (!ci + || (ci->class != CTL_EDIT + && ci->class != CTL_COMBOBOX + && ci->class != CTL_LISTBOX + && ci->class != CTL_SCROLLBAR))) { fprintf (e, " "); res_id_print (e, control->text, 1); @@ -2675,7 +2778,7 @@ write_rc_toolbar (FILE *e, const rc_toolbar *tb) indent (e, 2); if (it->id.u.id == 0) fprintf (e, "SEPARATOR\n"); - else + else fprintf (e, "BUTTON %d\n", (int) it->id.u.id); it = it->next; } @@ -2790,7 +2893,7 @@ test_rc_datablock_text (rc_uint_type length, const bfd_byte *data) int has_nl; rc_uint_type c; rc_uint_type i; - + if (length <= 1) return 0; @@ -2821,6 +2924,7 @@ write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data) { int has_error = 0; const struct bin_messagetable *mt; + fprintf (e, "BEGIN\n"); write_rc_datablock (e, length, data, 0, 0, 0); @@ -2830,53 +2934,68 @@ write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data) if (length < BIN_MESSAGETABLE_SIZE) has_error = 1; else - do { - rc_uint_type m, i; - mt = (const struct bin_messagetable *) data; - m = windres_get_32 (&wrtarget, mt->cblocks, length); - if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) - { - has_error = 1; - break; - } - for (i = 0; i < m; i++) - { - rc_uint_type low, high, offset; - const struct bin_messagetable_item *mti; + do + { + rc_uint_type m, i; + + mt = (const struct bin_messagetable *) data; + m = windres_get_32 (&wrtarget, mt->cblocks, length); + + if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) + { + has_error = 1; + break; + } + for (i = 0; i < m; i++) + { + rc_uint_type low, high, offset; + const struct bin_messagetable_item *mti; + + low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); + high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); + offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); + + while (low <= high) + { + rc_uint_type elen, flags; + if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) + { + has_error = 1; + break; + } + mti = (const struct bin_messagetable_item *) &data[offset]; + elen = windres_get_16 (&wrtarget, mti->length, 2); + flags = windres_get_16 (&wrtarget, mti->flags, 2); + if ((offset + elen) > length) + { + has_error = 1; + break; + } + wr_printcomment (e, "MessageId = 0x%x", low); + wr_printcomment (e, ""); + + if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) + { + /* PR 17512: file: 5c3232dc. */ + if (elen > BIN_MESSAGETABLE_ITEM_SIZE * 2) + unicode_print (e, (const unichar *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); + } + else + { + if (elen > BIN_MESSAGETABLE_ITEM_SIZE) + ascii_print (e, (const char *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE)); + } + + wr_printcomment (e,""); + ++low; + offset += elen; + } + } + } + while (0); - low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); - high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); - offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); - while (low <= high) - { - rc_uint_type elen, flags; - if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) - { - has_error = 1; - break; - } - mti = (const struct bin_messagetable_item *) &data[offset]; - elen = windres_get_16 (&wrtarget, mti->length, 2); - flags = windres_get_16 (&wrtarget, mti->flags, 2); - if ((offset + elen) > length) - { - has_error = 1; - break; - } - wr_printcomment (e, "MessageId = 0x%x", low); - wr_printcomment (e, ""); - if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) - unicode_print (e, (const unichar *) mti->data, - (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); - else - ascii_print (e, (const char *) mti->data, - (elen - BIN_MESSAGETABLE_ITEM_SIZE)); - wr_printcomment (e,""); - ++low; - offset += elen; - } - } - } while (0); if (has_error) wr_printcomment (e, "Illegal data"); wr_print_flush (e); @@ -2893,7 +3012,7 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_ fprintf (e, "BEGIN\n"); if (show_comment == -1) - { + { if (test_rc_datablock_text(length, data)) { rc_uint_type i, c; @@ -2906,12 +3025,12 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_ ; if (i < length && data[i] == '\n') ++i, ++c; - ascii_print (e, (const char *) &data[i - c], c); + ascii_print(e, (const char *) &data[i - c], c); fprintf (e, "\""); if (i < length) fprintf (e, "\n"); } - + if (i == 0) { indent (e, 2); @@ -2934,7 +3053,7 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_ u = (const unichar *) &data[i]; indent (e, 2); fprintf (e, "L\""); - + for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2) ; if (i < length && u[c] == '\n') @@ -2972,9 +3091,9 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_ { rc_uint_type k; rc_uint_type comment_start; - + comment_start = i; - + if (! first) indent (e, 2); @@ -2982,10 +3101,10 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_ { if (k == 0) plen = fprintf (e, "0x%lxL", - (long) windres_get_32 (&wrtarget, data + i, length - i)); + (unsigned long) windres_get_32 (&wrtarget, data + i, length - i)); else plen = fprintf (e, " 0x%lxL", - (long) windres_get_32 (&wrtarget, data + i, length - i)) - 1; + (unsigned long) windres_get_32 (&wrtarget, data + i, length - i)) - 1; if (has_next || (i + 4) < length) { if (plen>0 && plen < 11) @@ -3131,7 +3250,7 @@ write_rc_stringtable (FILE *e, const rc_res_id *name, { if (stringtable->strings[i].length != 0) { - fprintf (e, " %lu, ", (long) offset + i); + fprintf (e, " %lu, ", (unsigned long) offset + i); unicode_print_quoted (e, stringtable->strings[i].string, stringtable->strings[i].length); fprintf (e, "\n"); @@ -3184,25 +3303,31 @@ write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo) { case VERINFO_STRING: { + const rc_ver_stringtable *vst; const rc_ver_stringinfo *vs; fprintf (e, " BLOCK \"StringFileInfo\"\n"); fprintf (e, " BEGIN\n"); - fprintf (e, " BLOCK "); - unicode_print_quoted (e, vi->u.string.language, -1); - fprintf (e, "\n"); - fprintf (e, " BEGIN\n"); - for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) + for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next) { - fprintf (e, " VALUE "); - unicode_print_quoted (e, vs->key, -1); - fprintf (e, ", "); - unicode_print_quoted (e, vs->value, -1); + fprintf (e, " BLOCK "); + unicode_print_quoted (e, vst->language, -1); + fprintf (e, "\n"); - } + fprintf (e, " BEGIN\n"); - fprintf (e, " END\n"); + for (vs = vst->strings; vs != NULL; vs = vs->next) + { + fprintf (e, " VALUE "); + unicode_print_quoted (e, vs->key, -1); + fprintf (e, ", "); + unicode_print_quoted (e, vs->value, -1); + fprintf (e, "\n"); + } + + fprintf (e, " END\n"); + } fprintf (e, " END\n"); break; }