OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [resrc.c] - Blame information for rev 163

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 khays
/* resrc.c -- read and write Windows rc files.
2 163 khays
   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2011
3 15 khays
   Free Software Foundation, Inc.
4
   Written by Ian Lance Taylor, Cygnus Support.
5
   Rewritten by Kai Tietz, Onevision.
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
11
   the Free Software Foundation; either version 3 of the License, or
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
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22
   02110-1301, USA.  */
23
 
24
/* This file contains functions that read and write Windows rc files.
25
   These are text files that represent resources.  */
26
 
27
#include "sysdep.h"
28
#include "bfd.h"
29
#include "bucomm.h"
30
#include "libiberty.h"
31
#include "safe-ctype.h"
32
#include "windres.h"
33
 
34
#include <assert.h>
35
#include <errno.h>
36
#include <sys/stat.h>
37
#ifdef HAVE_UNISTD_H
38
#include <unistd.h>
39
#endif
40
 
41
#ifdef HAVE_SYS_WAIT_H
42
#include <sys/wait.h>
43
#else /* ! HAVE_SYS_WAIT_H */
44
#if ! defined (_WIN32) || defined (__CYGWIN__)
45
#ifndef WIFEXITED
46
#define WIFEXITED(w)    (((w)&0377) == 0)
47
#endif
48
#ifndef WIFSIGNALED
49
#define WIFSIGNALED(w)  (((w)&0377) != 0177 && ((w)&~0377) == 0)
50
#endif
51
#ifndef WTERMSIG
52
#define WTERMSIG(w)     ((w) & 0177)
53
#endif
54
#ifndef WEXITSTATUS
55
#define WEXITSTATUS(w)  (((w) >> 8) & 0377)
56
#endif
57
#else /* defined (_WIN32) && ! defined (__CYGWIN__) */
58
#ifndef WIFEXITED
59
#define WIFEXITED(w)    (((w) & 0xff) == 0)
60
#endif
61
#ifndef WIFSIGNALED
62
#define WIFSIGNALED(w)  (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
63
#endif
64
#ifndef WTERMSIG
65
#define WTERMSIG(w)     ((w) & 0x7f)
66
#endif
67
#ifndef WEXITSTATUS
68
#define WEXITSTATUS(w)  (((w) & 0xff00) >> 8)
69
#endif
70
#endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
71
#endif /* ! HAVE_SYS_WAIT_H */
72
 
73
#ifndef STDOUT_FILENO
74
#define STDOUT_FILENO 1
75
#endif
76
 
77
#if defined (_WIN32) && ! defined (__CYGWIN__)
78
#define popen _popen
79
#define pclose _pclose
80
#endif
81
 
82
/* The default preprocessor.  */
83
 
84
#define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
85
 
86
/* We read the directory entries in a cursor or icon file into
87
   instances of this structure.  */
88
 
89
struct icondir
90
{
91
  /* Width of image.  */
92
  bfd_byte width;
93
  /* Height of image.  */
94
  bfd_byte height;
95
  /* Number of colors in image.  */
96
  bfd_byte colorcount;
97
  union
98
  {
99
    struct
100
    {
101
      /* Color planes.  */
102
      unsigned short planes;
103
      /* Bits per pixel.  */
104
      unsigned short bits;
105
    } icon;
106
    struct
107
    {
108
      /* X coordinate of hotspot.  */
109
      unsigned short xhotspot;
110
      /* Y coordinate of hotspot.  */
111
      unsigned short yhotspot;
112
    } cursor;
113
  } u;
114
  /* Bytes in image.  */
115
  unsigned long bytes;
116
  /* File offset of image.  */
117
  unsigned long offset;
118
};
119
 
120
/* The name of the rc file we are reading.  */
121
 
122
char *rc_filename;
123
 
124
/* The line number in the rc file.  */
125
 
126
int rc_lineno;
127
 
128
/* The pipe we are reading from, so that we can close it if we exit.  */
129
 
130
FILE *cpp_pipe;
131
 
132
/* The temporary file used if we're not using popen, so we can delete it
133
   if we exit.  */
134
 
135
static char *cpp_temp_file;
136
 
137
/* Input stream is either a file or a pipe.  */
138
 
139
static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
140
 
141
/* As we read the rc file, we attach information to this structure.  */
142
 
143
static rc_res_directory *resources;
144
 
145
/* The number of cursor resources we have written out.  */
146
 
147
static int cursors;
148
 
149
/* The number of font resources we have written out.  */
150
 
151
static int fonts;
152
 
153
/* Font directory information.  */
154
 
155
rc_fontdir *fontdirs;
156
 
157
/* Resource info to use for fontdirs.  */
158
 
159
rc_res_res_info fontdirs_resinfo;
160
 
161
/* The number of icon resources we have written out.  */
162
 
163
static int icons;
164
 
165
/* The windres target bfd .  */
166
 
167
static windres_bfd wrtarget =
168
{
169
  (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET
170
};
171
 
172
/* Local functions for rcdata based resource definitions.  */
173
 
174
static void define_font_rcdata (rc_res_id, const rc_res_res_info *,
175
                                rc_rcdata_item *);
176
static void define_icon_rcdata (rc_res_id, const rc_res_res_info *,
177
                                rc_rcdata_item *);
178
static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *,
179
                                  rc_rcdata_item *);
180
static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *,
181
                                  rc_rcdata_item *);
182
static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *,
183
                                   rc_rcdata_item *);
184
static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *,
185
                                        rc_rcdata_item *);
186
static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *);
187
static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *);
188
 
189
static int run_cmd (char *, const char *);
190
static FILE *open_input_stream (char *);
191
static FILE *look_for_default
192
  (char *, const char *, int, const char *, const char *);
193
static void close_input_stream (void);
194
static void unexpected_eof (const char *);
195
static int get_word (FILE *, const char *);
196
static unsigned long get_long (FILE *, const char *);
197
static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *);
198
static void define_fontdirs (void);
199
 
200
/* Run `cmd' and redirect the output to `redir'.  */
201
 
202
static int
203
run_cmd (char *cmd, const char *redir)
204
{
205
  char *s;
206
  int pid, wait_status, retcode;
207
  int i;
208
  const char **argv;
209
  char *errmsg_fmt, *errmsg_arg;
210
  char *temp_base = choose_temp_base ();
211
  int in_quote;
212
  char sep;
213
  int redir_handle = -1;
214
  int stdout_save = -1;
215
 
216
  /* Count the args.  */
217
  i = 0;
218
 
219
  for (s = cmd; *s; s++)
220
    if (*s == ' ')
221
      i++;
222
 
223
  i++;
224
  argv = alloca (sizeof (char *) * (i + 3));
225
  i = 0;
226
  s = cmd;
227
 
228
  while (1)
229
    {
230
      while (*s == ' ' && *s != 0)
231
        s++;
232
 
233
      if (*s == 0)
234
        break;
235
 
236
      in_quote = (*s == '\'' || *s == '"');
237
      sep = (in_quote) ? *s++ : ' ';
238
      argv[i++] = s;
239
 
240
      while (*s != sep && *s != 0)
241
        s++;
242
 
243
      if (*s == 0)
244
        break;
245
 
246
      *s++ = 0;
247
 
248
      if (in_quote)
249
        s++;
250
    }
251
  argv[i++] = NULL;
252
 
253
  /* Setup the redirection.  We can't use the usual fork/exec and redirect
254
     since we may be running on non-POSIX Windows host.  */
255
 
256
  fflush (stdout);
257
  fflush (stderr);
258
 
259
  /* Open temporary output file.  */
260
  redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
261
  if (redir_handle == -1)
262
    fatal (_("can't open temporary file `%s': %s"), redir,
263
           strerror (errno));
264
 
265
  /* Duplicate the stdout file handle so it can be restored later.  */
266
  stdout_save = dup (STDOUT_FILENO);
267
  if (stdout_save == -1)
268
    fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
269
 
270
  /* Redirect stdout to our output file.  */
271
  dup2 (redir_handle, STDOUT_FILENO);
272
 
273
  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
274
                  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
275
 
276
  /* Restore stdout to its previous setting.  */
277
  dup2 (stdout_save, STDOUT_FILENO);
278
 
279
  /* Close response file.  */
280
  close (redir_handle);
281
 
282
  if (pid == -1)
283
    {
284
      fatal ("%s %s: %s", errmsg_fmt, errmsg_arg, strerror (errno));
285
      return 1;
286
    }
287
 
288
  retcode = 0;
289
  pid = pwait (pid, &wait_status, 0);
290
 
291
  if (pid == -1)
292
    {
293
      fatal (_("wait: %s"), strerror (errno));
294
      retcode = 1;
295
    }
296
  else if (WIFSIGNALED (wait_status))
297
    {
298
      fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
299
      retcode = 1;
300
    }
301
  else if (WIFEXITED (wait_status))
302
    {
303
      if (WEXITSTATUS (wait_status) != 0)
304
        {
305
          fatal (_("%s exited with status %d"), cmd,
306
                 WEXITSTATUS (wait_status));
307
          retcode = 1;
308
        }
309
    }
310
  else
311
    retcode = 1;
312
 
313
  return retcode;
314
}
315
 
316
static FILE *
317
open_input_stream (char *cmd)
318
{
319
  if (istream_type == ISTREAM_FILE)
320
    {
321
      char *fileprefix;
322
 
323
      fileprefix = choose_temp_base ();
324
      cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
325
      sprintf (cpp_temp_file, "%s.irc", fileprefix);
326
      free (fileprefix);
327
 
328
      if (run_cmd (cmd, cpp_temp_file))
329
        fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
330
 
331
      cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
332
      if (cpp_pipe == NULL)
333
        fatal (_("can't open temporary file `%s': %s"),
334
               cpp_temp_file, strerror (errno));
335
 
336
      if (verbose)
337
        fprintf (stderr,
338
                 _("Using temporary file `%s' to read preprocessor output\n"),
339
                 cpp_temp_file);
340
    }
341
  else
342
    {
343
      cpp_pipe = popen (cmd, FOPEN_RT);
344
      if (cpp_pipe == NULL)
345
        fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
346
      if (verbose)
347
        fprintf (stderr, _("Using popen to read preprocessor output\n"));
348
    }
349
 
350
  xatexit (close_input_stream);
351
  return cpp_pipe;
352
}
353
 
354
/* Determine if FILENAME contains special characters that
355
   can cause problems unless the entire filename is quoted.  */
356
 
357
static int
358
filename_need_quotes (const char *filename)
359
{
360
  if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
361
    return 0;
362
 
363
  while (*filename != 0)
364
    {
365
      switch (*filename)
366
        {
367
        case '&':
368
        case ' ':
369
        case '<':
370
        case '>':
371
        case '|':
372
        case '%':
373
          return 1;
374
        }
375
      ++filename;
376
    }
377
  return 0;
378
}
379
 
380
/* Look for the preprocessor program.  */
381
 
382
static FILE *
383
look_for_default (char *cmd, const char *prefix, int end_prefix,
384
                  const char *preprocargs, const char *filename)
385
{
386
  char *space;
387
  int found;
388
  struct stat s;
389
  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
390
 
391
  strcpy (cmd, prefix);
392
 
393
  sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
394
  space = strchr (cmd + end_prefix, ' ');
395
  if (space)
396
    *space = 0;
397
 
398
  if (
399
#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
400
      strchr (cmd, '\\') ||
401
#endif
402
      strchr (cmd, '/'))
403
    {
404
      found = (stat (cmd, &s) == 0
405
#ifdef HAVE_EXECUTABLE_SUFFIX
406
               || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
407
#endif
408
               );
409
 
410
      if (! found)
411
        {
412
          if (verbose)
413
            fprintf (stderr, _("Tried `%s'\n"), cmd);
414
          return NULL;
415
        }
416
    }
417
 
418
  strcpy (cmd, prefix);
419
 
420
  sprintf (cmd + end_prefix, "%s %s %s%s%s",
421
           DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
422
 
423
  if (verbose)
424
    fprintf (stderr, _("Using `%s'\n"), cmd);
425
 
426
  cpp_pipe = open_input_stream (cmd);
427
  return cpp_pipe;
428
}
429
 
430
/* Read an rc file.  */
431
 
432
rc_res_directory *
433
read_rc_file (const char *filename, const char *preprocessor,
434
              const char *preprocargs, int language, int use_temp_file)
435
{
436
  char *cmd;
437
  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
438
 
439
  if (filename == NULL)
440
    filename = "-";
441
  /* Setup the default resource import path taken from input file.  */
442
  else if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL)
443
    {
444
      char *edit, *dir;
445
 
446
      if (filename[0] == '/'
447
          || filename[0] == '\\'
448
          || filename[1] == ':')
449
        /* Absolute path.  */
450
        edit = dir = xstrdup (filename);
451
      else
452
        {
453
          /* Relative path.  */
454
          edit = dir = xmalloc (strlen (filename) + 3);
455
          sprintf (dir, "./%s", filename);
456
        }
457
 
458
      /* Walk dir backwards stopping at the first directory separator.  */
459
      edit += strlen (dir);
460
      while (edit > dir && (edit[-1] != '\\' && edit[-1] != '/'))
461
        {
462
          --edit;
463
          edit[0] = 0;
464
        }
465
 
466
      /* Cut off trailing slash.  */
467
      --edit;
468
      edit[0] = 0;
469
 
470
      /* Convert all back slashes to forward slashes.  */
471
      while ((edit = strchr (dir, '\\')) != NULL)
472
        *edit = '/';
473
 
474
      windres_add_include_dir (dir);
475
    }
476
 
477
  istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
478
 
479
  if (preprocargs == NULL)
480
    preprocargs = "";
481
 
482
  if (preprocessor)
483
    {
484
      cmd = xmalloc (strlen (preprocessor)
485
                     + strlen (preprocargs)
486
                     + strlen (filename)
487
                     + strlen (fnquotes) * 2
488
                     + 10);
489
      sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs,
490
               fnquotes, filename, fnquotes);
491
 
492
      cpp_pipe = open_input_stream (cmd);
493
    }
494
  else
495
    {
496
      char *dash, *slash, *cp;
497
 
498
      preprocessor = DEFAULT_PREPROCESSOR;
499
 
500
      cmd = xmalloc (strlen (program_name)
501
                     + strlen (preprocessor)
502
                     + strlen (preprocargs)
503
                     + strlen (filename)
504
                     + strlen (fnquotes) * 2
505
#ifdef HAVE_EXECUTABLE_SUFFIX
506
                     + strlen (EXECUTABLE_SUFFIX)
507
#endif
508
                     + 10);
509
 
510
 
511
      dash = slash = 0;
512
      for (cp = program_name; *cp; cp++)
513
        {
514
          if (*cp == '-')
515
            dash = cp;
516
          if (
517
#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
518
              *cp == ':' || *cp == '\\' ||
519
#endif
520
              *cp == '/')
521
            {
522
              slash = cp;
523
              dash = 0;
524
            }
525
        }
526
 
527
      cpp_pipe = 0;
528
 
529
      if (dash)
530
        {
531
          /* First, try looking for a prefixed gcc in the windres
532
             directory, with the same prefix as windres */
533
 
534
          cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1,
535
                                       preprocargs, filename);
536
        }
537
 
538
      if (slash && ! cpp_pipe)
539
        {
540
          /* Next, try looking for a gcc in the same directory as
541
             that windres */
542
 
543
          cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1,
544
                                       preprocargs, filename);
545
        }
546
 
547
      if (! cpp_pipe)
548
        {
549
          /* Sigh, try the default */
550
 
551
          cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
552
        }
553
 
554
    }
555
 
556
  free (cmd);
557
 
558
  rc_filename = xstrdup (filename);
559
  rc_lineno = 1;
560
  if (language != -1)
561
    rcparse_set_language (language);
562
  yyparse ();
563
  rcparse_discard_strings ();
564
 
565
  close_input_stream ();
566
 
567
  if (fontdirs != NULL)
568
    define_fontdirs ();
569
 
570
  free (rc_filename);
571
  rc_filename = NULL;
572
 
573
  return resources;
574
}
575
 
576
/* Close the input stream if it is open.  */
577
 
578
static void
579
close_input_stream (void)
580
{
581
  if (istream_type == ISTREAM_FILE)
582
    {
583
      if (cpp_pipe != NULL)
584
        fclose (cpp_pipe);
585
 
586
      if (cpp_temp_file != NULL)
587
        {
588
          int errno_save = errno;
589
 
590
          unlink (cpp_temp_file);
591
          errno = errno_save;
592
          free (cpp_temp_file);
593
        }
594
    }
595
  else
596
    {
597
      if (cpp_pipe != NULL)
598
        {
599
          int err;
600
          err = pclose (cpp_pipe);
601
          /* We are reading from a pipe, therefore we don't
602
             know if cpp failed or succeeded until pclose.  */
603
          if (err != 0 || errno == ECHILD)
604
            {
605
              /* Since this is also run via xatexit, safeguard.  */
606
              cpp_pipe = NULL;
607
              cpp_temp_file = NULL;
608
              fatal (_("preprocessing failed."));
609
            }
610
        }
611
    }
612
 
613
  /* Since this is also run via xatexit, safeguard.  */
614
  cpp_pipe = NULL;
615
  cpp_temp_file = NULL;
616
}
617
 
618
/* Report an error while reading an rc file.  */
619
 
620
void
621
yyerror (const char *msg)
622
{
623
  fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
624
}
625
 
626
/* Issue a warning while reading an rc file.  */
627
 
628
void
629
rcparse_warning (const char *msg)
630
{
631
  fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
632
}
633
 
634
/* Die if we get an unexpected end of file.  */
635
 
636
static void
637
unexpected_eof (const char *msg)
638
{
639
  fatal (_("%s: unexpected EOF"), msg);
640
}
641
 
642
/* Read a 16 bit word from a file.  The data is assumed to be little
643
   endian.  */
644
 
645
static int
646
get_word (FILE *e, const char *msg)
647
{
648
  int b1, b2;
649
 
650
  b1 = getc (e);
651
  b2 = getc (e);
652
  if (feof (e))
653
    unexpected_eof (msg);
654
  return ((b2 & 0xff) << 8) | (b1 & 0xff);
655
}
656
 
657
/* Read a 32 bit word from a file.  The data is assumed to be little
658
   endian.  */
659
 
660
static unsigned long
661
get_long (FILE *e, const char *msg)
662
{
663
  int b1, b2, b3, b4;
664
 
665
  b1 = getc (e);
666
  b2 = getc (e);
667
  b3 = getc (e);
668
  b4 = getc (e);
669
  if (feof (e))
670
    unexpected_eof (msg);
671
  return (((((((b4 & 0xff) << 8)
672
              | (b3 & 0xff)) << 8)
673
            | (b2 & 0xff)) << 8)
674
          | (b1 & 0xff));
675
}
676
 
677
/* Read data from a file.  This is a wrapper to do error checking.  */
678
 
679
static void
680
get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg)
681
{
682
  rc_uint_type got; // $$$d
683
 
684
  got = (rc_uint_type) fread (p, 1, c, e);
685
  if (got == c)
686
    return;
687
 
688
  fatal (_("%s: read of %lu returned %lu"),
689
         msg, (unsigned long) c, (unsigned long) got);
690
}
691
 
692
/* Define an accelerator resource.  */
693
 
694
void
695
define_accelerator (rc_res_id id, const rc_res_res_info *resinfo,
696
                    rc_accelerator *data)
697
{
698
  rc_res_resource *r;
699
 
700
  r = define_standard_resource (&resources, RT_ACCELERATOR, id,
701
                                resinfo->language, 0);
702
  r->type = RES_TYPE_ACCELERATOR;
703
  r->u.acc = data;
704
  r->res_info = *resinfo;
705
}
706
 
707
/* Define a bitmap resource.  Bitmap data is stored in a file.  The
708
   first 14 bytes of the file are a standard header, which is not
709
   included in the resource data.  */
710
 
711
#define BITMAP_SKIP (14)
712
 
713
void
714
define_bitmap (rc_res_id id, const rc_res_res_info *resinfo,
715
               const char *filename)
716
{
717
  FILE *e;
718
  char *real_filename;
719
  struct stat s;
720
  bfd_byte *data;
721
  rc_uint_type i;
722
  rc_res_resource *r;
723
 
724
  e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
725
 
726
  if (stat (real_filename, &s) < 0)
727
    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
728
           strerror (errno));
729
 
730
  data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP);
731
 
732
  for (i = 0; i < BITMAP_SKIP; i++)
733
    getc (e);
734
 
735
  get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
736
 
737
  fclose (e);
738
  free (real_filename);
739
 
740
  r = define_standard_resource (&resources, RT_BITMAP, id,
741
                                resinfo->language, 0);
742
 
743
  r->type = RES_TYPE_BITMAP;
744
  r->u.data.length = s.st_size - BITMAP_SKIP;
745
  r->u.data.data = data;
746
  r->res_info = *resinfo;
747
}
748
 
749
/* Define a cursor resource.  A cursor file may contain a set of
750
   bitmaps, each representing the same cursor at various different
751
   resolutions.  They each get written out with a different ID.  The
752
   real cursor resource is then a group resource which can be used to
753
   select one of the actual cursors.  */
754
 
755
void
756
define_cursor (rc_res_id id, const rc_res_res_info *resinfo,
757
               const char *filename)
758
{
759
  FILE *e;
760
  char *real_filename;
761
  int type, count, i;
762
  struct icondir *icondirs;
763
  int first_cursor;
764
  rc_res_resource *r;
765
  rc_group_cursor *first, **pp;
766
 
767
  e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
768
 
769
  /* A cursor file is basically an icon file.  The start of the file
770
     is a three word structure.  The first word is ignored.  The
771
     second word is the type of data.  The third word is the number of
772
     entries.  */
773
 
774
  get_word (e, real_filename);
775
  type = get_word (e, real_filename);
776
  count = get_word (e, real_filename);
777
  if (type != 2)
778
    fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
779
 
780
  /* Read in the icon directory entries.  */
781
 
782
  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
783
 
784
  for (i = 0; i < count; i++)
785
    {
786
      icondirs[i].width = getc (e);
787
      icondirs[i].height = getc (e);
788
      icondirs[i].colorcount = getc (e);
789
      getc (e);
790
      icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
791
      icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
792
      icondirs[i].bytes = get_long (e, real_filename);
793
      icondirs[i].offset = get_long (e, real_filename);
794
 
795
      if (feof (e))
796
        unexpected_eof (real_filename);
797
    }
798
 
799
  /* Define each cursor as a unique resource.  */
800
 
801
  first_cursor = cursors;
802
 
803
  for (i = 0; i < count; i++)
804
    {
805
      bfd_byte *data;
806
      rc_res_id name;
807
      rc_cursor *c;
808
 
809
      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
810
        fatal (_("%s: fseek to %lu failed: %s"), real_filename,
811
               icondirs[i].offset, strerror (errno));
812
 
813
      data = (bfd_byte *) res_alloc (icondirs[i].bytes);
814
 
815
      get_data (e, data, icondirs[i].bytes, real_filename);
816
 
817
      c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
818
      c->xhotspot = icondirs[i].u.cursor.xhotspot;
819
      c->yhotspot = icondirs[i].u.cursor.yhotspot;
820
      c->length = icondirs[i].bytes;
821
      c->data = data;
822
 
823
      ++cursors;
824
 
825
      name.named = 0;
826
      name.u.id = cursors;
827
 
828
      r = define_standard_resource (&resources, RT_CURSOR, name,
829
                                    resinfo->language, 0);
830
      r->type = RES_TYPE_CURSOR;
831
      r->u.cursor = c;
832
      r->res_info = *resinfo;
833
    }
834
 
835
  fclose (e);
836
  free (real_filename);
837
 
838
  /* Define a cursor group resource.  */
839
 
840
  first = NULL;
841
  pp = &first;
842
  for (i = 0; i < count; i++)
843
    {
844
      rc_group_cursor *cg;
845
 
846
      cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
847
      cg->next = NULL;
848
      cg->width = icondirs[i].width;
849
      cg->height = 2 * icondirs[i].height;
850
 
851
      /* FIXME: What should these be set to?  */
852
      cg->planes = 1;
853
      cg->bits = 1;
854
 
855
      cg->bytes = icondirs[i].bytes + 4;
856
      cg->index = first_cursor + i + 1;
857
 
858
      *pp = cg;
859
      pp = &(*pp)->next;
860
    }
861
 
862
  free (icondirs);
863
 
864
  r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
865
                                resinfo->language, 0);
866
  r->type = RES_TYPE_GROUP_CURSOR;
867
  r->u.group_cursor = first;
868
  r->res_info = *resinfo;
869
}
870
 
871
/* Define a dialog resource.  */
872
 
873
void
874
define_dialog (rc_res_id id, const rc_res_res_info *resinfo,
875
               const rc_dialog *dialog)
876
{
877
  rc_dialog *copy;
878
  rc_res_resource *r;
879
 
880
  copy = (rc_dialog *) res_alloc (sizeof *copy);
881
  *copy = *dialog;
882
 
883
  r = define_standard_resource (&resources, RT_DIALOG, id,
884
                                resinfo->language, 0);
885
  r->type = RES_TYPE_DIALOG;
886
  r->u.dialog = copy;
887
  r->res_info = *resinfo;
888
}
889
 
890
/* Define a dialog control.  This does not define a resource, but
891
   merely allocates and fills in a structure.  */
892
 
893
rc_dialog_control *
894
define_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x,
895
                rc_uint_type y, rc_uint_type width, rc_uint_type height,
896
                const rc_res_id class, rc_uint_type style,
897
                rc_uint_type exstyle)
898
{
899
  rc_dialog_control *n;
900
 
901
  n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
902
  n->next = NULL;
903
  n->id = id;
904
  n->style = style;
905
  n->exstyle = exstyle;
906
  n->x = x;
907
  n->y = y;
908
  n->width = width;
909
  n->height = height;
910
  n->class = class;
911
  n->text = iid;
912
  n->data = NULL;
913
  n->help = 0;
914
 
915
  return n;
916
}
917
 
918
rc_dialog_control *
919
define_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x,
920
                     rc_uint_type y, rc_uint_type style,
921
                     rc_uint_type exstyle, rc_uint_type help,
922
                     rc_rcdata_item *data, rc_dialog_ex *ex)
923
{
924
  rc_dialog_control *n;
925
  rc_res_id tid;
926
  rc_res_id cid;
927
 
928
  if (style == 0)
929
    style = SS_ICON | WS_CHILD | WS_VISIBLE;
930
  res_string_to_id (&tid, "");
931
  cid.named = 0;
932
  cid.u.id = CTL_STATIC;
933
  n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle);
934
  n->text = iid;
935
  if (help && ! ex)
936
    rcparse_warning (_("help ID requires DIALOGEX"));
937
  if (data && ! ex)
938
    rcparse_warning (_("control data requires DIALOGEX"));
939
  n->help = help;
940
  n->data = data;
941
 
942
  return n;
943
}
944
 
945
/* Define a font resource.  */
946
 
947
void
948
define_font (rc_res_id id, const rc_res_res_info *resinfo,
949
             const char *filename)
950
{
951
  FILE *e;
952
  char *real_filename;
953
  struct stat s;
954
  bfd_byte *data;
955
  rc_res_resource *r;
956
  long offset;
957
  long fontdatalength;
958
  bfd_byte *fontdata;
959
  rc_fontdir *fd;
960
  const char *device, *face;
961
  rc_fontdir **pp;
962
 
963
  e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
964
 
965
  if (stat (real_filename, &s) < 0)
966
    fatal (_("stat failed on font file `%s': %s"), real_filename,
967
           strerror (errno));
968
 
969
  data = (bfd_byte *) res_alloc (s.st_size);
970
 
971
  get_data (e, data, s.st_size, real_filename);
972
 
973
  fclose (e);
974
  free (real_filename);
975
 
976
  r = define_standard_resource (&resources, RT_FONT, id,
977
                                resinfo->language, 0);
978
 
979
  r->type = RES_TYPE_FONT;
980
  r->u.data.length = s.st_size;
981
  r->u.data.data = data;
982
  r->res_info = *resinfo;
983
 
984
  /* For each font resource, we must add an entry in the FONTDIR
985
     resource.  The FONTDIR resource includes some strings in the font
986
     file.  To find them, we have to do some magic on the data we have
987
     read.  */
988
 
989
  offset = ((((((data[47] << 8)
990
                | data[46]) << 8)
991
              | data[45]) << 8)
992
            | data[44]);
993
  if (offset > 0 && offset < s.st_size)
994
    device = (char *) data + offset;
995
  else
996
    device = "";
997
 
998
  offset = ((((((data[51] << 8)
999
                | data[50]) << 8)
1000
              | data[49]) << 8)
1001
            | data[48]);
1002
  if (offset > 0 && offset < s.st_size)
1003
    face = (char *) data + offset;
1004
  else
1005
    face = "";
1006
 
1007
  ++fonts;
1008
 
1009
  fontdatalength = 58 + strlen (device) + strlen (face);
1010
  fontdata = (bfd_byte *) res_alloc (fontdatalength);
1011
  memcpy (fontdata, data, 56);
1012
  strcpy ((char *) fontdata + 56, device);
1013
  strcpy ((char *) fontdata + 57 + strlen (device), face);
1014
 
1015
  fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
1016
  fd->next = NULL;
1017
  fd->index = fonts;
1018
  fd->length = fontdatalength;
1019
  fd->data = fontdata;
1020
 
1021
  for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
1022
    ;
1023
  *pp = fd;
1024
 
1025
  /* For the single fontdirs resource, we always use the resource
1026
     information of the last font.  I don't know what else to do.  */
1027
  fontdirs_resinfo = *resinfo;
1028
}
1029
 
1030
static void
1031
define_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
1032
                    rc_rcdata_item *data)
1033
{
1034
  rc_res_resource *r;
1035
  rc_uint_type len_data;
1036
  bfd_byte *pb_data;
1037
 
1038
  r = define_standard_resource (&resources, RT_FONT, id,
1039
                                resinfo->language, 0);
1040
 
1041
  pb_data = rcdata_render_as_buffer (data, &len_data);
1042
 
1043
  r->type = RES_TYPE_FONT;
1044
  r->u.data.length = len_data;
1045
  r->u.data.data = pb_data;
1046
  r->res_info = *resinfo;
1047
}
1048
 
1049
/* Define the fontdirs resource.  This is called after the entire rc
1050
   file has been parsed, if any font resources were seen.  */
1051
 
1052
static void
1053
define_fontdirs (void)
1054
{
1055
  rc_res_resource *r;
1056
  rc_res_id id;
1057
 
1058
  id.named = 0;
1059
  id.u.id = 1;
1060
 
1061
  r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
1062
 
1063
  r->type = RES_TYPE_FONTDIR;
1064
  r->u.fontdir = fontdirs;
1065
  r->res_info = fontdirs_resinfo;
1066
}
1067
 
1068
static bfd_byte *
1069
rcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen)
1070
{
1071
  const rc_rcdata_item *d;
1072
  bfd_byte *ret = NULL, *pret;
1073
  rc_uint_type len = 0;
1074
 
1075
  for (d = data; d != NULL; d = d->next)
1076
    len += rcdata_copy (d, NULL);
1077
  if (len != 0)
1078
    {
1079
      ret = pret = (bfd_byte *) res_alloc (len);
1080
      for (d = data; d != NULL; d = d->next)
1081
        pret += rcdata_copy (d, pret);
1082
    }
1083
  if (plen)
1084
    *plen = len;
1085
  return ret;
1086
}
1087
 
1088
static void
1089
define_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
1090
                       rc_rcdata_item *data)
1091
{
1092
  rc_res_resource *r;
1093
  rc_fontdir *fd, *fd_first, *fd_cur;
1094
  rc_uint_type len_data;
1095
  bfd_byte *pb_data;
1096
  rc_uint_type c;
1097
 
1098
  fd_cur = fd_first = NULL;
1099
  r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
1100
 
1101
  pb_data = rcdata_render_as_buffer (data, &len_data);
1102
 
1103
  if (pb_data)
1104
    {
1105
      rc_uint_type off = 2;
1106
      c = windres_get_16 (&wrtarget, pb_data, len_data);
1107
      for (; c > 0; c--)
1108
        {
1109
          size_t len;
1110
          rc_uint_type safe_pos = off;
1111
          const struct bin_fontdir_item *bfi;
1112
 
1113
          bfi = (const struct bin_fontdir_item *) pb_data + off;
1114
          fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
1115
          fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off);
1116
          fd->data = pb_data + off;
1117
          off += 56;
1118
          len = strlen ((char *) bfi->device_name) + 1;
1119
          off += (rc_uint_type) len;
1120
          off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1;
1121
          fd->length = (off - safe_pos);
1122
          fd->next = NULL;
1123
          if (fd_first == NULL)
1124
            fd_first = fd;
1125
          else
1126
            fd_cur->next = fd;
1127
          fd_cur = fd;
1128
        }
1129
    }
1130
  r->type = RES_TYPE_FONTDIR;
1131
  r->u.fontdir = fd_first;
1132
  r->res_info = *resinfo;
1133
}
1134
 
1135
static void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1136
                                        rc_rcdata_item *data)
1137
{
1138
  rc_res_resource *r;
1139
  rc_uint_type len_data;
1140
  bfd_byte *pb_data;
1141
 
1142
  r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0);
1143
 
1144
  pb_data = rcdata_render_as_buffer (data, &len_data);
1145
  r->type = RES_TYPE_MESSAGETABLE;
1146
  r->u.data.length = len_data;
1147
  r->u.data.data = pb_data;
1148
  r->res_info = *resinfo;
1149
}
1150
 
1151
/* Define an icon resource.  An icon file may contain a set of
1152
   bitmaps, each representing the same icon at various different
1153
   resolutions.  They each get written out with a different ID.  The
1154
   real icon resource is then a group resource which can be used to
1155
   select one of the actual icon bitmaps.  */
1156
 
1157
void
1158
define_icon (rc_res_id id, const rc_res_res_info *resinfo,
1159
             const char *filename)
1160
{
1161
  FILE *e;
1162
  char *real_filename;
1163
  int type, count, i;
1164
  struct icondir *icondirs;
1165
  int first_icon;
1166
  rc_res_resource *r;
1167
  rc_group_icon *first, **pp;
1168
 
1169
  e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
1170
 
1171
  /* The start of an icon file is a three word structure.  The first
1172
     word is ignored.  The second word is the type of data.  The third
1173
     word is the number of entries.  */
1174
 
1175
  get_word (e, real_filename);
1176
  type = get_word (e, real_filename);
1177
  count = get_word (e, real_filename);
1178
  if (type != 1)
1179
    fatal (_("icon file `%s' does not contain icon data"), real_filename);
1180
 
1181
  /* Read in the icon directory entries.  */
1182
 
1183
  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
1184
 
1185
  for (i = 0; i < count; i++)
1186
    {
1187
      icondirs[i].width = getc (e);
1188
      icondirs[i].height = getc (e);
1189
      icondirs[i].colorcount = getc (e);
1190
      getc (e);
1191
      icondirs[i].u.icon.planes = get_word (e, real_filename);
1192
      icondirs[i].u.icon.bits = get_word (e, real_filename);
1193
      icondirs[i].bytes = get_long (e, real_filename);
1194
      icondirs[i].offset = get_long (e, real_filename);
1195
 
1196
      if (feof (e))
1197
        unexpected_eof (real_filename);
1198
    }
1199
 
1200
  /* Define each icon as a unique resource.  */
1201
 
1202
  first_icon = icons;
1203
 
1204
  for (i = 0; i < count; i++)
1205
    {
1206
      bfd_byte *data;
1207
      rc_res_id name;
1208
 
1209
      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1210
        fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1211
               icondirs[i].offset, strerror (errno));
1212
 
1213
      data = (bfd_byte *) res_alloc (icondirs[i].bytes);
1214
 
1215
      get_data (e, data, icondirs[i].bytes, real_filename);
1216
 
1217
      ++icons;
1218
 
1219
      name.named = 0;
1220
      name.u.id = icons;
1221
 
1222
      r = define_standard_resource (&resources, RT_ICON, name,
1223
                                    resinfo->language, 0);
1224
      r->type = RES_TYPE_ICON;
1225
      r->u.data.length = icondirs[i].bytes;
1226
      r->u.data.data = data;
1227
      r->res_info = *resinfo;
1228
    }
1229
 
1230
  fclose (e);
1231
  free (real_filename);
1232
 
1233
  /* Define an icon group resource.  */
1234
 
1235
  first = NULL;
1236
  pp = &first;
1237
  for (i = 0; i < count; i++)
1238
    {
1239
      rc_group_icon *cg;
1240
 
1241
      /* For some reason, at least in some files the planes and bits
1242
         are zero.  We instead set them from the color.  This is
1243
         copied from rcl.  */
1244
 
1245
      cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
1246
      cg->next = NULL;
1247
      cg->width = icondirs[i].width;
1248
      cg->height = icondirs[i].height;
1249
      cg->colors = icondirs[i].colorcount;
1250
 
1251
      if (icondirs[i].u.icon.planes)
1252
        cg->planes = icondirs[i].u.icon.planes;
1253
      else
1254
        cg->planes = 1;
1255
 
1256
      if (icondirs[i].u.icon.bits)
1257
        cg->bits = icondirs[i].u.icon.bits;
1258
      else
1259
        {
1260
          cg->bits = 0;
1261
 
1262
          while ((1L << cg->bits) < cg->colors)
1263
            ++cg->bits;
1264
        }
1265
 
1266
      cg->bytes = icondirs[i].bytes;
1267
      cg->index = first_icon + i + 1;
1268
 
1269
      *pp = cg;
1270
      pp = &(*pp)->next;
1271
    }
1272
 
1273
  free (icondirs);
1274
 
1275
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1276
                                resinfo->language, 0);
1277
  r->type = RES_TYPE_GROUP_ICON;
1278
  r->u.group_icon = first;
1279
  r->res_info = *resinfo;
1280
}
1281
 
1282
static void
1283
define_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1284
                          rc_rcdata_item *data)
1285
{
1286
  rc_res_resource *r;
1287
  rc_group_icon *cg, *first, *cur;
1288
  rc_uint_type len_data;
1289
  bfd_byte *pb_data;
1290
 
1291
  pb_data = rcdata_render_as_buffer (data, &len_data);
1292
 
1293
  cur = NULL;
1294
  first = NULL;
1295
 
1296
  while (len_data >= 6)
1297
    {
1298
      int c, i;
1299
      unsigned short type;
1300
      type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1301
      if (type != 1)
1302
        fatal (_("unexpected group icon type %d"), type);
1303
      c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1304
      len_data -= 6;
1305
      pb_data += 6;
1306
 
1307
      for (i = 0; i < c; i++)
1308
        {
1309
          if (len_data < 14)
1310
            fatal ("too small group icon rcdata");
1311
          cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
1312
          cg->next = NULL;
1313
          cg->width = pb_data[0];
1314
          cg->height = pb_data[1];
1315
          cg->colors = pb_data[2];
1316
          cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1317
          cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
1318
          cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
1319
          cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
1320
          if (! first)
1321
            first = cg;
1322
          else
1323
            cur->next = cg;
1324
          cur = cg;
1325
          pb_data += 14;
1326
          len_data -= 14;
1327
        }
1328
    }
1329
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1330
                                resinfo->language, 0);
1331
  r->type = RES_TYPE_GROUP_ICON;
1332
  r->u.group_icon = first;
1333
  r->res_info = *resinfo;
1334
}
1335
 
1336
static void
1337
define_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1338
                            rc_rcdata_item *data)
1339
{
1340
  rc_res_resource *r;
1341
  rc_group_cursor *cg, *first, *cur;
1342
  rc_uint_type len_data;
1343
  bfd_byte *pb_data;
1344
 
1345
  pb_data = rcdata_render_as_buffer (data, &len_data);
1346
 
1347
  first = cur = NULL;
1348
 
1349
  while (len_data >= 6)
1350
    {
1351
      int c, i;
1352
      unsigned short type;
1353
      type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1354
      if (type != 2)
1355
        fatal (_("unexpected group cursor type %d"), type);
1356
      c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1357
      len_data -= 6;
1358
      pb_data += 6;
1359
 
1360
      for (i = 0; i < c; i++)
1361
        {
1362
          if (len_data < 14)
1363
            fatal ("too small group icon rcdata");
1364
          cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
1365
          cg->next = NULL;
1366
          cg->width = windres_get_16 (&wrtarget, pb_data, len_data);
1367
          cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1368
          cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1369
          cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
1370
          cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
1371
          cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
1372
          if (! first)
1373
            first = cg;
1374
          else
1375
            cur->next = cg;
1376
          cur = cg;
1377
          pb_data += 14;
1378
          len_data -= 14;
1379
        }
1380
    }
1381
 
1382
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1383
                                resinfo->language, 0);
1384
  r->type = RES_TYPE_GROUP_CURSOR;
1385
  r->u.group_cursor = first;
1386
  r->res_info = *resinfo;
1387
}
1388
 
1389
static void
1390
define_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1391
                      rc_rcdata_item *data)
1392
{
1393
  rc_cursor *c;
1394
  rc_res_resource *r;
1395
  rc_uint_type len_data;
1396
  bfd_byte *pb_data;
1397
 
1398
  pb_data = rcdata_render_as_buffer (data, &len_data);
1399
 
1400
  c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
1401
  c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data);
1402
  c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1403
  c->length = len_data - BIN_CURSOR_SIZE;
1404
  c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE);
1405
 
1406
  r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0);
1407
  r->type = RES_TYPE_CURSOR;
1408
  r->u.cursor = c;
1409
  r->res_info = *resinfo;
1410
}
1411
 
1412
static void
1413
define_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1414
                      rc_rcdata_item *data)
1415
{
1416
  rc_res_resource *r;
1417
  rc_uint_type len_data;
1418
  bfd_byte *pb_data;
1419
 
1420
  pb_data = rcdata_render_as_buffer (data, &len_data);
1421
 
1422
  r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0);
1423
  r->type = RES_TYPE_BITMAP;
1424
  r->u.data.length = len_data;
1425
  r->u.data.data = pb_data;
1426
  r->res_info = *resinfo;
1427
}
1428
 
1429
static void
1430
define_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1431
                    rc_rcdata_item *data)
1432
{
1433
  rc_res_resource *r;
1434
  rc_uint_type len_data;
1435
  bfd_byte *pb_data;
1436
 
1437
  pb_data = rcdata_render_as_buffer (data, &len_data);
1438
 
1439
  r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0);
1440
  r->type = RES_TYPE_ICON;
1441
  r->u.data.length = len_data;
1442
  r->u.data.data = pb_data;
1443
  r->res_info = *resinfo;
1444
}
1445
 
1446
/* Define a menu resource.  */
1447
 
1448
void
1449
define_menu (rc_res_id id, const rc_res_res_info *resinfo,
1450
             rc_menuitem *menuitems)
1451
{
1452
  rc_menu *m;
1453
  rc_res_resource *r;
1454
 
1455
  m = (rc_menu *) res_alloc (sizeof (rc_menu));
1456
  m->items = menuitems;
1457
  m->help = 0;
1458
 
1459
  r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1460
  r->type = RES_TYPE_MENU;
1461
  r->u.menu = m;
1462
  r->res_info = *resinfo;
1463
}
1464
 
1465
/* Define a menu item.  This does not define a resource, but merely
1466
   allocates and fills in a structure.  */
1467
 
1468
rc_menuitem *
1469
define_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type,
1470
                 rc_uint_type state, rc_uint_type help,
1471
                 rc_menuitem *menuitems)
1472
{
1473
  rc_menuitem *mi;
1474
 
1475
  mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
1476
  mi->next = NULL;
1477
  mi->type = type;
1478
  mi->state = state;
1479
  mi->id = menuid;
1480
  mi->text = unichar_dup (text);
1481
  mi->help = help;
1482
  mi->popup = menuitems;
1483
  return mi;
1484
}
1485
 
1486
/* Define a messagetable resource.  */
1487
 
1488
void
1489
define_messagetable (rc_res_id id, const rc_res_res_info *resinfo,
1490
                     const char *filename)
1491
{
1492
  FILE *e;
1493
  char *real_filename;
1494
  struct stat s;
1495
  bfd_byte *data;
1496
  rc_res_resource *r;
1497
 
1498
  e = open_file_search (filename, FOPEN_RB, "messagetable file",
1499
                        &real_filename);
1500
 
1501
  if (stat (real_filename, &s) < 0)
1502
    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1503
           strerror (errno));
1504
 
1505
  data = (bfd_byte *) res_alloc (s.st_size);
1506
 
1507
  get_data (e, data, s.st_size, real_filename);
1508
 
1509
  fclose (e);
1510
  free (real_filename);
1511
 
1512
  r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1513
                                resinfo->language, 0);
1514
 
1515
  r->type = RES_TYPE_MESSAGETABLE;
1516
  r->u.data.length = s.st_size;
1517
  r->u.data.data = data;
1518
  r->res_info = *resinfo;
1519
}
1520
 
1521
/* Define an rcdata resource.  */
1522
 
1523
void
1524
define_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1525
               rc_rcdata_item *data)
1526
{
1527
  rc_res_resource *r;
1528
 
1529
  r = define_standard_resource (&resources, RT_RCDATA, id,
1530
                                resinfo->language, 0);
1531
  r->type = RES_TYPE_RCDATA;
1532
  r->u.rcdata = data;
1533
  r->res_info = *resinfo;
1534
}
1535
 
1536
/* Create an rcdata item holding a string.  */
1537
 
1538
rc_rcdata_item *
1539
define_rcdata_string (const char *string, rc_uint_type len)
1540
{
1541
  rc_rcdata_item *ri;
1542
  char *s;
1543
 
1544
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1545
  ri->next = NULL;
1546
  ri->type = RCDATA_STRING;
1547
  ri->u.string.length = len;
1548
  s = (char *) res_alloc (len);
1549
  memcpy (s, string, len);
1550
  ri->u.string.s = s;
1551
 
1552
  return ri;
1553
}
1554
 
1555
/* Create an rcdata item holding a unicode string.  */
1556
 
1557
rc_rcdata_item *
1558
define_rcdata_unistring (const unichar *string, rc_uint_type len)
1559
{
1560
  rc_rcdata_item *ri;
1561
  unichar *s;
1562
 
1563
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1564
  ri->next = NULL;
1565
  ri->type = RCDATA_WSTRING;
1566
  ri->u.wstring.length = len;
1567
  s = (unichar *) res_alloc (len * sizeof (unichar));
1568
  memcpy (s, string, len * sizeof (unichar));
1569
  ri->u.wstring.w = s;
1570
 
1571
  return ri;
1572
}
1573
 
1574
/* Create an rcdata item holding a number.  */
1575
 
1576
rc_rcdata_item *
1577
define_rcdata_number (rc_uint_type val, int dword)
1578
{
1579
  rc_rcdata_item *ri;
1580
 
1581
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1582
  ri->next = NULL;
1583
  ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1584
  ri->u.word = val;
1585
 
1586
  return ri;
1587
}
1588
 
1589
/* Define a stringtable resource.  This is called for each string
1590
   which appears in a STRINGTABLE statement.  */
1591
 
1592
void
1593
define_stringtable (const rc_res_res_info *resinfo,
1594 163 khays
                    rc_uint_type stringid, const unichar *string, int len)
1595 15 khays
{
1596 163 khays
  unichar *h;
1597 15 khays
  rc_res_id id;
1598
  rc_res_resource *r;
1599
 
1600
  id.named = 0;
1601
  id.u.id = (stringid >> 4) + 1;
1602
  r = define_standard_resource (&resources, RT_STRING, id,
1603
                                resinfo->language, 1);
1604
 
1605
  if (r->type == RES_TYPE_UNINITIALIZED)
1606
    {
1607
      int i;
1608
 
1609
      r->type = RES_TYPE_STRINGTABLE;
1610
      r->u.stringtable = ((rc_stringtable *)
1611
                          res_alloc (sizeof (rc_stringtable)));
1612
      for (i = 0; i < 16; i++)
1613
        {
1614
          r->u.stringtable->strings[i].length = 0;
1615
          r->u.stringtable->strings[i].string = NULL;
1616
        }
1617
 
1618
      r->res_info = *resinfo;
1619
    }
1620 163 khays
  h = (unichar *) res_alloc ((len + 1) * sizeof (unichar));
1621
  if (len)
1622
    memcpy (h, string, len * sizeof (unichar));
1623
  h[len] = 0;
1624
  r->u.stringtable->strings[stringid & 0xf].length = (rc_uint_type) len;
1625
  r->u.stringtable->strings[stringid & 0xf].string = h;
1626 15 khays
}
1627
 
1628
void
1629
define_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height,
1630
                rc_toolbar_item *items)
1631
{
1632
  rc_toolbar *t;
1633
  rc_res_resource *r;
1634
 
1635
  t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
1636
  t->button_width = width;
1637
  t->button_height = height;
1638
  t->nitems = 0;
1639
  t->items = items;
1640
  while (items != NULL)
1641
  {
1642
    t->nitems+=1;
1643
    items = items->next;
1644
  }
1645
  r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0);
1646
  r->type = RES_TYPE_TOOLBAR;
1647
  r->u.toolbar = t;
1648
  r->res_info = *resinfo;
1649
}
1650
 
1651
/* Define a user data resource where the data is in the rc file.  */
1652
 
1653
void
1654
define_user_data (rc_res_id id, rc_res_id type,
1655
                  const rc_res_res_info *resinfo,
1656
                  rc_rcdata_item *data)
1657
{
1658
  rc_res_id ids[3];
1659
  rc_res_resource *r;
1660
  bfd_byte *pb_data;
1661
  rc_uint_type len_data;
1662
 
1663
  /* We have to check if the binary data is parsed specially.  */
1664
  if (type.named == 0)
1665
    {
1666
      switch (type.u.id)
1667
      {
1668
      case RT_FONTDIR:
1669
        define_fontdir_rcdata (id, resinfo, data);
1670
        return;
1671
      case RT_FONT:
1672
        define_font_rcdata (id, resinfo, data);
1673
        return;
1674
      case RT_ICON:
1675
        define_icon_rcdata (id, resinfo, data);
1676
        return;
1677
      case RT_BITMAP:
1678
        define_bitmap_rcdata (id, resinfo, data);
1679
        return;
1680
      case RT_CURSOR:
1681
        define_cursor_rcdata (id, resinfo, data);
1682
        return;
1683
      case RT_GROUP_ICON:
1684
        define_group_icon_rcdata (id, resinfo, data);
1685
        return;
1686
      case RT_GROUP_CURSOR:
1687
        define_group_cursor_rcdata (id, resinfo, data);
1688
        return;
1689
      case RT_MESSAGETABLE:
1690
        define_messagetable_rcdata (id, resinfo, data);
1691
        return;
1692
      default:
1693
        /* Treat as normal user-data.  */
1694
        break;
1695
      }
1696
    }
1697
  ids[0] = type;
1698
  ids[1] = id;
1699
  ids[2].named = 0;
1700
  ids[2].u.id = resinfo->language;
1701
 
1702
  r = define_resource (& resources, 3, ids, 0);
1703
  r->type = RES_TYPE_USERDATA;
1704
  r->u.userdata = ((rc_rcdata_item *)
1705
                   res_alloc (sizeof (rc_rcdata_item)));
1706
  r->u.userdata->next = NULL;
1707
  r->u.userdata->type = RCDATA_BUFFER;
1708
  pb_data = rcdata_render_as_buffer (data, &len_data);
1709
  r->u.userdata->u.buffer.length = len_data;
1710
  r->u.userdata->u.buffer.data = pb_data;
1711
  r->res_info = *resinfo;
1712
}
1713
 
1714
void
1715
define_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo,
1716
                    const char *filename)
1717
{
1718
  rc_rcdata_item *ri;
1719
  FILE *e;
1720
  char *real_filename;
1721
  struct stat s;
1722
  bfd_byte *data;
1723
 
1724
  e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1725
 
1726
 
1727
  if (stat (real_filename, &s) < 0)
1728
    fatal (_("stat failed on file `%s': %s"), real_filename,
1729
           strerror (errno));
1730
 
1731
  data = (bfd_byte *) res_alloc (s.st_size);
1732
 
1733
  get_data (e, data, s.st_size, real_filename);
1734
 
1735
  fclose (e);
1736
  free (real_filename);
1737
 
1738
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1739
  ri->next = NULL;
1740
  ri->type = RCDATA_BUFFER;
1741
  ri->u.buffer.length = s.st_size;
1742
  ri->u.buffer.data = data;
1743
 
1744
  define_rcdata (id, resinfo, ri);
1745
}
1746
 
1747
/* Define a user data resource where the data is in a file.  */
1748
 
1749
void
1750
define_user_file (rc_res_id id, rc_res_id type,
1751
                  const rc_res_res_info *resinfo, const char *filename)
1752
{
1753
  FILE *e;
1754
  char *real_filename;
1755
  struct stat s;
1756
  bfd_byte *data;
1757
  rc_res_id ids[3];
1758
  rc_res_resource *r;
1759
 
1760
  e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1761
 
1762
  if (stat (real_filename, &s) < 0)
1763
    fatal (_("stat failed on file `%s': %s"), real_filename,
1764
           strerror (errno));
1765
 
1766
  data = (bfd_byte *) res_alloc (s.st_size);
1767
 
1768
  get_data (e, data, s.st_size, real_filename);
1769
 
1770
  fclose (e);
1771
  free (real_filename);
1772
 
1773
  ids[0] = type;
1774
  ids[1] = id;
1775
  ids[2].named = 0;
1776
  ids[2].u.id = resinfo->language;
1777
 
1778
  r = define_resource (&resources, 3, ids, 0);
1779
  r->type = RES_TYPE_USERDATA;
1780
  r->u.userdata = ((rc_rcdata_item *)
1781
                   res_alloc (sizeof (rc_rcdata_item)));
1782
  r->u.userdata->next = NULL;
1783
  r->u.userdata->type = RCDATA_BUFFER;
1784
  r->u.userdata->u.buffer.length = s.st_size;
1785
  r->u.userdata->u.buffer.data = data;
1786
  r->res_info = *resinfo;
1787
}
1788
 
1789
/* Define a versioninfo resource.  */
1790
 
1791
void
1792
define_versioninfo (rc_res_id id, rc_uint_type language,
1793
                    rc_fixed_versioninfo *fixedverinfo,
1794
                    rc_ver_info *verinfo)
1795
{
1796
  rc_res_resource *r;
1797
 
1798
  r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1799
  r->type = RES_TYPE_VERSIONINFO;
1800
  r->u.versioninfo = ((rc_versioninfo *)
1801
                      res_alloc (sizeof (rc_versioninfo)));
1802
  r->u.versioninfo->fixed = fixedverinfo;
1803
  r->u.versioninfo->var = verinfo;
1804
  r->res_info.language = language;
1805
}
1806
 
1807
/* Add string version info to a list of version information.  */
1808
 
1809
rc_ver_info *
1810 163 khays
append_ver_stringfileinfo (rc_ver_info *verinfo,
1811
                           rc_ver_stringtable *stringtables)
1812 15 khays
{
1813
  rc_ver_info *vi, **pp;
1814
 
1815
  vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
1816
  vi->next = NULL;
1817
  vi->type = VERINFO_STRING;
1818 163 khays
  vi->u.string.stringtables = stringtables;
1819 15 khays
 
1820
  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1821
    ;
1822
  *pp = vi;
1823
 
1824
  return verinfo;
1825
}
1826
 
1827 163 khays
rc_ver_stringtable *
1828
append_ver_stringtable (rc_ver_stringtable *stringtable,
1829
                        const char *language,
1830
                        rc_ver_stringinfo *strings)
1831
{
1832
  rc_ver_stringtable *vst, **pp;
1833
 
1834
  vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable));
1835
  vst->next = NULL;
1836
  unicode_from_ascii ((rc_uint_type *) NULL, &vst->language, language);
1837
  vst->strings = strings;
1838
 
1839
  for (pp = &stringtable; *pp != NULL; pp = &(*pp)->next)
1840
    ;
1841
  *pp = vst;
1842
 
1843
  return stringtable;
1844
}
1845
 
1846 15 khays
/* Add variable version info to a list of version information.  */
1847
 
1848
rc_ver_info *
1849
append_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key,
1850
                        rc_ver_varinfo *var)
1851
{
1852
  rc_ver_info *vi, **pp;
1853
 
1854
  vi = (rc_ver_info *) res_alloc (sizeof *vi);
1855
  vi->next = NULL;
1856
  vi->type = VERINFO_VAR;
1857
  vi->u.var.key = unichar_dup (key);
1858
  vi->u.var.var = var;
1859
 
1860
  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1861
    ;
1862
  *pp = vi;
1863
 
1864
  return verinfo;
1865
}
1866
 
1867
/* Append version string information to a list.  */
1868
 
1869
rc_ver_stringinfo *
1870
append_verval (rc_ver_stringinfo *strings, const unichar *key,
1871
               const unichar *value)
1872
{
1873
  rc_ver_stringinfo *vs, **pp;
1874
 
1875
  vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
1876
  vs->next = NULL;
1877
  vs->key = unichar_dup (key);
1878
  vs->value = unichar_dup (value);
1879
 
1880
  for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1881
    ;
1882
  *pp = vs;
1883
 
1884
  return strings;
1885
}
1886
 
1887
/* Append version variable information to a list.  */
1888
 
1889
rc_ver_varinfo *
1890
append_vertrans (rc_ver_varinfo *var, rc_uint_type language,
1891
                 rc_uint_type charset)
1892
{
1893
  rc_ver_varinfo *vv, **pp;
1894
 
1895
  vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
1896
  vv->next = NULL;
1897
  vv->language = language;
1898
  vv->charset = charset;
1899
 
1900
  for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1901
    ;
1902
  *pp = vv;
1903
 
1904
  return var;
1905
}
1906
 
1907
/* Local functions used to write out an rc file.  */
1908
 
1909
static void indent (FILE *, int);
1910
static void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *,
1911
                                const rc_res_id *, rc_uint_type *, int);
1912
static void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *,
1913
                             const rc_res_id *, rc_uint_type *, int);
1914
static void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *,
1915
                               const rc_res_resource *, rc_uint_type *);
1916
static void write_rc_accelerators (FILE *, const rc_accelerator *);
1917
static void write_rc_cursor (FILE *, const rc_cursor *);
1918
static void write_rc_group_cursor (FILE *, const rc_group_cursor *);
1919
static void write_rc_dialog (FILE *, const rc_dialog *);
1920
static void write_rc_dialog_control (FILE *, const rc_dialog_control *);
1921
static void write_rc_fontdir (FILE *, const rc_fontdir *);
1922
static void write_rc_group_icon (FILE *, const rc_group_icon *);
1923
static void write_rc_menu (FILE *, const rc_menu *, int);
1924
static void write_rc_toolbar (FILE *, const rc_toolbar *);
1925
static void write_rc_menuitems (FILE *, const rc_menuitem *, int, int);
1926
static void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *);
1927
 
1928
static void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int);
1929
static void write_rc_rcdata (FILE *, const rc_rcdata_item *, int);
1930
static void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *);
1931
static void write_rc_versioninfo (FILE *, const rc_versioninfo *);
1932
 
1933
/* Indent a given number of spaces.  */
1934
 
1935
static void
1936
indent (FILE *e, int c)
1937
{
1938
  int i;
1939
 
1940
  for (i = 0; i < c; i++)
1941
    putc (' ', e);
1942
}
1943
 
1944
/* Dump the resources we have read in the format of an rc file.
1945
 
1946
   Reasoned by the fact, that some resources need to be stored into file and
1947
   refer to that file, we use the user-data model for that to express it binary
1948
   without the need to store it somewhere externally.  */
1949
 
1950
void
1951
write_rc_file (const char *filename, const rc_res_directory *res_dir)
1952
{
1953
  FILE *e;
1954
  rc_uint_type language;
1955
 
1956
  if (filename == NULL)
1957
    e = stdout;
1958
  else
1959
    {
1960
      e = fopen (filename, FOPEN_WT);
1961
      if (e == NULL)
1962
        fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1963
    }
1964
 
1965
  language = (rc_uint_type) ((bfd_signed_vma) -1);
1966
  write_rc_directory (e, res_dir, (const rc_res_id *) NULL,
1967
                      (const rc_res_id *) NULL, &language, 1);
1968
}
1969
 
1970
/* Write out a directory.  E is the file to write to.  RD is the
1971
   directory.  TYPE is a pointer to the level 1 ID which serves as the
1972
   resource type.  NAME is a pointer to the level 2 ID which serves as
1973
   an individual resource name.  LANGUAGE is a pointer to the current
1974
   language.  LEVEL is the level in the tree.  */
1975
 
1976
static void
1977
write_rc_directory (FILE *e, const rc_res_directory *rd,
1978
                    const rc_res_id *type, const rc_res_id *name,
1979
                    rc_uint_type *language, int level)
1980
{
1981
  const rc_res_entry *re;
1982
 
1983
  /* Print out some COFF information that rc files can't represent.  */
1984
  if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0)
1985
    {
1986
      wr_printcomment (e, "COFF information not part of RC");
1987
  if (rd->time != 0)
1988
        wr_printcomment (e, "Time stamp: %u", rd->time);
1989
  if (rd->characteristics != 0)
1990
        wr_printcomment (e, "Characteristics: %u", rd->characteristics);
1991
  if (rd->major != 0 || rd->minor != 0)
1992
        wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor);
1993
    }
1994
 
1995
  for (re = rd->entries;  re != NULL; re = re->next)
1996
    {
1997
      switch (level)
1998
        {
1999
        case 1:
2000
          /* If we're at level 1, the key of this resource is the
2001
             type.  This normally duplicates the information we have
2002
             stored with the resource itself, but we need to remember
2003
             the type if this is a user define resource type.  */
2004
          type = &re->id;
2005
          break;
2006
 
2007
        case 2:
2008
          /* If we're at level 2, the key of this resource is the name
2009
             we are going to use in the rc printout.  */
2010
          name = &re->id;
2011
          break;
2012
 
2013
        case 3:
2014
          /* If we're at level 3, then this key represents a language.
2015
             Use it to update the current language.  */
2016
          if (! re->id.named
2017
              && re->id.u.id != (unsigned long) (unsigned int) *language
2018
              && (re->id.u.id & 0xffff) == re->id.u.id)
2019
            {
2020
              wr_print (e, "LANGUAGE %u, %u\n",
2021
                       re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
2022
                       (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
2023
              *language = re->id.u.id;
2024
            }
2025
          break;
2026
 
2027
        default:
2028
          break;
2029
        }
2030
 
2031
      if (re->subdir)
2032
        write_rc_subdir (e, re, type, name, language, level);
2033
      else
2034
        {
2035
          if (level == 3)
2036
            {
2037
              /* This is the normal case: the three levels are
2038
                 TYPE/NAME/LANGUAGE.  NAME will have been set at level
2039
                 2, and represents the name to use.  We probably just
2040
                 set LANGUAGE, and it will probably match what the
2041
                 resource itself records if anything.  */
2042
              write_rc_resource (e, type, name, re->u.res, language);
2043
            }
2044
          else
2045
            {
2046
              wr_printcomment (e, "Resource at unexpected level %d", level);
2047
              write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res,
2048
                                 language);
2049
            }
2050
        }
2051
    }
2052
  if (rd->entries == NULL)
2053
    {
2054
      wr_print_flush (e);
2055
    }
2056
}
2057
 
2058
/* Write out a subdirectory entry.  E is the file to write to.  RE is
2059
   the subdirectory entry.  TYPE and NAME are pointers to higher level
2060
   IDs, or NULL.  LANGUAGE is a pointer to the current language.
2061
   LEVEL is the level in the tree.  */
2062
 
2063
static void
2064
write_rc_subdir (FILE *e, const rc_res_entry *re,
2065
                 const rc_res_id *type, const rc_res_id *name,
2066
                 rc_uint_type *language, int level)
2067
{
2068
  fprintf (e, "\n");
2069
  switch (level)
2070
    {
2071
    case 1:
2072
      wr_printcomment (e, "Type: ");
2073
      if (re->id.named)
2074
        res_id_print (e, re->id, 1);
2075
      else
2076
        {
2077
          const char *s;
2078
 
2079
          switch (re->id.u.id)
2080
            {
2081
            case RT_CURSOR: s = "cursor"; break;
2082
            case RT_BITMAP: s = "bitmap"; break;
2083
            case RT_ICON: s = "icon"; break;
2084
            case RT_MENU: s = "menu"; break;
2085
            case RT_DIALOG: s = "dialog"; break;
2086
            case RT_STRING: s = "stringtable"; break;
2087
            case RT_FONTDIR: s = "fontdir"; break;
2088
            case RT_FONT: s = "font"; break;
2089
            case RT_ACCELERATOR: s = "accelerators"; break;
2090
            case RT_RCDATA: s = "rcdata"; break;
2091
            case RT_MESSAGETABLE: s = "messagetable"; break;
2092
            case RT_GROUP_CURSOR: s = "group cursor"; break;
2093
            case RT_GROUP_ICON: s = "group icon"; break;
2094
            case RT_VERSION: s = "version"; break;
2095
            case RT_DLGINCLUDE: s = "dlginclude"; break;
2096
            case RT_PLUGPLAY: s = "plugplay"; break;
2097
            case RT_VXD: s = "vxd"; break;
2098
            case RT_ANICURSOR: s = "anicursor"; break;
2099
            case RT_ANIICON: s = "aniicon"; break;
2100
            case RT_TOOLBAR: s = "toolbar"; break;
2101
            case RT_HTML: s = "html"; break;
2102
            default: s = NULL; break;
2103
            }
2104
 
2105
          if (s != NULL)
2106
            fprintf (e, "%s", s);
2107
          else
2108
            res_id_print (e, re->id, 1);
2109
        }
2110
      break;
2111
 
2112
    case 2:
2113
      wr_printcomment (e, "Name: ");
2114
      res_id_print (e, re->id, 1);
2115
      break;
2116
 
2117
    case 3:
2118
      wr_printcomment (e, "Language: ");
2119
      res_id_print (e, re->id, 1);
2120
      break;
2121
 
2122
    default:
2123
      wr_printcomment (e, "Level %d: ", level);
2124
      res_id_print (e, re->id, 1);
2125
    }
2126
 
2127
  write_rc_directory (e, re->u.dir, type, name, language, level + 1);
2128
}
2129
 
2130
/* Write out a single resource.  E is the file to write to.  TYPE is a
2131
   pointer to the type of the resource.  NAME is a pointer to the name
2132
   of the resource; it will be NULL if there is a level mismatch.  RES
2133
   is the resource data.  LANGUAGE is a pointer to the current
2134
   language.  */
2135
 
2136
static void
2137
write_rc_resource (FILE *e, const rc_res_id *type,
2138
                   const rc_res_id *name, const rc_res_resource *res,
2139
                   rc_uint_type *language)
2140
{
2141
  const char *s;
2142
  int rt;
2143
  int menuex = 0;
2144
 
2145
  switch (res->type)
2146
    {
2147
    default:
2148
      abort ();
2149
 
2150
    case RES_TYPE_ACCELERATOR:
2151
      s = "ACCELERATORS";
2152
      rt = RT_ACCELERATOR;
2153
      break;
2154
 
2155
    case RES_TYPE_BITMAP:
2156
      s = "2 /* RT_BITMAP */";
2157
      rt = RT_BITMAP;
2158
      break;
2159
 
2160
    case RES_TYPE_CURSOR:
2161
      s = "1 /* RT_CURSOR */";
2162
      rt = RT_CURSOR;
2163
      break;
2164
 
2165
    case RES_TYPE_GROUP_CURSOR:
2166
      s = "12 /* RT_GROUP_CURSOR */";
2167
      rt = RT_GROUP_CURSOR;
2168
      break;
2169
 
2170
    case RES_TYPE_DIALOG:
2171
      if (extended_dialog (res->u.dialog))
2172
        s = "DIALOGEX";
2173
      else
2174
        s = "DIALOG";
2175
      rt = RT_DIALOG;
2176
      break;
2177
 
2178
    case RES_TYPE_FONT:
2179
      s = "8 /* RT_FONT */";
2180
      rt = RT_FONT;
2181
      break;
2182
 
2183
    case RES_TYPE_FONTDIR:
2184
      s = "7 /* RT_FONTDIR */";
2185
      rt = RT_FONTDIR;
2186
      break;
2187
 
2188
    case RES_TYPE_ICON:
2189
      s = "3 /* RT_ICON */";
2190
      rt = RT_ICON;
2191
      break;
2192
 
2193
    case RES_TYPE_GROUP_ICON:
2194
      s = "14 /* RT_GROUP_ICON */";
2195
      rt = RT_GROUP_ICON;
2196
      break;
2197
 
2198
    case RES_TYPE_MENU:
2199
      if (extended_menu (res->u.menu))
2200
        {
2201
          s = "MENUEX";
2202
          menuex = 1;
2203
        }
2204
      else
2205
        {
2206
          s = "MENU";
2207
          menuex = 0;
2208
        }
2209
      rt = RT_MENU;
2210
      break;
2211
 
2212
    case RES_TYPE_MESSAGETABLE:
2213
      s = "11 /* RT_MESSAGETABLE */";
2214
      rt = RT_MESSAGETABLE;
2215
      break;
2216
 
2217
    case RES_TYPE_RCDATA:
2218
      s = "RCDATA";
2219
      rt = RT_RCDATA;
2220
      break;
2221
 
2222
    case RES_TYPE_STRINGTABLE:
2223
      s = "STRINGTABLE";
2224
      rt = RT_STRING;
2225
      break;
2226
 
2227
    case RES_TYPE_USERDATA:
2228
      s = NULL;
2229
      rt = 0;
2230
      break;
2231
 
2232
    case RES_TYPE_VERSIONINFO:
2233
      s = "VERSIONINFO";
2234
      rt = RT_VERSION;
2235
      break;
2236
 
2237
    case RES_TYPE_TOOLBAR:
2238
      s = "TOOLBAR";
2239
      rt = RT_TOOLBAR;
2240
      break;
2241
    }
2242
 
2243
  if (rt != 0
2244
      && type != NULL
2245
      && (type->named || type->u.id != (unsigned long) rt))
2246
    {
2247
      wr_printcomment (e, "Unexpected resource type mismatch: ");
2248
      res_id_print (e, *type, 1);
2249
      fprintf (e, " != %d", rt);
2250
    }
2251
 
2252
  if (res->coff_info.codepage != 0)
2253
    wr_printcomment (e, "Code page: %u", res->coff_info.codepage);
2254
  if (res->coff_info.reserved != 0)
2255
    wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved);
2256
 
2257
  wr_print (e, "\n");
2258
  if (rt == RT_STRING)
2259
    ;
2260
  else
2261
    {
2262
  if (name != NULL)
2263
        res_id_print (e, *name, 1);
2264
  else
2265
    fprintf (e, "??Unknown-Name??");
2266
  fprintf (e, " ");
2267
    }
2268
 
2269
  if (s != NULL)
2270
    fprintf (e, "%s", s);
2271
  else if (type != NULL)
2272
    {
2273
      if (type->named == 0)
2274
        {
2275
#define PRINT_RT_NAME(NAME) case NAME: \
2276
        fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
2277
        break
2278
 
2279
          switch (type->u.id)
2280
            {
2281
            default:
2282
    res_id_print (e, *type, 0);
2283
              break;
2284
 
2285
            PRINT_RT_NAME(RT_MANIFEST);
2286
            PRINT_RT_NAME(RT_ANICURSOR);
2287
            PRINT_RT_NAME(RT_ANIICON);
2288
            PRINT_RT_NAME(RT_RCDATA);
2289
            PRINT_RT_NAME(RT_ICON);
2290
            PRINT_RT_NAME(RT_CURSOR);
2291
            PRINT_RT_NAME(RT_BITMAP);
2292
            PRINT_RT_NAME(RT_PLUGPLAY);
2293
            PRINT_RT_NAME(RT_VXD);
2294
            PRINT_RT_NAME(RT_FONT);
2295
            PRINT_RT_NAME(RT_FONTDIR);
2296
            PRINT_RT_NAME(RT_HTML);
2297
            PRINT_RT_NAME(RT_MESSAGETABLE);
2298
            PRINT_RT_NAME(RT_DLGINCLUDE);
2299
            PRINT_RT_NAME(RT_DLGINIT);
2300
            }
2301
#undef PRINT_RT_NAME
2302
        }
2303
      else
2304
        res_id_print (e, *type, 1);
2305
    }
2306
  else
2307
    fprintf (e, "??Unknown-Type??");
2308
 
2309
  if (res->res_info.memflags != 0)
2310
    {
2311
      if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
2312
        fprintf (e, " MOVEABLE");
2313
      if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
2314
        fprintf (e, " PURE");
2315
      if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
2316
        fprintf (e, " PRELOAD");
2317
      if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
2318
        fprintf (e, " DISCARDABLE");
2319
    }
2320
 
2321
  if (res->type == RES_TYPE_DIALOG)
2322
    {
2323
      fprintf (e, " %d, %d, %d, %d",
2324
               (int) res->u.dialog->x, (int) res->u.dialog->y,
2325
               (int) res->u.dialog->width, (int) res->u.dialog->height);
2326
      if (res->u.dialog->ex != NULL
2327
          && res->u.dialog->ex->help != 0)
2328
        fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help);
2329
    }
2330
  else if (res->type == RES_TYPE_TOOLBAR)
2331
  {
2332
    fprintf (e, " %d, %d", (int) res->u.toolbar->button_width,
2333
             (int) res->u.toolbar->button_height);
2334
    }
2335
 
2336
  fprintf (e, "\n");
2337
 
2338
  if ((res->res_info.language != 0 && res->res_info.language != *language)
2339
      || res->res_info.characteristics != 0
2340
      || res->res_info.version != 0)
2341
    {
2342
      int modifiers;
2343
 
2344
      switch (res->type)
2345
        {
2346
        case RES_TYPE_ACCELERATOR:
2347
        case RES_TYPE_DIALOG:
2348
        case RES_TYPE_MENU:
2349
        case RES_TYPE_RCDATA:
2350
        case RES_TYPE_STRINGTABLE:
2351
          modifiers = 1;
2352
          break;
2353
 
2354
        default:
2355
          modifiers = 0;
2356
          break;
2357
        }
2358
 
2359
      if (res->res_info.language != 0 && res->res_info.language != *language)
2360
        fprintf (e, "%sLANGUAGE %d, %d\n",
2361
                 modifiers ? "// " : "",
2362
                 (int) res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
2363
                 (int) (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
2364
      if (res->res_info.characteristics != 0)
2365
        fprintf (e, "%sCHARACTERISTICS %u\n",
2366
                 modifiers ? "// " : "",
2367
                 (unsigned int) res->res_info.characteristics);
2368
      if (res->res_info.version != 0)
2369
        fprintf (e, "%sVERSION %u\n",
2370
                 modifiers ? "// " : "",
2371
                 (unsigned int) res->res_info.version);
2372
    }
2373
 
2374
  switch (res->type)
2375
    {
2376
    default:
2377
      abort ();
2378
 
2379
    case RES_TYPE_ACCELERATOR:
2380
      write_rc_accelerators (e, res->u.acc);
2381
      break;
2382
 
2383
    case RES_TYPE_CURSOR:
2384
      write_rc_cursor (e, res->u.cursor);
2385
      break;
2386
 
2387
    case RES_TYPE_GROUP_CURSOR:
2388
      write_rc_group_cursor (e, res->u.group_cursor);
2389
      break;
2390
 
2391
    case RES_TYPE_DIALOG:
2392
      write_rc_dialog (e, res->u.dialog);
2393
      break;
2394
 
2395
    case RES_TYPE_FONTDIR:
2396
      write_rc_fontdir (e, res->u.fontdir);
2397
      break;
2398
 
2399
    case RES_TYPE_GROUP_ICON:
2400
      write_rc_group_icon (e, res->u.group_icon);
2401
      break;
2402
 
2403
    case RES_TYPE_MENU:
2404
      write_rc_menu (e, res->u.menu, menuex);
2405
      break;
2406
 
2407
    case RES_TYPE_RCDATA:
2408
      write_rc_rcdata (e, res->u.rcdata, 0);
2409
      break;
2410
 
2411
    case RES_TYPE_STRINGTABLE:
2412
      write_rc_stringtable (e, name, res->u.stringtable);
2413
      break;
2414
 
2415
    case RES_TYPE_USERDATA:
2416
      write_rc_rcdata (e, res->u.userdata, 0);
2417
      break;
2418
 
2419
    case RES_TYPE_TOOLBAR:
2420
      write_rc_toolbar (e, res->u.toolbar);
2421
      break;
2422
 
2423
    case RES_TYPE_VERSIONINFO:
2424
      write_rc_versioninfo (e, res->u.versioninfo);
2425
      break;
2426
 
2427
    case RES_TYPE_BITMAP:
2428
    case RES_TYPE_FONT:
2429
    case RES_TYPE_ICON:
2430
      write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0);
2431
      break;
2432
    case RES_TYPE_MESSAGETABLE:
2433
      write_rc_messagetable (e, res->u.data.length, res->u.data.data);
2434
      break;
2435
    }
2436
}
2437
 
2438
/* Write out accelerator information.  */
2439
 
2440
static void
2441
write_rc_accelerators (FILE *e, const rc_accelerator *accelerators)
2442
{
2443
  const rc_accelerator *acc;
2444
 
2445
  fprintf (e, "BEGIN\n");
2446
  for (acc = accelerators; acc != NULL; acc = acc->next)
2447
    {
2448
      int printable;
2449
 
2450
      fprintf (e, "  ");
2451
 
2452
      if ((acc->key & 0x7f) == acc->key
2453
          && ISPRINT (acc->key)
2454
          && (acc->flags & ACC_VIRTKEY) == 0)
2455
        {
2456
          fprintf (e, "\"%c\"", (char) acc->key);
2457
          printable = 1;
2458
        }
2459
      else
2460
        {
2461
          fprintf (e, "%d", (int) acc->key);
2462
          printable = 0;
2463
        }
2464
 
2465
      fprintf (e, ", %d", (int) acc->id);
2466
 
2467
      if (! printable)
2468
        {
2469
          if ((acc->flags & ACC_VIRTKEY) != 0)
2470
            fprintf (e, ", VIRTKEY");
2471
          else
2472
            fprintf (e, ", ASCII");
2473
        }
2474
 
2475
      if ((acc->flags & ACC_SHIFT) != 0)
2476
        fprintf (e, ", SHIFT");
2477
      if ((acc->flags & ACC_CONTROL) != 0)
2478
        fprintf (e, ", CONTROL");
2479
      if ((acc->flags & ACC_ALT) != 0)
2480
        fprintf (e, ", ALT");
2481
 
2482
      fprintf (e, "\n");
2483
    }
2484
 
2485
  fprintf (e, "END\n");
2486
}
2487
 
2488
/* Write out cursor information.  This would normally be in a separate
2489
   file, which the rc file would include.  */
2490
 
2491
static void
2492
write_rc_cursor (FILE *e, const rc_cursor *cursor)
2493
{
2494
  fprintf (e, "BEGIN\n");
2495
  indent (e, 2);
2496
  fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d.  */\n",
2497
           (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot,
2498
           (int) cursor->xhotspot, (int) cursor->yhotspot);
2499
  write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data,
2500
                      0, 0, 0);
2501
  fprintf (e, "END\n");
2502
}
2503
 
2504
/* Write out group cursor data.  This would normally be built from the
2505
   cursor data.  */
2506
 
2507
static void
2508
write_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor)
2509
{
2510
  const rc_group_cursor *gc;
2511
  int c;
2512
 
2513
  for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++)
2514
    ;
2515
  fprintf (e, "BEGIN\n");
2516
 
2517
  indent (e, 2);
2518
  fprintf (e, "0, 2, %d%s\t /* Having %d items.  */\n", c, (c != 0 ? "," : ""), c);
2519
  indent (e, 4);
2520
  fprintf (e, "/* width, height, planes, bits, bytes, index.  */\n");
2521
 
2522
  for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++)
2523
    {
2524
      indent (e, 4);
2525
      fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
2526
        (int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits,
2527
        (unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c);
2528
      fprintf (e, "/* width: %d; height %d; planes %d; bits %d.  */\n",
2529
             (int) gc->width, (int) gc->height, (int) gc->planes,
2530
             (int) gc->bits);
2531
    }
2532
  fprintf (e, "END\n");
2533
}
2534
 
2535
/* Write dialog data.  */
2536
 
2537
static void
2538
write_rc_dialog (FILE *e, const rc_dialog *dialog)
2539
{
2540
  const rc_dialog_control *control;
2541
 
2542
  fprintf (e, "STYLE 0x%x\n", dialog->style);
2543
 
2544
  if (dialog->exstyle != 0)
2545
    fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle);
2546
 
2547
  if ((dialog->class.named && dialog->class.u.n.length > 0)
2548
      || dialog->class.u.id != 0)
2549
    {
2550
      fprintf (e, "CLASS ");
2551
      res_id_print (e, dialog->class, 1);
2552
      fprintf (e, "\n");
2553
    }
2554
 
2555
  if (dialog->caption != NULL)
2556
    {
2557
      fprintf (e, "CAPTION ");
2558
      unicode_print_quoted (e, dialog->caption, -1);
2559
      fprintf (e, "\n");
2560
    }
2561
 
2562
  if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2563
      || dialog->menu.u.id != 0)
2564
    {
2565
      fprintf (e, "MENU ");
2566
      res_id_print (e, dialog->menu, 0);
2567
      fprintf (e, "\n");
2568
    }
2569
 
2570
  if (dialog->font != NULL)
2571
    {
2572
      fprintf (e, "FONT %d, ", (int) dialog->pointsize);
2573
      unicode_print_quoted (e, dialog->font, -1);
2574
      if (dialog->ex != NULL
2575
          && (dialog->ex->weight != 0
2576
              || dialog->ex->italic != 0
2577
              || dialog->ex->charset != 1))
2578
        fprintf (e, ", %d, %d, %d",
2579
                 (int) dialog->ex->weight,
2580
                 (int) dialog->ex->italic,
2581
                 (int) dialog->ex->charset);
2582
      fprintf (e, "\n");
2583
    }
2584
 
2585
  fprintf (e, "BEGIN\n");
2586
 
2587
  for (control = dialog->controls; control != NULL; control = control->next)
2588
    write_rc_dialog_control (e, control);
2589
 
2590
  fprintf (e, "END\n");
2591
}
2592
 
2593
/* For each predefined control keyword, this table provides the class
2594
   and the style.  */
2595
 
2596
struct control_info
2597
{
2598
  const char *name;
2599
  unsigned short class;
2600
  unsigned long style;
2601
};
2602
 
2603
static const struct control_info control_info[] =
2604
{
2605
  { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2606
  { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2607
  { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2608
  { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2609
  { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2610
  { "CTEXT", CTL_STATIC, SS_CENTER },
2611
  { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2612
  { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2613
  { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2614
  { "ICON", CTL_STATIC, SS_ICON },
2615
  { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2616
  { "LTEXT", CTL_STATIC, SS_LEFT },
2617
  { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2618
  { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2619
  { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2620
  { "RTEXT", CTL_STATIC, SS_RIGHT },
2621
  { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2622
  { "STATE3", CTL_BUTTON, BS_3STATE },
2623
  /* It's important that USERBUTTON come after all the other button
2624
     types, so that it won't be matched too early.  */
2625
  { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2626
  { NULL, 0, 0 }
2627
};
2628
 
2629
/* Write a dialog control.  */
2630
 
2631
static void
2632
write_rc_dialog_control (FILE *e, const rc_dialog_control *control)
2633
{
2634
  const struct control_info *ci;
2635
 
2636
  fprintf (e, "  ");
2637
 
2638
  if (control->class.named)
2639
    ci = NULL;
2640
  else
2641
    {
2642
      for (ci = control_info; ci->name != NULL; ++ci)
2643
        if (ci->class == control->class.u.id
2644
            && (ci->style == (unsigned long) -1
2645
                || ci->style == (control->style & 0xff)))
2646
          break;
2647
    }
2648
  if (ci == NULL)
2649
    fprintf (e, "CONTROL");
2650
  else if (ci->name != NULL)
2651
    fprintf (e, "%s", ci->name);
2652
  else
2653
    {
2654
    fprintf (e, "CONTROL");
2655
      ci = NULL;
2656
    }
2657
 
2658
  if (control->text.named || control->text.u.id != 0)
2659
    {
2660
      fprintf (e, " ");
2661
      res_id_print (e, control->text, 1);
2662
      fprintf (e, ",");
2663
    }
2664
 
2665
  fprintf (e, " %d, ", (int) control->id);
2666
 
2667
  if (ci == NULL)
2668
    {
2669
      if (control->class.named)
2670
        fprintf (e, "\"");
2671
      res_id_print (e, control->class, 0);
2672
      if (control->class.named)
2673
        fprintf (e, "\"");
2674
      fprintf (e, ", 0x%x, ", (unsigned int) control->style);
2675
    }
2676
 
2677
  fprintf (e, "%d, %d", (int) control->x, (int) control->y);
2678
 
2679
  if (control->style != SS_ICON
2680
      || control->exstyle != 0
2681
      || control->width != 0
2682
      || control->height != 0
2683
      || control->help != 0)
2684
    {
2685
      fprintf (e, ", %d, %d", (int) control->width, (int) control->height);
2686
 
2687
      /* FIXME: We don't need to print the style if it is the default.
2688
         More importantly, in certain cases we actually need to turn
2689
         off parts of the forced style, by using NOT.  */
2690
      if (ci != NULL)
2691
        fprintf (e, ", 0x%x", (unsigned int) control->style);
2692
 
2693
      if (control->exstyle != 0 || control->help != 0)
2694
        fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle,
2695
                 (unsigned int) control->help);
2696
    }
2697
 
2698
  fprintf (e, "\n");
2699
 
2700
  if (control->data != NULL)
2701
    write_rc_rcdata (e, control->data, 2);
2702
}
2703
 
2704
/* Write out font directory data.  This would normally be built from
2705
   the font data.  */
2706
 
2707
static void
2708
write_rc_fontdir (FILE *e, const rc_fontdir *fontdir)
2709
{
2710
  const rc_fontdir *fc;
2711
  int c;
2712
 
2713
  for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++)
2714
    ;
2715
  fprintf (e, "BEGIN\n");
2716
  indent (e, 2);
2717
  fprintf (e, "%d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
2718
  for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++)
2719
    {
2720
      indent (e, 4);
2721
      fprintf (e, "%d,\t/* Font no %d with index %d.  */\n",
2722
        (int) fc->index, c, (int) fc->index);
2723
      write_rc_datablock (e, (rc_uint_type) fc->length - 2,
2724
                          (const bfd_byte *) fc->data + 4,fc->next != NULL,
2725
                          0, 0);
2726
    }
2727
  fprintf (e, "END\n");
2728
}
2729
 
2730
/* Write out group icon data.  This would normally be built from the
2731
   icon data.  */
2732
 
2733
static void
2734
write_rc_group_icon (FILE *e, const rc_group_icon *group_icon)
2735
{
2736
  const rc_group_icon *gi;
2737
  int c;
2738
 
2739
  for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++)
2740
    ;
2741
 
2742
  fprintf (e, "BEGIN\n");
2743
  indent (e, 2);
2744
  fprintf (e, " 0, 1, %d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
2745
 
2746
  indent (e, 4);
2747
  fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index.  */\n");
2748
  for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++)
2749
    {
2750
      indent (e, 4);
2751
      fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d.  */\n",
2752
        gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits,
2753
        (unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c);
2754
    }
2755
  fprintf (e, "END\n");
2756
}
2757
 
2758
/* Write out a menu resource.  */
2759
 
2760
static void
2761
write_rc_menu (FILE *e, const rc_menu *menu, int menuex)
2762
{
2763
  if (menu->help != 0)
2764
    fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help);
2765
  write_rc_menuitems (e, menu->items, menuex, 0);
2766
}
2767
 
2768
static void
2769
write_rc_toolbar (FILE *e, const rc_toolbar *tb)
2770
{
2771
  rc_toolbar_item *it;
2772
  indent (e, 0);
2773
  fprintf (e, "BEGIN\n");
2774
  it = tb->items;
2775
  while(it != NULL)
2776
  {
2777
    indent (e, 2);
2778
    if (it->id.u.id == 0)
2779
      fprintf (e, "SEPARATOR\n");
2780
    else
2781
      fprintf (e, "BUTTON %d\n", (int) it->id.u.id);
2782
    it = it->next;
2783
  }
2784
  indent (e, 0);
2785
  fprintf (e, "END\n");
2786
}
2787
 
2788
/* Write out menuitems.  */
2789
 
2790
static void
2791
write_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex,
2792
                    int ind)
2793
{
2794
  const rc_menuitem *mi;
2795
 
2796
  indent (e, ind);
2797
  fprintf (e, "BEGIN\n");
2798
 
2799
  for (mi = menuitems; mi != NULL; mi = mi->next)
2800
    {
2801
      indent (e, ind + 2);
2802
 
2803
      if (mi->popup == NULL)
2804
        fprintf (e, "MENUITEM");
2805
      else
2806
        fprintf (e, "POPUP");
2807
 
2808
      if (! menuex
2809
          && mi->popup == NULL
2810
          && mi->text == NULL
2811
          && mi->type == 0
2812
          && mi->id == 0)
2813
        {
2814
          fprintf (e, " SEPARATOR\n");
2815
          continue;
2816
        }
2817
 
2818
      if (mi->text == NULL)
2819
        fprintf (e, " \"\"");
2820
      else
2821
        {
2822
          fprintf (e, " ");
2823
          unicode_print_quoted (e, mi->text, -1);
2824
        }
2825
 
2826
      if (! menuex)
2827
        {
2828
          if (mi->popup == NULL)
2829
            fprintf (e, ", %d", (int) mi->id);
2830
 
2831
          if ((mi->type & MENUITEM_CHECKED) != 0)
2832
            fprintf (e, ", CHECKED");
2833
          if ((mi->type & MENUITEM_GRAYED) != 0)
2834
            fprintf (e, ", GRAYED");
2835
          if ((mi->type & MENUITEM_HELP) != 0)
2836
            fprintf (e, ", HELP");
2837
          if ((mi->type & MENUITEM_INACTIVE) != 0)
2838
            fprintf (e, ", INACTIVE");
2839
          if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2840
            fprintf (e, ", MENUBARBREAK");
2841
          if ((mi->type & MENUITEM_MENUBREAK) != 0)
2842
            fprintf (e, ", MENUBREAK");
2843
        }
2844
      else
2845
        {
2846
          if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2847
            {
2848
              fprintf (e, ", %d", (int) mi->id);
2849
              if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2850
                {
2851
                  fprintf (e, ", %u", (unsigned int) mi->type);
2852
                  if (mi->state != 0 || mi->help != 0)
2853
                    {
2854
                      fprintf (e, ", %u", (unsigned int) mi->state);
2855
                      if (mi->help != 0)
2856
                        fprintf (e, ", %u", (unsigned int) mi->help);
2857
                    }
2858
                }
2859
            }
2860
        }
2861
 
2862
      fprintf (e, "\n");
2863
 
2864
      if (mi->popup != NULL)
2865
        write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2866
    }
2867
 
2868
  indent (e, ind);
2869
  fprintf (e, "END\n");
2870
}
2871
 
2872
static int
2873
test_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data)
2874
{
2875
  rc_uint_type i;
2876
  if ((length & 1) != 0)
2877
    return 0;
2878
 
2879
  for (i = 0; i < length; i += 2)
2880
    {
2881
      if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length)
2882
        return 0;
2883
      if (data[i] == 0xff && data[i + 1] == 0xff)
2884
        return 0;
2885
    }
2886
  return 1;
2887
}
2888
 
2889
static int
2890
test_rc_datablock_text (rc_uint_type length, const bfd_byte *data)
2891
{
2892
  int has_nl;
2893
  rc_uint_type c;
2894
  rc_uint_type i;
2895
 
2896
  if (length <= 1)
2897
    return 0;
2898
 
2899
  has_nl = 0;
2900
  for (i = 0, c = 0; i < length; i++)
2901
    {
2902
      if (! ISPRINT (data[i]) && data[i] != '\n'
2903
          && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n')
2904
          && data[i] != '\t'
2905
          && ! (data[i] == 0 && (i + 1) != length))
2906
        {
2907
          if (data[i] <= 7)
2908
            return 0;
2909
          c++;
2910
        }
2911
      else if (data[i] == '\n') has_nl++;
2912
    }
2913
  if (length > 80 && ! has_nl)
2914
    return 0;
2915
  c = (((c * 10000) + (i / 100) - 1)) / i;
2916
  if (c >= 150)
2917
    return 0;
2918
  return 1;
2919
}
2920
 
2921
static void
2922
write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data)
2923
{
2924
  int has_error = 0;
2925
  const struct bin_messagetable *mt;
2926
  fprintf (e, "BEGIN\n");
2927
 
2928
  write_rc_datablock (e, length, data, 0, 0, 0);
2929
 
2930
  fprintf (e, "\n");
2931
  wr_printcomment (e, "MC syntax dump");
2932
  if (length < BIN_MESSAGETABLE_SIZE)
2933
    has_error = 1;
2934
  else
2935
    do {
2936
      rc_uint_type m, i;
2937
      mt = (const struct bin_messagetable *) data;
2938
      m = windres_get_32 (&wrtarget, mt->cblocks, length);
2939
      if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
2940
        {
2941
          has_error = 1;
2942
          break;
2943
        }
2944
      for (i = 0; i < m; i++)
2945
        {
2946
          rc_uint_type low, high, offset;
2947
          const struct bin_messagetable_item *mti;
2948
 
2949
          low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
2950
          high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
2951
          offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
2952
          while (low <= high)
2953
            {
2954
              rc_uint_type elen, flags;
2955
              if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
2956
                {
2957
                  has_error = 1;
2958
          break;
2959
                }
2960
              mti = (const struct bin_messagetable_item *) &data[offset];
2961
              elen = windres_get_16 (&wrtarget, mti->length, 2);
2962
              flags = windres_get_16 (&wrtarget, mti->flags, 2);
2963
              if ((offset + elen) > length)
2964
                {
2965
                  has_error = 1;
2966
                  break;
2967
                }
2968
              wr_printcomment (e, "MessageId = 0x%x", low);
2969
              wr_printcomment (e, "");
2970
              if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
2971
                unicode_print (e, (const unichar *) mti->data,
2972
                               (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
2973
              else
2974
                ascii_print (e, (const char *) mti->data,
2975
                             (elen - BIN_MESSAGETABLE_ITEM_SIZE));
2976
              wr_printcomment (e,"");
2977
              ++low;
2978
              offset += elen;
2979
            }
2980
        }
2981
    } while (0);
2982
  if (has_error)
2983
    wr_printcomment (e, "Illegal data");
2984
  wr_print_flush (e);
2985
  fprintf (e, "END\n");
2986
}
2987
 
2988
static void
2989
write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next,
2990
                    int hasblock, int show_comment)
2991
{
2992
  int plen;
2993
 
2994
  if (hasblock)
2995
    fprintf (e, "BEGIN\n");
2996
 
2997
  if (show_comment == -1)
2998
          {
2999
      if (test_rc_datablock_text(length, data))
3000
        {
3001
          rc_uint_type i, c;
3002
          for (i = 0; i < length;)
3003
            {
3004
              indent (e, 2);
3005
              fprintf (e, "\"");
3006
 
3007
              for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++)
3008
                ;
3009
              if (i < length && data[i] == '\n')
3010
                ++i, ++c;
3011
              ascii_print (e, (const char *) &data[i - c], c);
3012
            fprintf (e, "\"");
3013
              if (i < length)
3014
                fprintf (e, "\n");
3015
            }
3016
 
3017
          if (i == 0)
3018
              {
3019
              indent (e, 2);
3020
              fprintf (e, "\"\"");
3021
              }
3022
          if (has_next)
3023
            fprintf (e, ",");
3024
          fprintf (e, "\n");
3025
          if (hasblock)
3026
            fprintf (e, "END\n");
3027
          return;
3028
          }
3029
      if (test_rc_datablock_unicode (length, data))
3030
        {
3031
          rc_uint_type i, c;
3032
          for (i = 0; i < length;)
3033
            {
3034
              const unichar *u;
3035
 
3036
              u = (const unichar *) &data[i];
3037
              indent (e, 2);
3038
          fprintf (e, "L\"");
3039
 
3040
              for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2)
3041
                ;
3042
              if (i < length && u[c] == '\n')
3043
                i += 2, ++c;
3044
              unicode_print (e, u, c);
3045
          fprintf (e, "\"");
3046
              if (i < length)
3047
                fprintf (e, "\n");
3048
            }
3049
 
3050
          if (i == 0)
3051
          {
3052
              indent (e, 2);
3053
              fprintf (e, "L\"\"");
3054
            }
3055
          if (has_next)
3056
            fprintf (e, ",");
3057
          fprintf (e, "\n");
3058
          if (hasblock)
3059
            fprintf (e, "END\n");
3060
          return;
3061
        }
3062
 
3063
      show_comment = 0;
3064
    }
3065
 
3066
  if (length != 0)
3067
              {
3068
      rc_uint_type i, max_row;
3069
      int first = 1;
3070
 
3071
      max_row = (show_comment ? 4 : 8);
3072
      indent (e, 2);
3073
      for (i = 0; i + 3 < length;)
3074
                  {
3075
          rc_uint_type k;
3076
          rc_uint_type comment_start;
3077
 
3078
          comment_start = i;
3079
 
3080
          if (! first)
3081
            indent (e, 2);
3082
 
3083
          for (k = 0; k < max_row && i + 3 < length; k++, i += 4)
3084
                      {
3085
              if (k == 0)
3086
                plen  = fprintf (e, "0x%lxL",
3087
                                 (unsigned long) windres_get_32 (&wrtarget, data + i, length - i));
3088
                        else
3089
                plen = fprintf (e, " 0x%lxL",
3090
                                (unsigned long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
3091
              if (has_next || (i + 4) < length)
3092
                          {
3093
                  if (plen>0 && plen < 11)
3094
                    indent (e, 11 - plen);
3095
                  fprintf (e, ",");
3096
                          }
3097
                      }
3098
          if (show_comment)
3099
            {
3100
              fprintf (e, "\t/* ");
3101
              ascii_print (e, (const char *) &data[comment_start], i - comment_start);
3102
              fprintf (e, ".  */");
3103
                  }
3104
                fprintf (e, "\n");
3105
                first = 0;
3106
              }
3107
 
3108
      if (i + 1 < length)
3109
              {
3110
                if (! first)
3111
            indent (e, 2);
3112
          plen = fprintf (e, "0x%x",
3113
                          (int) windres_get_16 (&wrtarget, data + i, length - i));
3114
          if (has_next || i + 2 < length)
3115
                  {
3116
              if (plen > 0 && plen < 11)
3117
                indent (e, 11 - plen);
3118
              fprintf (e, ",");
3119
                      }
3120
          if (show_comment)
3121
            {
3122
              fprintf (e, "\t/* ");
3123
              ascii_print (e, (const char *) &data[i], 2);
3124
              fprintf (e, ".  */");
3125
                  }
3126
                fprintf (e, "\n");
3127
                i += 2;
3128
                first = 0;
3129
              }
3130
 
3131
      if (i < length)
3132
              {
3133
                if (! first)
3134
            indent (e, 2);
3135
          fprintf (e, "\"");
3136
          ascii_print (e, (const char *) &data[i], 1);
3137
          fprintf (e, "\"");
3138
          if (has_next)
3139
                  fprintf (e, ",");
3140
                fprintf (e, "\n");
3141
                first = 0;
3142
              }
3143
    }
3144
  if (hasblock)
3145
    fprintf (e, "END\n");
3146
}
3147
 
3148
/* Write out an rcdata resource.  This is also used for other types of
3149
   resources that need to print arbitrary data.  */
3150
 
3151
static void
3152
write_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind)
3153
{
3154
  const rc_rcdata_item *ri;
3155
 
3156
  indent (e, ind);
3157
  fprintf (e, "BEGIN\n");
3158
 
3159
  for (ri = rcdata; ri != NULL; ri = ri->next)
3160
    {
3161
      if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
3162
        continue;
3163
 
3164
      switch (ri->type)
3165
        {
3166
        default:
3167
          abort ();
3168
 
3169
        case RCDATA_WORD:
3170
          indent (e, ind + 2);
3171
          fprintf (e, "%ld", (long) (ri->u.word & 0xffff));
3172
          break;
3173
 
3174
        case RCDATA_DWORD:
3175
          indent (e, ind + 2);
3176
          fprintf (e, "%luL", (unsigned long) ri->u.dword);
3177
          break;
3178
 
3179
        case RCDATA_STRING:
3180
          indent (e, ind + 2);
3181
          fprintf (e, "\"");
3182
          ascii_print (e, ri->u.string.s, ri->u.string.length);
3183
          fprintf (e, "\"");
3184
          break;
3185
 
3186
        case RCDATA_WSTRING:
3187
          indent (e, ind + 2);
3188
          fprintf (e, "L\"");
3189
          unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
3190
          fprintf (e, "\"");
3191
          break;
3192
 
3193
        case RCDATA_BUFFER:
3194
          write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length,
3195
                              (const bfd_byte *) ri->u.buffer.data,
3196
                              ri->next != NULL, 0, -1);
3197
            break;
3198
        }
3199
 
3200
      if (ri->type != RCDATA_BUFFER)
3201
        {
3202
          if (ri->next != NULL)
3203
            fprintf (e, ",");
3204
          fprintf (e, "\n");
3205
        }
3206
    }
3207
 
3208
  indent (e, ind);
3209
  fprintf (e, "END\n");
3210
}
3211
 
3212
/* Write out a stringtable resource.  */
3213
 
3214
static void
3215
write_rc_stringtable (FILE *e, const rc_res_id *name,
3216
                      const rc_stringtable *stringtable)
3217
{
3218
  rc_uint_type offset;
3219
  int i;
3220
 
3221
  if (name != NULL && ! name->named)
3222
    offset = (name->u.id - 1) << 4;
3223
  else
3224
    {
3225
      fprintf (e, "/* %s string table name.  */\n",
3226
               name == NULL ? "Missing" : "Invalid");
3227
      offset = 0;
3228
    }
3229
 
3230
  fprintf (e, "BEGIN\n");
3231
 
3232
  for (i = 0; i < 16; i++)
3233
    {
3234
      if (stringtable->strings[i].length != 0)
3235
        {
3236
          fprintf (e, "  %lu, ", (unsigned long) offset + i);
3237
          unicode_print_quoted (e, stringtable->strings[i].string,
3238
                         stringtable->strings[i].length);
3239
          fprintf (e, "\n");
3240
        }
3241
    }
3242
 
3243
  fprintf (e, "END\n");
3244
}
3245
 
3246
/* Write out a versioninfo resource.  */
3247
 
3248
static void
3249
write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo)
3250
{
3251
  const rc_fixed_versioninfo *f;
3252
  const rc_ver_info *vi;
3253
 
3254
  f = versioninfo->fixed;
3255
  if (f->file_version_ms != 0 || f->file_version_ls != 0)
3256
    fprintf (e, " FILEVERSION %u, %u, %u, %u\n",
3257
             (unsigned int) ((f->file_version_ms >> 16) & 0xffff),
3258
             (unsigned int) (f->file_version_ms & 0xffff),
3259
             (unsigned int) ((f->file_version_ls >> 16) & 0xffff),
3260
             (unsigned int) (f->file_version_ls & 0xffff));
3261
  if (f->product_version_ms != 0 || f->product_version_ls != 0)
3262
    fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n",
3263
             (unsigned int) ((f->product_version_ms >> 16) & 0xffff),
3264
             (unsigned int) (f->product_version_ms & 0xffff),
3265
             (unsigned int) ((f->product_version_ls >> 16) & 0xffff),
3266
             (unsigned int) (f->product_version_ls & 0xffff));
3267
  if (f->file_flags_mask != 0)
3268
    fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask);
3269
  if (f->file_flags != 0)
3270
    fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags);
3271
  if (f->file_os != 0)
3272
    fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os);
3273
  if (f->file_type != 0)
3274
    fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type);
3275
  if (f->file_subtype != 0)
3276
    fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype);
3277
  if (f->file_date_ms != 0 || f->file_date_ls != 0)
3278
    fprintf (e, "/* Date: %u, %u.  */\n",
3279
             (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls);
3280
 
3281
  fprintf (e, "BEGIN\n");
3282
 
3283
  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
3284
    {
3285
      switch (vi->type)
3286
        {
3287
        case VERINFO_STRING:
3288
          {
3289 163 khays
            const rc_ver_stringtable *vst;
3290 15 khays
            const rc_ver_stringinfo *vs;
3291
 
3292
            fprintf (e, "  BLOCK \"StringFileInfo\"\n");
3293
            fprintf (e, "  BEGIN\n");
3294
 
3295 163 khays
            for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next)
3296 15 khays
              {
3297 163 khays
                fprintf (e, "    BLOCK ");
3298
                unicode_print_quoted (e, vst->language, -1);
3299
 
3300 15 khays
                fprintf (e, "\n");
3301 163 khays
                fprintf (e, "    BEGIN\n");
3302
 
3303
                for (vs = vst->strings; vs != NULL; vs = vs->next)
3304
                  {
3305
                    fprintf (e, "      VALUE ");
3306
                    unicode_print_quoted (e, vs->key, -1);
3307
                    fprintf (e, ", ");
3308
                    unicode_print_quoted (e, vs->value, -1);
3309
                    fprintf (e, "\n");
3310
                  }
3311
 
3312
                fprintf (e, "    END\n");
3313 15 khays
              }
3314
            fprintf (e, "  END\n");
3315
            break;
3316
          }
3317
 
3318
        case VERINFO_VAR:
3319
          {
3320
            const rc_ver_varinfo *vv;
3321
 
3322
            fprintf (e, "  BLOCK \"VarFileInfo\"\n");
3323
            fprintf (e, "  BEGIN\n");
3324
            fprintf (e, "    VALUE ");
3325
            unicode_print_quoted (e, vi->u.var.key, -1);
3326
 
3327
            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
3328
              fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
3329
                       (int) vv->charset);
3330
 
3331
            fprintf (e, "\n  END\n");
3332
 
3333
            break;
3334
          }
3335
        }
3336
    }
3337
 
3338
  fprintf (e, "END\n");
3339
}
3340
 
3341
static rc_uint_type
3342
rcdata_copy (const rc_rcdata_item *src, bfd_byte *dst)
3343
{
3344
  if (! src)
3345
    return 0;
3346
  switch (src->type)
3347
        {
3348
    case RCDATA_WORD:
3349
      if (dst)
3350
        windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word);
3351
      return 2;
3352
    case RCDATA_DWORD:
3353
      if (dst)
3354
        windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword);
3355
      return 4;
3356
    case RCDATA_STRING:
3357
      if (dst && src->u.string.length)
3358
        memcpy (dst, src->u.string.s, src->u.string.length);
3359
      return (rc_uint_type) src->u.string.length;
3360
    case RCDATA_WSTRING:
3361
      if (dst && src->u.wstring.length)
3362
        memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar));
3363
      return (rc_uint_type) (src->u.wstring.length  * sizeof (unichar));
3364
    case RCDATA_BUFFER:
3365
      if (dst && src->u.buffer.length)
3366
        memcpy (dst, src->u.buffer.data, src->u.buffer.length);
3367
      return (rc_uint_type) src->u.buffer.length;
3368
    default:
3369
      abort ();
3370
    }
3371
  /* Never reached.  */
3372
  return 0;
3373
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.