[BACK]Return to windres.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils / dist / binutils

Annotation of src/external/gpl3/binutils/dist/binutils/windres.c, Revision 1.1.1.4.2.1

1.1       skrll       1: /* windres.c -- a program to manipulate Windows resources
1.1.1.4.2.1! pgoyette    2:    Copyright (C) 1997-2016 Free Software Foundation, Inc.
1.1       skrll       3:    Written by Ian Lance Taylor, Cygnus Support.
                      4:    Rewritten by Kai Tietz, Onevision.
                      5:
                      6:    This file is part of GNU Binutils.
                      7:
                      8:    This program is free software; you can redistribute it and/or modify
                      9:    it under the terms of the GNU General Public License as published by
                     10:    the Free Software Foundation; either version 3 of the License, or
                     11:    (at your option) any later version.
                     12:
                     13:    This program is distributed in the hope that it will be useful,
                     14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16:    GNU General Public License for more details.
                     17:
                     18:    You should have received a copy of the GNU General Public License
                     19:    along with this program; if not, write to the Free Software
                     20:    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
                     21:    02110-1301, USA.  */
                     22:
                     23: /* This program can read and write Windows resources in various
                     24:    formats.  In particular, it can act like the rc resource compiler
                     25:    program, and it can act like the cvtres res to COFF conversion
                     26:    program.
                     27:
                     28:    It is based on information taken from the following sources:
                     29:
                     30:    * Microsoft documentation.
                     31:
                     32:    * The rcl program, written by Gunther Ebert
                     33:      <gunther.ebert@ixos-leipzig.de>.
                     34:
                     35:    * The res2coff program, written by Pedro A. Aranda <paag@tid.es>.  */
                     36:
                     37: #include "sysdep.h"
                     38: #include <assert.h>
                     39: #include "bfd.h"
                     40: #include "getopt.h"
                     41: #include "bucomm.h"
                     42: #include "libiberty.h"
                     43: #include "safe-ctype.h"
                     44: #include "obstack.h"
                     45: #include "windres.h"
                     46:
                     47: /* Used by resrc.c at least.  */
                     48:
                     49: int verbose = 0;
                     50:
                     51: int target_is_bigendian = 0;
                     52: const char *def_target_arch;
                     53:
1.1.1.3   christos   54: static void set_endianness (bfd *, const char *);
1.1       skrll      55:
                     56: /* An enumeration of format types.  */
                     57:
                     58: enum res_format
                     59: {
                     60:   /* Unknown format.  */
                     61:   RES_FORMAT_UNKNOWN,
                     62:   /* Textual RC file.  */
                     63:   RES_FORMAT_RC,
                     64:   /* Binary RES file.  */
                     65:   RES_FORMAT_RES,
                     66:   /* COFF file.  */
                     67:   RES_FORMAT_COFF
                     68: };
                     69:
                     70: /* A structure used to map between format types and strings.  */
                     71:
                     72: struct format_map
                     73: {
                     74:   const char *name;
                     75:   enum res_format format;
                     76: };
                     77:
                     78: /* A mapping between names and format types.  */
                     79:
                     80: static const struct format_map format_names[] =
                     81: {
                     82:   { "rc", RES_FORMAT_RC },
                     83:   { "res", RES_FORMAT_RES },
                     84:   { "coff", RES_FORMAT_COFF },
                     85:   { NULL, RES_FORMAT_UNKNOWN }
                     86: };
                     87:
                     88: /* A mapping from file extensions to format types.  */
                     89:
                     90: static const struct format_map format_fileexts[] =
                     91: {
                     92:   { "rc", RES_FORMAT_RC },
                     93:   { "res", RES_FORMAT_RES },
                     94:   { "exe", RES_FORMAT_COFF },
                     95:   { "obj", RES_FORMAT_COFF },
                     96:   { "o", RES_FORMAT_COFF },
                     97:   { NULL, RES_FORMAT_UNKNOWN }
                     98: };
                     99:
                    100: /* A list of include directories.  */
                    101:
                    102: struct include_dir
                    103: {
                    104:   struct include_dir *next;
                    105:   char *dir;
                    106: };
                    107:
                    108: static struct include_dir *include_dirs;
                    109:
                    110: /* Static functions.  */
                    111:
                    112: static void res_init (void);
                    113: static int extended_menuitems (const rc_menuitem *);
                    114: static enum res_format format_from_name (const char *, int);
                    115: static enum res_format format_from_filename (const char *, int);
                    116: static void usage (FILE *, int);
                    117: static int cmp_res_entry (const void *, const void *);
                    118: static rc_res_directory *sort_resources (rc_res_directory *);
                    119: static void reswr_init (void);
                    120: static const char * quot (const char *);
                    121: 
                    122: static rc_uint_type target_get_8 (const void *, rc_uint_type);
                    123: static void target_put_8 (void *, rc_uint_type);
                    124: static rc_uint_type target_get_16 (const void *, rc_uint_type);
                    125: static void target_put_16 (void *, rc_uint_type);
                    126: static rc_uint_type target_get_32 (const void *, rc_uint_type);
                    127: static void target_put_32 (void *, rc_uint_type);
                    128:
                    129: 
                    130: /* When we are building a resource tree, we allocate everything onto
                    131:    an obstack, so that we can free it all at once if we want.  */
                    132:
                    133: #define obstack_chunk_alloc xmalloc
                    134: #define obstack_chunk_free free
                    135:
                    136: /* The resource building obstack.  */
                    137:
                    138: static struct obstack res_obstack;
                    139:
                    140: /* Initialize the resource building obstack.  */
                    141:
                    142: static void
                    143: res_init (void)
                    144: {
                    145:   obstack_init (&res_obstack);
                    146: }
                    147:
                    148: /* Allocate space on the resource building obstack.  */
                    149:
                    150: void *
                    151: res_alloc (rc_uint_type bytes)
                    152: {
1.1.1.2   christos  153:   return obstack_alloc (&res_obstack, (size_t) bytes);
1.1       skrll     154: }
                    155:
                    156: /* We also use an obstack to save memory used while writing out a set
                    157:    of resources.  */
                    158:
                    159: static struct obstack reswr_obstack;
                    160:
                    161: /* Initialize the resource writing obstack.  */
                    162:
                    163: static void
                    164: reswr_init (void)
                    165: {
                    166:   obstack_init (&reswr_obstack);
                    167: }
                    168:
                    169: /* Allocate space on the resource writing obstack.  */
                    170:
                    171: void *
                    172: reswr_alloc (rc_uint_type bytes)
                    173: {
1.1.1.2   christos  174:   return obstack_alloc (&reswr_obstack, (size_t) bytes);
1.1       skrll     175: }
                    176: 
                    177: /* Open a file using the include directory search list.  */
                    178:
                    179: FILE *
                    180: open_file_search (const char *filename, const char *mode, const char *errmsg,
                    181:                  char **real_filename)
                    182: {
                    183:   FILE *e;
                    184:   struct include_dir *d;
                    185:
                    186:   e = fopen (filename, mode);
                    187:   if (e != NULL)
                    188:     {
                    189:       *real_filename = xstrdup (filename);
                    190:       return e;
                    191:     }
                    192:
                    193:   if (errno == ENOENT)
                    194:     {
                    195:       for (d = include_dirs; d != NULL; d = d->next)
                    196:        {
                    197:          char *n;
                    198:
                    199:          n = (char *) xmalloc (strlen (d->dir) + strlen (filename) + 2);
                    200:          sprintf (n, "%s/%s", d->dir, filename);
                    201:          e = fopen (n, mode);
                    202:          if (e != NULL)
                    203:            {
                    204:              *real_filename = n;
                    205:              return e;
                    206:            }
1.1.1.4   christos  207:          free (n);
1.1       skrll     208:
                    209:          if (errno != ENOENT)
                    210:            break;
                    211:        }
                    212:     }
                    213:
                    214:   fatal (_("can't open %s `%s': %s"), errmsg, filename, strerror (errno));
                    215:
                    216:   /* Return a value to avoid a compiler warning.  */
                    217:   return NULL;
                    218: }
                    219: 
                    220: /* Compare two resource ID's.  We consider name entries to come before
                    221:    numeric entries, because that is how they appear in the COFF .rsrc
                    222:    section.  */
                    223:
                    224: int
                    225: res_id_cmp (rc_res_id a, rc_res_id b)
                    226: {
                    227:   if (! a.named)
                    228:     {
                    229:       if (b.named)
                    230:        return 1;
                    231:       if (a.u.id > b.u.id)
                    232:        return 1;
                    233:       else if (a.u.id < b.u.id)
                    234:        return -1;
                    235:       else
                    236:        return 0;
                    237:     }
                    238:   else
                    239:     {
                    240:       unichar *as, *ase, *bs, *bse;
                    241:
                    242:       if (! b.named)
                    243:        return -1;
                    244:
                    245:       as = a.u.n.name;
                    246:       ase = as + a.u.n.length;
                    247:       bs = b.u.n.name;
                    248:       bse = bs + b.u.n.length;
                    249:
                    250:       while (as < ase)
                    251:        {
                    252:          int i;
                    253:
                    254:          if (bs >= bse)
                    255:            return 1;
                    256:          i = (int) *as - (int) *bs;
                    257:          if (i != 0)
                    258:            return i;
                    259:          ++as;
                    260:          ++bs;
                    261:        }
                    262:
                    263:       if (bs < bse)
                    264:        return -1;
                    265:
                    266:       return 0;
                    267:     }
                    268: }
                    269:
                    270: /* Print a resource ID.  */
                    271:
                    272: void
                    273: res_id_print (FILE *stream, rc_res_id id, int quote)
                    274: {
                    275:   if (! id.named)
                    276:     fprintf (stream, "%u", (int) id.u.id);
                    277:   else
                    278:     {
                    279:       if (quote)
                    280:        unicode_print_quoted (stream, id.u.n.name, id.u.n.length);
                    281:       else
                    282:       unicode_print (stream, id.u.n.name, id.u.n.length);
                    283:     }
                    284: }
                    285:
                    286: /* Print a list of resource ID's.  */
                    287:
                    288: void
                    289: res_ids_print (FILE *stream, int cids, const rc_res_id *ids)
                    290: {
                    291:   int i;
                    292:
                    293:   for (i = 0; i < cids; i++)
                    294:     {
                    295:       res_id_print (stream, ids[i], 1);
                    296:       if (i + 1 < cids)
                    297:        fprintf (stream, ": ");
                    298:     }
                    299: }
                    300:
                    301: /* Convert an ASCII string to a resource ID.  */
                    302:
                    303: void
                    304: res_string_to_id (rc_res_id *res_id, const char *string)
                    305: {
                    306:   res_id->named = 1;
                    307:   unicode_from_ascii (&res_id->u.n.length, &res_id->u.n.name, string);
                    308: }
                    309:
                    310: /* Convert an unicode string to a resource ID.  */
                    311: void
                    312: res_unistring_to_id (rc_res_id *res_id, const unichar *u)
                    313: {
                    314:   res_id->named = 1;
                    315:   res_id->u.n.length = unichar_len (u);
                    316:   res_id->u.n.name = unichar_dup_uppercase (u);
                    317: }
                    318:
                    319: /* Define a resource.  The arguments are the resource tree, RESOURCES,
                    320:    and the location at which to put it in the tree, CIDS and IDS.
                    321:    This returns a newly allocated rc_res_resource structure, which the
                    322:    caller is expected to initialize.  If DUPOK is non-zero, then if a
                    323:    resource with this ID exists, it is returned.  Otherwise, a warning
                    324:    is issued, and a new resource is created replacing the existing
                    325:    one.  */
                    326:
                    327: rc_res_resource *
                    328: define_resource (rc_res_directory **resources, int cids,
                    329:                 const rc_res_id *ids, int dupok)
                    330: {
                    331:   rc_res_entry *re = NULL;
                    332:   int i;
                    333:
                    334:   assert (cids > 0);
                    335:   for (i = 0; i < cids; i++)
                    336:     {
                    337:       rc_res_entry **pp;
                    338:
                    339:       if (*resources == NULL)
                    340:        {
                    341:          *resources = ((rc_res_directory *)
                    342:                        res_alloc (sizeof (rc_res_directory)));
                    343:          (*resources)->characteristics = 0;
1.1.1.4   christos  344:          /* Using a real timestamp only serves to create non-deterministic
                    345:             results.  Use zero instead.  */
                    346:          (*resources)->time = 0;
1.1       skrll     347:          (*resources)->major = 0;
                    348:          (*resources)->minor = 0;
                    349:          (*resources)->entries = NULL;
                    350:        }
                    351:
                    352:       for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
                    353:        if (res_id_cmp ((*pp)->id, ids[i]) == 0)
                    354:          break;
                    355:
                    356:       if (*pp != NULL)
                    357:        re = *pp;
                    358:       else
                    359:        {
                    360:          re = (rc_res_entry *) res_alloc (sizeof (rc_res_entry));
                    361:          re->next = NULL;
                    362:          re->id = ids[i];
                    363:          if ((i + 1) < cids)
                    364:            {
                    365:              re->subdir = 1;
                    366:              re->u.dir = NULL;
                    367:            }
                    368:          else
                    369:            {
                    370:              re->subdir = 0;
                    371:              re->u.res = NULL;
                    372:            }
                    373:
                    374:          *pp = re;
                    375:        }
                    376:
                    377:       if ((i + 1) < cids)
                    378:        {
                    379:          if (! re->subdir)
                    380:            {
                    381:              fprintf (stderr, "%s: ", program_name);
                    382:              res_ids_print (stderr, i, ids);
                    383:              fprintf (stderr, _(": expected to be a directory\n"));
                    384:              xexit (1);
                    385:            }
                    386:
                    387:          resources = &re->u.dir;
                    388:        }
                    389:     }
                    390:
                    391:   if (re->subdir)
                    392:     {
                    393:       fprintf (stderr, "%s: ", program_name);
                    394:       res_ids_print (stderr, cids, ids);
                    395:       fprintf (stderr, _(": expected to be a leaf\n"));
                    396:       xexit (1);
                    397:     }
                    398:
                    399:   if (re->u.res != NULL)
                    400:     {
                    401:       if (dupok)
                    402:        return re->u.res;
                    403:
                    404:       fprintf (stderr, _("%s: warning: "), program_name);
                    405:       res_ids_print (stderr, cids, ids);
                    406:       fprintf (stderr, _(": duplicate value\n"));
                    407:     }
                    408:
                    409:   re->u.res = ((rc_res_resource *)
                    410:               res_alloc (sizeof (rc_res_resource)));
                    411:   memset (re->u.res, 0, sizeof (rc_res_resource));
                    412:
                    413:   re->u.res->type = RES_TYPE_UNINITIALIZED;
                    414:   return re->u.res;
                    415: }
                    416:
                    417: /* Define a standard resource.  This is a version of define_resource
                    418:    that just takes type, name, and language arguments.  */
                    419:
                    420: rc_res_resource *
                    421: define_standard_resource (rc_res_directory **resources, int type,
                    422:                          rc_res_id name, rc_uint_type language, int dupok)
                    423: {
                    424:   rc_res_id a[3];
                    425:
                    426:   a[0].named = 0;
                    427:   a[0].u.id = type;
                    428:   a[1] = name;
                    429:   a[2].named = 0;
                    430:   a[2].u.id = language;
                    431:   return define_resource (resources, 3, a, dupok);
                    432: }
                    433:
                    434: /* Comparison routine for resource sorting.  */
                    435:
                    436: static int
                    437: cmp_res_entry (const void *p1, const void *p2)
                    438: {
                    439:   const rc_res_entry **re1, **re2;
                    440:
                    441:   re1 = (const rc_res_entry **) p1;
                    442:   re2 = (const rc_res_entry **) p2;
                    443:   return res_id_cmp ((*re1)->id, (*re2)->id);
                    444: }
                    445:
                    446: /* Sort the resources.  */
                    447:
                    448: static rc_res_directory *
                    449: sort_resources (rc_res_directory *resdir)
                    450: {
                    451:   int c, i;
                    452:   rc_res_entry *re;
                    453:   rc_res_entry **a;
                    454:
                    455:   if (resdir->entries == NULL)
                    456:     return resdir;
                    457:
                    458:   c = 0;
                    459:   for (re = resdir->entries; re != NULL; re = re->next)
                    460:     ++c;
                    461:
                    462:   /* This is a recursive routine, so using xmalloc is probably better
                    463:      than alloca.  */
                    464:   a = (rc_res_entry **) xmalloc (c * sizeof (rc_res_entry *));
                    465:
                    466:   for (i = 0, re = resdir->entries; re != NULL; re = re->next, i++)
                    467:     a[i] = re;
                    468:
                    469:   qsort (a, c, sizeof (rc_res_entry *), cmp_res_entry);
                    470:
                    471:   resdir->entries = a[0];
                    472:   for (i = 0; i < c - 1; i++)
                    473:     a[i]->next = a[i + 1];
                    474:   a[i]->next = NULL;
                    475:
                    476:   free (a);
                    477:
                    478:   /* Now sort the subdirectories.  */
                    479:
                    480:   for (re = resdir->entries; re != NULL; re = re->next)
                    481:     if (re->subdir)
                    482:       re->u.dir = sort_resources (re->u.dir);
                    483:
                    484:   return resdir;
                    485: }
                    486: 
                    487: /* Return whether the dialog resource DIALOG is a DIALOG or a
                    488:    DIALOGEX.  */
                    489:
                    490: int
                    491: extended_dialog (const rc_dialog *dialog)
                    492: {
                    493:   const rc_dialog_control *c;
                    494:
                    495:   if (dialog->ex != NULL)
                    496:     return 1;
                    497:
                    498:   for (c = dialog->controls; c != NULL; c = c->next)
                    499:     if (c->data != NULL || c->help != 0)
                    500:       return 1;
                    501:
                    502:   return 0;
                    503: }
                    504:
                    505: /* Return whether MENUITEMS are a MENU or a MENUEX.  */
                    506:
                    507: int
                    508: extended_menu (const rc_menu *menu)
                    509: {
                    510:   return extended_menuitems (menu->items);
                    511: }
                    512:
                    513: static int
                    514: extended_menuitems (const rc_menuitem *menuitems)
                    515: {
                    516:   const rc_menuitem *mi;
                    517:
                    518:   for (mi = menuitems; mi != NULL; mi = mi->next)
                    519:     {
                    520:       if (mi->help != 0 || mi->state != 0)
                    521:        return 1;
                    522:       if (mi->popup != NULL && mi->id != 0)
                    523:        return 1;
                    524:       if ((mi->type
                    525:           & ~ (MENUITEM_CHECKED
                    526:                | MENUITEM_GRAYED
                    527:                | MENUITEM_HELP
                    528:                | MENUITEM_INACTIVE
                    529:                | MENUITEM_MENUBARBREAK
                    530:                | MENUITEM_MENUBREAK))
                    531:          != 0)
                    532:        return 1;
                    533:       if (mi->popup != NULL)
                    534:        {
                    535:          if (extended_menuitems (mi->popup))
                    536:            return 1;
                    537:        }
                    538:     }
                    539:
                    540:   return 0;
                    541: }
                    542: 
                    543: /* Convert a string to a format type, or exit if it can't be done.  */
                    544:
                    545: static enum res_format
                    546: format_from_name (const char *name, int exit_on_error)
                    547: {
                    548:   const struct format_map *m;
                    549:
                    550:   for (m = format_names; m->name != NULL; m++)
                    551:     if (strcasecmp (m->name, name) == 0)
                    552:       break;
                    553:
                    554:   if (m->name == NULL && exit_on_error)
                    555:     {
                    556:       non_fatal (_("unknown format type `%s'"), name);
                    557:       fprintf (stderr, _("%s: supported formats:"), program_name);
                    558:       for (m = format_names; m->name != NULL; m++)
                    559:        fprintf (stderr, " %s", m->name);
                    560:       fprintf (stderr, "\n");
                    561:       xexit (1);
                    562:     }
                    563:
                    564:   return m->format;
                    565: }
                    566:
                    567: /* Work out a format type given a file name.  If INPUT is non-zero,
                    568:    it's OK to look at the file itself.  */
                    569:
                    570: static enum res_format
                    571: format_from_filename (const char *filename, int input)
                    572: {
                    573:   const char *ext;
                    574:   FILE *e;
                    575:   bfd_byte b1, b2, b3, b4, b5;
                    576:   int magic;
                    577:
                    578:   /* If we have an extension, see if we recognize it as implying a
                    579:      particular format.  */
                    580:   ext = strrchr (filename, '.');
                    581:   if (ext != NULL)
                    582:     {
                    583:       const struct format_map *m;
                    584:
                    585:       ++ext;
                    586:       for (m = format_fileexts; m->name != NULL; m++)
                    587:        if (strcasecmp (m->name, ext) == 0)
                    588:          return m->format;
                    589:     }
                    590:
                    591:   /* If we don't recognize the name of an output file, assume it's a
                    592:      COFF file.  */
                    593:   if (! input)
                    594:     return RES_FORMAT_COFF;
                    595:
                    596:   /* Read the first few bytes of the file to see if we can guess what
                    597:      it is.  */
                    598:   e = fopen (filename, FOPEN_RB);
                    599:   if (e == NULL)
                    600:     fatal ("%s: %s", filename, strerror (errno));
                    601:
                    602:   b1 = getc (e);
                    603:   b2 = getc (e);
                    604:   b3 = getc (e);
                    605:   b4 = getc (e);
                    606:   b5 = getc (e);
                    607:
                    608:   fclose (e);
                    609:
                    610:   /* A PE executable starts with 0x4d 0x5a.  */
                    611:   if (b1 == 0x4d && b2 == 0x5a)
                    612:     return RES_FORMAT_COFF;
                    613:
                    614:   /* A COFF .o file starts with a COFF magic number.  */
                    615:   magic = (b2 << 8) | b1;
                    616:   switch (magic)
                    617:     {
                    618:     case 0x14c: /* i386 */
                    619:     case 0x166: /* MIPS */
                    620:     case 0x184: /* Alpha */
                    621:     case 0x268: /* 68k */
                    622:     case 0x1f0: /* PowerPC */
                    623:     case 0x290: /* PA */
                    624:       return RES_FORMAT_COFF;
                    625:     }
                    626:
                    627:   /* A RES file starts with 0x0 0x0 0x0 0x0 0x20 0x0 0x0 0x0.  */
                    628:   if (b1 == 0 && b2 == 0 && b3 == 0 && b4 == 0 && b5 == 0x20)
                    629:     return RES_FORMAT_RES;
                    630:
                    631:   /* If every character is printable or space, assume it's an RC file.  */
                    632:   if ((ISPRINT (b1) || ISSPACE (b1))
                    633:       && (ISPRINT (b2) || ISSPACE (b2))
                    634:       && (ISPRINT (b3) || ISSPACE (b3))
                    635:       && (ISPRINT (b4) || ISSPACE (b4))
                    636:       && (ISPRINT (b5) || ISSPACE (b5)))
                    637:     return RES_FORMAT_RC;
                    638:
                    639:   /* Otherwise, we give up.  */
                    640:   fatal (_("can not determine type of file `%s'; use the -J option"),
                    641:         filename);
                    642:
                    643:   /* Return something to silence the compiler warning.  */
                    644:   return RES_FORMAT_UNKNOWN;
                    645: }
                    646:
                    647: /* Print a usage message and exit.  */
                    648:
                    649: static void
                    650: usage (FILE *stream, int status)
                    651: {
                    652:   fprintf (stream, _("Usage: %s [option(s)] [input-file] [output-file]\n"),
                    653:           program_name);
                    654:   fprintf (stream, _(" The options are:\n\
                    655:   -i --input=<file>            Name input file\n\
                    656:   -o --output=<file>           Name output file\n\
                    657:   -J --input-format=<format>   Specify input format\n\
                    658:   -O --output-format=<format>  Specify output format\n\
                    659:   -F --target=<target>         Specify COFF target\n\
                    660:      --preprocessor=<program>  Program to use to preprocess rc file\n\
1.1.1.3   christos  661:      --preprocessor-arg=<arg>  Additional preprocessor argument\n\
1.1       skrll     662:   -I --include-dir=<dir>       Include directory when preprocessing rc file\n\
                    663:   -D --define <sym>[=<val>]    Define SYM when preprocessing rc file\n\
                    664:   -U --undefine <sym>          Undefine SYM when preprocessing rc file\n\
                    665:   -v --verbose                 Verbose - tells you what it's doing\n\
                    666:   -c --codepage=<codepage>     Specify default codepage\n\
                    667:   -l --language=<val>          Set language when reading rc file\n\
                    668:      --use-temp-file           Use a temporary file instead of popen to read\n\
                    669:                                the preprocessor output\n\
                    670:      --no-use-temp-file        Use popen (default)\n"));
                    671: #ifdef YYDEBUG
                    672:   fprintf (stream, _("\
                    673:      --yydebug                 Turn on parser debugging\n"));
                    674: #endif
                    675:   fprintf (stream, _("\
                    676:   -r                           Ignored for compatibility with rc\n\
                    677:   @<file>                      Read options from <file>\n\
                    678:   -h --help                    Print this help message\n\
                    679:   -V --version                 Print version information\n"));
                    680:   fprintf (stream, _("\
                    681: FORMAT is one of rc, res, or coff, and is deduced from the file name\n\
                    682: extension if not specified.  A single file name is an input file.\n\
                    683: No input-file is stdin, default rc.  No output-file is stdout, default rc.\n"));
                    684:
                    685:   list_supported_targets (program_name, stream);
                    686:
                    687:   if (REPORT_BUGS_TO[0] && status == 0)
                    688:     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
                    689:
                    690:   exit (status);
                    691: }
                    692:
                    693: /* Quote characters that will confuse the shell when we run the preprocessor.  */
                    694:
                    695: static const char *
                    696: quot (const char *string)
                    697: {
                    698:   static char *buf = 0;
                    699:   static int buflen = 0;
                    700:   int slen = strlen (string);
                    701:   const char *src;
                    702:   char *dest;
                    703:
                    704:   if ((buflen < slen * 2 + 2) || ! buf)
                    705:     {
                    706:       buflen = slen * 2 + 2;
                    707:       if (buf)
                    708:        free (buf);
                    709:       buf = (char *) xmalloc (buflen);
                    710:     }
                    711:
                    712:   for (src=string, dest=buf; *src; src++, dest++)
                    713:     {
                    714:       if (*src == '(' || *src == ')' || *src == ' ')
                    715:        *dest++ = '\\';
                    716:       *dest = *src;
                    717:     }
                    718:   *dest = 0;
                    719:   return buf;
                    720: }
                    721:
                    722: /* Long options.  */
                    723:
1.1.1.2   christos  724: enum option_values
                    725: {
                    726:   /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
                    727:   OPTION_PREPROCESSOR  = 150,
                    728:   OPTION_USE_TEMP_FILE,
                    729:   OPTION_NO_USE_TEMP_FILE,
                    730:   OPTION_YYDEBUG,
1.1.1.3   christos  731:   OPTION_INCLUDE_DIR,
                    732:   OPTION_PREPROCESSOR_ARG
1.1.1.2   christos  733: };
1.1       skrll     734:
                    735: static const struct option long_options[] =
                    736: {
                    737:   {"input", required_argument, 0, 'i'},
                    738:   {"output", required_argument, 0, 'o'},
                    739:   {"input-format", required_argument, 0, 'J'},
                    740:   {"output-format", required_argument, 0, 'O'},
                    741:   {"target", required_argument, 0, 'F'},
                    742:   {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
1.1.1.3   christos  743:   {"preprocessor-arg", required_argument, 0, OPTION_PREPROCESSOR_ARG},
1.1.1.2   christos  744:   {"include-dir", required_argument, 0, OPTION_INCLUDE_DIR},
1.1       skrll     745:   {"define", required_argument, 0, 'D'},
                    746:   {"undefine", required_argument, 0, 'U'},
                    747:   {"verbose", no_argument, 0, 'v'},
                    748:   {"codepage", required_argument, 0, 'c'},
                    749:   {"language", required_argument, 0, 'l'},
                    750:   {"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
                    751:   {"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
                    752:   {"yydebug", no_argument, 0, OPTION_YYDEBUG},
                    753:   {"version", no_argument, 0, 'V'},
                    754:   {"help", no_argument, 0, 'h'},
                    755:   {0, no_argument, 0, 0}
                    756: };
                    757:
                    758: void
                    759: windres_add_include_dir (const char *p)
                    760: {
                    761:   struct include_dir *n, **pp;
                    762:
                    763:   /* Computing paths is often complicated and error prone.
                    764:      The easiest way to check for mistakes is at the time
                    765:      we add them to include_dirs.  */
                    766:   assert (p != NULL);
                    767:   assert (*p != '\0');
                    768:
                    769:   n = xmalloc (sizeof *n);
                    770:   n->next = NULL;
                    771:   n->dir = (char * ) p;
                    772:
                    773:   for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
                    774:     ;
                    775:   *pp = n;
                    776: }
                    777:
                    778: /* This keeps gcc happy when using -Wmissing-prototypes -Wstrict-prototypes.  */
                    779: int main (int, char **);
                    780:
                    781: /* The main function.  */
                    782:
                    783: int
                    784: main (int argc, char **argv)
                    785: {
                    786:   int c;
                    787:   char *input_filename;
                    788:   char *output_filename;
                    789:   enum res_format input_format;
                    790:   enum res_format input_format_tmp;
                    791:   enum res_format output_format;
                    792:   char *target;
                    793:   char *preprocessor;
                    794:   char *preprocargs;
                    795:   const char *quotedarg;
                    796:   int language;
                    797:   rc_res_directory *resources;
                    798:   int use_temp_file;
                    799:
                    800: #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
                    801:   setlocale (LC_MESSAGES, "");
                    802: #endif
                    803: #if defined (HAVE_SETLOCALE)
                    804:   setlocale (LC_CTYPE, "");
                    805: #endif
                    806:   bindtextdomain (PACKAGE, LOCALEDIR);
                    807:   textdomain (PACKAGE);
                    808:
                    809:   program_name = argv[0];
                    810:   xmalloc_set_program_name (program_name);
1.1.1.4   christos  811:   bfd_set_error_program_name (program_name);
1.1       skrll     812:
                    813:   expandargv (&argc, &argv);
                    814:
                    815:   bfd_init ();
                    816:   set_default_bfd_target ();
                    817:
                    818:   res_init ();
                    819:
                    820:   input_filename = NULL;
                    821:   output_filename = NULL;
                    822:   input_format = RES_FORMAT_UNKNOWN;
                    823:   output_format = RES_FORMAT_UNKNOWN;
                    824:   target = NULL;
                    825:   preprocessor = NULL;
                    826:   preprocargs = NULL;
                    827:   language = 0x409;   /* LANG_ENGLISH, SUBLANG_ENGLISH_US.  */
                    828:   use_temp_file = 0;
                    829:
                    830:   while ((c = getopt_long (argc, argv, "c:f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
                    831:                           (int *) 0)) != EOF)
                    832:     {
                    833:       switch (c)
                    834:        {
                    835:        case 'c':
                    836:          {
                    837:            rc_uint_type ncp;
                    838:
                    839:            if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X'))
                    840:              ncp = (rc_uint_type) strtol (optarg + 2, NULL, 16);
                    841:            else
                    842:              ncp = (rc_uint_type) strtol (optarg, NULL, 10);
                    843:            if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
                    844:              fatal (_("invalid codepage specified.\n"));
                    845:            wind_default_codepage = wind_current_codepage = ncp;
                    846:          }
                    847:          break;
                    848:
                    849:        case 'i':
                    850:          input_filename = optarg;
                    851:          break;
                    852:
                    853:        case 'f':
                    854:          /* For compatibility with rc we accept "-fo <name>" as being the
                    855:             equivalent of "-o <name>".  We do not advertise this fact
                    856:             though, as we do not want users to use non-GNU like command
                    857:             line switches.  */
                    858:          if (*optarg != 'o')
                    859:            fatal (_("invalid option -f\n"));
                    860:          optarg++;
                    861:          if (* optarg == 0)
                    862:            {
                    863:              if (optind == argc)
                    864:                fatal (_("No filename following the -fo option.\n"));
                    865:              optarg = argv [optind++];
                    866:            }
                    867:          /* Fall through.  */
                    868:
                    869:        case 'o':
                    870:          output_filename = optarg;
                    871:          break;
                    872:
                    873:        case 'J':
                    874:          input_format = format_from_name (optarg, 1);
                    875:          break;
                    876:
                    877:        case 'O':
                    878:          output_format = format_from_name (optarg, 1);
                    879:          break;
                    880:
                    881:        case 'F':
                    882:          target = optarg;
                    883:          break;
                    884:
                    885:        case OPTION_PREPROCESSOR:
                    886:          preprocessor = optarg;
                    887:          break;
                    888:
1.1.1.3   christos  889:        case OPTION_PREPROCESSOR_ARG:
                    890:          if (preprocargs == NULL)
                    891:            {
                    892:              quotedarg = quot (optarg);
                    893:              preprocargs = xstrdup (quotedarg);
                    894:            }
                    895:          else
                    896:            {
                    897:              char *n;
                    898:
                    899:              quotedarg = quot (optarg);
                    900:              n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 2);
                    901:              sprintf (n, "%s %s", preprocargs, quotedarg);
                    902:              free (preprocargs);
                    903:              preprocargs = n;
                    904:            }
                    905:          break;
                    906:
1.1       skrll     907:        case 'D':
                    908:        case 'U':
                    909:          if (preprocargs == NULL)
                    910:            {
                    911:              quotedarg = quot (optarg);
                    912:              preprocargs = xmalloc (strlen (quotedarg) + 3);
                    913:              sprintf (preprocargs, "-%c%s", c, quotedarg);
                    914:            }
                    915:          else
                    916:            {
                    917:              char *n;
                    918:
                    919:              quotedarg = quot (optarg);
                    920:              n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
                    921:              sprintf (n, "%s -%c%s", preprocargs, c, quotedarg);
                    922:              free (preprocargs);
                    923:              preprocargs = n;
                    924:            }
                    925:          break;
                    926:
                    927:        case 'r':
                    928:          /* Ignored for compatibility with rc.  */
                    929:          break;
                    930:
                    931:        case 'v':
                    932:          verbose ++;
                    933:          break;
                    934:
                    935:        case 'I':
                    936:          /* For backward compatibility, should be removed in the future.  */
                    937:          input_format_tmp = format_from_name (optarg, 0);
                    938:          if (input_format_tmp != RES_FORMAT_UNKNOWN)
                    939:            {
1.1.1.2   christos  940:              struct stat statbuf;
                    941:              char modebuf[11];
1.1.1.4   christos  942:
1.1.1.2   christos  943:              if (stat (optarg, & statbuf) == 0
                    944:                  /* Coded this way to avoid importing knowledge of S_ISDIR into this file.  */
                    945:                  && (mode_string (statbuf.st_mode, modebuf), modebuf[0] == 'd'))
                    946:                /* We have a -I option with a directory name that just happens
                    947:                   to match a format name as well.  eg: -I res  Assume that the
                    948:                   user knows what they are doing and do not complain.  */
                    949:                ;
                    950:              else
                    951:                {
                    952:                  fprintf (stderr,
                    953:                           _("Option -I is deprecated for setting the input format, please use -J instead.\n"));
                    954:                  input_format = input_format_tmp;
                    955:                  break;
                    956:                }
1.1       skrll     957:            }
1.1.1.2   christos  958:          /* Fall through.  */
1.1       skrll     959:
1.1.1.2   christos  960:        case OPTION_INCLUDE_DIR:
1.1       skrll     961:          if (preprocargs == NULL)
                    962:            {
                    963:              quotedarg = quot (optarg);
                    964:              preprocargs = xmalloc (strlen (quotedarg) + 3);
                    965:              sprintf (preprocargs, "-I%s", quotedarg);
                    966:            }
                    967:          else
                    968:            {
                    969:              char *n;
                    970:
                    971:              quotedarg = quot (optarg);
                    972:              n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
                    973:              sprintf (n, "%s -I%s", preprocargs, quotedarg);
                    974:              free (preprocargs);
                    975:              preprocargs = n;
                    976:            }
                    977:
                    978:          windres_add_include_dir (optarg);
                    979:
                    980:          break;
                    981:
                    982:        case 'l':
                    983:          language = strtol (optarg, (char **) NULL, 16);
                    984:          break;
                    985:
                    986:        case OPTION_USE_TEMP_FILE:
                    987:          use_temp_file = 1;
                    988:          break;
                    989:
                    990:        case OPTION_NO_USE_TEMP_FILE:
                    991:          use_temp_file = 0;
                    992:          break;
                    993:
                    994: #ifdef YYDEBUG
                    995:        case OPTION_YYDEBUG:
                    996:          yydebug = 1;
                    997:          break;
                    998: #endif
                    999:
                   1000:        case 'h':
                   1001:        case 'H':
                   1002:          usage (stdout, 0);
                   1003:          break;
                   1004:
                   1005:        case 'V':
                   1006:          print_version ("windres");
                   1007:          break;
                   1008:
                   1009:        default:
                   1010:          usage (stderr, 1);
                   1011:          break;
                   1012:        }
                   1013:     }
                   1014:
                   1015:   if (input_filename == NULL && optind < argc)
                   1016:     {
                   1017:       input_filename = argv[optind];
                   1018:       ++optind;
                   1019:     }
                   1020:
                   1021:   if (output_filename == NULL && optind < argc)
                   1022:     {
                   1023:       output_filename = argv[optind];
                   1024:       ++optind;
                   1025:     }
                   1026:
                   1027:   if (argc != optind)
                   1028:     usage (stderr, 1);
                   1029:
                   1030:   if (input_format == RES_FORMAT_UNKNOWN)
                   1031:     {
                   1032:       if (input_filename == NULL)
                   1033:        input_format = RES_FORMAT_RC;
                   1034:       else
                   1035:        input_format = format_from_filename (input_filename, 1);
                   1036:     }
                   1037:
                   1038:   if (output_format == RES_FORMAT_UNKNOWN)
                   1039:     {
                   1040:       if (output_filename == NULL)
                   1041:        output_format = RES_FORMAT_RC;
                   1042:       else
                   1043:        output_format = format_from_filename (output_filename, 0);
                   1044:     }
                   1045:
1.1.1.3   christos 1046:   set_endianness (NULL, target);
1.1       skrll    1047:
                   1048:   /* Read the input file.  */
                   1049:   switch (input_format)
                   1050:     {
                   1051:     default:
                   1052:       abort ();
                   1053:     case RES_FORMAT_RC:
                   1054:       resources = read_rc_file (input_filename, preprocessor, preprocargs,
                   1055:                                language, use_temp_file);
                   1056:       break;
                   1057:     case RES_FORMAT_RES:
                   1058:       resources = read_res_file (input_filename);
                   1059:       break;
                   1060:     case RES_FORMAT_COFF:
                   1061:       resources = read_coff_rsrc (input_filename, target);
                   1062:       break;
                   1063:     }
                   1064:
                   1065:   if (resources == NULL)
                   1066:     fatal (_("no resources"));
                   1067:
                   1068:   /* Sort the resources.  This is required for COFF, convenient for
                   1069:      rc, and unimportant for res.  */
                   1070:   resources = sort_resources (resources);
                   1071:
                   1072:   /* Write the output file.  */
                   1073:   reswr_init ();
                   1074:
                   1075:   switch (output_format)
                   1076:     {
                   1077:     default:
                   1078:       abort ();
                   1079:     case RES_FORMAT_RC:
                   1080:       write_rc_file (output_filename, resources);
                   1081:       break;
                   1082:     case RES_FORMAT_RES:
                   1083:       write_res_file (output_filename, resources);
                   1084:       break;
                   1085:     case RES_FORMAT_COFF:
                   1086:       write_coff_file (output_filename, target, resources);
                   1087:       break;
                   1088:     }
                   1089:
                   1090:   xexit (0);
                   1091:   return 0;
                   1092: }
                   1093:
                   1094: static void
1.1.1.3   christos 1095: set_endianness (bfd *abfd, const char *target)
1.1       skrll    1096: {
                   1097:   const bfd_target *target_vec;
                   1098:
                   1099:   def_target_arch = NULL;
1.1.1.2   christos 1100:   target_vec = bfd_get_target_info (target, abfd, &target_is_bigendian, NULL,
                   1101:                                    &def_target_arch);
1.1       skrll    1102:   if (! target_vec)
1.1.1.3   christos 1103:     fatal ("Can't detect target endianness and architecture.");
1.1.1.2   christos 1104:   if (! def_target_arch)
                   1105:     fatal ("Can't detect architecture.");
1.1       skrll    1106: }
                   1107:
                   1108: bfd *
                   1109: windres_open_as_binary (const char *filename, int rdmode)
                   1110: {
                   1111:   bfd *abfd;
                   1112:
                   1113:   abfd = (rdmode ? bfd_openr (filename, "binary") : bfd_openw (filename, "binary"));
                   1114:   if (! abfd)
                   1115:     fatal ("can't open `%s' for %s", filename, (rdmode ? "input" : "output"));
                   1116:
                   1117:   if (rdmode && ! bfd_check_format (abfd, bfd_object))
                   1118:     fatal ("can't open `%s' for input.", filename);
1.1.1.4   christos 1119:
1.1       skrll    1120:   return abfd;
                   1121: }
                   1122:
                   1123: void
1.1.1.3   christos 1124: set_windres_bfd_endianness (windres_bfd *wrbfd, int is_bigendian)
1.1       skrll    1125: {
                   1126:   assert (!! wrbfd);
                   1127:   switch (WR_KIND(wrbfd))
                   1128:   {
                   1129:   case WR_KIND_BFD_BIN_L:
                   1130:     if (is_bigendian)
                   1131:       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_B;
                   1132:     break;
                   1133:   case WR_KIND_BFD_BIN_B:
                   1134:     if (! is_bigendian)
                   1135:       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_L;
                   1136:     break;
                   1137:   default:
                   1138:     /* only binary bfd can be overriden. */
                   1139:     abort ();
                   1140:   }
                   1141: }
                   1142:
                   1143: void
                   1144: set_windres_bfd (windres_bfd *wrbfd, bfd *abfd, asection *sec, rc_uint_type kind)
                   1145: {
                   1146:   assert (!! wrbfd);
                   1147:   switch (kind)
                   1148:   {
                   1149:   case WR_KIND_TARGET:
                   1150:     abfd = NULL;
                   1151:     sec = NULL;
                   1152:     break;
                   1153:   case WR_KIND_BFD:
                   1154:   case WR_KIND_BFD_BIN_L:
                   1155:   case WR_KIND_BFD_BIN_B:
                   1156:     assert (!! abfd);
                   1157:     assert (!!sec);
                   1158:     break;
                   1159:   default:
                   1160:     abort ();
                   1161:   }
                   1162:   WR_KIND(wrbfd) = kind;
                   1163:   WR_BFD(wrbfd) = abfd;
                   1164:   WR_SECTION(wrbfd) = sec;
                   1165: }
                   1166:
                   1167: void
                   1168: set_windres_bfd_content (windres_bfd *wrbfd, const void *data, rc_uint_type off,
                   1169:                         rc_uint_type length)
                   1170: {
                   1171:   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
                   1172:     {
                   1173:       if (! bfd_set_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
                   1174:        bfd_fatal ("bfd_set_section_contents");
                   1175:     }
                   1176:   else
                   1177:     abort ();
                   1178: }
                   1179:
                   1180: void
                   1181: get_windres_bfd_content (windres_bfd *wrbfd, void *data, rc_uint_type off,
                   1182:                         rc_uint_type length)
                   1183: {
                   1184:   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
                   1185:     {
                   1186:       if (! bfd_get_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
                   1187:        bfd_fatal ("bfd_get_section_contents");
                   1188:     }
                   1189:   else
                   1190:     abort ();
                   1191: }
                   1192:
                   1193: void
                   1194: windres_put_8 (windres_bfd *wrbfd, void *p, rc_uint_type value)
                   1195: {
                   1196:   switch (WR_KIND(wrbfd))
                   1197:     {
                   1198:     case WR_KIND_TARGET:
                   1199:       target_put_8 (p, value);
                   1200:       break;
                   1201:     case WR_KIND_BFD:
                   1202:     case WR_KIND_BFD_BIN_L:
                   1203:     case WR_KIND_BFD_BIN_B:
                   1204:       bfd_put_8 (WR_BFD(wrbfd), value, p);
                   1205:       break;
                   1206:     default:
                   1207:       abort ();
                   1208:     }
                   1209: }
                   1210:
                   1211: void
                   1212: windres_put_16 (windres_bfd *wrbfd, void *data, rc_uint_type value)
                   1213: {
                   1214:   switch (WR_KIND(wrbfd))
                   1215:     {
                   1216:     case WR_KIND_TARGET:
                   1217:       target_put_16 (data, value);
                   1218:       break;
                   1219:     case WR_KIND_BFD:
                   1220:     case WR_KIND_BFD_BIN_B:
                   1221:       bfd_put_16 (WR_BFD(wrbfd), value, data);
                   1222:       break;
                   1223:     case WR_KIND_BFD_BIN_L:
                   1224:       bfd_putl16 (value, data);
                   1225:       break;
                   1226:     default:
                   1227:       abort ();
                   1228:     }
                   1229: }
                   1230:
                   1231: void
                   1232: windres_put_32 (windres_bfd *wrbfd, void *data, rc_uint_type value)
                   1233: {
                   1234:   switch (WR_KIND(wrbfd))
                   1235:     {
                   1236:     case WR_KIND_TARGET:
                   1237:       target_put_32 (data, value);
                   1238:       break;
                   1239:     case WR_KIND_BFD:
                   1240:     case WR_KIND_BFD_BIN_B:
                   1241:       bfd_put_32 (WR_BFD(wrbfd), value, data);
                   1242:       break;
                   1243:     case WR_KIND_BFD_BIN_L:
                   1244:       bfd_putl32 (value, data);
                   1245:       break;
                   1246:     default:
                   1247:       abort ();
                   1248:     }
                   1249: }
                   1250:
                   1251: rc_uint_type
                   1252: windres_get_8 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
                   1253: {
                   1254:   if (length < 1)
                   1255:     fatal ("windres_get_8: unexpected eob.");
                   1256:   switch (WR_KIND(wrbfd))
                   1257:     {
                   1258:     case WR_KIND_TARGET:
                   1259:       return target_get_8 (data, length);
                   1260:     case WR_KIND_BFD:
                   1261:     case WR_KIND_BFD_BIN_B:
                   1262:     case WR_KIND_BFD_BIN_L:
                   1263:       return bfd_get_8 (WR_BFD(wrbfd), data);
                   1264:     default:
                   1265:       abort ();
                   1266:     }
                   1267:   return 0;
                   1268: }
                   1269:
                   1270: rc_uint_type
                   1271: windres_get_16 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
                   1272: {
                   1273:   if (length < 2)
                   1274:     fatal ("windres_get_16: unexpected eob.");
                   1275:   switch (WR_KIND(wrbfd))
                   1276:     {
                   1277:     case WR_KIND_TARGET:
                   1278:       return target_get_16 (data, length);
                   1279:     case WR_KIND_BFD:
                   1280:     case WR_KIND_BFD_BIN_B:
                   1281:       return bfd_get_16 (WR_BFD(wrbfd), data);
                   1282:     case WR_KIND_BFD_BIN_L:
                   1283:       return bfd_getl16 (data);
                   1284:     default:
                   1285:       abort ();
                   1286:     }
                   1287:   return 0;
                   1288: }
                   1289:
                   1290: rc_uint_type
                   1291: windres_get_32 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
                   1292: {
                   1293:   if (length < 4)
                   1294:     fatal ("windres_get_32: unexpected eob.");
                   1295:   switch (WR_KIND(wrbfd))
                   1296:     {
                   1297:     case WR_KIND_TARGET:
                   1298:       return target_get_32 (data, length);
                   1299:     case WR_KIND_BFD:
                   1300:     case WR_KIND_BFD_BIN_B:
                   1301:       return bfd_get_32 (WR_BFD(wrbfd), data);
                   1302:     case WR_KIND_BFD_BIN_L:
                   1303:       return bfd_getl32 (data);
                   1304:     default:
                   1305:       abort ();
                   1306:     }
                   1307:   return 0;
                   1308: }
                   1309:
                   1310: static rc_uint_type
                   1311: target_get_8 (const void *p, rc_uint_type length)
                   1312: {
                   1313:   rc_uint_type ret;
1.1.1.4   christos 1314:
1.1       skrll    1315:   if (length < 1)
                   1316:     fatal ("Resource too small for getting 8-bit value.");
                   1317:
                   1318:   ret = (rc_uint_type) *((const bfd_byte *) p);
                   1319:   return ret & 0xff;
                   1320: }
                   1321:
                   1322: static rc_uint_type
                   1323: target_get_16 (const void *p, rc_uint_type length)
                   1324: {
                   1325:   if (length < 2)
                   1326:     fatal ("Resource too small for getting 16-bit value.");
1.1.1.4   christos 1327:
1.1       skrll    1328:   if (target_is_bigendian)
                   1329:     return bfd_getb16 (p);
                   1330:   else
                   1331:     return bfd_getl16 (p);
                   1332: }
                   1333:
                   1334: static rc_uint_type
                   1335: target_get_32 (const void *p, rc_uint_type length)
                   1336: {
                   1337:   if (length < 4)
                   1338:     fatal ("Resource too small for getting 32-bit value.");
1.1.1.4   christos 1339:
1.1       skrll    1340:   if (target_is_bigendian)
                   1341:     return bfd_getb32 (p);
                   1342:   else
                   1343:     return bfd_getl32 (p);
                   1344: }
                   1345:
                   1346: static void
                   1347: target_put_8 (void *p, rc_uint_type value)
                   1348: {
                   1349:   assert (!! p);
                   1350:   *((bfd_byte *) p)=(bfd_byte) value;
                   1351: }
                   1352:
                   1353: static void
                   1354: target_put_16 (void *p, rc_uint_type value)
                   1355: {
                   1356:   assert (!! p);
1.1.1.4   christos 1357:
1.1       skrll    1358:   if (target_is_bigendian)
                   1359:     bfd_putb16 (value, p);
                   1360:   else
                   1361:     bfd_putl16 (value, p);
                   1362: }
                   1363:
                   1364: static void
                   1365: target_put_32 (void *p, rc_uint_type value)
                   1366: {
                   1367:   assert (!! p);
1.1.1.4   christos 1368:
1.1       skrll    1369:   if (target_is_bigendian)
                   1370:     bfd_putb32 (value, p);
                   1371:   else
                   1372:     bfd_putl32 (value, p);
                   1373: }
                   1374:
                   1375: static int isInComment = 0;
                   1376:
                   1377: int wr_printcomment (FILE *e, const char *fmt, ...)
                   1378: {
                   1379:   va_list arg;
                   1380:   int r = 0;
                   1381:
                   1382:   if (isInComment)
                   1383:     r += fprintf (e, "\n   ");
                   1384:   else
                   1385:     fprintf (e, "/* ");
                   1386:   isInComment = 1;
                   1387:   if (fmt == NULL)
                   1388:     return r;
                   1389:   va_start (arg, fmt);
                   1390:   r += vfprintf (e, fmt, arg);
                   1391:   va_end (arg);
                   1392:   return r;
                   1393: }
                   1394:
                   1395: int wr_print (FILE *e, const char *fmt, ...)
                   1396: {
                   1397:   va_list arg;
                   1398:   int r = 0;
                   1399:   if (isInComment)
                   1400:     r += fprintf (e, ".  */\n");
                   1401:   isInComment = 0;
                   1402:   if (! fmt)
                   1403:     return r;
                   1404:   va_start (arg, fmt);
                   1405:   r += vfprintf (e, fmt, arg);
                   1406:   va_end (arg);
1.1.1.4   christos 1407:   return r;
1.1       skrll    1408: }

CVSweb <webmaster@jp.NetBSD.org>