69fe91f23e43f2fd9b62b7a640ef0c84de33cc7f
[deliverable/binutils-gdb.git] / binutils / dlltool.c
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
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
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
32 DLL. A .o file can contain information in special ".drective" sections
33 with export information.
34
35 A DEF file contains any number of the following commands:
36
37
38 NAME <name> [ , <base> ]
39 The result is going to be <name>.EXE
40
41 LIBRARY <name> [ , <base> ]
42 The result is going to be <name>.DLL
43
44 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
45 Declares name1 as an exported symbol from the
46 DLL, with optional ordinal number <integer>
47
48 IMPORTS ( [ <name> = ] <name> . <name> ) *
49 Ignored for compatibility
50
51 DESCRIPTION <string>
52 Puts <string> into output .exp file in the .rdata section
53
54 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
55 Generates --stack|--heap <number-reserve>,<number-commit>
56 in the output .drective section. The linker will
57 see this and act upon it.
58
59 [CODE|DATA] <attr>+
60 SECTIONS ( <sectionname> <attr>+ )*
61 <attr> = READ | WRITE | EXECUTE | SHARED
62 Generates --attr <sectionname> <attr> in the output
63 .drective section. The linker will see this and act
64 upon it.
65
66
67 A -export:<name> in a .drective section in an input .o or .a
68 file to this program is equivalent to a EXPORTS <name>
69 in a .DEF file.
70
71
72
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.
76
77 The output files are <prefix>.exp.s and <prefix>.lib.s
78
79 The .exp.s file contains the information necessary to export
80 the routines in the DLL. The .lib.s file contains the information
81 necessary to use the DLL's routines from a referencing program.
82
83
84
85 Example:
86
87 file1.c:
88 asm (".section .drectve");
89 asm (".ascii \"-export:adef\"");
90
91 adef(char *s)
92 {
93 printf("hello from the dll %s\n",s);
94 }
95
96 bdef(char *s)
97 {
98 printf("hello from the dll and the other entry point %s\n",s);
99 }
100
101 file2.c:
102 asm (".section .drectve");
103 asm (".ascii \"-export:cdef\"");
104 asm (".ascii \"-export:ddef\"");
105 cdef(char *s)
106 {
107 printf("hello from the dll %s\n",s);
108 }
109
110 ddef(char *s)
111 {
112 printf("hello from the dll and the other entry point %s\n",s);
113 }
114
115 printf()
116 {
117 return 9;
118 }
119
120 main.c
121
122 main()
123 {
124 cdef();
125 }
126
127 thedll.def
128
129 LIBRARY thedll
130 HEAPSIZE 0x40000, 0x2000
131 EXPORTS bdef @ 20
132 cdef @ 30 NONAME
133
134 SECTIONS donkey READ WRITE
135 aardvark EXECUTE
136
137
138 # compile up the parts of the dll
139
140 gcc -c file1.c
141 gcc -c file2.c
142
143 # put them in a library (you don't have to, you
144 # could name all the .os on the dlltool line)
145
146 ar qcv thedll.in file1.o file2.o
147 ranlib thedll.in
148
149 # run this tool over the library and the def file
150 ./dlltool -o thedll -d thedll.def thedll.in
151
152 # build the export table for the dll
153 as -o thedll.exp thedll.exp.s
154 # build the dll with the library with file1.o, file2.o and the export table
155 ld -o thedll.dll thedll.exp thedll.in
156
157 # build the import table for the executable
158 as -o thedll.lib thedll.lib.s
159
160 # build the mainline
161 gcc -c themain.c
162
163 # link the executable with the import library
164 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.lib
165
166
167 */
168
169 #include <stdio.h>
170 #include <stdlib.h>
171 #include <string.h>
172 #include "getopt.h"
173 #include "bfd.h"
174 int yydebug;
175 char *def_file;
176 char *program_name;
177 char *strrchr ();
178 char *outfile_prefix;
179 char *xmalloc ();
180 char *strdup ();
181
182 static int machine;
183
184 #ifdef DLLTOOL_ARM
185 static char *mname = "arm";
186 #endif
187
188 #ifdef DLLTOOL_I386
189 static char *mname = "i386";
190 #endif
191
192 struct mac
193 {
194 char *type;
195 char *how_byte;
196 char *how_short;
197 char *how_long;
198 char *how_asciz;
199 char *how_comment;
200 char *how_jump;
201 char *how_global;
202 char *how_space;
203 } mtable[]
204 = {{"arm",".byte",".short",".long",".asciz","@","bl",".global",".space"},
205 {"i386",".byte",".short",".long",".asciz",";","jmp",".global",".space"},
206 0};
207
208 #define ASM_BYTE mtable[machine].how_byte
209 #define ASM_SHORT mtable[machine].how_short
210 #define ASM_LONG mtable[machine].how_long
211 #define ASM_TEXT mtable[machine].how_asciz
212 #define ASM_C mtable[machine].how_comment
213 #define ASM_JUMP mtable[machine].how_jump
214 #define ASM_GLOBAL mtable[machine].how_global
215 #define ASM_SPACE mtable[machine].how_space
216
217 #define PATHMAX 250 /* What's the right name for this ? */
218 static char **oav;
219
220 int i;
221
222 FILE *yyin; /* communications with flex */
223 extern int linenumber;
224 void
225 process_def_file (name)
226 char *name;
227 {
228 FILE *f = fopen (name, "r");
229 if (!f)
230 {
231 fprintf (stderr, "Can't open def file %s\n", name);
232 exit (1);
233 }
234
235 yyin = f;
236
237 yyparse ();
238 }
239
240 /**********************************************************************/
241
242 /* Communications with the parser */
243
244
245 typedef struct dlist
246 {
247 char *text;
248 struct dlist *next;
249 } dlist_type;
250
251 typedef struct export
252 {
253 char *name;
254 char *equal;
255 int ordinal;
256 int constant;
257 int noname;
258 struct export *next;
259 }
260 export_type;
261
262 static char *d_name; /* Arg to NAME or LIBRARY */
263 static int d_nfuncs; /* Number of functions exported */
264 static int d_ord; /* Base ordinal index */
265 static export_type *d_exports; /*list of exported functions */
266 static char *d_suffix = "dll";
267 static dlist_type *d_list; /* Descriptions */
268 static dlist_type *a_list; /* Stuff to go in directives */
269
270 static int d_is_dll;
271 static int d_is_exe;
272
273 yyerror ()
274 {
275 fprintf (stderr, "Syntax error in def file %s:%d\n",
276 def_file, linenumber);
277 }
278
279 void
280 def_exports (name, equal, ordinal, noname, constant)
281 char *name;
282 char *equal;
283 int ordinal;
284 int noname;
285 int constant;
286 {
287 struct export *p = (struct export *) xmalloc (sizeof (*p));
288
289 p->name = name;
290 p->equal = equal;
291 p->ordinal = ordinal;
292 p->constant = constant;
293 p->noname = noname;
294 p->next = d_exports;
295 d_exports = p;
296 d_nfuncs++;
297
298
299 printf ("EXPORTS %s", name);
300 if (equal)
301 printf ("=%s", equal);
302 if (ordinal > 0)
303 printf ("@%d", ordinal);
304 if (constant)
305 printf (" CONSTANT");
306 printf ("\n");
307 }
308
309 void
310 def_name (name, base)
311 char *name;
312 int base;
313 {
314 printf ("NAME %s base %x\n", name, base);
315 if (d_is_dll)
316 {
317 fprintf (stderr, "Can't have LIBRARY and NAME\n");
318 }
319 d_name = name;
320 if (strchr (d_name, '.'))
321 d_suffix = strdup (strchr (d_name, '.') + 1);
322 d_is_exe = 1;
323 }
324
325 void
326 def_library (name, base)
327 char *name;
328 int base;
329 {
330 printf ("LIBRARY %s base %x\n", name, base);
331 if (d_is_exe)
332 {
333 fprintf (stderr, "Can't have LIBRARY and NAME\n");
334 }
335 d_name = name;
336 if (strchr (d_name, '.'))
337 d_suffix = strdup (strchr (d_name, '.') + 1);
338 d_is_dll = 1;
339 }
340
341 void
342 def_description (desc)
343 char *desc;
344 {
345 dlist_type *d = (dlist_type *)xmalloc(sizeof(dlist_type));
346 d->text = strdup (desc);
347 d->next = d_list;
348 d_list = d;
349 }
350
351 void new_directive(dir)
352 char *dir;
353 {
354 dlist_type *d = (dlist_type *)xmalloc(sizeof(dlist_type));
355 d->text = strdup (dir);
356 d->next = a_list;
357 a_list = d;
358 }
359
360 void
361 def_stacksize (reserve, commit)
362 int reserve;
363 int commit;
364 {
365 char b[200];
366 if (commit>0)
367 sprintf (b,"-stack 0x%x,0x%x ", reserve, commit);
368 else
369 sprintf (b,"-stack 0x%x ", reserve);
370 new_directive (strdup(b));
371 }
372
373 void
374 def_heapsize (reserve, commit)
375 int reserve;
376 int commit;
377 {
378 char b[200];
379 if (commit>0)
380 sprintf (b,"-heap 0x%x,0x%x ", reserve, commit);
381 else
382 sprintf (b,"-heap 0x%x ", reserve);
383 new_directive (strdup(b));
384 }
385
386
387 void
388 def_import (internal, module, entry)
389 char *internal;
390 char *module;
391 char *entry;
392 {
393 fprintf (stderr, "IMPORTS are ignored");
394 }
395
396 void
397 def_version (major, minor)
398 {
399 printf ("VERSION %d.%d\n", major, minor);
400 }
401
402
403 void
404 def_section (name, attr)
405 char *name;
406 int attr;
407 {
408 char buf[200];
409 char atts[5];
410 char *d = atts;
411 if (attr & 1)
412 *d++= 'R';
413
414 if (attr & 2)
415 *d++ = 'W';
416 if (attr & 4)
417 *d++ = 'X';
418 if (attr & 8)
419 *d++ = 'S';
420 *d++ = 0;
421 sprintf (buf, "-attr %s %s", name, atts);
422 new_directive (strdup(buf));
423 }
424 void
425 def_code (attr)
426 int attr;
427 {
428
429 def_section ("CODE", attr);
430 }
431
432 void
433 def_data (attr)
434 int attr;
435 {
436 def_section ("DATA",attr);
437 }
438
439
440 /**********************************************************************/
441
442 void
443 scan_open_obj_file (abfd)
444 bfd *abfd;
445 {
446 /* Look for .drectives */
447 asection *s = bfd_get_section_by_name (abfd, ".drectve");
448 if (s)
449 {
450 int size = bfd_get_section_size_before_reloc (s);
451 char *buf = xmalloc (size);
452 char *p;
453 char *e;
454 bfd_get_section_contents (abfd, s, buf, 0, size);
455 printf ("Sucking in info from %s\n",
456 bfd_get_filename (abfd));
457
458 /* Search for -export: strings */
459 p = buf;
460 e = buf + size;
461 while (p < e)
462 {
463 if (p[0] == '-'
464 && strncmp (p, "-export:", 8) == 0)
465 {
466 char *name;
467 char *c;
468 p += 8;
469 name = p;
470 while (*p != ' ' && *p != '-' && p < e)
471 p++;
472 c = xmalloc (p - name + 1);
473 memcpy (c, name, p - name);
474 c[p - name] = 0;
475 def_exports (c, 0, -1, 0);
476 }
477 else
478 p++;
479 }
480 free (buf);
481 }
482 }
483
484
485 void
486 scan_obj_file (filename)
487 char *filename;
488 {
489 bfd *f = bfd_openr (filename, 0);
490
491 if (!f)
492 {
493 fprintf (stderr, "Unable to open object file %s\n", filename);
494 exit (1);
495 }
496 if (bfd_check_format (f, bfd_archive))
497 {
498 bfd *arfile = bfd_openr_next_archived_file (f, 0);
499 while (arfile)
500 {
501 if (bfd_check_format (arfile, bfd_object))
502 scan_open_obj_file (arfile);
503 bfd_close (arfile);
504 arfile = bfd_openr_next_archived_file (f, arfile);
505 }
506 }
507
508 if (bfd_check_format (f, bfd_object))
509 {
510 scan_open_obj_file (f);
511 }
512
513 bfd_close (f);
514 }
515
516 /**********************************************************************/
517
518
519 /* return the bit of the name before the last . */
520
521 static
522 char *
523 prefix (name)
524 char *name;
525 {
526 char *res = strdup (name);
527 char *p = strrchr (res, '.');
528 if (p)
529 *p = 0;
530 return res;
531 }
532
533 void
534 dump_def_info (f)
535 FILE *f;
536 {
537 int i;
538 export_type *exp;
539 fprintf(f,"%s ", ASM_C);
540 for (i= 0; oav[i]; i++)
541 fprintf(f,"%s ", oav[i]);
542 fprintf(f,"\n");
543 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
544 {
545 fprintf (f, "%s %d %s @ %d %s%s\n",
546 ASM_C,
547 i,
548 exp->name, exp->ordinal,
549 exp->noname ? "NONAME " : "",
550 exp->constant ? "CONSTANT" : "");
551 }
552 }
553 /* Generate the .exp file */
554
555
556 void
557 gen_exp_file ()
558 {
559 FILE *f;
560 char outfile[PATHMAX];
561 int i;
562 export_type *exp;
563 dlist_type *dl;
564 sprintf (outfile, "%s.exp.s", outfile_prefix);
565
566 f = fopen (outfile, "w");
567 if (!f)
568 {
569 fprintf (stderr, "Unable to open output file %s\n", outfile);
570 exit (1);
571 }
572 dump_def_info (f);
573 fprintf (f, "\t.section .edata\n\n");
574 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
575 fprintf (f, "\t%s %d %s Time and date\n", ASM_LONG, time (0), ASM_C);
576 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
577 fprintf (f, "\t%s name %s Ptr to name of dll\n", ASM_LONG, ASM_C);
578 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
579 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
580 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
581 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
582 fprintf (f, "\t%s always the number of names field\n", ASM_C);
583 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
584 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
585 fprintf (f, "\t%s afuncs %s Address of functions\n", ASM_LONG, ASM_C);
586 fprintf (f, "\t%s anames %s Address of names\n", ASM_LONG, ASM_C);
587 fprintf (f, "\t%s anords %s Address of ordinals\n", ASM_LONG, ASM_C);
588
589 fprintf (f, "name: %s \"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
590
591 fprintf (f, "afuncs:\n");
592 i = d_ord;
593 for (exp = d_exports; exp; exp = exp->next)
594 {
595 if (exp->ordinal != i)
596 {
597 fprintf (f, "\t%s\t%d\t@ %d..%d missing\n", ASM_SPACE,
598 (exp->ordinal - i) * 4,
599 i, exp->ordinal - 1);
600 i = exp->ordinal;
601 }
602 fprintf (f, "\t%s %s\t%s %d\n", ASM_LONG, exp->name, ASM_C, exp->ordinal);
603 i++;
604 }
605
606
607 fprintf (f, "anames:\n");
608 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
609 if (exp->noname)
610 fprintf (f, "\t%s 0\t%sNoname\n", ASM_LONG, ASM_C);
611 else
612 fprintf (f, "\t%s n%d\n", ASM_LONG, i);
613
614 fprintf (f, "anords:\n");
615 for (exp = d_exports; exp; exp = exp->next)
616 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
617
618 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
619 if (exp->noname)
620 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
621 else
622 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
623
624
625 if (a_list)
626 {
627 fprintf(f,"\t.section .drectve\n");
628 for (dl = a_list; dl; dl = dl->next)
629 {
630 fprintf (f,"\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
631 }
632 }
633 if (d_list)
634 {
635 fprintf(f,"\t.section .rdata\n");
636 for (dl = d_list; dl; dl = dl->next)
637 {
638 char *p;
639 int l;
640 /* We dont output as ascii 'cause there can
641 be quote characters in the string */
642
643 l = 0;
644 for (p = dl->text; *p; p++) {
645 if (l == 0)
646 fprintf(f,"\t%s\t", ASM_BYTE);
647 else
648 fprintf(f,",");
649 fprintf(f,"%d", *p);
650 if (p[1] == 0) {
651 fprintf(f,",0\n");
652 break;
653 }
654 if (++l == 10) {
655 fprintf(f,"\n");
656 l = 0;
657 }
658 }
659 }
660 }
661 fclose (f);
662 }
663
664 /**********************************************************************/
665 gen_lib_file ()
666 {
667 char outfile[PATHMAX];
668 int i;
669 FILE *f;
670 export_type *exp;
671
672 sprintf (outfile, "%s.lib.s", outfile_prefix);
673
674 f = fopen (outfile, "w");
675 if (!f)
676 {
677 fprintf (stderr, "Unable to open output file %s\n", outfile);
678 exit (1);
679 }
680
681
682 dump_def_info (f);
683 fprintf (f, "\t.text\n");
684 fprintf (f, "%s Thunk table\n", ASM_C);
685 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
686 {
687 fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name);
688 fprintf (f, "\t%s\t__imp__%s\n", ASM_GLOBAL, exp->name);
689 }
690
691 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
692 {
693 fprintf (f, "%s:\t%s\t__imp__%s\n", exp->name, ASM_JUMP, exp->name);
694 }
695
696
697 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
698 fprintf (f, "\t.section .idata$2\n");
699 fprintf (f, "\t%s\thname\t%s Ptr to image import by name list\n", ASM_LONG, ASM_C);
700 fprintf (f, "\t%s\t%d\t%s time\n", ASM_LONG, time (0), ASM_C);
701 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
702 fprintf (f, "\t%s\tiname\t%s imported dll's name\n", ASM_LONG, ASM_C);
703 fprintf (f, "\t%s\tfthunk\t%s pointer to firstthunk\n", ASM_LONG, ASM_C);
704
705 fprintf (f, "\n%s Loader modifies this\n", ASM_C);
706 fprintf (f, "\t.section .idata$5\n");
707 fprintf (f, "fthunk:\n");
708 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
709 {
710 fprintf (f, "__imp__%s:\n", exp->name);
711 fprintf (f, "\t%s\tID%d\n", ASM_LONG, i);
712 }
713
714 fprintf (f, "\n%s Hint name array\n", ASM_C);
715 fprintf (f, "\t.section .idata$4\n");
716 fprintf (f, "hname:\n");
717 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
718 {
719 fprintf (f, "\t%s\tID%d\n", ASM_LONG, i);
720 }
721
722 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
723 fprintf (f, "\t.section .idata$6\n");
724
725 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
726 {
727 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
728 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, exp->name);
729 }
730
731 fprintf (f, "iname:\t%s\t\"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
732 fclose (f);
733 }
734 /**********************************************************************/
735
736 /* Run through the information gathered from the .o files and the
737 .def file and work out the best stuff */
738 int
739 pfunc (a, b)
740 void *a;
741 void *b;
742 {
743 export_type *ap = *(export_type **) a;
744 export_type *bp = *(export_type **) b;
745 if (ap->ordinal == bp->ordinal)
746 return 0;
747
748 /* unset ordinals go to the bottom */
749 if (ap->ordinal == -1)
750 return 1;
751 if (bp->ordinal == -1)
752 return -1;
753 return (ap->ordinal - bp->ordinal);
754 }
755
756
757 int
758 nfunc (a, b)
759 void *a;
760 void *b;
761 {
762 export_type *ap = *(export_type **) a;
763 export_type *bp = *(export_type **) b;
764
765 return (strcmp (ap->name, bp->name));
766 }
767
768 static
769 void
770 remove_null_names (ptr)
771 export_type **ptr;
772 {
773 int src;
774 int dst;
775 for (dst = src = 0; src < d_nfuncs; src++)
776 {
777 if (ptr[src])
778 {
779 ptr[dst] = ptr[src];
780 dst++;
781 }
782 }
783 d_nfuncs = dst;
784 }
785
786 static void
787 dtab (ptr)
788 export_type **ptr;
789 {
790 #ifdef SACDEBUG
791 int i;
792 for (i = 0; i < d_nfuncs; i++)
793 {
794 if (ptr[i])
795 {
796 printf ("%d %s @ %d %s%s\n",
797 i, ptr[i]->name, ptr[i]->ordinal,
798 ptr[i]->noname ? "NONAME " : "",
799 ptr[i]->constant ? "CONSTANT" : "");
800 }
801 else
802 printf ("empty\n");
803 }
804 #endif
805 }
806
807 static void
808 process_duplicates (d_export_vec)
809 export_type **d_export_vec;
810 {
811 int more = 1;
812
813 while (more)
814 {
815 more = 0;
816 /* Remove duplicates */
817 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
818
819 dtab (d_export_vec);
820 for (i = 0; i < d_nfuncs - 1; i++)
821 {
822 if (strcmp (d_export_vec[i]->name,
823 d_export_vec[i + 1]->name) == 0)
824 {
825
826 export_type *a = d_export_vec[i];
827 export_type *b = d_export_vec[i + 1];
828
829 more = 1;
830
831 fprintf (stderr, "warning, ignoring duplicate EXPORT %s\n",
832 a->name);
833 if (a->ordinal != -1
834 && b->ordinal != -1)
835 {
836
837 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
838 a->name);
839 exit (1);
840 }
841 /* Merge attributes */
842 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
843 b->constant |= a->constant;
844 b->noname |= a->noname;
845 d_export_vec[i] = 0;
846 }
847
848 dtab (d_export_vec);
849 remove_null_names (d_export_vec);
850 dtab (d_export_vec);
851 }
852 }
853 }
854
855 static void
856 fill_ordinals (d_export_vec)
857 export_type **d_export_vec;
858 {
859 int lowest = 0;
860 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
861
862 /* fill in the unset ordinals with ones from the minimum */
863 for (i = 0; i < d_nfuncs; i++)
864 {
865 if (d_export_vec[i]->ordinal == -1)
866 {
867 d_export_vec[i]->ordinal = lowest++;
868 }
869 else
870 {
871 if (lowest == d_export_vec[i]->ordinal)
872 {
873 fprintf (stderr, "Warning, Duplicate ordinal %s @ %d\n",
874 d_export_vec[i]->name,
875 d_export_vec[i]->ordinal);
876 }
877 lowest = d_export_vec[i]->ordinal + 1;
878 }
879 }
880
881 /* Work out the lowest ordinal number */
882 if (d_export_vec[0])
883 d_ord = d_export_vec[0]->ordinal;
884 }
885 void
886 mangle_defs ()
887 {
888 /* First work out the minimum ordinal chosen */
889
890 export_type *exp;
891 int lowest = 0;
892 int i;
893 export_type **d_export_vec
894 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
895
896 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
897 {
898 d_export_vec[i] = exp;
899 }
900
901 process_duplicates (d_export_vec);
902 fill_ordinals (d_export_vec);
903
904 /* Put back the list in the new order */
905 d_exports = 0;
906 for (i = d_nfuncs - 1; i >= 0; i--)
907 {
908 d_export_vec[i]->next = d_exports;
909 d_exports = d_export_vec[i];
910 }
911 }
912
913
914 /**********************************************************************/
915
916 void
917 usage (file, status)
918 FILE *file;
919 int status;
920 {
921 fprintf (file, "Usage %s [-m|--machine machine] [-o outprefix] [-d|--def deffile] [--def deffile]\n", program_name);
922 exit (status);
923 }
924
925 static struct option long_options[] =
926 {
927 {"def", required_argument, NULL, 'd'},
928 {"help", no_argument, NULL, 'h'},
929 {"machine", required_argument, NULL, 'm'},
930 0
931 };
932
933 int
934 main (ac, av)
935 int ac;
936 char **av;
937 {
938 int c;
939 char *firstarg = 0;
940 program_name = av[0];
941 oav = av;
942
943 while ((c = getopt_long (ac, av, "h?m:o:Dd:", long_options, 0)) != EOF)
944 {
945 switch (c)
946 {
947 case 'h':
948 case '?':
949 usage(stderr,0);
950 break;
951 case 'm':
952 mname = optarg;
953 break;
954 case 'o':
955 outfile_prefix = optarg;
956 break;
957 case 'D':
958 yydebug = 1;
959 break;
960 case 'd':
961 def_file = optarg;
962 break;
963 default:
964 usage (stderr, 1);
965 }
966 }
967
968
969 for (i = 0; mtable[i].type; i++)
970 {
971 if (strcmp (mtable[i].type, mname) == 0)
972 break;
973 }
974
975 if (!mtable[i].type)
976 {
977 fprintf(stderr,"Machine not supported\n");
978 exit(1);
979 }
980 machine = i;
981
982
983 if (def_file)
984 {
985
986 process_def_file (def_file);
987 }
988 while (optind < ac)
989 {
990 if (!firstarg)
991 firstarg = av[optind];
992 scan_obj_file (av[optind]);
993 optind++;
994 }
995
996 if (!outfile_prefix)
997 {
998 if (d_name)
999 outfile_prefix = d_name;
1000 else if (def_file)
1001 outfile_prefix = def_file;
1002 else if (firstarg)
1003 outfile_prefix = firstarg;
1004 else
1005 {
1006 fprintf (stderr, "No way to create an output filename\n");
1007 exit (1);
1008 }
1009 }
1010 outfile_prefix = prefix (outfile_prefix);
1011
1012 mangle_defs ();
1013 gen_exp_file ();
1014 gen_lib_file ();
1015 return 0;
1016 }
This page took 0.051874 seconds and 4 git commands to generate.