* pe-dll.c (auto_export): Use bsearch to speed up scan of exports
[binutils.git] / ld / deffilep.y
blob58f3dd27b78bd54fe62504fb7f5ec1422c1a31b8
1 %{ /* deffilep.y - parser for .def files */
3 /* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
4 2007, 2009 Free Software Foundation, Inc.
6 This file is part of GNU Binutils.
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.
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.
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,
21 MA 02110-1301, USA. */
23 #include "sysdep.h"
24 #include "libiberty.h"
25 #include "safe-ctype.h"
26 #include "bfd.h"
27 #include "ld.h"
28 #include "ldmisc.h"
29 #include "deffile.h"
31 #define TRACE 0
33 #define ROUND_UP(a, b) (((a)+((b)-1))&~((b)-1))
35 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
36 as well as gratuitiously global symbol names, so we can have multiple
37 yacc generated parsers in ld. Note that these are only the variables
38 produced by yacc. If other parser generators (bison, byacc, etc) produce
39 additional global names that conflict at link time, then those parser
40 generators need to be fixed instead of adding those names to this list. */
42 #define yymaxdepth def_maxdepth
43 #define yyparse def_parse
44 #define yylex def_lex
45 #define yyerror def_error
46 #define yylval def_lval
47 #define yychar def_char
48 #define yydebug def_debug
49 #define yypact def_pact
50 #define yyr1 def_r1
51 #define yyr2 def_r2
52 #define yydef def_def
53 #define yychk def_chk
54 #define yypgo def_pgo
55 #define yyact def_act
56 #define yyexca def_exca
57 #define yyerrflag def_errflag
58 #define yynerrs def_nerrs
59 #define yyps def_ps
60 #define yypv def_pv
61 #define yys def_s
62 #define yy_yys def_yys
63 #define yystate def_state
64 #define yytmp def_tmp
65 #define yyv def_v
66 #define yy_yyv def_yyv
67 #define yyval def_val
68 #define yylloc def_lloc
69 #define yyreds def_reds /* With YYDEBUG defined. */
70 #define yytoks def_toks /* With YYDEBUG defined. */
71 #define yylhs def_yylhs
72 #define yylen def_yylen
73 #define yydefred def_yydefred
74 #define yydgoto def_yydgoto
75 #define yysindex def_yysindex
76 #define yyrindex def_yyrindex
77 #define yygindex def_yygindex
78 #define yytable def_yytable
79 #define yycheck def_yycheck
81 typedef struct def_pool_str {
82 struct def_pool_str *next;
83 char data[1];
84 } def_pool_str;
86 static def_pool_str *pool_strs = NULL;
88 static char *def_pool_alloc (size_t sz);
89 static char *def_pool_strdup (const char *str);
90 static void def_pool_free (void);
92 static void def_description (const char *);
93 static void def_exports (const char *, const char *, int, int, const char *);
94 static void def_heapsize (int, int);
95 static void def_import (const char *, const char *, const char *, const char *,
96 int, const char *);
97 static void def_image_name (const char *, int, int);
98 static void def_section (const char *, int);
99 static void def_section_alt (const char *, const char *);
100 static void def_stacksize (int, int);
101 static void def_version (int, int);
102 static void def_directive (char *);
103 static void def_aligncomm (char *str, int align);
104 static int def_parse (void);
105 static int def_error (const char *);
106 static int def_lex (void);
108 static int lex_forced_token = 0;
109 static const char *lex_parse_string = 0;
110 static const char *lex_parse_string_end = 0;
114 %union {
115 char *id;
116 int number;
117 char *digits;
120 %token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
121 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
122 %token PRIVATEU PRIVATEL ALIGNCOMM
123 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE EQUAL
124 %token <id> ID
125 %token <digits> DIGITS
126 %type <number> NUMBER
127 %type <digits> opt_digits
128 %type <number> opt_base opt_ordinal
129 %type <number> attr attr_list opt_number exp_opt_list exp_opt
130 %type <id> opt_name opt_equal_name dot_name anylang_id opt_id
131 %type <id> opt_equalequal_name
135 start: start command
136 | command
139 command:
140 NAME opt_name opt_base { def_image_name ($2, $3, 0); }
141 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
142 | DESCRIPTION ID { def_description ($2);}
143 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);}
144 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
145 | CODE attr_list { def_section ("CODE", $2);}
146 | DATAU attr_list { def_section ("DATA", $2);}
147 | SECTIONS seclist
148 | EXPORTS explist
149 | IMPORTS implist
150 | VERSIONK NUMBER { def_version ($2, 0);}
151 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
152 | DIRECTIVE ID { def_directive ($2);}
153 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);}
157 explist:
158 /* EMPTY */
159 | expline
160 | explist expline
163 expline:
164 /* The opt_comma is necessary to support both the usual
165 DEF file syntax as well as .drectve syntax which
166 mandates <expsym>,<expoptlist>. */
167 dot_name opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name
168 { def_exports ($1, $2, $3, $5, $7); }
170 exp_opt_list:
171 /* The opt_comma is necessary to support both the usual
172 DEF file syntax as well as .drectve syntax which
173 allows for comma separated opt list. */
174 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
175 | { $$ = 0; }
177 exp_opt:
178 NONAMEU { $$ = 1; }
179 | NONAMEL { $$ = 1; }
180 | CONSTANTU { $$ = 2; }
181 | CONSTANTL { $$ = 2; }
182 | DATAU { $$ = 4; }
183 | DATAL { $$ = 4; }
184 | PRIVATEU { $$ = 8; }
185 | PRIVATEL { $$ = 8; }
187 implist:
188 implist impline
189 | impline
192 impline:
193 ID '=' ID '.' ID '.' ID opt_equalequal_name
194 { def_import ($1, $3, $5, $7, -1, $8); }
195 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name
196 { def_import ($1, $3, $5, 0, $7, $8); }
197 | ID '=' ID '.' ID opt_equalequal_name
198 { def_import ($1, $3, 0, $5, -1, $6); }
199 | ID '=' ID '.' NUMBER opt_equalequal_name
200 { def_import ($1, $3, 0, 0, $5, $6); }
201 | ID '.' ID '.' ID opt_equalequal_name
202 { def_import( 0, $1, $3, $5, -1, $6); }
203 | ID '.' ID opt_equalequal_name
204 { def_import ( 0, $1, 0, $3, -1, $4); }
207 seclist:
208 seclist secline
209 | secline
212 secline:
213 ID attr_list { def_section ($1, $2);}
214 | ID ID { def_section_alt ($1, $2);}
217 attr_list:
218 attr_list opt_comma attr { $$ = $1 | $3; }
219 | attr { $$ = $1; }
222 opt_comma:
226 opt_number: ',' NUMBER { $$=$2;}
227 | { $$=-1;}
230 attr:
231 READ { $$ = 1;}
232 | WRITE { $$ = 2;}
233 | EXECUTE { $$=4;}
234 | SHARED { $$=8;}
237 opt_name: ID { $$ = $1; }
238 | '.' ID
240 char *name = def_pool_alloc (strlen ($2) + 2);
241 sprintf (name, ".%s", $2);
242 $$ = name;
244 | ID '.' ID
246 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
247 sprintf (name, "%s.%s", $1, $3);
248 $$ = name;
250 | { $$ = ""; }
253 opt_equalequal_name: EQUAL ID { $$ = $2; }
254 | { $$ = 0; }
257 opt_ordinal:
258 '@' NUMBER { $$ = $2;}
259 | { $$ = -1;}
262 opt_equal_name:
263 '=' dot_name { $$ = $2; }
264 | { $$ = 0; }
267 opt_base: BASE '=' NUMBER { $$ = $3;}
268 | { $$ = -1;}
271 dot_name: ID { $$ = $1; }
272 | '.' ID
274 char *name = def_pool_alloc (strlen ($2) + 2);
275 sprintf (name, ".%s", $2);
276 $$ = name;
278 | dot_name '.' ID
280 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
281 sprintf (name, "%s.%s", $1, $3);
282 $$ = name;
286 anylang_id: ID { $$ = $1; }
287 | '.' ID
289 char *id = def_pool_alloc (strlen ($2) + 2);
290 sprintf (id, ".%s", $2);
291 $$ = id;
293 | anylang_id '.' opt_digits opt_id
295 char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
296 sprintf (id, "%s.%s%s", $1, $3, $4);
297 $$ = id;
301 opt_digits: DIGITS { $$ = $1; }
302 | { $$ = ""; }
305 opt_id: ID { $$ = $1; }
306 | { $$ = ""; }
309 NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); }
313 /*****************************************************************************
315 *****************************************************************************/
317 static FILE *the_file;
318 static const char *def_filename;
319 static int linenumber;
320 static def_file *def;
321 static int saw_newline;
323 struct directive
325 struct directive *next;
326 char *name;
327 int len;
330 static struct directive *directives = 0;
332 def_file *
333 def_file_empty (void)
335 def_file *rv = xmalloc (sizeof (def_file));
336 memset (rv, 0, sizeof (def_file));
337 rv->is_dll = -1;
338 rv->base_address = (bfd_vma) -1;
339 rv->stack_reserve = rv->stack_commit = -1;
340 rv->heap_reserve = rv->heap_commit = -1;
341 rv->version_major = rv->version_minor = -1;
342 return rv;
345 def_file *
346 def_file_parse (const char *filename, def_file *add_to)
348 struct directive *d;
350 the_file = fopen (filename, "r");
351 def_filename = filename;
352 linenumber = 1;
353 if (!the_file)
355 perror (filename);
356 return 0;
358 if (add_to)
360 def = add_to;
362 else
364 def = def_file_empty ();
367 saw_newline = 1;
368 if (def_parse ())
370 def_file_free (def);
371 fclose (the_file);
372 def_pool_free ();
373 return 0;
376 fclose (the_file);
378 while ((d = directives) != NULL)
380 #if TRACE
381 printf ("Adding directive %08x `%s'\n", d->name, d->name);
382 #endif
383 def_file_add_directive (def, d->name, d->len);
384 directives = d->next;
385 free (d->name);
386 free (d);
388 def_pool_free ();
390 return def;
393 void
394 def_file_free (def_file *fdef)
396 int i;
398 if (!fdef)
399 return;
400 if (fdef->name)
401 free (fdef->name);
402 if (fdef->description)
403 free (fdef->description);
405 if (fdef->section_defs)
407 for (i = 0; i < fdef->num_section_defs; i++)
409 if (fdef->section_defs[i].name)
410 free (fdef->section_defs[i].name);
411 if (fdef->section_defs[i].class)
412 free (fdef->section_defs[i].class);
414 free (fdef->section_defs);
417 if (fdef->exports)
419 for (i = 0; i < fdef->num_exports; i++)
421 if (fdef->exports[i].internal_name
422 && fdef->exports[i].internal_name != fdef->exports[i].name)
423 free (fdef->exports[i].internal_name);
424 if (fdef->exports[i].name)
425 free (fdef->exports[i].name);
426 if (fdef->exports[i].its_name)
427 free (fdef->exports[i].its_name);
429 free (fdef->exports);
432 if (fdef->imports)
434 for (i = 0; i < fdef->num_imports; i++)
436 if (fdef->imports[i].internal_name
437 && fdef->imports[i].internal_name != fdef->imports[i].name)
438 free (fdef->imports[i].internal_name);
439 if (fdef->imports[i].name)
440 free (fdef->imports[i].name);
441 if (fdef->imports[i].its_name)
442 free (fdef->imports[i].its_name);
444 free (fdef->imports);
447 while (fdef->modules)
449 def_file_module *m = fdef->modules;
451 fdef->modules = fdef->modules->next;
452 free (m);
455 while (fdef->aligncomms)
457 def_file_aligncomm *c = fdef->aligncomms;
459 fdef->aligncomms = fdef->aligncomms->next;
460 free (c->symbol_name);
461 free (c);
464 free (fdef);
467 #ifdef DEF_FILE_PRINT
468 void
469 def_file_print (FILE *file, def_file *fdef)
471 int i;
473 fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
474 if (fdef->name)
475 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)");
476 if (fdef->is_dll != -1)
477 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no");
478 if (fdef->base_address != (bfd_vma) -1)
479 fprintf (file, " base address: 0x%08x\n", fdef->base_address);
480 if (fdef->description)
481 fprintf (file, " description: `%s'\n", fdef->description);
482 if (fdef->stack_reserve != -1)
483 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
484 if (fdef->stack_commit != -1)
485 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
486 if (fdef->heap_reserve != -1)
487 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
488 if (fdef->heap_commit != -1)
489 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
491 if (fdef->num_section_defs > 0)
493 fprintf (file, " section defs:\n");
495 for (i = 0; i < fdef->num_section_defs; i++)
497 fprintf (file, " name: `%s', class: `%s', flags:",
498 fdef->section_defs[i].name, fdef->section_defs[i].class);
499 if (fdef->section_defs[i].flag_read)
500 fprintf (file, " R");
501 if (fdef->section_defs[i].flag_write)
502 fprintf (file, " W");
503 if (fdef->section_defs[i].flag_execute)
504 fprintf (file, " X");
505 if (fdef->section_defs[i].flag_shared)
506 fprintf (file, " S");
507 fprintf (file, "\n");
511 if (fdef->num_exports > 0)
513 fprintf (file, " exports:\n");
515 for (i = 0; i < fdef->num_exports; i++)
517 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
518 fdef->exports[i].name, fdef->exports[i].internal_name,
519 fdef->exports[i].ordinal);
520 if (fdef->exports[i].flag_private)
521 fprintf (file, " P");
522 if (fdef->exports[i].flag_constant)
523 fprintf (file, " C");
524 if (fdef->exports[i].flag_noname)
525 fprintf (file, " N");
526 if (fdef->exports[i].flag_data)
527 fprintf (file, " D");
528 fprintf (file, "\n");
532 if (fdef->num_imports > 0)
534 fprintf (file, " imports:\n");
536 for (i = 0; i < fdef->num_imports; i++)
538 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
539 fdef->imports[i].internal_name,
540 fdef->imports[i].module,
541 fdef->imports[i].name,
542 fdef->imports[i].ordinal);
546 if (fdef->version_major != -1)
547 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
549 fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
551 #endif
553 /* Helper routine to check for identity of string pointers,
554 which might be NULL. */
556 static int
557 are_names_equal (const char *s1, const char *s2)
559 if (!s1 && !s2)
560 return 0;
561 if (!s1 || !s2)
562 return (!s1 ? -1 : 1);
563 return strcmp (s1, s2);
566 static int
567 cmp_export_elem (const def_file_export *e, const char *ex_name,
568 const char *in_name, const char *its_name,
569 int ord)
571 int r;
573 if ((r = are_names_equal (ex_name, e->name)) != 0)
574 return r;
575 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
576 return r;
577 if ((r = are_names_equal (its_name, e->its_name)) != 0)
578 return r;
579 return (ord - e->ordinal);
582 /* Search the position of the identical element, or returns the position
583 of the next higher element. If last valid element is smaller, then MAX
584 is returned. */
586 static int
587 find_export_in_list (def_file_export *b, int max,
588 const char *ex_name, const char *in_name,
589 const char *its_name, int ord, int *is_ident)
591 int e, l, r, p;
593 *is_ident = 0;
594 if (!max)
595 return 0;
596 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
597 return 0;
598 if (max == 1)
599 return 1;
600 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
601 return max;
602 else if (!e || max == 2)
603 return max - 1;
604 l = 0; r = max - 1;
605 while (l < r)
607 p = (l + r) / 2;
608 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
609 if (!e)
611 *is_ident = 1;
612 return p;
614 else if (e < 0)
615 r = p - 1;
616 else if (e > 0)
617 l = p + 1;
619 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
620 ++l;
621 else if (!e)
622 *is_ident = 1;
623 return l;
626 def_file_export *
627 def_file_add_export (def_file *fdef,
628 const char *external_name,
629 const char *internal_name,
630 int ordinal,
631 const char *its_name,
632 int *is_dup)
634 def_file_export *e;
635 int pos;
636 int max_exports = ROUND_UP(fdef->num_exports, 32);
638 if (internal_name && !external_name)
639 external_name = internal_name;
640 if (external_name && !internal_name)
641 internal_name = external_name;
643 /* We need to avoid duplicates. */
644 *is_dup = 0;
645 pos = find_export_in_list (fdef->exports, fdef->num_exports,
646 external_name, internal_name,
647 its_name, ordinal, is_dup);
649 if (*is_dup != 0)
650 return (fdef->exports + pos);
652 if (fdef->num_exports >= max_exports)
654 max_exports = ROUND_UP(fdef->num_exports + 1, 32);
655 if (fdef->exports)
656 fdef->exports = xrealloc (fdef->exports,
657 max_exports * sizeof (def_file_export));
658 else
659 fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
662 e = fdef->exports + pos;
663 if (pos != fdef->num_exports)
664 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
665 memset (e, 0, sizeof (def_file_export));
666 e->name = xstrdup (external_name);
667 e->internal_name = xstrdup (internal_name);
668 e->its_name = (its_name ? xstrdup (its_name) : NULL);
669 e->ordinal = ordinal;
670 fdef->num_exports++;
671 return e;
674 def_file_module *
675 def_get_module (def_file *fdef, const char *name)
677 def_file_module *s;
679 for (s = fdef->modules; s; s = s->next)
680 if (strcmp (s->name, name) == 0)
681 return s;
683 return NULL;
686 static def_file_module *
687 def_stash_module (def_file *fdef, const char *name)
689 def_file_module *s;
691 if ((s = def_get_module (fdef, name)) != NULL)
692 return s;
693 s = xmalloc (sizeof (def_file_module) + strlen (name));
694 s->next = fdef->modules;
695 fdef->modules = s;
696 s->user_data = 0;
697 strcpy (s->name, name);
698 return s;
701 static int
702 cmp_import_elem (const def_file_import *e, const char *ex_name,
703 const char *in_name, const char *module,
704 int ord)
706 int r;
708 if ((r = are_names_equal (ex_name, e->name)) != 0)
709 return r;
710 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
711 return r;
712 if (ord != e->ordinal)
713 return (ord < e->ordinal ? -1 : 1);
714 return are_names_equal (module, (e->module ? e->module->name : NULL));
717 /* Search the position of the identical element, or returns the position
718 of the next higher element. If last valid element is smaller, then MAX
719 is returned. */
721 static int
722 find_import_in_list (def_file_import *b, int max,
723 const char *ex_name, const char *in_name,
724 const char *module, int ord, int *is_ident)
726 int e, l, r, p;
728 *is_ident = 0;
729 if (!max)
730 return 0;
731 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
732 return 0;
733 if (max == 1)
734 return 1;
735 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
736 return max;
737 else if (!e || max == 2)
738 return max - 1;
739 l = 0; r = max - 1;
740 while (l < r)
742 p = (l + r) / 2;
743 e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
744 if (!e)
746 *is_ident = 1;
747 return p;
749 else if (e < 0)
750 r = p - 1;
751 else if (e > 0)
752 l = p + 1;
754 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
755 ++l;
756 else if (!e)
757 *is_ident = 1;
758 return l;
761 def_file_import *
762 def_file_add_import (def_file *fdef,
763 const char *name,
764 const char *module,
765 int ordinal,
766 const char *internal_name,
767 const char *its_name,
768 int *is_dup)
770 def_file_import *i;
771 int pos;
772 int max_imports = ROUND_UP (fdef->num_imports, 16);
774 /* We need to avoid here duplicates. */
775 *is_dup = 0;
776 pos = find_import_in_list (fdef->imports, fdef->num_imports,
777 name,
778 (!internal_name ? name : internal_name),
779 module, ordinal, is_dup);
780 if (*is_dup != 0)
781 return fdef->imports + pos;
783 if (fdef->num_imports >= max_imports)
785 max_imports = ROUND_UP (fdef->num_imports+1, 16);
787 if (fdef->imports)
788 fdef->imports = xrealloc (fdef->imports,
789 max_imports * sizeof (def_file_import));
790 else
791 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
793 i = fdef->imports + pos;
794 if (pos != fdef->num_imports)
795 memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos)));
796 memset (i, 0, sizeof (def_file_import));
797 if (name)
798 i->name = xstrdup (name);
799 if (module)
800 i->module = def_stash_module (fdef, module);
801 i->ordinal = ordinal;
802 if (internal_name)
803 i->internal_name = xstrdup (internal_name);
804 else
805 i->internal_name = i->name;
806 i->its_name = (its_name ? xstrdup (its_name) : NULL);
807 fdef->num_imports++;
809 return i;
812 struct
814 char *param;
815 int token;
817 diropts[] =
819 { "-heap", HEAPSIZE },
820 { "-stack", STACKSIZE_K },
821 { "-attr", SECTIONS },
822 { "-export", EXPORTS },
823 { "-aligncomm", ALIGNCOMM },
824 { 0, 0 }
827 void
828 def_file_add_directive (def_file *my_def, const char *param, int len)
830 def_file *save_def = def;
831 const char *pend = param + len;
832 char * tend = (char *) param;
833 int i;
835 def = my_def;
837 while (param < pend)
839 while (param < pend
840 && (ISSPACE (*param) || *param == '\n' || *param == 0))
841 param++;
843 if (param == pend)
844 break;
846 /* Scan forward until we encounter any of:
847 - the end of the buffer
848 - the start of a new option
849 - a newline seperating options
850 - a NUL seperating options. */
851 for (tend = (char *) (param + 1);
852 (tend < pend
853 && !(ISSPACE (tend[-1]) && *tend == '-')
854 && *tend != '\n' && *tend != 0);
855 tend++)
858 for (i = 0; diropts[i].param; i++)
860 len = strlen (diropts[i].param);
862 if (tend - param >= len
863 && strncmp (param, diropts[i].param, len) == 0
864 && (param[len] == ':' || param[len] == ' '))
866 lex_parse_string_end = tend;
867 lex_parse_string = param + len + 1;
868 lex_forced_token = diropts[i].token;
869 saw_newline = 0;
870 if (def_parse ())
871 continue;
872 break;
876 if (!diropts[i].param)
878 char saved;
880 saved = * tend;
881 * tend = 0;
882 /* xgettext:c-format */
883 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
884 * tend = saved;
887 lex_parse_string = 0;
888 param = tend;
891 def = save_def;
892 def_pool_free ();
895 /* Parser Callbacks. */
897 static void
898 def_image_name (const char *name, int base, int is_dll)
900 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
901 to do here. We retain the output filename specified on command line. */
902 if (*name)
904 const char* image_name = lbasename (name);
906 if (image_name != name)
907 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
908 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
909 name);
910 if (def->name)
911 free (def->name);
912 /* Append the default suffix, if none specified. */
913 if (strchr (image_name, '.') == 0)
915 const char * suffix = is_dll ? ".dll" : ".exe";
917 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
918 sprintf (def->name, "%s%s", image_name, suffix);
920 else
921 def->name = xstrdup (image_name);
924 /* Honor a BASE address statement, even if LIBRARY string is empty. */
925 def->base_address = base;
926 def->is_dll = is_dll;
929 static void
930 def_description (const char *text)
932 int len = def->description ? strlen (def->description) : 0;
934 len += strlen (text) + 1;
935 if (def->description)
937 def->description = xrealloc (def->description, len);
938 strcat (def->description, text);
940 else
942 def->description = xmalloc (len);
943 strcpy (def->description, text);
947 static void
948 def_stacksize (int reserve, int commit)
950 def->stack_reserve = reserve;
951 def->stack_commit = commit;
954 static void
955 def_heapsize (int reserve, int commit)
957 def->heap_reserve = reserve;
958 def->heap_commit = commit;
961 static void
962 def_section (const char *name, int attr)
964 def_file_section *s;
965 int max_sections = ROUND_UP (def->num_section_defs, 4);
967 if (def->num_section_defs >= max_sections)
969 max_sections = ROUND_UP (def->num_section_defs+1, 4);
971 if (def->section_defs)
972 def->section_defs = xrealloc (def->section_defs,
973 max_sections * sizeof (def_file_import));
974 else
975 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
977 s = def->section_defs + def->num_section_defs;
978 memset (s, 0, sizeof (def_file_section));
979 s->name = xstrdup (name);
980 if (attr & 1)
981 s->flag_read = 1;
982 if (attr & 2)
983 s->flag_write = 1;
984 if (attr & 4)
985 s->flag_execute = 1;
986 if (attr & 8)
987 s->flag_shared = 1;
989 def->num_section_defs++;
992 static void
993 def_section_alt (const char *name, const char *attr)
995 int aval = 0;
997 for (; *attr; attr++)
999 switch (*attr)
1001 case 'R':
1002 case 'r':
1003 aval |= 1;
1004 break;
1005 case 'W':
1006 case 'w':
1007 aval |= 2;
1008 break;
1009 case 'X':
1010 case 'x':
1011 aval |= 4;
1012 break;
1013 case 'S':
1014 case 's':
1015 aval |= 8;
1016 break;
1019 def_section (name, aval);
1022 static void
1023 def_exports (const char *external_name,
1024 const char *internal_name,
1025 int ordinal,
1026 int flags,
1027 const char *its_name)
1029 def_file_export *dfe;
1030 int is_dup = 0;
1032 if (!internal_name && external_name)
1033 internal_name = external_name;
1034 #if TRACE
1035 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1036 #endif
1038 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
1039 its_name, &is_dup);
1041 /* We might check here for flag redefinition and warn. For now we
1042 ignore duplicates silently. */
1043 if (is_dup)
1044 return;
1046 if (flags & 1)
1047 dfe->flag_noname = 1;
1048 if (flags & 2)
1049 dfe->flag_constant = 1;
1050 if (flags & 4)
1051 dfe->flag_data = 1;
1052 if (flags & 8)
1053 dfe->flag_private = 1;
1056 static void
1057 def_import (const char *internal_name,
1058 const char *module,
1059 const char *dllext,
1060 const char *name,
1061 int ordinal,
1062 const char *its_name)
1064 char *buf = 0;
1065 const char *ext = dllext ? dllext : "dll";
1066 int is_dup = 0;
1068 buf = xmalloc (strlen (module) + strlen (ext) + 2);
1069 sprintf (buf, "%s.%s", module, ext);
1070 module = buf;
1072 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1073 &is_dup);
1074 free (buf);
1077 static void
1078 def_version (int major, int minor)
1080 def->version_major = major;
1081 def->version_minor = minor;
1084 static void
1085 def_directive (char *str)
1087 struct directive *d = xmalloc (sizeof (struct directive));
1089 d->next = directives;
1090 directives = d;
1091 d->name = xstrdup (str);
1092 d->len = strlen (str);
1095 static void
1096 def_aligncomm (char *str, int align)
1098 def_file_aligncomm *c, *p;
1100 p = NULL;
1101 c = def->aligncomms;
1102 while (c != NULL)
1104 int e = strcmp (c->symbol_name, str);
1105 if (!e)
1107 /* Not sure if we want to allow here duplicates with
1108 different alignments, but for now we keep them. */
1109 e = (int) c->alignment - align;
1110 if (!e)
1111 return;
1113 if (e > 0)
1114 break;
1115 c = (p = c)->next;
1118 c = xmalloc (sizeof (def_file_aligncomm));
1119 c->symbol_name = xstrdup (str);
1120 c->alignment = (unsigned int) align;
1121 if (!p)
1123 c->next = def->aligncomms;
1124 def->aligncomms = c;
1126 else
1128 c->next = p->next;
1129 p->next = c;
1133 static int
1134 def_error (const char *err)
1136 einfo ("%P: %s:%d: %s\n",
1137 def_filename ? def_filename : "<unknown-file>", linenumber, err);
1138 return 0;
1142 /* Lexical Scanner. */
1144 #undef TRACE
1145 #define TRACE 0
1147 /* Never freed, but always reused as needed, so no real leak. */
1148 static char *buffer = 0;
1149 static int buflen = 0;
1150 static int bufptr = 0;
1152 static void
1153 put_buf (char c)
1155 if (bufptr == buflen)
1157 buflen += 50; /* overly reasonable, eh? */
1158 if (buffer)
1159 buffer = xrealloc (buffer, buflen + 1);
1160 else
1161 buffer = xmalloc (buflen + 1);
1163 buffer[bufptr++] = c;
1164 buffer[bufptr] = 0; /* not optimal, but very convenient. */
1167 static struct
1169 char *name;
1170 int token;
1172 tokens[] =
1174 { "BASE", BASE },
1175 { "CODE", CODE },
1176 { "CONSTANT", CONSTANTU },
1177 { "constant", CONSTANTL },
1178 { "DATA", DATAU },
1179 { "data", DATAL },
1180 { "DESCRIPTION", DESCRIPTION },
1181 { "DIRECTIVE", DIRECTIVE },
1182 { "EXECUTE", EXECUTE },
1183 { "EXPORTS", EXPORTS },
1184 { "HEAPSIZE", HEAPSIZE },
1185 { "IMPORTS", IMPORTS },
1186 { "LIBRARY", LIBRARY },
1187 { "NAME", NAME },
1188 { "NONAME", NONAMEU },
1189 { "noname", NONAMEL },
1190 { "PRIVATE", PRIVATEU },
1191 { "private", PRIVATEL },
1192 { "READ", READ },
1193 { "SECTIONS", SECTIONS },
1194 { "SEGMENTS", SECTIONS },
1195 { "SHARED", SHARED },
1196 { "STACKSIZE", STACKSIZE_K },
1197 { "VERSION", VERSIONK },
1198 { "WRITE", WRITE },
1199 { 0, 0 }
1202 static int
1203 def_getc (void)
1205 int rv;
1207 if (lex_parse_string)
1209 if (lex_parse_string >= lex_parse_string_end)
1210 rv = EOF;
1211 else
1212 rv = *lex_parse_string++;
1214 else
1216 rv = fgetc (the_file);
1218 if (rv == '\n')
1219 saw_newline = 1;
1220 return rv;
1223 static int
1224 def_ungetc (int c)
1226 if (lex_parse_string)
1228 lex_parse_string--;
1229 return c;
1231 else
1232 return ungetc (c, the_file);
1235 static int
1236 def_lex (void)
1238 int c, i, q;
1240 if (lex_forced_token)
1242 i = lex_forced_token;
1243 lex_forced_token = 0;
1244 #if TRACE
1245 printf ("lex: forcing token %d\n", i);
1246 #endif
1247 return i;
1250 c = def_getc ();
1252 /* Trim leading whitespace. */
1253 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1254 c = def_getc ();
1256 if (c == EOF)
1258 #if TRACE
1259 printf ("lex: EOF\n");
1260 #endif
1261 return 0;
1264 if (saw_newline && c == ';')
1268 c = def_getc ();
1270 while (c != EOF && c != '\n');
1271 if (c == '\n')
1272 return def_lex ();
1273 return 0;
1276 /* Must be something else. */
1277 saw_newline = 0;
1279 if (ISDIGIT (c))
1281 bufptr = 0;
1282 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1284 put_buf (c);
1285 c = def_getc ();
1287 if (c != EOF)
1288 def_ungetc (c);
1289 yylval.digits = def_pool_strdup (buffer);
1290 #if TRACE
1291 printf ("lex: `%s' returns DIGITS\n", buffer);
1292 #endif
1293 return DIGITS;
1296 if (ISALPHA (c) || strchr ("$:-_?@", c))
1298 bufptr = 0;
1299 q = c;
1300 put_buf (c);
1301 c = def_getc ();
1303 if (q == '@')
1305 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1306 return (q);
1307 else if (ISDIGIT (c)) /* '@' followed by digit. */
1309 def_ungetc (c);
1310 return (q);
1312 #if TRACE
1313 printf ("lex: @ returns itself\n");
1314 #endif
1317 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1319 put_buf (c);
1320 c = def_getc ();
1322 if (c != EOF)
1323 def_ungetc (c);
1324 if (ISALPHA (q)) /* Check for tokens. */
1326 for (i = 0; tokens[i].name; i++)
1327 if (strcmp (tokens[i].name, buffer) == 0)
1329 #if TRACE
1330 printf ("lex: `%s' is a string token\n", buffer);
1331 #endif
1332 return tokens[i].token;
1335 #if TRACE
1336 printf ("lex: `%s' returns ID\n", buffer);
1337 #endif
1338 yylval.id = def_pool_strdup (buffer);
1339 return ID;
1342 if (c == '\'' || c == '"')
1344 q = c;
1345 c = def_getc ();
1346 bufptr = 0;
1348 while (c != EOF && c != q)
1350 put_buf (c);
1351 c = def_getc ();
1353 yylval.id = def_pool_strdup (buffer);
1354 #if TRACE
1355 printf ("lex: `%s' returns ID\n", buffer);
1356 #endif
1357 return ID;
1360 if ( c == '=')
1362 c = def_getc ();
1363 if (c == '=')
1365 #if TRACE
1366 printf ("lex: `==' returns EQUAL\n");
1367 #endif
1368 return EQUAL;
1370 def_ungetc (c);
1371 #if TRACE
1372 printf ("lex: `=' returns itself\n");
1373 #endif
1374 return '=';
1376 if (c == '.' || c == ',')
1378 #if TRACE
1379 printf ("lex: `%c' returns itself\n", c);
1380 #endif
1381 return c;
1384 if (c == '\n')
1386 linenumber++;
1387 saw_newline = 1;
1390 /*printf ("lex: 0x%02x ignored\n", c); */
1391 return def_lex ();
1394 static char *
1395 def_pool_alloc (size_t sz)
1397 def_pool_str *e;
1399 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1400 e->next = pool_strs;
1401 pool_strs = e;
1402 return e->data;
1405 static char *
1406 def_pool_strdup (const char *str)
1408 char *s;
1409 size_t len;
1410 if (!str)
1411 return NULL;
1412 len = strlen (str) + 1;
1413 s = def_pool_alloc (len);
1414 memcpy (s, str, len);
1415 return s;
1418 static void
1419 def_pool_free (void)
1421 def_pool_str *p;
1422 while ((p = pool_strs) != NULL)
1424 pool_strs = p->next;
1425 free (p);