2007-12-19 Pierre Muller <muller@ics-u-strasbg.fr>
[deliverable/binutils-gdb.git] / binutils / resres.c
CommitLineData
252b5132 1/* resres.c: read_res_file and write_res_file implementation for windres.
4a594fce
NC
2 Copyright 1998, 1999, 2001, 2002, 2007
3 Free Software Foundation, Inc.
252b5132 4 Written by Anders Norlander <anorland@hem2.passagen.se>.
4a594fce 5 Rewritten by Kai Tietz, Onevision.
252b5132
RH
6
7 This file is part of GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
32866df7 11 the Free Software Foundation; either version 3 of the License, or
252b5132
RH
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
b43b5d5f
NC
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22 02110-1301, USA. */
252b5132 23
34ca6cf8
ILT
24/* FIXME: This file does not work correctly in a cross configuration.
25 It assumes that it can use fread and fwrite to read and write
26 integers. It does no swapping. */
27
3db64b00 28#include "sysdep.h"
252b5132 29#include "bfd.h"
3db64b00 30#include "bucomm.h"
4a594fce 31#include "libiberty.h"
252b5132
RH
32#include "windres.h"
33
34#include <assert.h>
35#include <time.h>
36
4a594fce
NC
37static rc_uint_type write_res_directory (windres_bfd *, rc_uint_type,
38 const rc_res_directory *, const rc_res_id *,
39 const rc_res_id *, rc_uint_type *, int);
40static rc_uint_type write_res_resource (windres_bfd *, rc_uint_type,const rc_res_id *,
41 const rc_res_id *, const rc_res_resource *,
42 rc_uint_type *);
43static rc_uint_type write_res_bin (windres_bfd *, rc_uint_type, const rc_res_resource *,
44 const rc_res_id *, const rc_res_id *,
45 const rc_res_res_info *);
252b5132 46
4a594fce
NC
47static rc_uint_type write_res_id (windres_bfd *, rc_uint_type, const rc_res_id *);
48static rc_uint_type write_res_info (windres_bfd *, rc_uint_type, const rc_res_res_info *);
49static rc_uint_type write_res_data_hdr (windres_bfd *, rc_uint_type, res_hdr *);
252b5132 50
4a594fce
NC
51static rc_uint_type write_res_header (windres_bfd *, rc_uint_type, rc_uint_type,
52 const rc_res_id *, const rc_res_id *,
53 const rc_res_res_info *);
54
55static int read_resource_entry (windres_bfd *, rc_uint_type *, rc_uint_type);
56static void read_res_data (windres_bfd *, rc_uint_type *, rc_uint_type, void *,
57 rc_uint_type);
58static void read_res_data_hdr (windres_bfd *, rc_uint_type *, rc_uint_type, res_hdr *);
59static void read_res_id (windres_bfd *, rc_uint_type *, rc_uint_type, rc_res_id *);
60static unichar *read_unistring (windres_bfd *, rc_uint_type *, rc_uint_type, rc_uint_type *);
61static void skip_null_resource (windres_bfd *, rc_uint_type *, rc_uint_type);
62static int probe_binary (windres_bfd *wrbfd, rc_uint_type);
63
64static unsigned long get_id_size (const rc_res_id *);
65
66static void res_add_resource (rc_res_resource *, const rc_res_id *,
67 const rc_res_id *, rc_uint_type, int);
252b5132 68
4a594fce
NC
69static void res_append_resource (rc_res_directory **, rc_res_resource *,
70 int, const rc_res_id *, int);
71
72static rc_res_directory *resources = NULL;
252b5132 73
252b5132
RH
74static const char *filename;
75
76extern char *program_name;
77
78/* Read resource file */
4a594fce
NC
79rc_res_directory *
80read_res_file (const char *fn)
252b5132 81{
4a594fce
NC
82 rc_uint_type off, flen;
83 windres_bfd wrbfd;
84 bfd *abfd;
85 asection *sec;
252b5132 86 filename = fn;
252b5132 87
4a594fce
NC
88 flen = (rc_uint_type) get_file_size (filename);
89 if (! flen)
90 fatal ("can't open '%s' for input.", filename);
91 abfd = windres_open_as_binary (filename, 1);
92 sec = bfd_get_section_by_name (abfd, ".data");
93 if (sec == NULL)
94 bfd_fatal ("bfd_get_section_by_name");
95 set_windres_bfd (&wrbfd, abfd, sec,
96 (target_is_bigendian ? WR_KIND_BFD_BIN_B
97 : WR_KIND_BFD_BIN_L));
98 off = 0;
99
100 if (! probe_binary (&wrbfd, flen))
101 set_windres_bfd_endianess (&wrbfd, ! target_is_bigendian);
102
103 skip_null_resource (&wrbfd, &off, flen);
252b5132 104
4a594fce 105 while (read_resource_entry (&wrbfd, &off, flen))
252b5132
RH
106 ;
107
4a594fce 108 bfd_close (abfd);
252b5132
RH
109
110 return resources;
111}
112
113/* Write resource file */
114void
4a594fce 115write_res_file (const char *fn,const rc_res_directory *resdir)
252b5132 116{
4a594fce
NC
117 asection *sec;
118 rc_uint_type language;
119 bfd *abfd;
120 windres_bfd wrbfd;
121 unsigned long sec_length = 0,sec_length_wrote;
122 static const bfd_byte sign[] =
252b5132
RH
123 {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
124 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
252b5132
RH
127
128 filename = fn;
129
4a594fce
NC
130 abfd = windres_open_as_binary (filename, 0);
131 sec = bfd_make_section (abfd, ".data");
132 if (sec == NULL)
133 bfd_fatal ("bfd_make_section");
134 if (! bfd_set_section_flags (abfd, sec,
135 (SEC_HAS_CONTENTS | SEC_ALLOC
136 | SEC_LOAD | SEC_DATA)))
137 bfd_fatal ("bfd_set_section_flags");
138 /* Requiring this is probably a bug in BFD. */
139 sec->output_section = sec;
140
141 set_windres_bfd (&wrbfd, abfd, sec,
142 (target_is_bigendian ? WR_KIND_BFD_BIN_B
143 : WR_KIND_BFD_BIN_L));
252b5132
RH
144
145 language = -1;
4a594fce
NC
146 sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir,
147 (const rc_res_id *) NULL,
148 (const rc_res_id *) NULL, &language, 1);
149 if (! bfd_set_section_size (abfd, sec, (sec_length + 3) & ~3))
150 bfd_fatal ("bfd_set_section_size");
151 if ((sec_length & 3) != 0)
152 set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3));
153 set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign));
154 language = -1;
155 sec_length_wrote = write_res_directory (&wrbfd, 0x20UL, resdir,
156 (const rc_res_id *) NULL,
157 (const rc_res_id *) NULL,
158 &language, 1);
159 if (sec_length != sec_length_wrote)
160 fatal ("res write failed with different sizes (%lu/%lu).", (long) sec_length,
161 (long) sec_length_wrote);
162
163 bfd_close (abfd);
164 return;
252b5132
RH
165}
166
167/* Read a resource entry, returns 0 when all resources are read */
168static int
4a594fce 169read_resource_entry (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax)
252b5132 170{
4a594fce
NC
171 rc_res_id type;
172 rc_res_id name;
173 rc_res_res_info resinfo;
174 res_hdr reshdr;
252b5132
RH
175 void *buff;
176
4a594fce
NC
177 rc_res_resource *r;
178 struct bin_res_info l;
252b5132 179
4a594fce 180 off[0] = (off[0] + 3) & ~3;
252b5132
RH
181
182 /* Read header */
4a594fce 183 if ((off[0] + 8) > omax)
252b5132 184 return 0;
4a594fce 185 read_res_data_hdr (wrbfd, off, omax, &reshdr);
252b5132
RH
186
187 /* read resource type */
4a594fce 188 read_res_id (wrbfd, off, omax, &type);
252b5132 189 /* read resource id */
4a594fce 190 read_res_id (wrbfd, off, omax, &name);
252b5132 191
4a594fce 192 off[0] = (off[0] + 3) & ~3;
252b5132
RH
193
194 /* Read additional resource header */
4a594fce
NC
195 read_res_data (wrbfd, off, omax, &l, BIN_RES_INFO_SIZE);
196 resinfo.version = windres_get_32 (wrbfd, l.version, 4);
197 resinfo.memflags = windres_get_16 (wrbfd, l.memflags, 2);
198 resinfo.language = windres_get_16 (wrbfd, l.language, 2);
199 /* resinfo.version2 = windres_get_32 (wrbfd, l.version2, 4); */
200 resinfo.characteristics = windres_get_32 (wrbfd, l.characteristics, 4);
252b5132 201
4a594fce 202 off[0] = (off[0] + 3) & ~3;
252b5132
RH
203
204 /* Allocate buffer for data */
205 buff = res_alloc (reshdr.data_size);
206 /* Read data */
4a594fce 207 read_res_data (wrbfd, off, omax, buff, reshdr.data_size);
252b5132 208 /* Convert binary data to resource */
4a594fce 209 r = bin_to_res (wrbfd, type, buff, reshdr.data_size);
252b5132
RH
210 r->res_info = resinfo;
211 /* Add resource to resource directory */
212 res_add_resource (r, &type, &name, resinfo.language, 0);
213
214 return 1;
215}
216
217/* write resource directory to binary resource file */
4a594fce
NC
218static rc_uint_type
219write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_directory *rd,
220 const rc_res_id *type, const rc_res_id *name, rc_uint_type *language,
221 int level)
252b5132 222{
4a594fce 223 const rc_res_entry *re;
252b5132
RH
224
225 for (re = rd->entries; re != NULL; re = re->next)
226 {
227 switch (level)
228 {
229 case 1:
230 /* If we're at level 1, the key of this resource is the
231 type. This normally duplicates the information we have
232 stored with the resource itself, but we need to remember
233 the type if this is a user define resource type. */
234 type = &re->id;
235 break;
236
237 case 2:
238 /* If we're at level 2, the key of this resource is the name
53c7db4b 239 we are going to use in the rc printout. */
252b5132
RH
240 name = &re->id;
241 break;
242
243 case 3:
244 /* If we're at level 3, then this key represents a language.
245 Use it to update the current language. */
4a594fce 246 if (! re->id.named
34ca6cf8 247 && re->id.u.id != (unsigned long) *language
252b5132
RH
248 && (re->id.u.id & 0xffff) == re->id.u.id)
249 {
250 *language = re->id.u.id;
251 }
252 break;
253
254 default:
255 break;
256 }
257
258 if (re->subdir)
4a594fce
NC
259 off = write_res_directory (wrbfd, off, re->u.dir, type, name, language,
260 level + 1);
252b5132
RH
261 else
262 {
263 if (level == 3)
264 {
265 /* This is the normal case: the three levels are
266 TYPE/NAME/LANGUAGE. NAME will have been set at level
267 2, and represents the name to use. We probably just
268 set LANGUAGE, and it will probably match what the
269 resource itself records if anything. */
4a594fce
NC
270 off = write_res_resource (wrbfd, off, type, name, re->u.res,
271 language);
252b5132
RH
272 }
273 else
274 {
275 fprintf (stderr, "// Resource at unexpected level %d\n", level);
4a594fce
NC
276 off = write_res_resource (wrbfd, off, type, (rc_res_id *) NULL,
277 re->u.res, language);
252b5132
RH
278 }
279 }
280 }
281
4a594fce 282 return off;
252b5132
RH
283}
284
4a594fce
NC
285static rc_uint_type
286write_res_resource (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *type,
287 const rc_res_id *name, const rc_res_resource *res,
288 rc_uint_type *language ATTRIBUTE_UNUSED)
252b5132
RH
289{
290 int rt;
291
292 switch (res->type)
293 {
294 default:
295 abort ();
296
297 case RES_TYPE_ACCELERATOR:
298 rt = RT_ACCELERATOR;
299 break;
300
301 case RES_TYPE_BITMAP:
302 rt = RT_BITMAP;
303 break;
304
305 case RES_TYPE_CURSOR:
306 rt = RT_CURSOR;
307 break;
308
309 case RES_TYPE_GROUP_CURSOR:
310 rt = RT_GROUP_CURSOR;
311 break;
312
313 case RES_TYPE_DIALOG:
314 rt = RT_DIALOG;
315 break;
316
317 case RES_TYPE_FONT:
318 rt = RT_FONT;
319 break;
320
321 case RES_TYPE_FONTDIR:
322 rt = RT_FONTDIR;
323 break;
324
325 case RES_TYPE_ICON:
326 rt = RT_ICON;
327 break;
328
329 case RES_TYPE_GROUP_ICON:
330 rt = RT_GROUP_ICON;
331 break;
332
333 case RES_TYPE_MENU:
334 rt = RT_MENU;
335 break;
336
337 case RES_TYPE_MESSAGETABLE:
338 rt = RT_MESSAGETABLE;
339 break;
340
341 case RES_TYPE_RCDATA:
342 rt = RT_RCDATA;
343 break;
344
345 case RES_TYPE_STRINGTABLE:
346 rt = RT_STRING;
347 break;
348
349 case RES_TYPE_USERDATA:
350 rt = 0;
351 break;
352
353 case RES_TYPE_VERSIONINFO:
354 rt = RT_VERSION;
355 break;
4a594fce
NC
356
357 case RES_TYPE_TOOLBAR:
358 rt = RT_TOOLBAR;
359 break;
252b5132
RH
360 }
361
362 if (rt != 0
363 && type != NULL
34ca6cf8 364 && (type->named || type->u.id != (unsigned long) rt))
252b5132
RH
365 {
366 fprintf (stderr, "// Unexpected resource type mismatch: ");
367 res_id_print (stderr, *type, 1);
368 fprintf (stderr, " != %d", rt);
369 abort ();
370 }
371
4a594fce 372 return write_res_bin (wrbfd, off, res, type, name, &res->res_info);
252b5132
RH
373}
374
375/* Write a resource in binary resource format */
4a594fce
NC
376static rc_uint_type
377write_res_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res,
378 const rc_res_id *type, const rc_res_id *name,
379 const rc_res_res_info *resinfo)
252b5132 380{
4a594fce
NC
381 rc_uint_type noff;
382 rc_uint_type datasize = 0;
252b5132 383
4a594fce
NC
384 noff = res_to_bin ((windres_bfd *) NULL, off, res);
385 datasize = noff - off;
252b5132 386
4a594fce
NC
387 off = write_res_header (wrbfd, off, datasize, type, name, resinfo);
388 return res_to_bin (wrbfd, off, res);
252b5132
RH
389}
390
391/* Get number of bytes needed to store an id in binary format */
392static unsigned long
393get_id_size (id)
4a594fce 394 const rc_res_id *id;
252b5132
RH
395{
396 if (id->named)
397 return sizeof (unichar) * (id->u.n.length + 1);
398 else
399 return sizeof (unichar) * 2;
400}
401
402/* Write a resource header */
4a594fce
NC
403static rc_uint_type
404write_res_header (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type datasize,
405 const rc_res_id *type, const rc_res_id *name,
406 const rc_res_res_info *resinfo)
252b5132 407{
4a594fce 408 res_hdr reshdr;
252b5132
RH
409 reshdr.data_size = datasize;
410 reshdr.header_size = 24 + get_id_size (type) + get_id_size (name);
411
5f16d855
DD
412 reshdr.header_size = (reshdr.header_size + 3) & ~3;
413
4a594fce
NC
414 off = (off + 3) & ~3;
415
416 off = write_res_data_hdr (wrbfd, off, &reshdr);
417 off = write_res_id (wrbfd, off, type);
418 off = write_res_id (wrbfd, off, name);
252b5132 419
4a594fce 420 off = (off + 3) & ~3;
252b5132 421
4a594fce
NC
422 off = write_res_info (wrbfd, off, resinfo);
423 off = (off + 3) & ~3;
424 return off;
252b5132
RH
425}
426
4a594fce
NC
427static rc_uint_type
428write_res_data_hdr (windres_bfd *wrbfd, rc_uint_type off, res_hdr *hdr)
429{
430 if (wrbfd)
431 {
432 struct bin_res_hdr brh;
433 windres_put_32 (wrbfd, brh.data_size, hdr->data_size);
434 windres_put_32 (wrbfd, brh.header_size, hdr->header_size);
435 set_windres_bfd_content (wrbfd, &brh, off, BIN_RES_HDR_SIZE);
436 }
437 return off + BIN_RES_HDR_SIZE;
438}
252b5132 439
252b5132 440static void
4a594fce
NC
441read_res_data_hdr (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax,
442 res_hdr *reshdr)
252b5132 443{
4a594fce
NC
444 struct bin_res_hdr brh;
445
446 if ((off[0] + BIN_RES_HDR_SIZE) > omax)
447 fatal ("%s: unexpected end of file %ld/%ld", filename,(long) off[0], (long) omax);
448
449 get_windres_bfd_content (wrbfd, &brh, off[0], BIN_RES_HDR_SIZE);
450 reshdr->data_size = windres_get_32 (wrbfd, brh.data_size, 4);
451 reshdr->header_size = windres_get_32 (wrbfd, brh.header_size, 4);
452 off[0] += BIN_RES_HDR_SIZE;
252b5132
RH
453}
454
455/* Read data from file, abort on failure */
456static void
4a594fce
NC
457read_res_data (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, void *data,
458 rc_uint_type size)
252b5132 459{
4a594fce
NC
460 if ((off[0] + size) > omax)
461 fatal ("%s: unexpected end of file %ld/%ld %ld", filename,(long) off[0],
462 (long) omax, (long) size);
463 get_windres_bfd_content (wrbfd, data, off[0], size);
464 off[0] += size;
252b5132
RH
465}
466
467/* Write a resource id */
4a594fce
NC
468static rc_uint_type
469write_res_id (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *id)
252b5132
RH
470{
471 if (id->named)
472 {
4a594fce
NC
473 rc_uint_type len = (((bfd_signed_vma) id->u.n.length < 0 ? 0 : id->u.n.length) + 1);
474 if (wrbfd)
475 {
476 rc_uint_type i;
477 bfd_byte *d = (bfd_byte *) xmalloc (len * sizeof (unichar));
478 for (i = 0; i < (len - 1); i++)
479 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id->u.n.name[i]);
480 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), 0);
481 set_windres_bfd_content (wrbfd, d, off, (len * sizeof (unichar)));
482 }
483 off += (len * sizeof (unichar));
252b5132
RH
484 }
485 else
486 {
4a594fce
NC
487 if (wrbfd)
488 {
489 struct bin_res_id bid;
490 windres_put_16 (wrbfd, bid.sig, 0xffff);
491 windres_put_16 (wrbfd, bid.id, id->u.id);
492 set_windres_bfd_content (wrbfd, &bid, off, BIN_RES_ID);
493 }
494 off += BIN_RES_ID;
252b5132 495 }
4a594fce 496 return off;
252b5132
RH
497}
498
499/* Write resource info */
4a594fce
NC
500static rc_uint_type
501write_res_info (windres_bfd *wrbfd, rc_uint_type off, const rc_res_res_info *info)
252b5132 502{
4a594fce
NC
503 if (wrbfd)
504 {
505 struct bin_res_info l;
506
507 windres_put_32 (wrbfd, l.version, info->version);
508 windres_put_16 (wrbfd, l.memflags, info->memflags);
509 windres_put_16 (wrbfd, l.language, info->language);
510 windres_put_32 (wrbfd, l.version2, info->version);
511 windres_put_32 (wrbfd, l.characteristics, info->characteristics);
512 set_windres_bfd_content (wrbfd, &l, off, BIN_RES_INFO_SIZE);
513 }
514 return off + BIN_RES_INFO_SIZE;
252b5132
RH
515}
516
517/* read a resource identifier */
4a594fce
NC
518static void
519read_res_id (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, rc_res_id *id)
252b5132 520{
4a594fce 521 struct bin_res_id bid;
252b5132
RH
522 unsigned short ord;
523 unichar *id_s = NULL;
4a594fce 524 rc_uint_type len;
252b5132 525
4a594fce
NC
526 read_res_data (wrbfd, off, omax, &bid, BIN_RES_ID - 2);
527 ord = (unsigned short) windres_get_16 (wrbfd, bid.sig, 2);
252b5132
RH
528 if (ord == 0xFFFF) /* an ordinal id */
529 {
4a594fce 530 read_res_data (wrbfd, off, omax, bid.id, BIN_RES_ID - 2);
252b5132 531 id->named = 0;
4a594fce 532 id->u.id = windres_get_16 (wrbfd, bid.id, 2);
252b5132
RH
533 }
534 else
535 /* named id */
536 {
4a594fce
NC
537 off[0] -= 2;
538 id_s = read_unistring (wrbfd, off, omax, &len);
252b5132
RH
539 id->named = 1;
540 id->u.n.length = len;
541 id->u.n.name = id_s;
542 }
543}
544
545/* Read a null terminated UNICODE string */
546static unichar *
4a594fce
NC
547read_unistring (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax,
548 rc_uint_type *len)
252b5132
RH
549{
550 unichar *s;
4a594fce 551 bfd_byte d[2];
252b5132
RH
552 unichar c;
553 unichar *p;
4a594fce
NC
554 rc_uint_type l;
555 rc_uint_type soff = off[0];
252b5132 556
03997556
NC
557 do
558 {
559 read_res_data (wrbfd, &soff, omax, d, sizeof (unichar));
560 c = windres_get_16 (wrbfd, d, 2);
561 }
562 while (c != 0);
4a594fce 563 l = ((soff - off[0]) / sizeof (unichar));
252b5132 564
4a594fce
NC
565 /* there are hardly any names longer than 256 characters, but anyway. */
566 p = s = (unichar *) xmalloc (sizeof (unichar) * l);
252b5132
RH
567 do
568 {
4a594fce
NC
569 read_res_data (wrbfd, off, omax, d, sizeof (unichar));
570 c = windres_get_16 (wrbfd, d, 2);
252b5132 571 *p++ = c;
252b5132
RH
572 }
573 while (c != 0);
4a594fce 574 *len = l - 1;
252b5132
RH
575 return s;
576}
577
4a594fce
NC
578static int
579probe_binary (windres_bfd *wrbfd, rc_uint_type omax)
252b5132 580{
4a594fce
NC
581 rc_uint_type off;
582 res_hdr reshdr;
583
584 off = 0;
585 read_res_data_hdr (wrbfd, &off, omax, &reshdr);
586 if (reshdr.data_size != 0)
587 return 1;
588 if ((reshdr.header_size != 0x20 && ! target_is_bigendian)
589 || (reshdr.header_size != 0x20000000 && target_is_bigendian))
590 return 1;
591
592 /* Subtract size of HeaderSize. DataSize has to be zero. */
593 off += 0x20 - BIN_RES_HDR_SIZE;
594 if ((off + BIN_RES_HDR_SIZE) >= omax)
595 return 1;
596 read_res_data_hdr (wrbfd, &off, omax, &reshdr);
03997556
NC
597 /* off is advanced by BIN_RES_HDR_SIZE in read_res_data_hdr()
598 which is part of reshdr.header_size. We shouldn't take it
599 into account twice. */
600 if ((off - BIN_RES_HDR_SIZE + reshdr.data_size + reshdr.header_size) > omax)
601 return 0;
4a594fce 602 return 1;
252b5132
RH
603}
604
605/* Check if file is a win32 binary resource file, if so
606 skip past the null resource. Returns 0 if successful, -1 on
607 error.
608 */
609static void
4a594fce 610skip_null_resource (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax)
252b5132 611{
4a594fce
NC
612 res_hdr reshdr;
613 read_res_data_hdr (wrbfd, off, omax, &reshdr);
614 if (reshdr.data_size != 0)
615 goto skip_err;
616 if ((reshdr.header_size != 0x20 && ! target_is_bigendian)
617 || (reshdr.header_size != 0x20000000 && target_is_bigendian))
252b5132
RH
618 goto skip_err;
619
4a594fce
NC
620 /* Subtract size of HeaderSize. DataSize has to be zero. */
621 off[0] += 0x20 - BIN_RES_HDR_SIZE;
622 if (off[0] >= omax)
252b5132
RH
623 goto skip_err;
624
625 return;
626
627skip_err:
628 fprintf (stderr, "%s: %s: Not a valid WIN32 resource file\n", program_name,
629 filename);
630 xexit (1);
631}
632
633/* Add a resource to resource directory */
4a594fce
NC
634static void
635res_add_resource (rc_res_resource *r, const rc_res_id *type, const rc_res_id *id,
636 rc_uint_type language, int dupok)
252b5132 637{
4a594fce 638 rc_res_id a[3];
252b5132
RH
639
640 a[0] = *type;
641 a[1] = *id;
642 a[2].named = 0;
643 a[2].u.id = language;
644 res_append_resource (&resources, r, 3, a, dupok);
645}
646
647/* Append a resource to resource directory.
648 This is just copied from define_resource
649 and modified to add an existing resource.
650 */
4a594fce
NC
651static void
652res_append_resource (rc_res_directory **resources, rc_res_resource *resource,
653 int cids, const rc_res_id *ids, int dupok)
252b5132 654{
4a594fce 655 rc_res_entry *re = NULL;
252b5132
RH
656 int i;
657
658 assert (cids > 0);
659 for (i = 0; i < cids; i++)
660 {
4a594fce 661 rc_res_entry **pp;
252b5132
RH
662
663 if (*resources == NULL)
664 {
665 static unsigned long timeval;
666
667 /* Use the same timestamp for every resource created in a
668 single run. */
669 if (timeval == 0)
670 timeval = time (NULL);
671
4a594fce
NC
672 *resources = ((rc_res_directory *)
673 res_alloc (sizeof (rc_res_directory)));
252b5132
RH
674 (*resources)->characteristics = 0;
675 (*resources)->time = timeval;
676 (*resources)->major = 0;
677 (*resources)->minor = 0;
678 (*resources)->entries = NULL;
679 }
680
681 for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
682 if (res_id_cmp ((*pp)->id, ids[i]) == 0)
683 break;
684
685 if (*pp != NULL)
686 re = *pp;
687 else
688 {
4a594fce 689 re = (rc_res_entry *) res_alloc (sizeof (rc_res_entry));
252b5132
RH
690 re->next = NULL;
691 re->id = ids[i];
692 if ((i + 1) < cids)
693 {
694 re->subdir = 1;
695 re->u.dir = NULL;
696 }
697 else
698 {
699 re->subdir = 0;
700 re->u.res = NULL;
701 }
702
703 *pp = re;
704 }
705
706 if ((i + 1) < cids)
707 {
4a594fce 708 if (! re->subdir)
252b5132
RH
709 {
710 fprintf (stderr, "%s: ", program_name);
711 res_ids_print (stderr, i, ids);
712 fprintf (stderr, ": expected to be a directory\n");
713 xexit (1);
714 }
715
716 resources = &re->u.dir;
717 }
718 }
719
720 if (re->subdir)
721 {
722 fprintf (stderr, "%s: ", program_name);
723 res_ids_print (stderr, cids, ids);
724 fprintf (stderr, ": expected to be a leaf\n");
725 xexit (1);
726 }
727
728 if (re->u.res != NULL)
729 {
730 if (dupok)
731 return;
732
733 fprintf (stderr, "%s: warning: ", program_name);
734 res_ids_print (stderr, cids, ids);
735 fprintf (stderr, ": duplicate value\n");
736 }
737
738 re->u.res = resource;
739}
This page took 0.375855 seconds and 4 git commands to generate.