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 241

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

powered by: WebSVN 2.1.0

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