042a454d90c6d7ad20a654c9001d9c56374b40b3
[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 *internal_name;
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, internal_name, ordinal, noname, constant)
281 char *name;
282 char *internal_name;
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->internal_name = internal_name ? internal_name : name;
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 void
300 def_name (name, base)
301 char *name;
302 int base;
303 {
304 printf ("NAME %s base %x\n", name, base);
305 if (d_is_dll)
306 {
307 fprintf (stderr, "Can't have LIBRARY and NAME\n");
308 }
309 d_name = name;
310 if (strchr (d_name, '.'))
311 d_suffix = strdup (strchr (d_name, '.') + 1);
312 d_is_exe = 1;
313 }
314
315 void
316 def_library (name, base)
317 char *name;
318 int base;
319 {
320 printf ("LIBRARY %s base %x\n", name, base);
321 if (d_is_exe)
322 {
323 fprintf (stderr, "Can't have LIBRARY and NAME\n");
324 }
325 d_name = name;
326 if (strchr (d_name, '.'))
327 d_suffix = strdup (strchr (d_name, '.') + 1);
328 d_is_dll = 1;
329 }
330
331 void
332 def_description (desc)
333 char *desc;
334 {
335 dlist_type *d = (dlist_type *)xmalloc(sizeof(dlist_type));
336 d->text = strdup (desc);
337 d->next = d_list;
338 d_list = d;
339 }
340
341 void new_directive(dir)
342 char *dir;
343 {
344 dlist_type *d = (dlist_type *)xmalloc(sizeof(dlist_type));
345 d->text = strdup (dir);
346 d->next = a_list;
347 a_list = d;
348 }
349
350 void
351 def_stacksize (reserve, commit)
352 int reserve;
353 int commit;
354 {
355 char b[200];
356 if (commit>0)
357 sprintf (b,"-stack 0x%x,0x%x ", reserve, commit);
358 else
359 sprintf (b,"-stack 0x%x ", reserve);
360 new_directive (strdup(b));
361 }
362
363 void
364 def_heapsize (reserve, commit)
365 int reserve;
366 int commit;
367 {
368 char b[200];
369 if (commit>0)
370 sprintf (b,"-heap 0x%x,0x%x ", reserve, commit);
371 else
372 sprintf (b,"-heap 0x%x ", reserve);
373 new_directive (strdup(b));
374 }
375
376
377 void
378 def_import (internal, module, entry)
379 char *internal;
380 char *module;
381 char *entry;
382 {
383 fprintf (stderr, "IMPORTS are ignored");
384 }
385
386 void
387 def_version (major, minor)
388 {
389 printf ("VERSION %d.%d\n", major, minor);
390 }
391
392
393 void
394 def_section (name, attr)
395 char *name;
396 int attr;
397 {
398 char buf[200];
399 char atts[5];
400 char *d = atts;
401 if (attr & 1)
402 *d++= 'R';
403
404 if (attr & 2)
405 *d++ = 'W';
406 if (attr & 4)
407 *d++ = 'X';
408 if (attr & 8)
409 *d++ = 'S';
410 *d++ = 0;
411 sprintf (buf, "-attr %s %s", name, atts);
412 new_directive (strdup(buf));
413 }
414 void
415 def_code (attr)
416 int attr;
417 {
418
419 def_section ("CODE", attr);
420 }
421
422 void
423 def_data (attr)
424 int attr;
425 {
426 def_section ("DATA",attr);
427 }
428
429
430 /**********************************************************************/
431
432 void
433 scan_open_obj_file (abfd)
434 bfd *abfd;
435 {
436 /* Look for .drectives */
437 asection *s = bfd_get_section_by_name (abfd, ".drectve");
438 if (s)
439 {
440 int size = bfd_get_section_size_before_reloc (s);
441 char *buf = xmalloc (size);
442 char *p;
443 char *e;
444 bfd_get_section_contents (abfd, s, buf, 0, size);
445 printf ("Sucking in info from %s\n",
446 bfd_get_filename (abfd));
447
448 /* Search for -export: strings */
449 p = buf;
450 e = buf + size;
451 while (p < e)
452 {
453 if (p[0] == '-'
454 && strncmp (p, "-export:", 8) == 0)
455 {
456 char *name;
457 char *c;
458 p += 8;
459 name = p;
460 while (*p != ' ' && *p != '-' && p < e)
461 p++;
462 c = xmalloc (p - name + 1);
463 memcpy (c, name, p - name);
464 c[p - name] = 0;
465 def_exports (c, 0, -1, 0);
466 }
467 else
468 p++;
469 }
470 free (buf);
471 }
472 }
473
474
475 void
476 scan_obj_file (filename)
477 char *filename;
478 {
479 bfd *f = bfd_openr (filename, 0);
480
481 if (!f)
482 {
483 fprintf (stderr, "Unable to open object file %s\n", filename);
484 exit (1);
485 }
486 if (bfd_check_format (f, bfd_archive))
487 {
488 bfd *arfile = bfd_openr_next_archived_file (f, 0);
489 while (arfile)
490 {
491 if (bfd_check_format (arfile, bfd_object))
492 scan_open_obj_file (arfile);
493 bfd_close (arfile);
494 arfile = bfd_openr_next_archived_file (f, arfile);
495 }
496 }
497
498 if (bfd_check_format (f, bfd_object))
499 {
500 scan_open_obj_file (f);
501 }
502
503 bfd_close (f);
504 }
505
506 /**********************************************************************/
507
508
509 /* return the bit of the name before the last . */
510
511 static
512 char *
513 prefix (name)
514 char *name;
515 {
516 char *res = strdup (name);
517 char *p = strrchr (res, '.');
518 if (p)
519 *p = 0;
520 return res;
521 }
522
523 void
524 dump_def_info (f)
525 FILE *f;
526 {
527 int i;
528 export_type *exp;
529 fprintf(f,"%s ", ASM_C);
530 for (i= 0; oav[i]; i++)
531 fprintf(f,"%s ", oav[i]);
532 fprintf(f,"\n");
533 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
534 {
535 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
536 ASM_C,
537 i,
538 exp->name,
539 exp->internal_name,
540 exp->ordinal,
541 exp->noname ? "NONAME " : "",
542 exp->constant ? "CONSTANT" : "");
543 }
544 }
545 /* Generate the .exp file */
546
547
548 void
549 gen_exp_file ()
550 {
551 FILE *f;
552 char outfile[PATHMAX];
553 int i;
554 export_type *exp;
555 dlist_type *dl;
556 sprintf (outfile, "%s.exp.s", outfile_prefix);
557
558 f = fopen (outfile, "w");
559 if (!f)
560 {
561 fprintf (stderr, "Unable to open output file %s\n", outfile);
562 exit (1);
563 }
564 dump_def_info (f);
565 fprintf (f, "\t.section .edata\n\n");
566 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
567 fprintf (f, "\t%s %d %s Time and date\n", ASM_LONG, time (0), ASM_C);
568 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
569 fprintf (f, "\t%s name %s Ptr to name of dll\n", ASM_LONG, ASM_C);
570 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
571 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
572 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
573 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
574 fprintf (f, "\t%s always the number of names field\n", ASM_C);
575 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
576 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
577 fprintf (f, "\t%s afuncs %s Address of functions\n", ASM_LONG, ASM_C);
578 fprintf (f, "\t%s anames %s Address of names\n", ASM_LONG, ASM_C);
579 fprintf (f, "\t%s anords %s Address of ordinals\n", ASM_LONG, ASM_C);
580
581 fprintf (f, "name: %s \"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
582
583 fprintf (f, "afuncs:\n");
584 i = d_ord;
585 for (exp = d_exports; exp; exp = exp->next)
586 {
587 if (exp->ordinal != i)
588 {
589 fprintf (f, "\t%s\t%d\t@ %d..%d missing\n", ASM_SPACE,
590 (exp->ordinal - i) * 4,
591 i, exp->ordinal - 1);
592 i = exp->ordinal;
593 }
594 fprintf (f, "\t%s %s\t%s %d\n", ASM_LONG, exp->internal_name, ASM_C, exp->ordinal);
595 i++;
596 }
597
598
599 fprintf (f, "anames:\n");
600 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
601 if (exp->noname)
602 fprintf (f, "\t%s 0\t%sNoname\n", ASM_LONG, ASM_C);
603 else
604 fprintf (f, "\t%s n%d\n", ASM_LONG, i);
605
606 fprintf (f, "anords:\n");
607 for (exp = d_exports; exp; exp = exp->next)
608 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
609
610 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
611 if (exp->noname)
612 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
613 else
614 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
615
616
617 if (a_list)
618 {
619 fprintf(f,"\t.section .drectve\n");
620 for (dl = a_list; dl; dl = dl->next)
621 {
622 fprintf (f,"\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
623 }
624 }
625 if (d_list)
626 {
627 fprintf(f,"\t.section .rdata\n");
628 for (dl = d_list; dl; dl = dl->next)
629 {
630 char *p;
631 int l;
632 /* We dont output as ascii 'cause there can
633 be quote characters in the string */
634
635 l = 0;
636 for (p = dl->text; *p; p++) {
637 if (l == 0)
638 fprintf(f,"\t%s\t", ASM_BYTE);
639 else
640 fprintf(f,",");
641 fprintf(f,"%d", *p);
642 if (p[1] == 0) {
643 fprintf(f,",0\n");
644 break;
645 }
646 if (++l == 10) {
647 fprintf(f,"\n");
648 l = 0;
649 }
650 }
651 }
652 }
653 fclose (f);
654 }
655
656 /**********************************************************************/
657 gen_lib_file ()
658 {
659 char outfile[PATHMAX];
660 int i;
661 FILE *f;
662 export_type *exp;
663
664 sprintf (outfile, "%s.lib.s", outfile_prefix);
665
666 f = fopen (outfile, "w");
667 if (!f)
668 {
669 fprintf (stderr, "Unable to open output file %s\n", outfile);
670 exit (1);
671 }
672
673
674 dump_def_info (f);
675 fprintf (f, "\t.text\n");
676 fprintf (f, "%s Thunk table\n", ASM_C);
677 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
678 {
679 fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name);
680 fprintf (f, "\t%s\t__imp__%s\n", ASM_GLOBAL, exp->name);
681 }
682
683 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
684 {
685 fprintf (f, "%s:\t%s\t__imp__%s\n", exp->name, ASM_JUMP, exp->name);
686 }
687
688
689 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
690 fprintf (f, "\t.section .idata$2\n");
691 fprintf (f, "\t%s\thname\t%s Ptr to image import by name list\n", ASM_LONG, ASM_C);
692 fprintf (f, "\t%s\t%d\t%s time\n", ASM_LONG, time (0), ASM_C);
693 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
694 fprintf (f, "\t%s\tiname\t%s imported dll's name\n", ASM_LONG, ASM_C);
695 fprintf (f, "\t%s\tfthunk\t%s pointer to firstthunk\n", ASM_LONG, ASM_C);
696
697 fprintf (f, "\n%s Loader modifies this\n", ASM_C);
698 fprintf (f, "\t.section .idata$5\n");
699 fprintf (f, "fthunk:\n");
700 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
701 {
702 fprintf (f, "__imp__%s:\n", exp->name);
703 fprintf (f, "\t%s\tID%d\n", ASM_LONG, i);
704 }
705
706 fprintf (f, "\n%s Hint name array\n", ASM_C);
707 fprintf (f, "\t.section .idata$4\n");
708 fprintf (f, "hname:\n");
709 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
710 {
711 fprintf (f, "\t%s\tID%d\n", ASM_LONG, i);
712 }
713
714 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
715 fprintf (f, "\t.section .idata$6\n");
716
717 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
718 {
719 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
720 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, exp->name);
721 }
722
723 fprintf (f, "iname:\t%s\t\"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
724 fclose (f);
725 }
726 /**********************************************************************/
727
728 /* Run through the information gathered from the .o files and the
729 .def file and work out the best stuff */
730 int
731 pfunc (a, b)
732 void *a;
733 void *b;
734 {
735 export_type *ap = *(export_type **) a;
736 export_type *bp = *(export_type **) b;
737 if (ap->ordinal == bp->ordinal)
738 return 0;
739
740 /* unset ordinals go to the bottom */
741 if (ap->ordinal == -1)
742 return 1;
743 if (bp->ordinal == -1)
744 return -1;
745 return (ap->ordinal - bp->ordinal);
746 }
747
748
749 int
750 nfunc (a, b)
751 void *a;
752 void *b;
753 {
754 export_type *ap = *(export_type **) a;
755 export_type *bp = *(export_type **) b;
756
757 return (strcmp (ap->name, bp->name));
758 }
759
760 static
761 void
762 remove_null_names (ptr)
763 export_type **ptr;
764 {
765 int src;
766 int dst;
767 for (dst = src = 0; src < d_nfuncs; src++)
768 {
769 if (ptr[src])
770 {
771 ptr[dst] = ptr[src];
772 dst++;
773 }
774 }
775 d_nfuncs = dst;
776 }
777
778 static void
779 dtab (ptr)
780 export_type **ptr;
781 {
782 #ifdef SACDEBUG
783 int i;
784 for (i = 0; i < d_nfuncs; i++)
785 {
786 if (ptr[i])
787 {
788 printf ("%d %s @ %d %s%s\n",
789 i, ptr[i]->name, ptr[i]->ordinal,
790 ptr[i]->noname ? "NONAME " : "",
791 ptr[i]->constant ? "CONSTANT" : "");
792 }
793 else
794 printf ("empty\n");
795 }
796 #endif
797 }
798
799 static void
800 process_duplicates (d_export_vec)
801 export_type **d_export_vec;
802 {
803 int more = 1;
804
805 while (more)
806 {
807 more = 0;
808 /* Remove duplicates */
809 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
810
811 dtab (d_export_vec);
812 for (i = 0; i < d_nfuncs - 1; i++)
813 {
814 if (strcmp (d_export_vec[i]->name,
815 d_export_vec[i + 1]->name) == 0)
816 {
817
818 export_type *a = d_export_vec[i];
819 export_type *b = d_export_vec[i + 1];
820
821 more = 1;
822
823 fprintf (stderr, "warning, ignoring duplicate EXPORT %s\n",
824 a->name);
825 if (a->ordinal != -1
826 && b->ordinal != -1)
827 {
828
829 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
830 a->name);
831 exit (1);
832 }
833 /* Merge attributes */
834 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
835 b->constant |= a->constant;
836 b->noname |= a->noname;
837 d_export_vec[i] = 0;
838 }
839
840 dtab (d_export_vec);
841 remove_null_names (d_export_vec);
842 dtab (d_export_vec);
843 }
844 }
845 }
846
847 static void
848 fill_ordinals (d_export_vec)
849 export_type **d_export_vec;
850 {
851 int lowest = 0;
852 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
853
854 /* fill in the unset ordinals with ones from the minimum */
855 for (i = 0; i < d_nfuncs; i++)
856 {
857 if (d_export_vec[i]->ordinal == -1)
858 {
859 d_export_vec[i]->ordinal = lowest++;
860 }
861 else
862 {
863 if (lowest == d_export_vec[i]->ordinal)
864 {
865 fprintf (stderr, "Warning, Duplicate ordinal %s @ %d\n",
866 d_export_vec[i]->name,
867 d_export_vec[i]->ordinal);
868 }
869 lowest = d_export_vec[i]->ordinal + 1;
870 }
871 }
872
873 /* Work out the lowest ordinal number */
874 if (d_export_vec[0])
875 d_ord = d_export_vec[0]->ordinal;
876 }
877 void
878 mangle_defs ()
879 {
880 /* First work out the minimum ordinal chosen */
881
882 export_type *exp;
883 int lowest = 0;
884 int i;
885 export_type **d_export_vec
886 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
887
888 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
889 {
890 d_export_vec[i] = exp;
891 }
892
893 process_duplicates (d_export_vec);
894 fill_ordinals (d_export_vec);
895
896 /* Put back the list in the new order */
897 d_exports = 0;
898 for (i = d_nfuncs - 1; i >= 0; i--)
899 {
900 d_export_vec[i]->next = d_exports;
901 d_exports = d_export_vec[i];
902 }
903 }
904
905
906 /**********************************************************************/
907
908 void
909 usage (file, status)
910 FILE *file;
911 int status;
912 {
913 fprintf (file, "Usage %s [-m|--machine machine] [-o outprefix] [-d|--def deffile] [--def deffile]\n", program_name);
914 exit (status);
915 }
916
917 static struct option long_options[] =
918 {
919 {"def", required_argument, NULL, 'd'},
920 {"help", no_argument, NULL, 'h'},
921 {"machine", required_argument, NULL, 'm'},
922 0
923 };
924
925 int
926 main (ac, av)
927 int ac;
928 char **av;
929 {
930 int c;
931 char *firstarg = 0;
932 program_name = av[0];
933 oav = av;
934
935 while ((c = getopt_long (ac, av, "h?m:o:Dd:", long_options, 0)) != EOF)
936 {
937 switch (c)
938 {
939 case 'h':
940 case '?':
941 usage(stderr,0);
942 break;
943 case 'm':
944 mname = optarg;
945 break;
946 case 'o':
947 outfile_prefix = optarg;
948 break;
949 case 'D':
950 yydebug = 1;
951 break;
952 case 'd':
953 def_file = optarg;
954 break;
955 default:
956 usage (stderr, 1);
957 }
958 }
959
960
961 for (i = 0; mtable[i].type; i++)
962 {
963 if (strcmp (mtable[i].type, mname) == 0)
964 break;
965 }
966
967 if (!mtable[i].type)
968 {
969 fprintf(stderr,"Machine not supported\n");
970 exit(1);
971 }
972 machine = i;
973
974
975 if (def_file)
976 {
977
978 process_def_file (def_file);
979 }
980 while (optind < ac)
981 {
982 if (!firstarg)
983 firstarg = av[optind];
984 scan_obj_file (av[optind]);
985 optind++;
986 }
987
988 if (!outfile_prefix)
989 {
990 if (d_name)
991 outfile_prefix = d_name;
992 else if (def_file)
993 outfile_prefix = def_file;
994 else if (firstarg)
995 outfile_prefix = firstarg;
996 else
997 {
998 fprintf (stderr, "No way to create an output filename\n");
999 exit (1);
1000 }
1001 }
1002 outfile_prefix = prefix (outfile_prefix);
1003
1004 mangle_defs ();
1005 gen_exp_file ();
1006 gen_lib_file ();
1007 return 0;
1008 }
This page took 0.051486 seconds and 4 git commands to generate.