Fix RELOC_FOR_GLOBAL_SYMBOLS macro so that it can cope with user defined symbols...
[binutils-gdb.git] / ld / deffilep.y
blobfb12e6dc7b858d604d8bdd26b14f4e3f70becb92
1 %{ /* deffilep.y - parser for .def files */
3 /* Copyright (C) 1995-2024 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
22 #include "sysdep.h"
23 #include "libiberty.h"
24 #include "safe-ctype.h"
25 #include "bfd.h"
26 #include "bfdlink.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 #define SYMBOL_LIST_ARRAY_GROW 64
37 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
38 as well as gratuitiously global symbol names, so we can have multiple
39 yacc generated parsers in ld. Note that these are only the variables
40 produced by yacc. If other parser generators (bison, byacc, etc) produce
41 additional global names that conflict at link time, then those parser
42 generators need to be fixed instead of adding those names to this list. */
44 #define yymaxdepth def_maxdepth
45 #define yyparse def_parse
46 #define yylex def_lex
47 #define yyerror def_error
48 #define yylval def_lval
49 #define yychar def_char
50 #define yydebug def_debug
51 #define yypact def_pact
52 #define yyr1 def_r1
53 #define yyr2 def_r2
54 #define yydef def_def
55 #define yychk def_chk
56 #define yypgo def_pgo
57 #define yyact def_act
58 #define yyexca def_exca
59 #define yyerrflag def_errflag
60 #define yynerrs def_nerrs
61 #define yyps def_ps
62 #define yypv def_pv
63 #define yys def_s
64 #define yy_yys def_yys
65 #define yystate def_state
66 #define yytmp def_tmp
67 #define yyv def_v
68 #define yy_yyv def_yyv
69 #define yyval def_val
70 #define yylloc def_lloc
71 #define yyreds def_reds /* With YYDEBUG defined. */
72 #define yytoks def_toks /* With YYDEBUG defined. */
73 #define yylhs def_yylhs
74 #define yylen def_yylen
75 #define yydefred def_yydefred
76 #define yydgoto def_yydgoto
77 #define yysindex def_yysindex
78 #define yyrindex def_yyrindex
79 #define yygindex def_yygindex
80 #define yytable def_yytable
81 #define yycheck def_yycheck
83 typedef struct def_pool_str {
84 struct def_pool_str *next;
85 char data[1];
86 } def_pool_str;
88 static def_pool_str *pool_strs = NULL;
90 static char *def_pool_alloc (size_t sz);
91 static char *def_pool_strdup (const char *str);
92 static void def_pool_free (void);
94 static void def_description (const char *);
95 static void def_exports (const char *, const char *, int, int, const char *);
96 static void def_heapsize (int, int);
97 static void def_import (const char *, const char *, const char *, const char *,
98 int, const char *);
99 static void def_image_name (const char *, bfd_vma, int);
100 static void def_section (const char *, int);
101 static void def_section_alt (const char *, const char *);
102 static void def_stacksize (int, int);
103 static void def_version (int, int);
104 static void def_directive (char *);
105 static void def_aligncomm (char *str, int align);
106 static void def_exclude_symbols (char *str);
107 static int def_parse (void);
108 static void def_error (const char *);
109 static int def_lex (void);
111 static int lex_forced_token = 0;
112 static const char *lex_parse_string = 0;
113 static const char *lex_parse_string_end = 0;
117 %union {
118 char *id;
119 const char *id_const;
120 int number;
121 bfd_vma vma;
122 char *digits;
125 %token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
126 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
127 %token PRIVATEU PRIVATEL ALIGNCOMM EXCLUDE_SYMBOLS
128 %token READ WRITE EXECUTE SHARED_K NONAMEU NONAMEL DIRECTIVE EQUAL
129 %token <id> ID
130 %token <digits> DIGITS
131 %type <number> NUMBER
132 %type <vma> VMA opt_base
133 %type <digits> opt_digits
134 %type <number> opt_ordinal
135 %type <number> attr attr_list opt_number exp_opt_list exp_opt
136 %type <id> opt_name opt_name2 opt_equal_name anylang_id opt_id
137 %type <id> opt_equalequal_name symbol_list
138 %type <id_const> keyword_as_name
142 start: start command
143 | command
146 command:
147 NAME opt_name opt_base { def_image_name ($2, $3, 0); }
148 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
149 | DESCRIPTION ID { def_description ($2);}
150 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);}
151 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
152 | CODE attr_list { def_section ("CODE", $2);}
153 | DATAU attr_list { def_section ("DATA", $2);}
154 | SECTIONS seclist
155 | EXPORTS explist
156 | IMPORTS implist
157 | VERSIONK NUMBER { def_version ($2, 0);}
158 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
159 | DIRECTIVE ID { def_directive ($2);}
160 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);}
161 | EXCLUDE_SYMBOLS symbol_list
165 explist:
166 /* EMPTY */
167 | expline
168 | explist expline
171 expline:
172 /* The opt_comma is necessary to support both the usual
173 DEF file syntax as well as .drectve syntax which
174 mandates <expsym>,<expoptlist>. */
175 opt_name2 opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name
176 { def_exports ($1, $2, $3, $5, $7); }
178 exp_opt_list:
179 /* The opt_comma is necessary to support both the usual
180 DEF file syntax as well as .drectve syntax which
181 allows for comma separated opt list. */
182 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
183 | { $$ = 0; }
185 exp_opt:
186 NONAMEU { $$ = 1; }
187 | NONAMEL { $$ = 1; }
188 | CONSTANTU { $$ = 2; }
189 | CONSTANTL { $$ = 2; }
190 | DATAU { $$ = 4; }
191 | DATAL { $$ = 4; }
192 | PRIVATEU { $$ = 8; }
193 | PRIVATEL { $$ = 8; }
195 implist:
196 implist impline
197 | impline
200 impline:
201 ID '=' ID '.' ID '.' ID opt_equalequal_name
202 { def_import ($1, $3, $5, $7, -1, $8); }
203 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name
204 { def_import ($1, $3, $5, 0, $7, $8); }
205 | ID '=' ID '.' ID opt_equalequal_name
206 { def_import ($1, $3, 0, $5, -1, $6); }
207 | ID '=' ID '.' NUMBER opt_equalequal_name
208 { def_import ($1, $3, 0, 0, $5, $6); }
209 | ID '.' ID '.' ID opt_equalequal_name
210 { def_import( 0, $1, $3, $5, -1, $6); }
211 | ID '.' ID opt_equalequal_name
212 { def_import ( 0, $1, 0, $3, -1, $4); }
215 seclist:
216 seclist secline
217 | secline
220 secline:
221 ID attr_list { def_section ($1, $2);}
222 | ID ID { def_section_alt ($1, $2);}
225 attr_list:
226 attr_list opt_comma attr { $$ = $1 | $3; }
227 | attr { $$ = $1; }
230 opt_comma:
234 opt_number: ',' NUMBER { $$=$2;}
235 | { $$=-1;}
238 attr:
239 READ { $$ = 1;}
240 | WRITE { $$ = 2;}
241 | EXECUTE { $$=4;}
242 | SHARED_K { $$=8;}
246 keyword_as_name: BASE { $$ = "BASE"; }
247 | CODE { $$ = "CODE"; }
248 | CONSTANTU { $$ = "CONSTANT"; }
249 | CONSTANTL { $$ = "constant"; }
250 | DATAU { $$ = "DATA"; }
251 | DATAL { $$ = "data"; }
252 | DESCRIPTION { $$ = "DESCRIPTION"; }
253 | DIRECTIVE { $$ = "DIRECTIVE"; }
254 | EXCLUDE_SYMBOLS { $$ = "EXCLUDE_SYMBOLS"; }
255 | EXECUTE { $$ = "EXECUTE"; }
256 | EXPORTS { $$ = "EXPORTS"; }
257 | HEAPSIZE { $$ = "HEAPSIZE"; }
258 | IMPORTS { $$ = "IMPORTS"; }
259 /* Disable LIBRARY keyword as valid symbol-name. This is necessary
260 for libtool, which places this command after EXPORTS command.
261 This behavior is illegal by specification, but sadly required by
262 by compatibility reasons.
263 See PR binutils/13710
264 | LIBRARY { $$ = "LIBRARY"; } */
265 | NAME { $$ = "NAME"; }
266 | NONAMEU { $$ = "NONAME"; }
267 | NONAMEL { $$ = "noname"; }
268 | PRIVATEU { $$ = "PRIVATE"; }
269 | PRIVATEL { $$ = "private"; }
270 | READ { $$ = "READ"; }
271 | SHARED_K { $$ = "SHARED"; }
272 | STACKSIZE_K { $$ = "STACKSIZE"; }
273 | VERSIONK { $$ = "VERSION"; }
274 | WRITE { $$ = "WRITE"; }
277 opt_name2: ID { $$ = $1; }
278 | '.' keyword_as_name
280 char *name = xmalloc (strlen ($2) + 2);
281 sprintf (name, ".%s", $2);
282 $$ = name;
284 | '.' opt_name2
286 char *name = def_pool_alloc (strlen ($2) + 2);
287 sprintf (name, ".%s", $2);
288 $$ = name;
290 | keyword_as_name '.' opt_name2
292 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
293 sprintf (name, "%s.%s", $1, $3);
294 $$ = name;
296 | ID '.' opt_name2
298 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
299 sprintf (name, "%s.%s", $1, $3);
300 $$ = name;
304 opt_name: opt_name2 { $$ = $1; }
305 | { $$ = ""; }
308 opt_equalequal_name: EQUAL ID { $$ = $2; }
309 | { $$ = 0; }
312 opt_ordinal:
313 '@' NUMBER { $$ = $2;}
314 | { $$ = -1;}
317 opt_equal_name:
318 '=' opt_name2 { $$ = $2; }
319 | { $$ = 0; }
322 opt_base: BASE '=' VMA { $$ = $3;}
323 | { $$ = (bfd_vma) -1;}
326 anylang_id: ID { $$ = $1; }
327 | '.' ID
329 char *id = def_pool_alloc (strlen ($2) + 2);
330 sprintf (id, ".%s", $2);
331 $$ = id;
333 | anylang_id '.' opt_digits opt_id
335 char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
336 sprintf (id, "%s.%s%s", $1, $3, $4);
337 $$ = id;
341 symbol_list:
342 anylang_id { def_exclude_symbols ($1); }
343 | symbol_list anylang_id { def_exclude_symbols ($2); }
344 | symbol_list ',' anylang_id { def_exclude_symbols ($3); }
347 opt_digits: DIGITS { $$ = $1; }
348 | { $$ = ""; }
351 opt_id: ID { $$ = $1; }
352 | { $$ = ""; }
355 NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); }
357 VMA: DIGITS { $$ = (bfd_vma) strtoull ($1, 0, 0); }
361 /*****************************************************************************
363 *****************************************************************************/
365 static FILE *the_file;
366 static const char *def_filename;
367 static int linenumber;
368 static def_file *def;
369 static int saw_newline;
371 struct directive
373 struct directive *next;
374 char *name;
375 int len;
378 static struct directive *directives = 0;
380 def_file *
381 def_file_empty (void)
383 def_file *rv = xmalloc (sizeof (def_file));
384 memset (rv, 0, sizeof (def_file));
385 rv->is_dll = -1;
386 rv->base_address = (bfd_vma) -1;
387 rv->stack_reserve = rv->stack_commit = -1;
388 rv->heap_reserve = rv->heap_commit = -1;
389 rv->version_major = rv->version_minor = -1;
390 return rv;
393 def_file *
394 def_file_parse (const char *filename, def_file *add_to)
396 struct directive *d;
398 the_file = fopen (filename, "r");
399 def_filename = filename;
400 linenumber = 1;
401 if (!the_file)
403 perror (filename);
404 return 0;
406 if (add_to)
408 def = add_to;
410 else
412 def = def_file_empty ();
415 saw_newline = 1;
416 if (def_parse ())
418 def_file_free (def);
419 fclose (the_file);
420 def_pool_free ();
421 return 0;
424 fclose (the_file);
426 while ((d = directives) != NULL)
428 #if TRACE
429 printf ("Adding directive %08x `%s'\n", d->name, d->name);
430 #endif
431 def_file_add_directive (def, d->name, d->len);
432 directives = d->next;
433 free (d->name);
434 free (d);
436 def_pool_free ();
438 return def;
441 void
442 def_file_free (def_file *fdef)
444 int i;
445 unsigned int ui;
447 if (!fdef)
448 return;
449 free (fdef->name);
450 free (fdef->description);
452 if (fdef->section_defs)
454 for (i = 0; i < fdef->num_section_defs; i++)
456 free (fdef->section_defs[i].name);
457 free (fdef->section_defs[i].class);
459 free (fdef->section_defs);
462 for (i = 0; i < fdef->num_exports; i++)
464 if (fdef->exports[i].internal_name != fdef->exports[i].name)
465 free (fdef->exports[i].internal_name);
466 free (fdef->exports[i].name);
467 free (fdef->exports[i].its_name);
469 free (fdef->exports);
471 for (i = 0; i < fdef->num_imports; i++)
473 if (fdef->imports[i].internal_name != fdef->imports[i].name)
474 free (fdef->imports[i].internal_name);
475 free (fdef->imports[i].name);
476 free (fdef->imports[i].its_name);
478 free (fdef->imports);
480 while (fdef->modules)
482 def_file_module *m = fdef->modules;
484 fdef->modules = fdef->modules->next;
485 free (m);
488 while (fdef->aligncomms)
490 def_file_aligncomm *c = fdef->aligncomms;
492 fdef->aligncomms = fdef->aligncomms->next;
493 free (c->symbol_name);
494 free (c);
497 for (ui = 0; ui < fdef->num_exclude_symbols; ui++)
499 free (fdef->exclude_symbols[ui].symbol_name);
501 free (fdef->exclude_symbols);
503 free (fdef);
506 #ifdef DEF_FILE_PRINT
507 void
508 def_file_print (FILE *file, def_file *fdef)
510 int i;
512 fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
513 if (fdef->name)
514 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)");
515 if (fdef->is_dll != -1)
516 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no");
517 if (fdef->base_address != (bfd_vma) -1)
518 fprintf (file, " base address: 0x%" PRIx64 "\n",
519 (uint64_t) fdef->base_address);
520 if (fdef->description)
521 fprintf (file, " description: `%s'\n", fdef->description);
522 if (fdef->stack_reserve != -1)
523 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
524 if (fdef->stack_commit != -1)
525 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
526 if (fdef->heap_reserve != -1)
527 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
528 if (fdef->heap_commit != -1)
529 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
531 if (fdef->num_section_defs > 0)
533 fprintf (file, " section defs:\n");
535 for (i = 0; i < fdef->num_section_defs; i++)
537 fprintf (file, " name: `%s', class: `%s', flags:",
538 fdef->section_defs[i].name, fdef->section_defs[i].class);
539 if (fdef->section_defs[i].flag_read)
540 fprintf (file, " R");
541 if (fdef->section_defs[i].flag_write)
542 fprintf (file, " W");
543 if (fdef->section_defs[i].flag_execute)
544 fprintf (file, " X");
545 if (fdef->section_defs[i].flag_shared)
546 fprintf (file, " S");
547 fprintf (file, "\n");
551 if (fdef->num_exports > 0)
553 fprintf (file, " exports:\n");
555 for (i = 0; i < fdef->num_exports; i++)
557 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
558 fdef->exports[i].name, fdef->exports[i].internal_name,
559 fdef->exports[i].ordinal);
560 if (fdef->exports[i].flag_private)
561 fprintf (file, " P");
562 if (fdef->exports[i].flag_constant)
563 fprintf (file, " C");
564 if (fdef->exports[i].flag_noname)
565 fprintf (file, " N");
566 if (fdef->exports[i].flag_data)
567 fprintf (file, " D");
568 fprintf (file, "\n");
572 if (fdef->num_imports > 0)
574 fprintf (file, " imports:\n");
576 for (i = 0; i < fdef->num_imports; i++)
578 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
579 fdef->imports[i].internal_name,
580 fdef->imports[i].module,
581 fdef->imports[i].name,
582 fdef->imports[i].ordinal);
586 if (fdef->version_major != -1)
587 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
589 fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
591 #endif
593 /* Helper routine to check for identity of string pointers,
594 which might be NULL. */
596 static int
597 are_names_equal (const char *s1, const char *s2)
599 if (!s1 && !s2)
600 return 0;
601 if (!s1 || !s2)
602 return (!s1 ? -1 : 1);
603 return strcmp (s1, s2);
606 static int
607 cmp_export_elem (const def_file_export *e, const char *ex_name,
608 const char *in_name, const char *its_name,
609 int ord)
611 int r;
613 if ((r = are_names_equal (its_name ? its_name : ex_name,
614 e->its_name ? e->its_name : e->name)) != 0)
615 return r;
616 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
617 return r;
618 return (ord - e->ordinal);
621 /* Search the position of the identical element, or returns the position
622 of the next higher element. If last valid element is smaller, then MAX
623 is returned. The max parameter indicates the number of elements in the
624 array. On return, *is_ident indicates whether the returned array index
625 points at an element which is identical to the one searched for. */
627 static unsigned int
628 find_export_in_list (def_file_export *b, unsigned int max,
629 const char *ex_name, const char *in_name,
630 const char *its_name, int ord, bool *is_ident)
632 int e;
633 unsigned int l, r, p;
635 *is_ident = false;
636 if (!max)
637 return 0;
638 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
640 if (!e)
641 *is_ident = true;
642 return 0;
644 if (max == 1)
645 return 1;
646 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
647 return max;
648 else if (!e || max == 2)
650 if (!e)
651 *is_ident = true;
652 return max - 1;
654 l = 0; r = max - 1;
655 while (l < r)
657 p = (l + r) / 2;
658 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
659 if (!e)
661 *is_ident = true;
662 return p;
664 else if (e < 0)
665 r = p - 1;
666 else if (e > 0)
667 l = p + 1;
669 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
670 ++l;
671 else if (!e)
672 *is_ident = true;
673 return l;
676 def_file_export *
677 def_file_add_export (def_file *fdef,
678 const char *external_name,
679 const char *internal_name,
680 int ordinal,
681 const char *its_name,
682 bool *is_dup)
684 def_file_export *e;
685 unsigned int pos;
687 if (internal_name && !external_name)
688 external_name = internal_name;
689 if (external_name && !internal_name)
690 internal_name = external_name;
692 /* We need to avoid duplicates. */
693 *is_dup = false;
694 pos = find_export_in_list (fdef->exports, fdef->num_exports,
695 external_name, internal_name,
696 its_name, ordinal, is_dup);
698 if (*is_dup)
699 return (fdef->exports + pos);
701 if ((unsigned)fdef->num_exports >= fdef->max_exports)
703 fdef->max_exports += SYMBOL_LIST_ARRAY_GROW;
704 fdef->exports = xrealloc (fdef->exports,
705 fdef->max_exports * sizeof (def_file_export));
708 e = fdef->exports + pos;
709 /* If we're inserting in the middle of the array, we need to move the
710 following elements forward. */
711 if (pos != (unsigned)fdef->num_exports)
712 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
713 /* Wipe the element for use as a new entry. */
714 memset (e, 0, sizeof (def_file_export));
715 e->name = xstrdup (external_name);
716 e->internal_name = xstrdup (internal_name);
717 e->its_name = (its_name ? xstrdup (its_name) : NULL);
718 e->ordinal = ordinal;
719 fdef->num_exports++;
720 return e;
723 def_file_module *
724 def_get_module (def_file *fdef, const char *name)
726 def_file_module *s;
728 for (s = fdef->modules; s; s = s->next)
729 if (strcmp (s->name, name) == 0)
730 return s;
732 return NULL;
735 static def_file_module *
736 def_stash_module (def_file *fdef, const char *name)
738 def_file_module *s;
740 if ((s = def_get_module (fdef, name)) != NULL)
741 return s;
742 s = xmalloc (sizeof (def_file_module) + strlen (name));
743 s->next = fdef->modules;
744 fdef->modules = s;
745 s->user_data = 0;
746 strcpy (s->name, name);
747 return s;
750 static int
751 cmp_import_elem (const def_file_import *e, const char *ex_name,
752 const char *in_name, const char *module,
753 int ord)
755 int r;
757 if ((r = are_names_equal (module, (e->module ? e->module->name : NULL))))
758 return r;
759 if ((r = are_names_equal (ex_name, e->name)) != 0)
760 return r;
761 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
762 return r;
763 if (ord != e->ordinal)
764 return (ord < e->ordinal ? -1 : 1);
765 return 0;
768 /* Search the position of the identical element, or returns the position
769 of the next higher element. If last valid element is smaller, then MAX
770 is returned. The max parameter indicates the number of elements in the
771 array. On return, *is_ident indicates whether the returned array index
772 points at an element which is identical to the one searched for. */
774 static unsigned int
775 find_import_in_list (def_file_import *b, unsigned int max,
776 const char *ex_name, const char *in_name,
777 const char *module, int ord, bool *is_ident)
779 int e;
780 unsigned int l, r, p;
782 *is_ident = false;
783 if (!max)
784 return 0;
785 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
787 if (!e)
788 *is_ident = true;
789 return 0;
791 if (max == 1)
792 return 1;
793 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
794 return max;
795 else if (!e || max == 2)
797 if (!e)
798 *is_ident = true;
799 return max - 1;
801 l = 0; r = max - 1;
802 while (l < r)
804 p = (l + r) / 2;
805 e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
806 if (!e)
808 *is_ident = true;
809 return p;
811 else if (e < 0)
812 r = p - 1;
813 else if (e > 0)
814 l = p + 1;
816 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
817 ++l;
818 else if (!e)
819 *is_ident = true;
820 return l;
823 static void
824 fill_in_import (def_file_import *i,
825 const char *name,
826 def_file_module *module,
827 int ordinal,
828 const char *internal_name,
829 const char *its_name)
831 memset (i, 0, sizeof (def_file_import));
832 if (name)
833 i->name = xstrdup (name);
834 i->module = module;
835 i->ordinal = ordinal;
836 if (internal_name)
837 i->internal_name = xstrdup (internal_name);
838 else
839 i->internal_name = i->name;
840 i->its_name = (its_name ? xstrdup (its_name) : NULL);
843 def_file_import *
844 def_file_add_import (def_file *fdef,
845 const char *name,
846 const char *module,
847 int ordinal,
848 const char *internal_name,
849 const char *its_name,
850 bool *is_dup)
852 def_file_import *i;
853 unsigned int pos;
855 /* We need to avoid here duplicates. */
856 *is_dup = false;
857 pos = find_import_in_list (fdef->imports, fdef->num_imports,
858 name,
859 (!internal_name ? name : internal_name),
860 module, ordinal, is_dup);
861 if (*is_dup)
862 return fdef->imports + pos;
864 if ((unsigned)fdef->num_imports >= fdef->max_imports)
866 fdef->max_imports += SYMBOL_LIST_ARRAY_GROW;
867 fdef->imports = xrealloc (fdef->imports,
868 fdef->max_imports * sizeof (def_file_import));
870 i = fdef->imports + pos;
871 /* If we're inserting in the middle of the array, we need to move the
872 following elements forward. */
873 if (pos != (unsigned)fdef->num_imports)
874 memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
876 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
877 internal_name, its_name);
878 fdef->num_imports++;
880 return i;
884 def_file_add_import_from (def_file *fdef,
885 int num_imports,
886 const char *name,
887 const char *module,
888 int ordinal,
889 const char *internal_name,
890 const char *its_name ATTRIBUTE_UNUSED)
892 def_file_import *i;
893 bool is_dup;
894 unsigned int pos;
896 /* We need to avoid here duplicates. */
897 is_dup = false;
898 pos = find_import_in_list (fdef->imports, fdef->num_imports,
899 name, internal_name ? internal_name : name,
900 module, ordinal, &is_dup);
901 if (is_dup)
902 return -1;
903 if (fdef->imports && pos != (unsigned)fdef->num_imports)
905 i = fdef->imports + pos;
906 if (i->module && strcmp (i->module->name, module) == 0)
907 return -1;
910 if ((unsigned)fdef->num_imports + num_imports - 1 >= fdef->max_imports)
912 fdef->max_imports = fdef->num_imports + num_imports +
913 SYMBOL_LIST_ARRAY_GROW;
915 fdef->imports = xrealloc (fdef->imports,
916 fdef->max_imports * sizeof (def_file_import));
918 i = fdef->imports + pos;
919 /* If we're inserting in the middle of the array, we need to move the
920 following elements forward. */
921 if (pos != (unsigned)fdef->num_imports)
922 memmove (i + num_imports, i,
923 sizeof (def_file_import) * (fdef->num_imports - pos));
925 return pos;
928 def_file_import *
929 def_file_add_import_at (def_file *fdef,
930 int pos,
931 const char *name,
932 const char *module,
933 int ordinal,
934 const char *internal_name,
935 const char *its_name)
937 def_file_import *i = fdef->imports + pos;
939 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
940 internal_name, its_name);
941 fdef->num_imports++;
943 return i;
946 /* Search the position of the identical element, or returns the position
947 of the next higher element. If last valid element is smaller, then MAX
948 is returned. The max parameter indicates the number of elements in the
949 array. On return, *is_ident indicates whether the returned array index
950 points at an element which is identical to the one searched for. */
952 static unsigned int
953 find_exclude_in_list (def_file_exclude_symbol *b, unsigned int max,
954 const char *name, bool *is_ident)
956 int e;
957 unsigned int l, r, p;
959 *is_ident = false;
960 if (!max)
961 return 0;
962 if ((e = strcmp (b[0].symbol_name, name)) <= 0)
964 if (!e)
965 *is_ident = true;
966 return 0;
968 if (max == 1)
969 return 1;
970 if ((e = strcmp (b[max - 1].symbol_name, name)) > 0)
971 return max;
972 else if (!e || max == 2)
974 if (!e)
975 *is_ident = true;
976 return max - 1;
978 l = 0; r = max - 1;
979 while (l < r)
981 p = (l + r) / 2;
982 e = strcmp (b[p].symbol_name, name);
983 if (!e)
985 *is_ident = true;
986 return p;
988 else if (e < 0)
989 r = p - 1;
990 else if (e > 0)
991 l = p + 1;
993 if ((e = strcmp (b[l].symbol_name, name)) > 0)
994 ++l;
995 else if (!e)
996 *is_ident = true;
997 return l;
1000 static def_file_exclude_symbol *
1001 def_file_add_exclude_symbol (def_file *fdef, const char *name)
1003 def_file_exclude_symbol *e;
1004 unsigned pos;
1005 bool is_dup = false;
1007 pos = find_exclude_in_list (fdef->exclude_symbols, fdef->num_exclude_symbols,
1008 name, &is_dup);
1010 /* We need to avoid duplicates. */
1011 if (is_dup)
1012 return (fdef->exclude_symbols + pos);
1014 if (fdef->num_exclude_symbols >= fdef->max_exclude_symbols)
1016 fdef->max_exclude_symbols += SYMBOL_LIST_ARRAY_GROW;
1017 fdef->exclude_symbols = xrealloc (fdef->exclude_symbols,
1018 fdef->max_exclude_symbols * sizeof (def_file_exclude_symbol));
1021 e = fdef->exclude_symbols + pos;
1022 /* If we're inserting in the middle of the array, we need to move the
1023 following elements forward. */
1024 if (pos != fdef->num_exclude_symbols)
1025 memmove (&e[1], e, (sizeof (def_file_exclude_symbol) * (fdef->num_exclude_symbols - pos)));
1026 /* Wipe the element for use as a new entry. */
1027 memset (e, 0, sizeof (def_file_exclude_symbol));
1028 e->symbol_name = xstrdup (name);
1029 fdef->num_exclude_symbols++;
1030 return e;
1033 struct
1035 char *param;
1036 int token;
1038 diropts[] =
1040 { "-heap", HEAPSIZE },
1041 { "-stack", STACKSIZE_K },
1042 { "-attr", SECTIONS },
1043 { "-export", EXPORTS },
1044 { "-aligncomm", ALIGNCOMM },
1045 { "-exclude-symbols", EXCLUDE_SYMBOLS },
1046 { 0, 0 }
1049 void
1050 def_file_add_directive (def_file *my_def, const char *param, int len)
1052 def_file *save_def = def;
1053 const char *pend = param + len;
1054 char * tend = (char *) param;
1055 int i;
1057 def = my_def;
1059 while (param < pend)
1061 while (param < pend
1062 && (ISSPACE (*param) || *param == '\n' || *param == 0))
1063 param++;
1065 if (param == pend)
1066 break;
1068 /* Scan forward until we encounter any of:
1069 - the end of the buffer
1070 - the start of a new option
1071 - a newline separating options
1072 - a NUL separating options. */
1073 for (tend = (char *) (param + 1);
1074 (tend < pend
1075 && !(ISSPACE (tend[-1]) && *tend == '-')
1076 && *tend != '\n' && *tend != 0);
1077 tend++)
1080 for (i = 0; diropts[i].param; i++)
1082 len = strlen (diropts[i].param);
1084 if (tend - param >= len
1085 && strncmp (param, diropts[i].param, len) == 0
1086 && (param[len] == ':' || param[len] == ' '))
1088 lex_parse_string_end = tend;
1089 lex_parse_string = param + len + 1;
1090 lex_forced_token = diropts[i].token;
1091 saw_newline = 0;
1092 if (def_parse ())
1093 continue;
1094 break;
1098 if (!diropts[i].param)
1100 if (tend < pend)
1102 char saved;
1104 saved = * tend;
1105 * tend = 0;
1106 /* xgettext:c-format */
1107 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
1108 * tend = saved;
1110 else
1112 einfo (_("Warning: corrupt .drectve at end of def file\n"));
1116 lex_parse_string = 0;
1117 param = tend;
1120 def = save_def;
1121 def_pool_free ();
1124 /* Parser Callbacks. */
1126 static void
1127 def_image_name (const char *name, bfd_vma base, int is_dll)
1129 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
1130 to do here. We retain the output filename specified on command line. */
1131 if (*name)
1133 const char* image_name = lbasename (name);
1135 if (image_name != name)
1136 einfo (_("%s:%d: Warning: path components stripped from %s, '%s'\n"),
1137 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
1138 name);
1139 free (def->name);
1140 /* Append the default suffix, if none specified. */
1141 if (strchr (image_name, '.') == 0)
1143 const char * suffix = is_dll ? ".dll" : ".exe";
1145 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
1146 sprintf (def->name, "%s%s", image_name, suffix);
1148 else
1149 def->name = xstrdup (image_name);
1152 /* Honor a BASE address statement, even if LIBRARY string is empty. */
1153 def->base_address = base;
1154 def->is_dll = is_dll;
1157 static void
1158 def_description (const char *text)
1160 int len = def->description ? strlen (def->description) : 0;
1162 len += strlen (text) + 1;
1163 if (def->description)
1165 def->description = xrealloc (def->description, len);
1166 strcat (def->description, text);
1168 else
1170 def->description = xmalloc (len);
1171 strcpy (def->description, text);
1175 static void
1176 def_stacksize (int reserve, int commit)
1178 def->stack_reserve = reserve;
1179 def->stack_commit = commit;
1182 static void
1183 def_heapsize (int reserve, int commit)
1185 def->heap_reserve = reserve;
1186 def->heap_commit = commit;
1189 static void
1190 def_section (const char *name, int attr)
1192 def_file_section *s;
1193 int max_sections = ROUND_UP (def->num_section_defs, 4);
1195 if (def->num_section_defs >= max_sections)
1197 max_sections = ROUND_UP (def->num_section_defs+1, 4);
1199 if (def->section_defs)
1200 def->section_defs = xrealloc (def->section_defs,
1201 max_sections * sizeof (def_file_import));
1202 else
1203 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
1205 s = def->section_defs + def->num_section_defs;
1206 memset (s, 0, sizeof (def_file_section));
1207 s->name = xstrdup (name);
1208 if (attr & 1)
1209 s->flag_read = 1;
1210 if (attr & 2)
1211 s->flag_write = 1;
1212 if (attr & 4)
1213 s->flag_execute = 1;
1214 if (attr & 8)
1215 s->flag_shared = 1;
1217 def->num_section_defs++;
1220 static void
1221 def_section_alt (const char *name, const char *attr)
1223 int aval = 0;
1225 for (; *attr; attr++)
1227 switch (*attr)
1229 case 'R':
1230 case 'r':
1231 aval |= 1;
1232 break;
1233 case 'W':
1234 case 'w':
1235 aval |= 2;
1236 break;
1237 case 'X':
1238 case 'x':
1239 aval |= 4;
1240 break;
1241 case 'S':
1242 case 's':
1243 aval |= 8;
1244 break;
1247 def_section (name, aval);
1250 static void
1251 def_exports (const char *external_name,
1252 const char *internal_name,
1253 int ordinal,
1254 int flags,
1255 const char *its_name)
1257 def_file_export *dfe;
1258 bool is_dup = false;
1260 if (!internal_name && external_name)
1261 internal_name = external_name;
1262 #if TRACE
1263 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1264 #endif
1266 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
1267 its_name, &is_dup);
1269 /* We might check here for flag redefinition and warn. For now we
1270 ignore duplicates silently. */
1271 if (is_dup)
1272 return;
1274 if (flags & 1)
1275 dfe->flag_noname = 1;
1276 if (flags & 2)
1277 dfe->flag_constant = 1;
1278 if (flags & 4)
1279 dfe->flag_data = 1;
1280 if (flags & 8)
1281 dfe->flag_private = 1;
1284 static void
1285 def_import (const char *internal_name,
1286 const char *module,
1287 const char *dllext,
1288 const char *name,
1289 int ordinal,
1290 const char *its_name)
1292 char *buf = 0;
1293 const char *ext = dllext ? dllext : "dll";
1294 bool is_dup = false;
1296 buf = xmalloc (strlen (module) + strlen (ext) + 2);
1297 sprintf (buf, "%s.%s", module, ext);
1298 module = buf;
1300 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1301 &is_dup);
1302 free (buf);
1305 static void
1306 def_version (int major, int minor)
1308 def->version_major = major;
1309 def->version_minor = minor;
1312 static void
1313 def_directive (char *str)
1315 struct directive *d = xmalloc (sizeof (struct directive));
1317 d->next = directives;
1318 directives = d;
1319 d->name = xstrdup (str);
1320 d->len = strlen (str);
1323 static void
1324 def_aligncomm (char *str, int align)
1326 def_file_aligncomm *c, *p;
1328 p = NULL;
1329 c = def->aligncomms;
1330 while (c != NULL)
1332 int e = strcmp (c->symbol_name, str);
1333 if (!e)
1335 /* Not sure if we want to allow here duplicates with
1336 different alignments, but for now we keep them. */
1337 e = (int) c->alignment - align;
1338 if (!e)
1339 return;
1341 if (e > 0)
1342 break;
1343 c = (p = c)->next;
1346 c = xmalloc (sizeof (def_file_aligncomm));
1347 c->symbol_name = xstrdup (str);
1348 c->alignment = (unsigned int) align;
1349 if (!p)
1351 c->next = def->aligncomms;
1352 def->aligncomms = c;
1354 else
1356 c->next = p->next;
1357 p->next = c;
1361 static void
1362 def_exclude_symbols (char *str)
1364 def_file_add_exclude_symbol (def, str);
1367 static void
1368 def_error (const char *err)
1370 einfo ("%P: %s:%d: %s\n",
1371 def_filename ? def_filename : "<unknown-file>", linenumber, err);
1375 /* Lexical Scanner. */
1377 #undef TRACE
1378 #define TRACE 0
1380 /* Never freed, but always reused as needed, so no real leak. */
1381 static char *buffer = 0;
1382 static int buflen = 0;
1383 static int bufptr = 0;
1385 static void
1386 put_buf (char c)
1388 if (bufptr == buflen)
1390 buflen += 50; /* overly reasonable, eh? */
1391 if (buffer)
1392 buffer = xrealloc (buffer, buflen + 1);
1393 else
1394 buffer = xmalloc (buflen + 1);
1396 buffer[bufptr++] = c;
1397 buffer[bufptr] = 0; /* not optimal, but very convenient. */
1400 static struct
1402 char *name;
1403 int token;
1405 tokens[] =
1407 { "BASE", BASE },
1408 { "CODE", CODE },
1409 { "CONSTANT", CONSTANTU },
1410 { "constant", CONSTANTL },
1411 { "DATA", DATAU },
1412 { "data", DATAL },
1413 { "DESCRIPTION", DESCRIPTION },
1414 { "DIRECTIVE", DIRECTIVE },
1415 { "EXCLUDE_SYMBOLS", EXCLUDE_SYMBOLS },
1416 { "EXECUTE", EXECUTE },
1417 { "EXPORTS", EXPORTS },
1418 { "HEAPSIZE", HEAPSIZE },
1419 { "IMPORTS", IMPORTS },
1420 { "LIBRARY", LIBRARY },
1421 { "NAME", NAME },
1422 { "NONAME", NONAMEU },
1423 { "noname", NONAMEL },
1424 { "PRIVATE", PRIVATEU },
1425 { "private", PRIVATEL },
1426 { "READ", READ },
1427 { "SECTIONS", SECTIONS },
1428 { "SEGMENTS", SECTIONS },
1429 { "SHARED", SHARED_K },
1430 { "STACKSIZE", STACKSIZE_K },
1431 { "VERSION", VERSIONK },
1432 { "WRITE", WRITE },
1433 { 0, 0 }
1436 static int
1437 def_getc (void)
1439 int rv;
1441 if (lex_parse_string)
1443 if (lex_parse_string >= lex_parse_string_end)
1444 rv = EOF;
1445 else
1446 rv = *lex_parse_string++;
1448 else
1450 rv = fgetc (the_file);
1452 if (rv == '\n')
1453 saw_newline = 1;
1454 return rv;
1457 static int
1458 def_ungetc (int c)
1460 if (lex_parse_string)
1462 lex_parse_string--;
1463 return c;
1465 else
1466 return ungetc (c, the_file);
1469 static int
1470 def_lex (void)
1472 int c, i, q;
1474 if (lex_forced_token)
1476 i = lex_forced_token;
1477 lex_forced_token = 0;
1478 #if TRACE
1479 printf ("lex: forcing token %d\n", i);
1480 #endif
1481 return i;
1484 c = def_getc ();
1486 /* Trim leading whitespace. */
1487 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1488 c = def_getc ();
1490 if (c == EOF)
1492 #if TRACE
1493 printf ("lex: EOF\n");
1494 #endif
1495 return 0;
1498 if (saw_newline && c == ';')
1502 c = def_getc ();
1504 while (c != EOF && c != '\n');
1505 if (c == '\n')
1506 return def_lex ();
1507 return 0;
1510 /* Must be something else. */
1511 saw_newline = 0;
1513 if (ISDIGIT (c))
1515 bufptr = 0;
1516 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1518 put_buf (c);
1519 c = def_getc ();
1521 if (c != EOF)
1522 def_ungetc (c);
1523 yylval.digits = def_pool_strdup (buffer);
1524 #if TRACE
1525 printf ("lex: `%s' returns DIGITS\n", buffer);
1526 #endif
1527 return DIGITS;
1530 if (ISALPHA (c) || strchr ("$:-_?@", c))
1532 bufptr = 0;
1533 q = c;
1534 put_buf (c);
1535 c = def_getc ();
1537 if (q == '@')
1539 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1540 return (q);
1541 else if (ISDIGIT (c)) /* '@' followed by digit. */
1543 def_ungetc (c);
1544 return (q);
1546 #if TRACE
1547 printf ("lex: @ returns itself\n");
1548 #endif
1551 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1553 put_buf (c);
1554 c = def_getc ();
1556 if (c != EOF)
1557 def_ungetc (c);
1558 if (ISALPHA (q)) /* Check for tokens. */
1560 for (i = 0; tokens[i].name; i++)
1561 if (strcmp (tokens[i].name, buffer) == 0)
1563 #if TRACE
1564 printf ("lex: `%s' is a string token\n", buffer);
1565 #endif
1566 return tokens[i].token;
1569 #if TRACE
1570 printf ("lex: `%s' returns ID\n", buffer);
1571 #endif
1572 yylval.id = def_pool_strdup (buffer);
1573 return ID;
1576 if (c == '\'' || c == '"')
1578 q = c;
1579 c = def_getc ();
1580 bufptr = 0;
1582 while (c != EOF && c != q)
1584 put_buf (c);
1585 c = def_getc ();
1587 yylval.id = def_pool_strdup (buffer);
1588 #if TRACE
1589 printf ("lex: `%s' returns ID\n", buffer);
1590 #endif
1591 return ID;
1594 if ( c == '=')
1596 c = def_getc ();
1597 if (c == '=')
1599 #if TRACE
1600 printf ("lex: `==' returns EQUAL\n");
1601 #endif
1602 return EQUAL;
1604 def_ungetc (c);
1605 #if TRACE
1606 printf ("lex: `=' returns itself\n");
1607 #endif
1608 return '=';
1610 if (c == '.' || c == ',')
1612 #if TRACE
1613 printf ("lex: `%c' returns itself\n", c);
1614 #endif
1615 return c;
1618 if (c == '\n')
1620 linenumber++;
1621 saw_newline = 1;
1624 /*printf ("lex: 0x%02x ignored\n", c); */
1625 return def_lex ();
1628 static char *
1629 def_pool_alloc (size_t sz)
1631 def_pool_str *e;
1633 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1634 e->next = pool_strs;
1635 pool_strs = e;
1636 return e->data;
1639 static char *
1640 def_pool_strdup (const char *str)
1642 char *s;
1643 size_t len;
1644 if (!str)
1645 return NULL;
1646 len = strlen (str) + 1;
1647 s = def_pool_alloc (len);
1648 memcpy (s, str, len);
1649 return s;
1652 static void
1653 def_pool_free (void)
1655 def_pool_str *p;
1656 while ((p = pool_strs) != NULL)
1658 pool_strs = p->next;
1659 free (p);