1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27: #include "sysdep.h"
28: #include "bfd.h"
29: #include "bucomm.h"
30: #include "libiberty.h"
31: #include "safe-ctype.h"
32: #include "windres.h"
33:
34: #include <assert.h>
35: #include <errno.h>
36: #include <sys/stat.h>
37: #ifdef HAVE_UNISTD_H
38: #include <unistd.h>
39: #endif
40:
41: #ifdef HAVE_SYS_WAIT_H
42: #include <sys/wait.h>
43: #else
44: #if ! defined (_WIN32) || defined (__CYGWIN__)
45: #ifndef WIFEXITED
46: #define WIFEXITED(w) (((w)&0377) == 0)
47: #endif
48: #ifndef WIFSIGNALED
49: #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
50: #endif
51: #ifndef WTERMSIG
52: #define WTERMSIG(w) ((w) & 0177)
53: #endif
54: #ifndef WEXITSTATUS
55: #define WEXITSTATUS(w) (((w) >> 8) & 0377)
56: #endif
57: #else
58: #ifndef WIFEXITED
59: #define WIFEXITED(w) (((w) & 0xff) == 0)
60: #endif
61: #ifndef WIFSIGNALED
62: #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
63: #endif
64: #ifndef WTERMSIG
65: #define WTERMSIG(w) ((w) & 0x7f)
66: #endif
67: #ifndef WEXITSTATUS
68: #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
69: #endif
70: #endif
71: #endif
72:
73: #ifndef STDOUT_FILENO
74: #define STDOUT_FILENO 1
75: #endif
76:
77: #if defined (_WIN32) && ! defined (__CYGWIN__)
78: #define popen _popen
79: #define pclose _pclose
80: #endif
81:
82:
83:
84: #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
85:
86:
87:
88:
89: struct icondir
90: {
91:
92: bfd_byte width;
93:
94: bfd_byte height;
95:
96: bfd_byte colorcount;
97: union
98: {
99: struct
100: {
101:
102: unsigned short planes;
103:
104: unsigned short bits;
105: } icon;
106: struct
107: {
108:
109: unsigned short xhotspot;
110:
111: unsigned short yhotspot;
112: } cursor;
113: } u;
114:
115: unsigned long bytes;
116:
117: unsigned long offset;
118: };
119:
120:
121:
122: char *rc_filename;
123:
124:
125:
126: int rc_lineno;
127:
128:
129:
130: FILE *cpp_pipe;
131:
132:
133:
134:
135: static char *cpp_temp_file;
136:
137:
138:
139: static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
140:
141:
142:
143: static rc_res_directory *resources;
144:
145:
146:
147: static int cursors;
148:
149:
150:
151: static int fonts;
152:
153:
154:
155: rc_fontdir *fontdirs;
156:
157:
158:
159: rc_res_res_info fontdirs_resinfo;
160:
161:
162:
163: static int icons;
164:
165:
166:
167: static windres_bfd wrtarget =
168: {
169: (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET
170: };
171:
172:
173:
174: static void define_font_rcdata (rc_res_id, const rc_res_res_info *,
175: rc_rcdata_item *);
176: static void define_icon_rcdata (rc_res_id, const rc_res_res_info *,
177: rc_rcdata_item *);
178: static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *,
179: rc_rcdata_item *);
180: static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *,
181: rc_rcdata_item *);
182: static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *,
183: rc_rcdata_item *);
184: static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *,
185: rc_rcdata_item *);
186: static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *);
187: static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *);
188:
189: static int run_cmd (char *, const char *);
190: static FILE *open_input_stream (char *);
191: static FILE *look_for_default
192: (char *, const char *, int, const char *, const char *);
193: static void close_input_stream (void);
194: static void unexpected_eof (const char *);
195: static int get_word (FILE *, const char *);
196: static unsigned long get_long (FILE *, const char *);
197: static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *);
198: static void define_fontdirs (void);
199: ^L
200:
201:
202: static int
203: run_cmd (char *cmd, const char *redir)
204: {
205: char *s;
206: int pid, wait_status, retcode;
207: int i;
208: const char **argv;
209: char *errmsg_fmt, *errmsg_arg;
210: char *temp_base = choose_temp_base ();
211: int in_quote;
212: char sep;
213: int redir_handle = -1;
214: int stdout_save = -1;
215:
216:
217: i = 0;
218:
219: for (s = cmd; *s; s++)
220: if (*s == ' ')
221: i++;
222:
223: i++;
224: argv = alloca (sizeof (char *) * (i + 3));
225: i = 0;
226: s = cmd;
227:
228: while (1)
229: {
230: while (*s == ' ' && *s != 0)
231: s++;
232:
233: if (*s == 0)
234: break;
235:
236: in_quote = (*s == '\'' || *s == '"');
237: sep = (in_quote) ? *s++ : ' ';
238: argv[i++] = s;
239:
240: while (*s != sep && *s != 0)
241: s++;
242:
243: if (*s == 0)
244: break;
245:
246: *s++ = 0;
247:
248: if (in_quote)
249: s++;
250: }
251: argv[i++] = NULL;
252:
253:
254:
255:
256: fflush (stdout);
257: fflush (stderr);
258:
259:
260: redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
261: if (redir_handle == -1)
262: fatal (_("can't open temporary file `%s': %s"), redir,
263: strerror (errno));
264:
265:
266: stdout_save = dup (STDOUT_FILENO);
267: if (stdout_save == -1)
268: fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
269:
270:
271: dup2 (redir_handle, STDOUT_FILENO);
272:
273: pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
274: &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
275:
276:
277: dup2 (stdout_save, STDOUT_FILENO);
278:
279:
280: close (redir_handle);
281:
282: if (pid == -1)
283: {
284: fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
285: return 1;
286: }
287:
288: retcode = 0;
289: pid = pwait (pid, &wait_status, 0);
290:
291: if (pid == -1)
292: {
293: fatal (_("wait: %s"), strerror (errno));
294: retcode = 1;
295: }
296: else if (WIFSIGNALED (wait_status))
297: {
298: fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
299: retcode = 1;
300: }
301: else if (WIFEXITED (wait_status))
302: {
303: if (WEXITSTATUS (wait_status) != 0)
304: {
305: fatal (_("%s exited with status %d"), cmd,
306: WEXITSTATUS (wait_status));
307: retcode = 1;
308: }
309: }
310: else
311: retcode = 1;
312:
313: return retcode;
314: }
315:
316: static FILE *
317: open_input_stream (char *cmd)
318: {
319: if (istream_type == ISTREAM_FILE)
320: {
321: char *fileprefix;
322:
323: fileprefix = choose_temp_base ();
324: cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
325: sprintf (cpp_temp_file, "%s.irc", fileprefix);
326: free (fileprefix);
327:
328: if (run_cmd (cmd, cpp_temp_file))
329: fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
330:
331: cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
332: if (cpp_pipe == NULL)
333: fatal (_("can't open temporary file `%s': %s"),
334: cpp_temp_file, strerror (errno));
335:
336: if (verbose)
337: fprintf (stderr,
338: _("Using temporary file `%s' to read preprocessor output\n"),
339: cpp_temp_file);
340: }
341: else
342: {
343: cpp_pipe = popen (cmd, FOPEN_RT);
344: if (cpp_pipe == NULL)
345: fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
346: if (verbose)
347: fprintf (stderr, _("Using popen to read preprocessor output\n"));
348: }
349:
350: xatexit (close_input_stream);
351: return cpp_pipe;
352: }
353:
354:
355:
356:
357: static int
358: filename_need_quotes (const char *filename)
359: {
360: if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
361: return 0;
362:
363: while (*filename != 0)
364: {
365: switch (*filename)
366: {
367: case '&':
368: case ' ':
369: case '<':
370: case '>':
371: case '|':
372: case '%':
373: return 1;
374: }
375: ++filename;
376: }
377: return 0;
378: }
379:
380:
381:
382: static FILE *
383: look_for_default (char *cmd, const char *prefix, int end_prefix,
384: const char *preprocargs, const char *filename)
385: {
386: char *space;
387: int found;
388: struct stat s;
389: const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
390:
391: strcpy (cmd, prefix);
392:
393: sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
394: space = strchr (cmd + end_prefix, ' ');
395: if (space)
396: *space = 0;
397:
398: if (
399: #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
400: strchr (cmd, '\\') ||
401: #endif
402: strchr (cmd, '/'))
403: {
404: found = (stat (cmd, &s) == 0
405: #ifdef HAVE_EXECUTABLE_SUFFIX
406: || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
407: #endif
408: );
409:
410: if (! found)
411: {
412: if (verbose)
413: fprintf (stderr, _("Tried `%s'\n"), cmd);
414: return NULL;
415: }
416: }
417:
418: strcpy (cmd, prefix);
419:
420: sprintf (cmd + end_prefix, "%s %s %s%s%s",
421: DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
422:
423: if (verbose)
424: fprintf (stderr, _("Using `%s'\n"), cmd);
425:
426: cpp_pipe = open_input_stream (cmd);
427: return cpp_pipe;
428: }
429:
430:
431:
432: rc_res_directory *
433: read_rc_file (const char *filename, const char *preprocessor,
434: const char *preprocargs, int language, int use_temp_file)
435: {
436: char *cmd;
437: const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
438:
439:
440: if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL)
441: {
442: char *e, *c;
443:
444: if (filename[0] == '/'
445: || filename[0] == '\\'
446: || filename[1] == ':')
447: e = c = xstrdup (filename);
448: else
449: {
450: e = c = xmalloc (strlen (filename) + 3);
451: sprintf (c, "./%s", filename);
452: }
453: e += strlen (c);
454: while (e > c && (e[-1] != '\\' && e[-1] != '/'))
455: {
456: --e;
457: e[0] = 0;
458: }
459:
460: --e;
461: e[0] = 0;
462: while ((e = strchr (c, '\\')) != NULL)
463: *e = '/';
464:
465: windres_add_include_dir (e);
466: }
467:
468: istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
469:
470: if (preprocargs == NULL)
471: preprocargs = "";
472: if (filename == NULL)
473: filename = "-";
474:
475: if (preprocessor)
476: {
477: cmd = xmalloc (strlen (preprocessor)
478: + strlen (preprocargs)
479: + strlen (filename)
480: + strlen (fnquotes) * 2
481: + 10);
482: sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs,
483: fnquotes, filename, fnquotes);
484:
485: cpp_pipe = open_input_stream (cmd);
486: }
487: else
488: {
489: char *dash, *slash, *cp;
490:
491: preprocessor = DEFAULT_PREPROCESSOR;
492:
493: cmd = xmalloc (strlen (program_name)
494: + strlen (preprocessor)
495: + strlen (preprocargs)
496: + strlen (filename)
497: + strlen (fnquotes) * 2
498: #ifdef HAVE_EXECUTABLE_SUFFIX
499: + strlen (EXECUTABLE_SUFFIX)
500: #endif
501: + 10);
502:
503:
504: dash = slash = 0;
505: for (cp = program_name; *cp; cp++)
506: {
507: if (*cp == '-')
508: dash = cp;
509: if (
510: #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
511: *cp == ':' || *cp == '\\' ||
512: #endif
513: *cp == '/')
514: {
515: slash = cp;
516: dash = 0;
517: }
518: }
519:
520: cpp_pipe = 0;
521:
522: if (dash)
523: {
524:
525:
526:
527: cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1,
528: preprocargs, filename);
529: }
530:
531: if (slash && ! cpp_pipe)
532: {
533:
534:
535:
536: cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1,
537: preprocargs, filename);
538: }
539:
540: if (! cpp_pipe)
541: {
542:
543:
544: cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
545: }
546:
547: }
548:
549: free (cmd);
550:
551: rc_filename = xstrdup (filename);
552: rc_lineno = 1;
553: if (language != -1)
554: rcparse_set_language (language);
555: yyparse ();
556: rcparse_discard_strings ();
557:
558: close_input_stream ();
559:
560: if (fontdirs != NULL)
561: define_fontdirs ();
562:
563: free (rc_filename);
564: rc_filename = NULL;
565:
566: return resources;
567: }
568:
569:
570:
571: static void
572: close_input_stream (void)
573: {
574: if (istream_type == ISTREAM_FILE)
575: {
576: if (cpp_pipe != NULL)
577: fclose (cpp_pipe);
578:
579: if (cpp_temp_file != NULL)
580: {
581: int errno_save = errno;
582:
583: unlink (cpp_temp_file);
584: errno = errno_save;
585: free (cpp_temp_file);
586: }
587: }
588: else
589: {
590: if