Fix .drectve spelling (was .drective) in several comments.
[deliverable/binutils-gdb.git] / binutils / dlltool.c
CommitLineData
765e60a9
SC
1/* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
fb257042 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
765e60a9
SC
19
20
21/*
22 This program allows you to build the files necessary to create
23 DLLs to run on a system which understands PE format image files.
24 (eg, Windows NT)
25
26 A DLL contains an export table which contains the information
27 which the runtime loader needs to tie up references from a
28 referencing program.
29
30 The export table is generated by this program by reading
31 in a .DEF file or scanning the .a and .o files which will be in the
199f5217 32 DLL. A .o file can contain information in special ".drectve" sections
765e60a9
SC
33 with export information.
34
35 A DEF file contains any number of the following commands:
36
37
38 NAME <name> [ , <base> ]
6f2d3212 39 The result is going to be <name>.EXE
765e60a9
SC
40
41 LIBRARY <name> [ , <base> ]
6f2d3212 42 The result is going to be <name>.DLL
765e60a9
SC
43
44 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
6f2d3212
SC
45 Declares name1 as an exported symbol from the
46 DLL, with optional ordinal number <integer>
765e60a9
SC
47
48 IMPORTS ( [ <name> = ] <name> . <name> ) *
6f2d3212 49 Ignored for compatibility
765e60a9
SC
50
51 DESCRIPTION <string>
6f2d3212 52 Puts <string> into output .exp file in the .rdata section
765e60a9
SC
53
54 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
6f2d3212 55 Generates --stack|--heap <number-reserve>,<number-commit>
199f5217 56 in the output .drectve section. The linker will
6f2d3212 57 see this and act upon it.
765e60a9
SC
58
59 [CODE|DATA] <attr>+
60 SECTIONS ( <sectionname> <attr>+ )*
6f2d3212
SC
61 <attr> = READ | WRITE | EXECUTE | SHARED
62 Generates --attr <sectionname> <attr> in the output
199f5217 63 .drectve section. The linker will see this and act
6f2d3212 64 upon it.
765e60a9
SC
65
66
199f5217 67 A -export:<name> in a .drectve section in an input .o or .a
765e60a9
SC
68 file to this program is equivalent to a EXPORTS <name>
69 in a .DEF file.
70
71
72
6f2d3212
SC
73 The program generates output files with the prefix supplied
74 on the command line, or in the def file, or taken from the first
75 supplied argument.
765e60a9 76
6f2d3212
SC
77 The .exp.s file contains the information necessary to export
78 the routines in the DLL. The .lib.s file contains the information
79 necessary to use the DLL's routines from a referencing program.
765e60a9
SC
80
81
82
6f2d3212 83 Example:
765e60a9 84
6f2d3212
SC
85 file1.c:
86 asm (".section .drectve");
87 asm (".ascii \"-export:adef\"");
765e60a9 88
6f2d3212
SC
89 adef(char *s)
90 {
91 printf("hello from the dll %s\n",s);
92 }
765e60a9 93
6f2d3212
SC
94 bdef(char *s)
95 {
96 printf("hello from the dll and the other entry point %s\n",s);
97 }
765e60a9 98
6f2d3212
SC
99 file2.c:
100 asm (".section .drectve");
101 asm (".ascii \"-export:cdef\"");
102 asm (".ascii \"-export:ddef\"");
103 cdef(char *s)
104 {
105 printf("hello from the dll %s\n",s);
106 }
765e60a9 107
6f2d3212
SC
108 ddef(char *s)
109 {
110 printf("hello from the dll and the other entry point %s\n",s);
111 }
765e60a9 112
6f2d3212
SC
113 printf()
114 {
115 return 9;
116 }
765e60a9 117
6f2d3212 118 main.c
765e60a9 119
6f2d3212
SC
120 main()
121 {
122 cdef();
123 }
765e60a9 124
6f2d3212 125 thedll.def
765e60a9 126
6f2d3212
SC
127 LIBRARY thedll
128 HEAPSIZE 0x40000, 0x2000
129 EXPORTS bdef @ 20
130 cdef @ 30 NONAME
765e60a9 131
6f2d3212
SC
132 SECTIONS donkey READ WRITE
133 aardvark EXECUTE
765e60a9
SC
134
135
6f2d3212 136 # compile up the parts of the dll
765e60a9 137
6f2d3212
SC
138 gcc -c file1.c
139 gcc -c file2.c
765e60a9 140
6f2d3212
SC
141 # put them in a library (you don't have to, you
142 # could name all the .os on the dlltool line)
765e60a9 143
6f2d3212
SC
144 ar qcv thedll.in file1.o file2.o
145 ranlib thedll.in
765e60a9 146
6f2d3212 147 # run this tool over the library and the def file
2757dc25 148 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
765e60a9 149
6f2d3212 150 # build the dll with the library with file1.o, file2.o and the export table
2757dc25 151 ld -o thedll.dll thedll.o thedll.in
765e60a9 152
6f2d3212
SC
153 # build the mainline
154 gcc -c themain.c
765e60a9 155
6f2d3212 156 # link the executable with the import library
2757dc25 157 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
765e60a9 158
6f2d3212 159 */
765e60a9 160
6f2d3212
SC
161#define PAGE_SIZE 4096
162#define PAGE_MASK (-PAGE_SIZE)
765e60a9
SC
163#include <stdio.h>
164#include <stdlib.h>
165#include <string.h>
166#include "getopt.h"
167#include "bfd.h"
2757dc25
SC
168#include <wait.h>
169
170char *ar_name = "ar";
171char *as_name = "as";
172char *ranlib_name = "ranlib";
fb257042 173
2757dc25
SC
174char *exp_name;
175char *imp_name;
176char *dll_name;
177
199f5217
DE
178int add_indirect = 0;
179
f88ebc68 180int dontdeltemps = 0;
fb257042 181
765e60a9
SC
182int yydebug;
183char *def_file;
2757dc25 184
765e60a9
SC
185char *program_name;
186char *strrchr ();
765e60a9
SC
187char *xmalloc ();
188char *strdup ();
189
190static int machine;
6f2d3212 191int suckunderscore;
00289839 192int killat;
6f2d3212
SC
193static int verbose;
194FILE *base_file;
765e60a9 195#ifdef DLLTOOL_ARM
6f2d3212 196static char *mname = "arm";
765e60a9
SC
197#endif
198
199#ifdef DLLTOOL_I386
6f2d3212 200static char *mname = "i386";
765e60a9 201#endif
6f2d3212 202#define PATHMAX 250 /* What's the right name for this ? */
765e60a9 203
6f2d3212 204char outfile[PATHMAX];
765e60a9 205struct mac
6f2d3212
SC
206 {
207 char *type;
208 char *how_byte;
209 char *how_short;
210 char *how_long;
211 char *how_asciz;
212 char *how_comment;
213 char *how_jump;
214 char *how_global;
215 char *how_space;
fb257042 216 char *how_align_short;
6f2d3212
SC
217 }
218mtable[]
219=
765e60a9 220{
6f2d3212 221 {
f88ebc68 222#define MARM 0
2757dc25 223 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",
6f2d3212
SC
224 }
225 ,
226 {
f88ebc68 227#define M386 1
2757dc25 228 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
6f2d3212
SC
229 }
230 ,
199f5217 231 0
6f2d3212 232};
765e60a9 233
2757dc25
SC
234
235char *rvaafter (machine)
236int machine;
237{
f88ebc68
SC
238 switch (machine)
239 {
240 case MARM:
241 return "";
242 case M386:
243 return "";
244 }
2757dc25
SC
245}
246
247char *rvabefore (machine)
248int machine;
249{
f88ebc68
SC
250 switch (machine)
251 {
252 case MARM:
253 return ".rva\t";
254 case M386:
255 return ".rva\t";
256 }
2757dc25 257}
199f5217
DE
258
259char *asm_prefix (machine)
260{
261 switch (machine)
262 {
263 case MARM:
264 return "";
265 case M386:
266 return "_";
267 }
268}
765e60a9
SC
269#define ASM_BYTE mtable[machine].how_byte
270#define ASM_SHORT mtable[machine].how_short
271#define ASM_LONG mtable[machine].how_long
272#define ASM_TEXT mtable[machine].how_asciz
273#define ASM_C mtable[machine].how_comment
274#define ASM_JUMP mtable[machine].how_jump
275#define ASM_GLOBAL mtable[machine].how_global
276#define ASM_SPACE mtable[machine].how_space
fb257042 277#define ASM_ALIGN_SHORT mtable[machine].how_align_short
2757dc25
SC
278#define ASM_RVA_BEFORE rvabefore(machine)
279#define ASM_RVA_AFTER rvaafter(machine)
199f5217 280#define ASM_PREFIX asm_prefix(machine)
765e60a9
SC
281static char **oav;
282
283int i;
284
285FILE *yyin; /* communications with flex */
286extern int linenumber;
287void
288process_def_file (name)
289 char *name;
290{
291 FILE *f = fopen (name, "r");
292 if (!f)
293 {
6f2d3212 294 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
765e60a9
SC
295 exit (1);
296 }
297
298 yyin = f;
299
300 yyparse ();
301}
302
303/**********************************************************************/
304
305/* Communications with the parser */
306
307
308typedef struct dlist
309{
310 char *text;
311 struct dlist *next;
6f2d3212
SC
312}
313dlist_type;
765e60a9
SC
314
315typedef struct export
6f2d3212
SC
316 {
317 char *name;
318 char *internal_name;
319 int ordinal;
320 int constant;
321 int noname;
322 struct export *next;
323 }
765e60a9
SC
324export_type;
325
326static char *d_name; /* Arg to NAME or LIBRARY */
327static int d_nfuncs; /* Number of functions exported */
328static int d_ord; /* Base ordinal index */
329static export_type *d_exports; /*list of exported functions */
6f2d3212
SC
330static dlist_type *d_list; /* Descriptions */
331static dlist_type *a_list; /* Stuff to go in directives */
765e60a9
SC
332
333static int d_is_dll;
334static int d_is_exe;
335
336yyerror ()
337{
6f2d3212
SC
338 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
339 program_name, def_file, linenumber);
765e60a9
SC
340}
341
342void
b990c244 343def_exports (name, internal_name, ordinal, noname, constant)
765e60a9 344 char *name;
b990c244 345 char *internal_name;
765e60a9
SC
346 int ordinal;
347 int noname;
348 int constant;
349{
350 struct export *p = (struct export *) xmalloc (sizeof (*p));
351
352 p->name = name;
b990c244 353 p->internal_name = internal_name ? internal_name : name;
765e60a9
SC
354 p->ordinal = ordinal;
355 p->constant = constant;
356 p->noname = noname;
357 p->next = d_exports;
358 d_exports = p;
359 d_nfuncs++;
765e60a9
SC
360}
361
6f2d3212 362
765e60a9
SC
363void
364def_name (name, base)
365 char *name;
366 int base;
367{
6f2d3212
SC
368 if (verbose)
369 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
765e60a9
SC
370 if (d_is_dll)
371 {
372 fprintf (stderr, "Can't have LIBRARY and NAME\n");
373 }
374 d_name = name;
765e60a9
SC
375 d_is_exe = 1;
376}
377
378void
379def_library (name, base)
380 char *name;
381 int base;
382{
6f2d3212
SC
383 if (verbose)
384 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
765e60a9
SC
385 if (d_is_exe)
386 {
6f2d3212 387 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
765e60a9
SC
388 }
389 d_name = name;
765e60a9
SC
390 d_is_dll = 1;
391}
392
393void
394def_description (desc)
395 char *desc;
396{
6f2d3212 397 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
398 d->text = strdup (desc);
399 d->next = d_list;
400 d_list = d;
401}
402
2757dc25 403void
6f2d3212
SC
404new_directive (dir)
405 char *dir;
765e60a9 406{
6f2d3212 407 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
408 d->text = strdup (dir);
409 d->next = a_list;
410 a_list = d;
411}
412
413void
414def_stacksize (reserve, commit)
415 int reserve;
416 int commit;
417{
418 char b[200];
6f2d3212
SC
419 if (commit > 0)
420 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
421 else
422 sprintf (b, "-stack 0x%x ", reserve);
423 new_directive (strdup (b));
765e60a9
SC
424}
425
426void
427def_heapsize (reserve, commit)
428 int reserve;
429 int commit;
430{
431 char b[200];
6f2d3212
SC
432 if (commit > 0)
433 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
434 else
435 sprintf (b, "-heap 0x%x ", reserve);
436 new_directive (strdup (b));
765e60a9
SC
437}
438
439
440void
441def_import (internal, module, entry)
442 char *internal;
443 char *module;
444 char *entry;
445{
6f2d3212
SC
446 if (verbose)
447 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
765e60a9
SC
448}
449
450void
451def_version (major, minor)
452{
453 printf ("VERSION %d.%d\n", major, minor);
454}
455
456
457void
458def_section (name, attr)
459 char *name;
460 int attr;
461{
462 char buf[200];
6f2d3212 463 char atts[5];
765e60a9
SC
464 char *d = atts;
465 if (attr & 1)
6f2d3212 466 *d++ = 'R';
765e60a9
SC
467
468 if (attr & 2)
469 *d++ = 'W';
470 if (attr & 4)
471 *d++ = 'X';
472 if (attr & 8)
473 *d++ = 'S';
474 *d++ = 0;
475 sprintf (buf, "-attr %s %s", name, atts);
6f2d3212 476 new_directive (strdup (buf));
765e60a9
SC
477}
478void
479def_code (attr)
480 int attr;
481{
482
6f2d3212 483 def_section ("CODE", attr);
765e60a9
SC
484}
485
486void
487def_data (attr)
488 int attr;
489{
6f2d3212 490 def_section ("DATA", attr);
765e60a9
SC
491}
492
493
494/**********************************************************************/
495
2757dc25
SC
496void
497run (what, args)
498 char *what;
499 char *args;
500{
501 char *s;
502 int pid;
503 int i;
504 char **argv;
505 extern char **environ;
506 if (verbose)
507 fprintf (stderr, "%s %s\n", what, args);
508
509 /* Count the args */
510 i = 0;
511 for (s = args; *s ; s++)
512 if (*s == ' ')
513 i++;
514 i++;
515 argv = alloca (sizeof (char *) * (i + 3));
516 i = 0;
517 argv[i++] = what;
518 s = args;
519 while (1) {
520 argv[i++] = s;
521 while (*s != ' ' && *s != 0)
522 s++;
523 if (*s == 0)
524 break;
525 *s++ = 0;
526 }
527 argv[i++] = 0;
528
529
530 pid = vfork ();
531 if (pid == 0)
532 {
533 execvp (what, argv);
534 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
535 exit (1);
536 }
537 else if (pid == -1)
538 {
539 extern int errno;
540 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
541 exit (1);
542 }
543 else
544 {
545 int status;
4828cdba 546 waitpid (pid, &status, 0);
2757dc25
SC
547 if (status)
548 {
549 if (WIFSIGNALED (status))
550 {
551 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
552 program_name, what, args, WTERMSIG (status));
553 exit (1);
554 }
555
556 if (WIFEXITED (status))
557 {
558 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
559 program_name, what, args, WEXITSTATUS (status));
560 exit (1);
561 }
562 }
563 }
564}
565
6f2d3212 566/* read in and block out the base relocations */
2757dc25 567static void
6f2d3212
SC
568basenames (abfd)
569 bfd *abfd;
570{
571
572
573
574
575}
576
765e60a9
SC
577void
578scan_open_obj_file (abfd)
579 bfd *abfd;
580{
199f5217 581 /* Look for .drectve's */
765e60a9
SC
582 asection *s = bfd_get_section_by_name (abfd, ".drectve");
583 if (s)
584 {
585 int size = bfd_get_section_size_before_reloc (s);
586 char *buf = xmalloc (size);
587 char *p;
588 char *e;
589 bfd_get_section_contents (abfd, s, buf, 0, size);
6f2d3212
SC
590 if (verbose)
591 fprintf (stderr, "%s: Sucking in info from %s\n",
592 program_name,
593 bfd_get_filename (abfd));
765e60a9
SC
594
595 /* Search for -export: strings */
596 p = buf;
597 e = buf + size;
598 while (p < e)
599 {
600 if (p[0] == '-'
601 && strncmp (p, "-export:", 8) == 0)
602 {
603 char *name;
604 char *c;
605 p += 8;
606 name = p;
607 while (*p != ' ' && *p != '-' && p < e)
608 p++;
609 c = xmalloc (p - name + 1);
610 memcpy (c, name, p - name);
611 c[p - name] = 0;
612 def_exports (c, 0, -1, 0);
613 }
614 else
615 p++;
616 }
617 free (buf);
618 }
6f2d3212
SC
619
620 basenames (abfd);
621
622 if (verbose)
623 fprintf (stderr, "%s: Done readin\n",
624 program_name);
625
765e60a9
SC
626}
627
628
629void
630scan_obj_file (filename)
631 char *filename;
632{
633 bfd *f = bfd_openr (filename, 0);
634
635 if (!f)
636 {
2757dc25
SC
637 fprintf (stderr, "%s: Unable to open object file %s\n",
638 program_name,
6f2d3212 639 filename);
765e60a9
SC
640 exit (1);
641 }
642 if (bfd_check_format (f, bfd_archive))
643 {
644 bfd *arfile = bfd_openr_next_archived_file (f, 0);
645 while (arfile)
646 {
647 if (bfd_check_format (arfile, bfd_object))
648 scan_open_obj_file (arfile);
649 bfd_close (arfile);
650 arfile = bfd_openr_next_archived_file (f, arfile);
651 }
652 }
653
654 if (bfd_check_format (f, bfd_object))
655 {
656 scan_open_obj_file (f);
657 }
658
659 bfd_close (f);
660}
661
662/**********************************************************************/
663
664
665/* return the bit of the name before the last . */
666
667static
668char *
669prefix (name)
670 char *name;
671{
672 char *res = strdup (name);
673 char *p = strrchr (res, '.');
674 if (p)
675 *p = 0;
676 return res;
677}
678
679void
680dump_def_info (f)
6f2d3212 681 FILE *f;
765e60a9
SC
682{
683 int i;
684 export_type *exp;
6f2d3212
SC
685 fprintf (f, "%s ", ASM_C);
686 for (i = 0; oav[i]; i++)
687 fprintf (f, "%s ", oav[i]);
688 fprintf (f, "\n");
765e60a9
SC
689 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
690 {
b990c244 691 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
765e60a9
SC
692 ASM_C,
693 i,
6f2d3212
SC
694 exp->name,
695 exp->internal_name,
b990c244 696 exp->ordinal,
765e60a9
SC
697 exp->noname ? "NONAME " : "",
698 exp->constant ? "CONSTANT" : "");
699 }
700}
701/* Generate the .exp file */
702
6f2d3212
SC
703int
704sfunc (a, b)
705 long *a;
706 long *b;
707{
708 return *a - *b;
709}
710
fb257042 711
fb257042 712
2757dc25 713static void
6f2d3212
SC
714flush_page (f, need, page_addr, on_page)
715 FILE *f;
716 long *need;
717 long page_addr;
718 int on_page;
719{
720 int i;
721 /* Flush this page */
4828cdba
DE
722 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
723 ASM_LONG,
ee473c97 724 page_addr,
6f2d3212
SC
725 ASM_C);
726 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
727 ASM_LONG,
728 (on_page * 2) + (on_page & 1) * 2 + 8,
729 ASM_C);
730 for (i = 0; i < on_page; i++)
731 {
732 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
733 }
734 /* And padding */
735 if (on_page & 1)
736 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
737
738}
739
765e60a9
SC
740
741void
742gen_exp_file ()
743{
744 FILE *f;
765e60a9
SC
745 int i;
746 export_type *exp;
747 dlist_type *dl;
6f2d3212
SC
748 int had_noname = 0;
749
2757dc25 750 sprintf (outfile, "t%s", exp_name);
6f2d3212
SC
751
752 if (verbose)
753 fprintf (stderr, "%s: Generate exp file %s\n",
2757dc25 754 program_name, exp_name);
765e60a9
SC
755
756 f = fopen (outfile, "w");
757 if (!f)
758 {
6f2d3212 759 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
765e60a9
SC
760 exit (1);
761 }
6f2d3212
SC
762 if (verbose)
763 {
764 fprintf (stderr, "%s: Opened file %s\n",
765 program_name, outfile);
766 }
767
765e60a9 768 dump_def_info (f);
f88ebc68
SC
769 if (d_exports) {
770 fprintf (f, "\t.section .edata\n\n");
771 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
199f5217 772 fprintf (f, "\t%s 0 %s Time and date\n", ASM_LONG, ASM_C);
f88ebc68 773 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
199f5217 774 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
f88ebc68
SC
775 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
776 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
777 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
778 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
779 fprintf (f, "\t%s always the number of names field\n", ASM_C);
780 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
781 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
782 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
783 fprintf (f, "\t%sanames%s %s Address of names\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
784 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
785
786 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
787
788 fprintf (f, "afuncs:\n");
789 i = d_ord;
790 for (exp = d_exports; exp; exp = exp->next)
791 {
6f2d3212 792#if 0
f88ebc68
SC
793 /* This seems necessary in the doc, but in real
794 life it's not used.. */
795 if (exp->ordinal != i)
796 {
797 fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
798 (exp->ordinal - i) * 4,
799 i, exp->ordinal - 1);
800 i = exp->ordinal;
801 }
6f2d3212 802#endif
199f5217
DE
803 fprintf (f, "\t%s%s%s%s\t%s %d\n",ASM_RVA_BEFORE,
804 ASM_PREFIX,
f88ebc68
SC
805 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
806 i++;
807 }
808
809
810 fprintf (f, "anames:\n");
811 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
812 {
813 if (exp->noname)
814 {
815 had_noname = 1;
816 fprintf (f, "\t%s nNoname\n", ASM_LONG, ASM_C);
817 }
818 else
819 {
820 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, i, ASM_RVA_AFTER);
821 }
822 }
823
824 fprintf (f, "anords:\n");
825 for (exp = d_exports; exp; exp = exp->next)
826 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
827
828 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
6f2d3212 829 if (exp->noname)
f88ebc68 830 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
6f2d3212 831 else
f88ebc68
SC
832 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
833
834 if (had_noname)
835 fprintf (f, "nNoname: %s \"__noname__\"\n", ASM_TEXT);
836
837 if (a_list)
838 {
839 fprintf (f, "\t.section .drectve\n");
840 for (dl = a_list; dl; dl = dl->next)
841 {
842 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
843 }
844 }
845 if (d_list)
846 {
847 fprintf (f, "\t.section .rdata\n");
848 for (dl = d_list; dl; dl = dl->next)
849 {
850 char *p;
851 int l;
852 /* We dont output as ascii 'cause there can
853 be quote characters in the string */
854
855 l = 0;
856 for (p = dl->text; *p; p++)
857 {
858 if (l == 0)
859 fprintf (f, "\t%s\t", ASM_BYTE);
860 else
861 fprintf (f, ",");
862 fprintf (f, "%d", *p);
863 if (p[1] == 0)
864 {
865 fprintf (f, ",0\n");
866 break;
867 }
868 if (++l == 10)
869 {
870 fprintf (f, "\n");
871 l = 0;
872 }
873 }
874 }
875 }
f88ebc68 876 }
199f5217
DE
877
878
879 /* Add to the output file a way of getting to the exported names
880 without using the import library. */
881 if (add_indirect)
882 {
883 fprintf (f,"\t.section\t.rdata\n");
884 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
885 if (!exp->noname) {
886 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
887 fprintf (f, "__imp_%s:\n", exp->name);
888 fprintf (f,"\t%s\t%s\n", ASM_LONG, exp->name);
889 }
890 }
891
6f2d3212
SC
892 /* Dump the reloc section if a base file is provided */
893 if (base_file)
894 {
895 int addr;
896 long need[PAGE_SIZE];
897 long page_addr;
898 int numbytes;
899 int num_entries;
900 long *copy;
901 int j;
902 int on_page;
f88ebc68
SC
903 fprintf (f,"\t.section\t.init\n");
904 fprintf (f,"lab:\n");
199f5217 905
6f2d3212
SC
906 fseek (base_file, 0, SEEK_END);
907 numbytes = ftell (base_file);
908 fseek (base_file, 0, SEEK_SET);
909 copy = malloc (numbytes);
910 fread (copy, 1, numbytes, base_file);
911 num_entries = numbytes / sizeof (long);
912
199f5217
DE
913 if (num_entries) {
914 fprintf (f, "\t.section\t.reloc\n");
915 qsort (copy, num_entries, sizeof (long), sfunc);
6f2d3212 916
199f5217
DE
917 addr = copy[0];
918 page_addr = addr & PAGE_MASK; /* work out the page addr */
919 on_page = 0;
920 for (j = 0; j < num_entries; j++)
921 {
922 addr = copy[j];
923 if ((addr & PAGE_MASK) != page_addr)
924 {
925 flush_page (f, need, page_addr, on_page);
926 on_page = 0;
927 page_addr = addr & PAGE_MASK;
928 }
929 need[on_page++] = addr;
930 }
931 flush_page (f, need, page_addr, on_page);
ee473c97 932
199f5217
DE
933 fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
934 }
765e60a9 935 }
6f2d3212 936
765e60a9 937 fclose (f);
2757dc25
SC
938
939 /* assemble the file */
940 sprintf (outfile,"-o %s t%s", exp_name, exp_name);
941 run (as_name, outfile);
f88ebc68 942 if (dontdeltemps==0)
2757dc25
SC
943 {
944 sprintf (outfile,"t%s", exp_name);
945 unlink (outfile);
946 }
765e60a9
SC
947}
948
6f2d3212
SC
949static char *
950xlate (char *name)
951{
00289839 952
6f2d3212
SC
953 if (!suckunderscore)
954 return name;
955
956 if (name[0] == '_')
957 name++;
2757dc25
SC
958 if (killat)
959 {
960 char *p;
961 p = strchr (name, '@');
962 if (p)
963 *p = 0;
964 }
6f2d3212
SC
965 return name;
966}
967
765e60a9 968/**********************************************************************/
199f5217 969static void
765e60a9
SC
970gen_lib_file ()
971{
765e60a9 972 int i;
2757dc25 973 int sol;
765e60a9
SC
974 FILE *f;
975 export_type *exp;
2757dc25
SC
976 char *output_filename;
977 char prefix[PATHMAX];
765e60a9 978
2757dc25
SC
979 sprintf (outfile, "%s", imp_name);
980 output_filename = strdup (outfile);
765e60a9 981
2757dc25 982 unlink (output_filename);
765e60a9 983
2757dc25
SC
984 strcpy (prefix, "d");
985 sprintf (outfile, "%sh.s", prefix);
765e60a9 986
2757dc25 987 f = fopen (outfile, "w");
765e60a9
SC
988
989 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
990 fprintf (f, "\t.section .idata$2\n");
2757dc25
SC
991
992 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name);
993 fprintf (f, "__%s_head:\n", imp_name);
994
f88ebc68 995 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
fb257042 996 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
199f5217 997
f88ebc68
SC
998 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
999 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
199f5217 1000 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
765e60a9 1001 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
f88ebc68 1002 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
fb257042 1003 ASM_RVA_BEFORE,
2757dc25 1004 imp_name,
fb257042
SC
1005 ASM_RVA_AFTER,
1006 ASM_C);
f88ebc68 1007 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
fb257042
SC
1008 ASM_RVA_BEFORE,
1009 ASM_RVA_AFTER, ASM_C);
765e60a9 1010
6f2d3212 1011 fprintf (f, "%sStuff for compatibility\n", ASM_C);
6f2d3212
SC
1012 fprintf (f, "\t.section\t.idata$5\n");
1013 fprintf (f, "\t%s\t0\n", ASM_LONG);
2757dc25 1014 fprintf (f, "fthunk:\n");
6f2d3212
SC
1015 fprintf (f, "\t.section\t.idata$4\n");
1016 fprintf (f, "\t%s\t0\n", ASM_LONG);
2757dc25
SC
1017 fprintf (f, "\t.section .idata$4\n");
1018 fprintf (f, "hname:\n");
1019
1020 fclose (f);
1021
1022 sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
1023 run (as_name, outfile);
6f2d3212 1024
765e60a9
SC
1025 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1026 {
2757dc25
SC
1027 sprintf (outfile, "%ss%d.s", prefix, i);
1028 f = fopen (outfile, "w");
2757dc25 1029 fprintf (f, "\t.text\n");
199f5217 1030 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
f88ebc68 1031 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
199f5217
DE
1032 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1033 exp->name, ASM_JUMP, exp->name);
2757dc25 1034
f88ebc68 1035 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
2757dc25 1036 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name);
2757dc25
SC
1037 fprintf (f, "\t.section .idata$5\n");
1038
1039
6f2d3212 1040 fprintf (f, "__imp_%s:\n", exp->name);
f88ebc68 1041 fprintf (f, "\t%sID%d%s\n",
fb257042
SC
1042 ASM_RVA_BEFORE,
1043 i,
1044 ASM_RVA_AFTER);
2757dc25
SC
1045
1046 fprintf (f, "\n%s Hint name array\n", ASM_C);
1047 fprintf (f, "\t.section .idata$4\n");
f88ebc68 1048 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
2757dc25
SC
1049 i,
1050 ASM_RVA_AFTER);
1051
1052 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
1053 fprintf (f, "\t.section .idata$6\n");
1054
1055 fprintf (f, "\t%s\n", ASM_ALIGN_SHORT);
1056 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
1057 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1058 fclose (f);
1059
1060
1061 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1062 run (as_name, outfile);
765e60a9 1063 }
2757dc25
SC
1064
1065 sprintf (outfile, "%st.s", prefix);
1066 f = fopen (outfile, "w");
56297cc6 1067 fprintf (f, "\t.section .idata$7\n");
2757dc25 1068 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name);
2757dc25
SC
1069 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1070 imp_name, ASM_TEXT, dll_name);
1071
765e60a9 1072
765e60a9 1073 fprintf (f, "\t.section .idata$4\n");
2757dc25
SC
1074 fprintf (f, "\t%s\t0\n", ASM_LONG);
1075
1076 fprintf (f, "\t.section .idata$5\n");
1077 fprintf (f, "\t%s\t0\n", ASM_LONG);
1078 fclose (f);
1079
1080 sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1081 run (as_name, outfile);
1082
1083 /* Now stick them all into the archive */
1084
1085
1086 sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1087 run (ar_name, outfile);
1088
1089 /* Do the rest in groups of however many fit into a command line */
1090 sol = 0;
765e60a9
SC
1091 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1092 {
2757dc25
SC
1093 if (sol == 0)
1094 {
1095 sol = sprintf (outfile, "crs %s", output_filename);
1096 }
1097
1098 sol += sprintf (outfile + sol, " %ss%d.o", prefix, i);
1099
1100 if (sol >100)
1101 {
1102 run (ar_name, outfile);
1103 sol = 0;
1104 }
1105
765e60a9 1106 }
2757dc25
SC
1107 if (sol)
1108 run (ar_name, outfile);
765e60a9 1109
2757dc25 1110 /* Delete all the temp files */
765e60a9 1111
f88ebc68 1112 if (dontdeltemps == 0)
2757dc25
SC
1113 {
1114 sprintf (outfile, "%sh.o", prefix);
1115 unlink (outfile);
1116 sprintf (outfile, "%sh.s", prefix);
1117 unlink (outfile);
1118 sprintf (outfile, "%st.o", prefix);
1119 unlink (outfile);
1120 sprintf (outfile, "%st.s", prefix);
1121 unlink (outfile);
1122 }
f88ebc68 1123
199f5217
DE
1124 if (dontdeltemps < 2)
1125 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1126 {
1127 sprintf (outfile, "%ss%d.o", prefix, i);
1128 unlink (outfile);
1129 sprintf (outfile, "%ss%d.s", prefix, i);
1130 unlink (outfile);
1131 }
2757dc25 1132
765e60a9
SC
1133}
1134/**********************************************************************/
1135
1136/* Run through the information gathered from the .o files and the
1137 .def file and work out the best stuff */
1138int
1139pfunc (a, b)
1140 void *a;
1141 void *b;
1142{
1143 export_type *ap = *(export_type **) a;
1144 export_type *bp = *(export_type **) b;
1145 if (ap->ordinal == bp->ordinal)
1146 return 0;
1147
1148 /* unset ordinals go to the bottom */
1149 if (ap->ordinal == -1)
1150 return 1;
1151 if (bp->ordinal == -1)
1152 return -1;
1153 return (ap->ordinal - bp->ordinal);
1154}
1155
1156
1157int
1158nfunc (a, b)
1159 void *a;
1160 void *b;
1161{
1162 export_type *ap = *(export_type **) a;
1163 export_type *bp = *(export_type **) b;
1164
1165 return (strcmp (ap->name, bp->name));
1166}
1167
1168static
1169void
1170remove_null_names (ptr)
1171 export_type **ptr;
1172{
1173 int src;
1174 int dst;
1175 for (dst = src = 0; src < d_nfuncs; src++)
1176 {
1177 if (ptr[src])
1178 {
1179 ptr[dst] = ptr[src];
1180 dst++;
1181 }
1182 }
1183 d_nfuncs = dst;
1184}
1185
1186static void
1187dtab (ptr)
1188 export_type **ptr;
1189{
1190#ifdef SACDEBUG
1191 int i;
1192 for (i = 0; i < d_nfuncs; i++)
1193 {
1194 if (ptr[i])
1195 {
1196 printf ("%d %s @ %d %s%s\n",
1197 i, ptr[i]->name, ptr[i]->ordinal,
1198 ptr[i]->noname ? "NONAME " : "",
1199 ptr[i]->constant ? "CONSTANT" : "");
1200 }
1201 else
1202 printf ("empty\n");
1203 }
1204#endif
1205}
1206
1207static void
1208process_duplicates (d_export_vec)
1209 export_type **d_export_vec;
1210{
1211 int more = 1;
1212
1213 while (more)
1214 {
1215 more = 0;
1216 /* Remove duplicates */
1217 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1218
1219 dtab (d_export_vec);
1220 for (i = 0; i < d_nfuncs - 1; i++)
1221 {
1222 if (strcmp (d_export_vec[i]->name,
1223 d_export_vec[i + 1]->name) == 0)
1224 {
1225
1226 export_type *a = d_export_vec[i];
1227 export_type *b = d_export_vec[i + 1];
1228
1229 more = 1;
6f2d3212
SC
1230 if (verbose)
1231 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1232 a->name,
1233 a->ordinal,
1234 b->ordinal);
765e60a9
SC
1235 if (a->ordinal != -1
1236 && b->ordinal != -1)
1237 {
1238
1239 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1240 a->name);
1241 exit (1);
1242 }
1243 /* Merge attributes */
1244 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1245 b->constant |= a->constant;
1246 b->noname |= a->noname;
1247 d_export_vec[i] = 0;
1248 }
1249
1250 dtab (d_export_vec);
1251 remove_null_names (d_export_vec);
1252 dtab (d_export_vec);
1253 }
1254 }
1255}
1256
1257static void
1258fill_ordinals (d_export_vec)
1259 export_type **d_export_vec;
1260{
1261 int lowest = 0;
6f2d3212
SC
1262 int unset = 0;
1263 char *ptr;
765e60a9
SC
1264 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1265
6f2d3212
SC
1266 /* fill in the unset ordinals with ones from our range */
1267
1268 ptr = (char *) malloc (65536);
1269
1270 memset (ptr, 65536, 0);
1271
1272 /* Mark in our large vector all the numbers that are taken */
765e60a9
SC
1273 for (i = 0; i < d_nfuncs; i++)
1274 {
6f2d3212 1275 if (d_export_vec[i]->ordinal != -1)
765e60a9 1276 {
6f2d3212
SC
1277 ptr[d_export_vec[i]->ordinal] = 1;
1278 if (lowest == 0)
1279 lowest = d_export_vec[i]->ordinal;
765e60a9 1280 }
6f2d3212
SC
1281 }
1282
1283 for (i = 0; i < d_nfuncs; i++)
1284 {
1285 if (d_export_vec[i]->ordinal == -1)
765e60a9 1286 {
6f2d3212
SC
1287 int j;
1288 for (j = lowest; j < 65536; j++)
1289 if (ptr[j] == 0)
1290 {
1291 ptr[j] = 1;
1292 d_export_vec[i]->ordinal = j;
1293 goto done;
1294 }
1295
1296 for (j = 1; j < lowest; j++)
1297 if (ptr[j] == 0)
1298 {
1299 ptr[j] = 1;
1300 d_export_vec[i]->ordinal = j;
1301 goto done;
1302 }
1303 done:;
1304
765e60a9
SC
1305 }
1306 }
1307
6f2d3212
SC
1308 free (ptr);
1309
1310 /* And resort */
1311
1312 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1313
765e60a9
SC
1314 /* Work out the lowest ordinal number */
1315 if (d_export_vec[0])
1316 d_ord = d_export_vec[0]->ordinal;
1317}
1318void
1319mangle_defs ()
1320{
1321 /* First work out the minimum ordinal chosen */
1322
1323 export_type *exp;
1324 int lowest = 0;
1325 int i;
1326 export_type **d_export_vec
1327 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1328
1329 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1330 {
1331 d_export_vec[i] = exp;
1332 }
1333
1334 process_duplicates (d_export_vec);
1335 fill_ordinals (d_export_vec);
1336
1337 /* Put back the list in the new order */
1338 d_exports = 0;
1339 for (i = d_nfuncs - 1; i >= 0; i--)
1340 {
1341 d_export_vec[i]->next = d_exports;
1342 d_exports = d_export_vec[i];
1343 }
1344}
1345
1346
2757dc25
SC
1347
1348 /* Work out exec prefix from the name of this file */
1349void
1350workout_prefix ()
1351{
1352 char *ps = 0;
1353 char *s = 0;
1354 char *p;
1355 /* See if we're running in a devo tree */
1356 for (p = program_name; *p; p++)
1357 {
1358 if (*p == '/' || *p == '\\')
1359 {
1360 ps = s;
1361 s = p;
1362 }
1363 }
1364
1365 if (ps && strncmp (ps, "/binutils", 9) == 0)
1366 {
1367 /* running in the binutils directory, the other
1368 executables will be surrounding it in the usual places. */
1369 int len = ps - program_name;
1370 ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1371 ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1372 as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1373
f88ebc68
SC
1374 memcpy (ar_name, program_name, len);
1375 strcpy (ar_name + len, "/binutils/ar");
1376 memcpy (ranlib_name, program_name, len);
1377 strcpy (ranlib_name + len, "/binutils/ranlib");
1378 memcpy (as_name, program_name, len);
1379 strcpy (as_name + len, "/gas/as.new");
2757dc25
SC
1380 }
1381 else
1382 {
1383 /* Otherwise chop off any prefix and use it for the rest of the progs,
1384 so i386-win32-dll generates i386-win32-ranlib etc etc */
1385
1386 for (p = program_name; *p; p++)
1387 {
1388 if (strncmp (p, "dlltool", 7) == 0)
1389 {
1390 int len = p - program_name;
1391 ar_name = xmalloc (len + strlen ("ar") +1);
1392 ranlib_name = xmalloc (len + strlen ("ranlib")+1);
1393 as_name = xmalloc (len + strlen ("as")+1);
1394
4828cdba
DE
1395 memcpy (ar_name, program_name, len);
1396 strcpy (ar_name + len, "ar");
1397 memcpy (ranlib_name, program_name, len);
1398 strcpy (ranlib_name + len, "ranlib");
1399 memcpy (as_name, program_name, len);
1400 strcpy (as_name + len, "as");
2757dc25
SC
1401 }
1402 }
1403 }
1404}
1405
1406
765e60a9
SC
1407/**********************************************************************/
1408
1409void
1410usage (file, status)
1411 FILE *file;
1412 int status;
1413{
6f2d3212 1414 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
f88ebc68
SC
1415 fprintf (file, " --machine <machine>\n");
1416 fprintf (file, " --output-exp <outname> Generate export file.\n");
1417 fprintf (file, " --output-lib <outname> Generate input library.\n");
199f5217 1418 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
f88ebc68
SC
1419 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1420 fprintf (file, " --def <deffile> Name input .def file\n");
1421 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1422 fprintf (file, " -v Verbose\n");
1423 fprintf (file, " -u Remove leading underscore from .lib\n");
1424 fprintf (file, " -k Kill @<n> from exported names\n");
1425 fprintf (file, " --nodelete Keep temp files.\n");
765e60a9
SC
1426 exit (status);
1427}
1428
1429static struct option long_options[] =
1430{
2757dc25
SC
1431 {"nodelete", no_argument, NULL,'n'},
1432 {"dllname", required_argument, NULL,'D'},
1433 {"output-exp", required_argument, NULL, 'e'},
1434 {"output-lib", required_argument, NULL, 'l'},
765e60a9 1435 {"def", required_argument, NULL, 'd'},
6f2d3212 1436 {"underscore", no_argument, NULL, 'u'},
00289839 1437 {"killat", no_argument, NULL, 'k'},
765e60a9
SC
1438 {"help", no_argument, NULL, 'h'},
1439 {"machine", required_argument, NULL, 'm'},
199f5217 1440 {"add-indirect", no_argument, NULL, 'a'},
6f2d3212 1441 {"base-file", required_argument, NULL, 'b'},
765e60a9
SC
1442 0
1443};
1444
2757dc25
SC
1445
1446
765e60a9
SC
1447int
1448main (ac, av)
1449 int ac;
1450 char **av;
1451{
1452 int c;
1453 char *firstarg = 0;
1454 program_name = av[0];
1455 oav = av;
6f2d3212 1456
199f5217 1457 while ((c = getopt_long (ac, av, "aD:l:e:nkvbuh?m:yd:", long_options, 0)) != EOF)
765e60a9
SC
1458 {
1459 switch (c)
1460 {
199f5217
DE
1461 case 'a':
1462 add_indirect = 1;
1463 break;
2757dc25
SC
1464 case 'D':
1465 dll_name = optarg;
1466 break;
1467 case 'l':
1468 imp_name = optarg;
1469 break;
1470 case 'e':
1471 exp_name = optarg;
1472 break;
765e60a9
SC
1473 case 'h':
1474 case '?':
6f2d3212 1475 usage (stderr, 0);
765e60a9
SC
1476 break;
1477 case 'm':
1478 mname = optarg;
1479 break;
6f2d3212
SC
1480 case 'v':
1481 verbose = 1;
1482 break;
2757dc25 1483 case 'y':
765e60a9
SC
1484 yydebug = 1;
1485 break;
6f2d3212
SC
1486 case 'u':
1487 suckunderscore = 1;
1488 break;
00289839
SC
1489 case 'k':
1490 killat = 1;
1491 break;
765e60a9
SC
1492 case 'd':
1493 def_file = optarg;
1494 break;
2757dc25 1495 case 'n':
f88ebc68 1496 dontdeltemps++;
2757dc25 1497 break;
6f2d3212
SC
1498 case 'b':
1499 base_file = fopen (optarg, "r");
1500 if (!base_file)
1501 {
1502 fprintf (stderr, "%s: Unable to open base-file %s\n",
1503 av[0],
1504 optarg);
1505 exit (1);
1506 }
1507 break;
765e60a9
SC
1508 default:
1509 usage (stderr, 1);
1510 }
1511 }
1512
1513
6f2d3212 1514 for (i = 0; mtable[i].type; i++)
765e60a9
SC
1515 {
1516 if (strcmp (mtable[i].type, mname) == 0)
1517 break;
1518 }
1519
6f2d3212 1520 if (!mtable[i].type)
765e60a9 1521 {
6f2d3212
SC
1522 fprintf (stderr, "Machine not supported\n");
1523 exit (1);
765e60a9
SC
1524 }
1525 machine = i;
1526
1527
2757dc25
SC
1528 if (!dll_name && exp_name)
1529 {
1530 char len = strlen (exp_name) + 5;
1531 dll_name = xmalloc (len);
1532 strcpy (dll_name, exp_name);
1533 strcat (dll_name, ".dll");
1534 }
1535 workout_prefix ();
1536
1537
765e60a9
SC
1538 if (def_file)
1539 {
765e60a9
SC
1540 process_def_file (def_file);
1541 }
1542 while (optind < ac)
1543 {
1544 if (!firstarg)
1545 firstarg = av[optind];
1546 scan_obj_file (av[optind]);
1547 optind++;
1548 }
1549
765e60a9
SC
1550
1551 mangle_defs ();
6f2d3212 1552
2757dc25
SC
1553 if (exp_name)
1554 gen_exp_file ();
1555 if (imp_name)
1556 gen_lib_file ();
6f2d3212 1557
765e60a9
SC
1558 return 0;
1559}
2757dc25 1560
This page took 0.154299 seconds and 4 git commands to generate.