OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [binutils/] [dllwrap.c] - Blame information for rev 595

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

Line No. Rev Author Line
1 205 julius
/* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
2
   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
3
   Free Software Foundation, Inc.
4
   Contributed by Mumit Khan (khan@xraylith.wisc.edu).
5
 
6
   This file is part of GNU Binutils.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21
   02110-1301, USA.  */
22
 
23
/* AIX requires this to be the first thing in the file.  */
24
#ifndef __GNUC__
25
# ifdef _AIX
26
 #pragma alloca
27
#endif
28
#endif
29
 
30
#include "sysdep.h"
31
#include "bfd.h"
32
#include "libiberty.h"
33
#include "getopt.h"
34
#include "dyn-string.h"
35
#include "bucomm.h"
36
 
37
#include <time.h>
38
#include <sys/stat.h>
39
 
40
#ifdef HAVE_SYS_WAIT_H
41
#include <sys/wait.h>
42
#else /* ! HAVE_SYS_WAIT_H */
43
#if ! defined (_WIN32) || defined (__CYGWIN32__)
44
#ifndef WIFEXITED
45
#define WIFEXITED(w)    (((w)&0377) == 0)
46
#endif
47
#ifndef WIFSIGNALED
48
#define WIFSIGNALED(w)  (((w)&0377) != 0177 && ((w)&~0377) == 0)
49
#endif
50
#ifndef WTERMSIG
51
#define WTERMSIG(w)     ((w) & 0177)
52
#endif
53
#ifndef WEXITSTATUS
54
#define WEXITSTATUS(w)  (((w) >> 8) & 0377)
55
#endif
56
#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
57
#ifndef WIFEXITED
58
#define WIFEXITED(w)    (((w) & 0xff) == 0)
59
#endif
60
#ifndef WIFSIGNALED
61
#define WIFSIGNALED(w)  (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
62
#endif
63
#ifndef WTERMSIG
64
#define WTERMSIG(w)     ((w) & 0x7f)
65
#endif
66
#ifndef WEXITSTATUS
67
#define WEXITSTATUS(w)  (((w) & 0xff00) >> 8)
68
#endif
69
#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
70
#endif /* ! HAVE_SYS_WAIT_H */
71
 
72
static char *driver_name = NULL;
73
static char *cygwin_driver_flags =
74
  "-Wl,--dll -nostartfiles";
75
static char *mingw32_driver_flags = "-mdll";
76
static char *generic_driver_flags = "-Wl,--dll";
77
 
78
static char *entry_point;
79
 
80
static char *dlltool_name = NULL;
81
 
82
static char *target = TARGET;
83
 
84
typedef enum {
85
  UNKNOWN_TARGET,
86
  CYGWIN_TARGET,
87
  MINGW_TARGET
88
}
89
target_type;
90
 
91
static target_type which_target = UNKNOWN_TARGET;
92
 
93
static int dontdeltemps = 0;
94
static int dry_run = 0;
95
 
96
static char *prog_name;
97
 
98
static int verbose = 0;
99
 
100
static char *dll_file_name;
101
static char *dll_name;
102
static char *base_file_name;
103
static char *exp_file_name;
104
static char *def_file_name;
105
static int delete_base_file = 1;
106
static int delete_exp_file = 1;
107
static int delete_def_file = 1;
108
 
109
static int run (const char *, char *);
110
static char *mybasename (const char *);
111
static int strhash (const char *);
112
static void usage (FILE *, int);
113
static void display (const char *, va_list) ATTRIBUTE_PRINTF(1,0);
114
static void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
115
static void warn (const char *, ...) ATTRIBUTE_PRINTF_1;
116
static char *look_for_prog (const char *, const char *, int);
117
static char *deduce_name (const char *);
118
static void delete_temp_files (void);
119
static void cleanup_and_exit (int);
120
 
121
/**********************************************************************/
122
 
123
/* Please keep the following 4 routines in sync with dlltool.c:
124
     display ()
125
     inform ()
126
     look_for_prog ()
127
     deduce_name ()
128
   It's not worth the hassle to break these out since dllwrap will
129
   (hopefully) soon be retired in favor of `ld --shared.  */
130
 
131
static void
132
display (const char * message, va_list args)
133
{
134
  if (prog_name != NULL)
135
    fprintf (stderr, "%s: ", prog_name);
136
 
137
  vfprintf (stderr, message, args);
138
  fputc ('\n', stderr);
139
}
140
 
141
 
142
static void
143
inform VPARAMS ((const char *message, ...))
144
{
145
  VA_OPEN (args, message);
146
  VA_FIXEDARG (args, const char *, message);
147
 
148
  if (!verbose)
149
    return;
150
 
151
  display (message, args);
152
 
153
  VA_CLOSE (args);
154
}
155
 
156
static void
157
warn VPARAMS ((const char *format, ...))
158
{
159
  VA_OPEN (args, format);
160
  VA_FIXEDARG (args, const char *, format);
161
 
162
  display (format, args);
163
 
164
  VA_CLOSE (args);
165
}
166
 
167
/* Look for the program formed by concatenating PROG_NAME and the
168
   string running from PREFIX to END_PREFIX.  If the concatenated
169
   string contains a '/', try appending EXECUTABLE_SUFFIX if it is
170
   appropriate.  */
171
 
172
static char *
173
look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
174
{
175
  struct stat s;
176
  char *cmd;
177
 
178
  cmd = xmalloc (strlen (prefix)
179
                 + strlen (prog_name)
180
#ifdef HAVE_EXECUTABLE_SUFFIX
181
                 + strlen (EXECUTABLE_SUFFIX)
182
#endif
183
                 + 10);
184
  strcpy (cmd, prefix);
185
 
186
  sprintf (cmd + end_prefix, "%s", prog_name);
187
 
188
  if (strchr (cmd, '/') != NULL)
189
    {
190
      int found;
191
 
192
      found = (stat (cmd, &s) == 0
193
#ifdef HAVE_EXECUTABLE_SUFFIX
194
               || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
195
#endif
196
               );
197
 
198
      if (! found)
199
        {
200
          /* xgettext:c-format */
201
          inform (_("Tried file: %s"), cmd);
202
          free (cmd);
203
          return NULL;
204
        }
205
    }
206
 
207
  /* xgettext:c-format */
208
  inform (_("Using file: %s"), cmd);
209
 
210
  return cmd;
211
}
212
 
213
/* Deduce the name of the program we are want to invoke.
214
   PROG_NAME is the basic name of the program we want to run,
215
   eg "as" or "ld".  The catch is that we might want actually
216
   run "i386-pe-as" or "ppc-pe-ld".
217
 
218
   If argv[0] contains the full path, then try to find the program
219
   in the same place, with and then without a target-like prefix.
220
 
221
   Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
222
   deduce_name("as") uses the following search order:
223
 
224
     /usr/local/bin/i586-cygwin32-as
225
     /usr/local/bin/as
226
     as
227
 
228
   If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
229
   name, it'll try without and then with EXECUTABLE_SUFFIX.
230
 
231
   Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
232
   as the fallback, but rather return i586-cygwin32-as.
233
 
234
   Oh, and given, argv[0] = dlltool, it'll return "as".
235
 
236
   Returns a dynamically allocated string.  */
237
 
238
static char *
239
deduce_name (const char * name)
240
{
241
  char *cmd;
242
  const char *dash;
243
  const char *slash;
244
  const char *cp;
245
 
246
  dash = NULL;
247
  slash = NULL;
248
  for (cp = prog_name; *cp != '\0'; ++cp)
249
    {
250
      if (*cp == '-')
251
        dash = cp;
252
 
253
      if (
254
#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
255
          *cp == ':' || *cp == '\\' ||
256
#endif
257
          *cp == '/')
258
        {
259
          slash = cp;
260
          dash = NULL;
261
        }
262
    }
263
 
264
  cmd = NULL;
265
 
266
  if (dash != NULL)
267
    /* First, try looking for a prefixed NAME in the
268
       PROG_NAME directory, with the same prefix as PROG_NAME.  */
269
    cmd = look_for_prog (name, prog_name, dash - prog_name + 1);
270
 
271
  if (slash != NULL && cmd == NULL)
272
    /* Next, try looking for a NAME in the same directory as
273
       that of this program.  */
274
    cmd = look_for_prog (name, prog_name, slash - prog_name + 1);
275
 
276
  if (cmd == NULL)
277
    /* Just return NAME as is.  */
278
    cmd = xstrdup (name);
279
 
280
  return cmd;
281
}
282
 
283
static void
284
delete_temp_files (void)
285
{
286
  if (delete_base_file && base_file_name)
287
    {
288
      if (verbose)
289
        {
290
          if (dontdeltemps)
291
            warn (_("Keeping temporary base file %s"), base_file_name);
292
          else
293
            warn (_("Deleting temporary base file %s"), base_file_name);
294
        }
295
      if (! dontdeltemps)
296
        {
297
          unlink (base_file_name);
298
          free (base_file_name);
299
        }
300
    }
301
 
302
  if (delete_exp_file && exp_file_name)
303
    {
304
      if (verbose)
305
        {
306
          if (dontdeltemps)
307
            warn (_("Keeping temporary exp file %s"), exp_file_name);
308
          else
309
            warn (_("Deleting temporary exp file %s"), exp_file_name);
310
        }
311
      if (! dontdeltemps)
312
        {
313
          unlink (exp_file_name);
314
          free (exp_file_name);
315
        }
316
    }
317
  if (delete_def_file && def_file_name)
318
    {
319
      if (verbose)
320
        {
321
          if (dontdeltemps)
322
            warn (_("Keeping temporary def file %s"), def_file_name);
323
          else
324
            warn (_("Deleting temporary def file %s"), def_file_name);
325
        }
326
      if (! dontdeltemps)
327
        {
328
          unlink (def_file_name);
329
          free (def_file_name);
330
        }
331
    }
332
}
333
 
334
static void
335
cleanup_and_exit (int status)
336
{
337
  delete_temp_files ();
338
  exit (status);
339
}
340
 
341
static int
342
run (const char *what, char *args)
343
{
344
  char *s;
345
  int pid, wait_status, retcode;
346
  int i;
347
  const char **argv;
348
  char *errmsg_fmt, *errmsg_arg;
349
  char *temp_base = choose_temp_base ();
350
  int in_quote;
351
  char sep;
352
 
353
  if (verbose || dry_run)
354
    fprintf (stderr, "%s %s\n", what, args);
355
 
356
  /* Count the args */
357
  i = 0;
358
  for (s = args; *s; s++)
359
    if (*s == ' ')
360
      i++;
361
  i++;
362
  argv = alloca (sizeof (char *) * (i + 3));
363
  i = 0;
364
  argv[i++] = what;
365
  s = args;
366
  while (1)
367
    {
368
      while (*s == ' ' && *s != 0)
369
        s++;
370
      if (*s == 0)
371
        break;
372
      in_quote = (*s == '\'' || *s == '"');
373
      sep = (in_quote) ? *s++ : ' ';
374
      argv[i++] = s;
375
      while (*s != sep && *s != 0)
376
        s++;
377
      if (*s == 0)
378
        break;
379
      *s++ = 0;
380
      if (in_quote)
381
        s++;
382
    }
383
  argv[i++] = NULL;
384
 
385
  if (dry_run)
386
    return 0;
387
 
388
  pid = pexecute (argv[0], (char * const *) argv, prog_name, temp_base,
389
                  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
390
 
391
  if (pid == -1)
392
    {
393
      int errno_val = errno;
394
 
395
      fprintf (stderr, "%s: ", prog_name);
396
      fprintf (stderr, errmsg_fmt, errmsg_arg);
397
      fprintf (stderr, ": %s\n", strerror (errno_val));
398
      return 1;
399
    }
400
 
401
  retcode = 0;
402
  pid = pwait (pid, &wait_status, 0);
403
  if (pid == -1)
404
    {
405
      warn ("wait: %s", strerror (errno));
406
      retcode = 1;
407
    }
408
  else if (WIFSIGNALED (wait_status))
409
    {
410
      warn (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
411
      retcode = 1;
412
    }
413
  else if (WIFEXITED (wait_status))
414
    {
415
      if (WEXITSTATUS (wait_status) != 0)
416
        {
417
          warn (_("%s exited with status %d"), what, WEXITSTATUS (wait_status));
418
          retcode = 1;
419
        }
420
    }
421
  else
422
    retcode = 1;
423
 
424
  return retcode;
425
}
426
 
427
static char *
428
mybasename (const char *name)
429
{
430
  const char *base = name;
431
 
432
  while (*name)
433
    {
434
      if (*name == '/' || *name == '\\')
435
        {
436
          base = name + 1;
437
        }
438
      ++name;
439
    }
440
  return (char *) base;
441
}
442
 
443
static int
444
strhash (const char *str)
445
{
446
  const unsigned char *s;
447
  unsigned long hash;
448
  unsigned int c;
449
  unsigned int len;
450
 
451
  hash = 0;
452
  len = 0;
453
  s = (const unsigned char *) str;
454
  while ((c = *s++) != '\0')
455
    {
456
      hash += c + (c << 17);
457
      hash ^= hash >> 2;
458
      ++len;
459
    }
460
  hash += len + (len << 17);
461
  hash ^= hash >> 2;
462
 
463
  return hash;
464
}
465
 
466
/**********************************************************************/
467
 
468
static void
469
usage (FILE *file, int status)
470
{
471
  fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), prog_name);
472
  fprintf (file, _("  Generic options:\n"));
473
  fprintf (file, _("   @<file>                Read options from <file>\n"));
474
  fprintf (file, _("   --quiet, -q            Work quietly\n"));
475
  fprintf (file, _("   --verbose, -v          Verbose\n"));
476
  fprintf (file, _("   --version              Print dllwrap version\n"));
477
  fprintf (file, _("   --implib <outname>     Synonym for --output-lib\n"));
478
  fprintf (file, _("  Options for %s:\n"), prog_name);
479
  fprintf (file, _("   --driver-name <driver> Defaults to \"gcc\"\n"));
480
  fprintf (file, _("   --driver-flags <flags> Override default ld flags\n"));
481
  fprintf (file, _("   --dlltool-name <dlltool> Defaults to \"dlltool\"\n"));
482
  fprintf (file, _("   --entry <entry>        Specify alternate DLL entry point\n"));
483
  fprintf (file, _("   --image-base <base>    Specify image base address\n"));
484
  fprintf (file, _("   --target <machine>     i386-cygwin32 or i386-mingw32\n"));
485
  fprintf (file, _("   --dry-run              Show what needs to be run\n"));
486
  fprintf (file, _("   --mno-cygwin           Create Mingw DLL\n"));
487
  fprintf (file, _("  Options passed to DLLTOOL:\n"));
488
  fprintf (file, _("   --machine <machine>\n"));
489
  fprintf (file, _("   --output-exp <outname> Generate export file.\n"));
490
  fprintf (file, _("   --output-lib <outname> Generate input library.\n"));
491
  fprintf (file, _("   --add-indirect         Add dll indirects to export file.\n"));
492
  fprintf (file, _("   --dllname <name>       Name of input dll to put into output lib.\n"));
493
  fprintf (file, _("   --def <deffile>        Name input .def file\n"));
494
  fprintf (file, _("   --output-def <deffile> Name output .def file\n"));
495
  fprintf (file, _("   --export-all-symbols     Export all symbols to .def\n"));
496
  fprintf (file, _("   --no-export-all-symbols  Only export .drectve symbols\n"));
497
  fprintf (file, _("   --exclude-symbols <list> Exclude <list> from .def\n"));
498
  fprintf (file, _("   --no-default-excludes    Zap default exclude symbols\n"));
499
  fprintf (file, _("   --base-file <basefile> Read linker generated base file\n"));
500
  fprintf (file, _("   --no-idata4           Don't generate idata$4 section\n"));
501
  fprintf (file, _("   --no-idata5           Don't generate idata$5 section\n"));
502
  fprintf (file, _("   -U                     Add underscores to .lib\n"));
503
  fprintf (file, _("   -k                     Kill @<n> from exported names\n"));
504
  fprintf (file, _("   --add-stdcall-alias    Add aliases without @<n>\n"));
505
  fprintf (file, _("   --as <name>            Use <name> for assembler\n"));
506
  fprintf (file, _("   --nodelete             Keep temp files.\n"));
507
  fprintf (file, _("  Rest are passed unmodified to the language driver\n"));
508
  fprintf (file, "\n\n");
509
  if (REPORT_BUGS_TO[0] && status == 0)
510
    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
511
  exit (status);
512
}
513
 
514
#define OPTION_START            149
515
 
516
/* GENERIC options.  */
517
#define OPTION_QUIET            (OPTION_START + 1)
518
#define OPTION_VERBOSE          (OPTION_QUIET + 1)
519
#define OPTION_VERSION          (OPTION_VERBOSE + 1)
520
 
521
/* DLLWRAP options.  */
522
#define OPTION_DRY_RUN          (OPTION_VERSION + 1)
523
#define OPTION_DRIVER_NAME      (OPTION_DRY_RUN + 1)
524
#define OPTION_DRIVER_FLAGS     (OPTION_DRIVER_NAME + 1)
525
#define OPTION_DLLTOOL_NAME     (OPTION_DRIVER_FLAGS + 1)
526
#define OPTION_ENTRY            (OPTION_DLLTOOL_NAME + 1)
527
#define OPTION_IMAGE_BASE       (OPTION_ENTRY + 1)
528
#define OPTION_TARGET           (OPTION_IMAGE_BASE + 1)
529
#define OPTION_MNO_CYGWIN       (OPTION_TARGET + 1)
530
 
531
/* DLLTOOL options.  */
532
#define OPTION_NODELETE         (OPTION_MNO_CYGWIN + 1)
533
#define OPTION_DLLNAME          (OPTION_NODELETE + 1)
534
#define OPTION_NO_IDATA4        (OPTION_DLLNAME + 1)
535
#define OPTION_NO_IDATA5        (OPTION_NO_IDATA4 + 1)
536
#define OPTION_OUTPUT_EXP       (OPTION_NO_IDATA5 + 1)
537
#define OPTION_OUTPUT_DEF       (OPTION_OUTPUT_EXP + 1)
538
#define OPTION_EXPORT_ALL_SYMS  (OPTION_OUTPUT_DEF + 1)
539
#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
540
#define OPTION_EXCLUDE_SYMS     (OPTION_NO_EXPORT_ALL_SYMS + 1)
541
#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
542
#define OPTION_OUTPUT_LIB       (OPTION_NO_DEFAULT_EXCLUDES + 1)
543
#define OPTION_DEF              (OPTION_OUTPUT_LIB + 1)
544
#define OPTION_ADD_UNDERSCORE   (OPTION_DEF + 1)
545
#define OPTION_KILLAT           (OPTION_ADD_UNDERSCORE + 1)
546
#define OPTION_HELP             (OPTION_KILLAT + 1)
547
#define OPTION_MACHINE          (OPTION_HELP + 1)
548
#define OPTION_ADD_INDIRECT     (OPTION_MACHINE + 1)
549
#define OPTION_BASE_FILE        (OPTION_ADD_INDIRECT + 1)
550
#define OPTION_AS               (OPTION_BASE_FILE + 1)
551
 
552
static const struct option long_options[] =
553
{
554
  /* generic options.  */
555
  {"quiet", no_argument, NULL, 'q'},
556
  {"verbose", no_argument, NULL, 'v'},
557
  {"version", no_argument, NULL, OPTION_VERSION},
558
  {"implib", required_argument, NULL, OPTION_OUTPUT_LIB},
559
 
560
  /* dllwrap options.  */
561
  {"dry-run", no_argument, NULL, OPTION_DRY_RUN},
562
  {"driver-name", required_argument, NULL, OPTION_DRIVER_NAME},
563
  {"driver-flags", required_argument, NULL, OPTION_DRIVER_FLAGS},
564
  {"dlltool-name", required_argument, NULL, OPTION_DLLTOOL_NAME},
565
  {"entry", required_argument, NULL, 'e'},
566
  {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
567
  {"target", required_argument, NULL, OPTION_TARGET},
568
 
569
  /* dlltool options.  */
570
  {"no-delete", no_argument, NULL, 'n'},
571
  {"dllname", required_argument, NULL, OPTION_DLLNAME},
572
  {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
573
  {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
574
  {"output-exp", required_argument, NULL, OPTION_OUTPUT_EXP},
575
  {"output-def", required_argument, NULL, OPTION_OUTPUT_DEF},
576
  {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
577
  {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
578
  {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
579
  {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
580
  {"output-lib", required_argument, NULL, OPTION_OUTPUT_LIB},
581
  {"def", required_argument, NULL, OPTION_DEF},
582
  {"add-underscore", no_argument, NULL, 'U'},
583
  {"killat", no_argument, NULL, 'k'},
584
  {"add-stdcall-alias", no_argument, NULL, 'A'},
585
  {"help", no_argument, NULL, 'h'},
586
  {"machine", required_argument, NULL, OPTION_MACHINE},
587
  {"add-indirect", no_argument, NULL, OPTION_ADD_INDIRECT},
588
  {"base-file", required_argument, NULL, OPTION_BASE_FILE},
589
  {"as", required_argument, NULL, OPTION_AS},
590
  {0, 0, 0, 0}
591
};
592
 
593
int main (int, char **);
594
 
595
int
596
main (int argc, char **argv)
597
{
598
  int c;
599
  int i;
600
 
601
  char **saved_argv = 0;
602
  int cmdline_len = 0;
603
 
604
  int export_all = 0;
605
 
606
  int *dlltool_arg_indices;
607
  int *driver_arg_indices;
608
 
609
  char *driver_flags = 0;
610
  char *output_lib_file_name = 0;
611
 
612
  dyn_string_t dlltool_cmdline;
613
  dyn_string_t driver_cmdline;
614
 
615
  int def_file_seen = 0;
616
 
617
  char *image_base_str = 0;
618
 
619
  prog_name = argv[0];
620
 
621
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
622
  setlocale (LC_MESSAGES, "");
623
#endif
624
#if defined (HAVE_SETLOCALE)
625
  setlocale (LC_CTYPE, "");
626
#endif
627
  bindtextdomain (PACKAGE, LOCALEDIR);
628
  textdomain (PACKAGE);
629
 
630
  expandargv (&argc, &argv);
631
 
632
  saved_argv = (char **) xmalloc (argc * sizeof (char*));
633
  dlltool_arg_indices = (int *) xmalloc (argc * sizeof (int));
634
  driver_arg_indices = (int *) xmalloc (argc * sizeof (int));
635
  for (i = 0; i < argc; ++i)
636
    {
637
      size_t len = strlen (argv[i]);
638
      char *arg = (char *) xmalloc (len + 1);
639
      strcpy (arg, argv[i]);
640
      cmdline_len += len;
641
      saved_argv[i] = arg;
642
      dlltool_arg_indices[i] = 0;
643
      driver_arg_indices[i] = 1;
644
    }
645
  cmdline_len++;
646
 
647
  /* We recognize dllwrap and dlltool options, and everything else is
648
     passed onto the language driver (eg., to GCC). We collect options
649
     to dlltool and driver in dlltool_args and driver_args.  */
650
 
651
  opterr = 0;
652
  while ((c = getopt_long_only (argc, argv, "nkAqve:Uho:l:L:I:",
653
                                long_options, (int *) 0)) != EOF)
654
    {
655
      int dlltool_arg;
656
      int driver_arg;
657
      int single_word_option_value_pair;
658
 
659
      dlltool_arg = 0;
660
      driver_arg = 1;
661
      single_word_option_value_pair = 0;
662
 
663
      if (c != '?')
664
        {
665
          /* We recognize this option, so it has to be either dllwrap or
666
             dlltool option. Do not pass to driver unless it's one of the
667
             generic options that are passed to all the tools (such as -v)
668
             which are dealt with later.  */
669
          driver_arg = 0;
670
        }
671
 
672
      /* deal with generic and dllwrap options first.  */
673
      switch (c)
674
        {
675
        case 'h':
676
          usage (stdout, 0);
677
          break;
678
        case 'q':
679
          verbose = 0;
680
          break;
681
        case 'v':
682
          verbose = 1;
683
          break;
684
        case OPTION_VERSION:
685
          print_version (prog_name);
686
          break;
687
        case 'e':
688
          entry_point = optarg;
689
          break;
690
        case OPTION_IMAGE_BASE:
691
          image_base_str = optarg;
692
          break;
693
        case OPTION_DEF:
694
          def_file_name = optarg;
695
          def_file_seen = 1;
696
          delete_def_file = 0;
697
          break;
698
        case 'n':
699
          dontdeltemps = 1;
700
          dlltool_arg = 1;
701
          break;
702
        case 'o':
703
          dll_file_name = optarg;
704
          break;
705
        case 'I':
706
        case 'l':
707
        case 'L':
708
          driver_arg = 1;
709
          break;
710
        case OPTION_DLLNAME:
711
          dll_name = optarg;
712
          break;
713
        case OPTION_DRY_RUN:
714
          dry_run = 1;
715
          break;
716
        case OPTION_DRIVER_NAME:
717
          driver_name = optarg;
718
          break;
719
        case OPTION_DRIVER_FLAGS:
720
          driver_flags = optarg;
721
          break;
722
        case OPTION_DLLTOOL_NAME:
723
          dlltool_name = optarg;
724
          break;
725
        case OPTION_TARGET:
726
          target = optarg;
727
          break;
728
        case OPTION_MNO_CYGWIN:
729
          target = "i386-mingw32";
730
          break;
731
        case OPTION_BASE_FILE:
732
          base_file_name = optarg;
733
          delete_base_file = 0;
734
          break;
735
        case OPTION_OUTPUT_EXP:
736
          exp_file_name = optarg;
737
          delete_exp_file = 0;
738
          break;
739
        case OPTION_EXPORT_ALL_SYMS:
740
          export_all = 1;
741
          break;
742
        case OPTION_OUTPUT_LIB:
743
          output_lib_file_name = optarg;
744
          break;
745
        case '?':
746
          break;
747
        default:
748
          dlltool_arg = 1;
749
          break;
750
        }
751
 
752
      /* Handle passing through --option=value case.  */
753
      if (optarg
754
          && saved_argv[optind-1][0] == '-'
755
          && saved_argv[optind-1][1] == '-'
756
          && strchr (saved_argv[optind-1], '='))
757
        single_word_option_value_pair = 1;
758
 
759
      if (dlltool_arg)
760
        {
761
          dlltool_arg_indices[optind-1] = 1;
762
          if (optarg && ! single_word_option_value_pair)
763
            {
764
              dlltool_arg_indices[optind-2] = 1;
765
            }
766
        }
767
 
768
      if (! driver_arg)
769
        {
770
          driver_arg_indices[optind-1] = 0;
771
          if (optarg && ! single_word_option_value_pair)
772
            {
773
              driver_arg_indices[optind-2] = 0;
774
            }
775
        }
776
    }
777
 
778
  /* Sanity checks.  */
779
  if (! dll_name && ! dll_file_name)
780
    {
781
      warn (_("Must provide at least one of -o or --dllname options"));
782
      exit (1);
783
    }
784
  else if (! dll_name)
785
    {
786
      dll_name = xstrdup (mybasename (dll_file_name));
787
    }
788
  else if (! dll_file_name)
789
    {
790
      dll_file_name = xstrdup (dll_name);
791
    }
792
 
793
  /* Deduce driver-name and dlltool-name from our own.  */
794
  if (driver_name == NULL)
795
    driver_name = deduce_name ("gcc");
796
 
797
  if (dlltool_name == NULL)
798
    dlltool_name = deduce_name ("dlltool");
799
 
800
  if (! def_file_seen)
801
    {
802
      char *fileprefix = choose_temp_base ();
803
 
804
      def_file_name = (char *) xmalloc (strlen (fileprefix) + 5);
805
      sprintf (def_file_name, "%s.def",
806
               (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
807
      delete_def_file = 1;
808
      free (fileprefix);
809
      delete_def_file = 1;
810
      warn (_("no export definition file provided.\n\
811
Creating one, but that may not be what you want"));
812
    }
813
 
814
  /* Set the target platform.  */
815
  if (strstr (target, "cygwin"))
816
    which_target = CYGWIN_TARGET;
817
  else if (strstr (target, "mingw"))
818
    which_target = MINGW_TARGET;
819
  else
820
    which_target = UNKNOWN_TARGET;
821
 
822
  /* Re-create the command lines as a string, taking care to quote stuff.  */
823
  dlltool_cmdline = dyn_string_new (cmdline_len);
824
  if (verbose)
825
    dyn_string_append_cstr (dlltool_cmdline, " -v");
826
 
827
  dyn_string_append_cstr (dlltool_cmdline, " --dllname ");
828
  dyn_string_append_cstr (dlltool_cmdline, dll_name);
829
 
830
  for (i = 1; i < argc; ++i)
831
    {
832
      if (dlltool_arg_indices[i])
833
        {
834
          char *arg = saved_argv[i];
835
          int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
836
          dyn_string_append_cstr (dlltool_cmdline,
837
                             (quote) ? " \"" : " ");
838
          dyn_string_append_cstr (dlltool_cmdline, arg);
839
          dyn_string_append_cstr (dlltool_cmdline,
840
                             (quote) ? "\"" : "");
841
        }
842
    }
843
 
844
  driver_cmdline = dyn_string_new (cmdline_len);
845
  if (! driver_flags || strlen (driver_flags) == 0)
846
    {
847
      switch (which_target)
848
        {
849
        case CYGWIN_TARGET:
850
          driver_flags = cygwin_driver_flags;
851
          break;
852
 
853
        case MINGW_TARGET:
854
          driver_flags = mingw32_driver_flags;
855
          break;
856
 
857
        default:
858
          driver_flags = generic_driver_flags;
859
          break;
860
        }
861
    }
862
  dyn_string_append_cstr (driver_cmdline, driver_flags);
863
  dyn_string_append_cstr (driver_cmdline, " -o ");
864
  dyn_string_append_cstr (driver_cmdline, dll_file_name);
865
 
866
  if (! entry_point || strlen (entry_point) == 0)
867
    {
868
      switch (which_target)
869
        {
870
        case CYGWIN_TARGET:
871
          entry_point = "__cygwin_dll_entry@12";
872
          break;
873
 
874
        case MINGW_TARGET:
875
          entry_point = "_DllMainCRTStartup@12";
876
          break;
877
 
878
        default:
879
          entry_point = "_DllMain@12";
880
          break;
881
        }
882
    }
883
  dyn_string_append_cstr (driver_cmdline, " -Wl,-e,");
884
  dyn_string_append_cstr (driver_cmdline, entry_point);
885
  dyn_string_append_cstr (dlltool_cmdline, " --exclude-symbol=");
886
  dyn_string_append_cstr (dlltool_cmdline,
887
                    (entry_point[0] == '_') ? entry_point+1 : entry_point);
888
 
889
  if (! image_base_str || strlen (image_base_str) == 0)
890
    {
891
      char *tmpbuf = (char *) xmalloc (sizeof ("0x12345678") + 1);
892
      unsigned long hash = strhash (dll_file_name);
893
      sprintf (tmpbuf, "0x%.8lX", 0x60000000|((hash<<16)&0xFFC0000));
894
      image_base_str = tmpbuf;
895
    }
896
 
897
  dyn_string_append_cstr (driver_cmdline, " -Wl,--image-base,");
898
  dyn_string_append_cstr (driver_cmdline, image_base_str);
899
 
900
  if (verbose)
901
    {
902
      dyn_string_append_cstr (driver_cmdline, " -v");
903
    }
904
 
905
  for (i = 1; i < argc; ++i)
906
    {
907
      if (driver_arg_indices[i])
908
        {
909
          char *arg = saved_argv[i];
910
          int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
911
          dyn_string_append_cstr (driver_cmdline,
912
                             (quote) ? " \"" : " ");
913
          dyn_string_append_cstr (driver_cmdline, arg);
914
          dyn_string_append_cstr (driver_cmdline,
915
                             (quote) ? "\"" : "");
916
        }
917
    }
918
 
919
  /* Step pre-1. If no --def <EXPORT_DEF> is specified,
920
     then create it and then pass it on.  */
921
 
922
  if (! def_file_seen)
923
    {
924
      int i;
925
      dyn_string_t step_pre1;
926
 
927
      step_pre1 = dyn_string_new (1024);
928
 
929
      dyn_string_append_cstr (step_pre1, dlltool_cmdline->s);
930
      if (export_all)
931
        {
932
          dyn_string_append_cstr (step_pre1, " --export-all --exclude-symbol=");
933
          dyn_string_append_cstr (step_pre1,
934
          "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
935
        }
936
      dyn_string_append_cstr (step_pre1, " --output-def ");
937
      dyn_string_append_cstr (step_pre1, def_file_name);
938
 
939
      for (i = 1; i < argc; ++i)
940
        {
941
          if (driver_arg_indices[i])
942
            {
943
              char *arg = saved_argv[i];
944
              size_t len = strlen (arg);
945
              if (len >= 2 && arg[len-2] == '.'
946
                  && (arg[len-1] == 'o' || arg[len-1] == 'a'))
947
                {
948
                  int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
949
                  dyn_string_append_cstr (step_pre1,
950
                                     (quote) ? " \"" : " ");
951
                  dyn_string_append_cstr (step_pre1, arg);
952
                  dyn_string_append_cstr (step_pre1,
953
                                     (quote) ? "\"" : "");
954
                }
955
            }
956
        }
957
 
958
      if (run (dlltool_name, step_pre1->s))
959
        cleanup_and_exit (1);
960
 
961
      dyn_string_delete (step_pre1);
962
    }
963
 
964
  dyn_string_append_cstr (dlltool_cmdline, " --def ");
965
  dyn_string_append_cstr (dlltool_cmdline, def_file_name);
966
 
967
  if (verbose)
968
    {
969
      fprintf (stderr, _("DLLTOOL name    : %s\n"), dlltool_name);
970
      fprintf (stderr, _("DLLTOOL options : %s\n"), dlltool_cmdline->s);
971
      fprintf (stderr, _("DRIVER name     : %s\n"), driver_name);
972
      fprintf (stderr, _("DRIVER options  : %s\n"), driver_cmdline->s);
973
    }
974
 
975
  /* Step 1. Call GCC/LD to create base relocation file. If using GCC, the
976
     driver command line will look like the following:
977
 
978
        % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
979
 
980
     If the user does not specify a base name, create temporary one that
981
     is deleted at exit.  */
982
 
983
  if (! base_file_name)
984
    {
985
      char *fileprefix = choose_temp_base ();
986
      base_file_name = (char *) xmalloc (strlen (fileprefix) + 6);
987
      sprintf (base_file_name, "%s.base",
988
               (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
989
      delete_base_file = 1;
990
      free (fileprefix);
991
    }
992
 
993
  {
994
    int quote;
995
 
996
    dyn_string_t step1 = dyn_string_new (driver_cmdline->length
997
                                         + strlen (base_file_name)
998
                                         + 20);
999
    dyn_string_append_cstr (step1, "-Wl,--base-file,");
1000
    quote = (strchr (base_file_name, ' ')
1001
             || strchr (base_file_name, '\t'));
1002
    dyn_string_append_cstr (step1,
1003
                       (quote) ? "\"" : "");
1004
    dyn_string_append_cstr (step1, base_file_name);
1005
    dyn_string_append_cstr (step1,
1006
                       (quote) ? "\"" : "");
1007
    if (driver_cmdline->length)
1008
      {
1009
        dyn_string_append_cstr (step1, " ");
1010
        dyn_string_append_cstr (step1, driver_cmdline->s);
1011
      }
1012
 
1013
    if (run (driver_name, step1->s))
1014
      cleanup_and_exit (1);
1015
 
1016
    dyn_string_delete (step1);
1017
  }
1018
 
1019
  /* Step 2. generate the exp file by running dlltool.
1020
     dlltool command line will look like the following:
1021
 
1022
        % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
1023
 
1024
     If the user does not specify a base name, create temporary one that
1025
     is deleted at exit.  */
1026
 
1027
  if (! exp_file_name)
1028
    {
1029
      char *p = strrchr (dll_name, '.');
1030
      size_t prefix_len = (p) ? (size_t) (p - dll_name) : strlen (dll_name);
1031
 
1032
      exp_file_name = (char *) xmalloc (prefix_len + 4 + 1);
1033
      strncpy (exp_file_name, dll_name, prefix_len);
1034
      exp_file_name[prefix_len] = '\0';
1035
      strcat (exp_file_name, ".exp");
1036
      delete_exp_file = 1;
1037
    }
1038
 
1039
  {
1040
    int quote;
1041
 
1042
    dyn_string_t step2 = dyn_string_new (dlltool_cmdline->length
1043
                                         + strlen (base_file_name)
1044
                                         + strlen (exp_file_name)
1045
                                         + 20);
1046
 
1047
    dyn_string_append_cstr (step2, "--base-file ");
1048
    quote = (strchr (base_file_name, ' ')
1049
             || strchr (base_file_name, '\t'));
1050
    dyn_string_append_cstr (step2,
1051
                       (quote) ? "\"" : "");
1052
    dyn_string_append_cstr (step2, base_file_name);
1053
    dyn_string_append_cstr (step2,
1054
                       (quote) ? "\" " : " ");
1055
 
1056
    dyn_string_append_cstr (step2, "--output-exp ");
1057
    quote = (strchr (exp_file_name, ' ')
1058
             || strchr (exp_file_name, '\t'));
1059
    dyn_string_append_cstr (step2,
1060
                       (quote) ? "\"" : "");
1061
    dyn_string_append_cstr (step2, exp_file_name);
1062
    dyn_string_append_cstr (step2,
1063
                       (quote) ? "\"" : "");
1064
 
1065
    if (dlltool_cmdline->length)
1066
      {
1067
        dyn_string_append_cstr (step2, " ");
1068
        dyn_string_append_cstr (step2, dlltool_cmdline->s);
1069
      }
1070
 
1071
    if (run (dlltool_name, step2->s))
1072
      cleanup_and_exit (1);
1073
 
1074
    dyn_string_delete (step2);
1075
  }
1076
 
1077
  /*
1078
   * Step 3. Call GCC/LD to again, adding the exp file this time.
1079
   * driver command line will look like the following:
1080
   *
1081
   *    % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
1082
   */
1083
 
1084
  {
1085
    int quote;
1086
 
1087
    dyn_string_t step3 = dyn_string_new (driver_cmdline->length
1088
                                         + strlen (exp_file_name)
1089
                                         + strlen (base_file_name)
1090
                                         + 20);
1091
    dyn_string_append_cstr (step3, "-Wl,--base-file,");
1092
    quote = (strchr (base_file_name, ' ')
1093
             || strchr (base_file_name, '\t'));
1094
    dyn_string_append_cstr (step3,
1095
                       (quote) ? "\"" : "");
1096
    dyn_string_append_cstr (step3, base_file_name);
1097
    dyn_string_append_cstr (step3,
1098
                       (quote) ? "\" " : " ");
1099
 
1100
    quote = (strchr (exp_file_name, ' ')
1101
             || strchr (exp_file_name, '\t'));
1102
    dyn_string_append_cstr (step3,
1103
                       (quote) ? "\"" : "");
1104
    dyn_string_append_cstr (step3, exp_file_name);
1105
    dyn_string_append_cstr (step3,
1106
                       (quote) ? "\"" : "");
1107
 
1108
    if (driver_cmdline->length)
1109
      {
1110
        dyn_string_append_cstr (step3, " ");
1111
        dyn_string_append_cstr (step3, driver_cmdline->s);
1112
      }
1113
 
1114
    if (run (driver_name, step3->s))
1115
      cleanup_and_exit (1);
1116
 
1117
    dyn_string_delete (step3);
1118
  }
1119
 
1120
 
1121
  /*
1122
   * Step 4. Run DLLTOOL again using the same command line.
1123
   */
1124
 
1125
  {
1126
    int quote;
1127
    dyn_string_t step4 = dyn_string_new (dlltool_cmdline->length
1128
                                         + strlen (base_file_name)
1129
                                         + strlen (exp_file_name)
1130
                                         + 20);
1131
 
1132
    dyn_string_append_cstr (step4, "--base-file ");
1133
    quote = (strchr (base_file_name, ' ')
1134
             || strchr (base_file_name, '\t'));
1135
    dyn_string_append_cstr (step4,
1136
                       (quote) ? "\"" : "");
1137
    dyn_string_append_cstr (step4, base_file_name);
1138
    dyn_string_append_cstr (step4,
1139
                       (quote) ? "\" " : " ");
1140
 
1141
    dyn_string_append_cstr (step4, "--output-exp ");
1142
    quote = (strchr (exp_file_name, ' ')
1143
             || strchr (exp_file_name, '\t'));
1144
    dyn_string_append_cstr (step4,
1145
                       (quote) ? "\"" : "");
1146
    dyn_string_append_cstr (step4, exp_file_name);
1147
    dyn_string_append_cstr (step4,
1148
                       (quote) ? "\"" : "");
1149
 
1150
    if (dlltool_cmdline->length)
1151
      {
1152
        dyn_string_append_cstr (step4, " ");
1153
        dyn_string_append_cstr (step4, dlltool_cmdline->s);
1154
      }
1155
 
1156
    if (output_lib_file_name)
1157
      {
1158
        dyn_string_append_cstr (step4, " --output-lib ");
1159
        dyn_string_append_cstr (step4, output_lib_file_name);
1160
      }
1161
 
1162
    if (run (dlltool_name, step4->s))
1163
      cleanup_and_exit (1);
1164
 
1165
    dyn_string_delete (step4);
1166
  }
1167
 
1168
 
1169
  /*
1170
   * Step 5. Link it all together and be done with it.
1171
   * driver command line will look like the following:
1172
   *
1173
   *    % gcc -Wl,--dll foo.exp [rest ...]
1174
   *
1175
   */
1176
 
1177
  {
1178
    int quote;
1179
 
1180
    dyn_string_t step5 = dyn_string_new (driver_cmdline->length
1181
                                         + strlen (exp_file_name)
1182
                                         + 20);
1183
    quote = (strchr (exp_file_name, ' ')
1184
             || strchr (exp_file_name, '\t'));
1185
    dyn_string_append_cstr (step5,
1186
                       (quote) ? "\"" : "");
1187
    dyn_string_append_cstr (step5, exp_file_name);
1188
    dyn_string_append_cstr (step5,
1189
                       (quote) ? "\"" : "");
1190
 
1191
    if (driver_cmdline->length)
1192
      {
1193
        dyn_string_append_cstr (step5, " ");
1194
        dyn_string_append_cstr (step5, driver_cmdline->s);
1195
      }
1196
 
1197
    if (run (driver_name, step5->s))
1198
      cleanup_and_exit (1);
1199
 
1200
    dyn_string_delete (step5);
1201
  }
1202
 
1203
  cleanup_and_exit (0);
1204
 
1205
  return 0;
1206
}

powered by: WebSVN 2.1.0

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