]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - ld/deffilep.y
Fix a conflict between the linker's need to rename some PE format input libraries...
[thirdparty/binutils-gdb.git] / ld / deffilep.y
1 %{ /* deffilep.y - parser for .def files */
2
3 /* Copyright (C) 1995-2022 Free Software Foundation, Inc.
4
5 This file is part of GNU Binutils.
6
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.
11
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.
16
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. */
21
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"
30
31 #define TRACE 0
32
33 #define ROUND_UP(a, b) (((a)+((b)-1))&~((b)-1))
34
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. */
41
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
80
81 typedef struct def_pool_str {
82 struct def_pool_str *next;
83 char data[1];
84 } def_pool_str;
85
86 static def_pool_str *pool_strs = NULL;
87
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);
91
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 *, bfd_vma, 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 void def_exclude_symbols (char *str);
105 static int def_parse (void);
106 static void def_error (const char *);
107 static int def_lex (void);
108
109 static int lex_forced_token = 0;
110 static const char *lex_parse_string = 0;
111 static const char *lex_parse_string_end = 0;
112
113 %}
114
115 %union {
116 char *id;
117 const char *id_const;
118 int number;
119 bfd_vma vma;
120 char *digits;
121 };
122
123 %token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
124 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
125 %token PRIVATEU PRIVATEL ALIGNCOMM EXCLUDE_SYMBOLS
126 %token READ WRITE EXECUTE SHARED_K NONAMEU NONAMEL DIRECTIVE EQUAL
127 %token <id> ID
128 %token <digits> DIGITS
129 %type <number> NUMBER
130 %type <vma> VMA opt_base
131 %type <digits> opt_digits
132 %type <number> opt_ordinal
133 %type <number> attr attr_list opt_number exp_opt_list exp_opt
134 %type <id> opt_name opt_name2 opt_equal_name anylang_id opt_id
135 %type <id> opt_equalequal_name symbol_list
136 %type <id_const> keyword_as_name
137
138 %%
139
140 start: start command
141 | command
142 ;
143
144 command:
145 NAME opt_name opt_base { def_image_name ($2, $3, 0); }
146 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
147 | DESCRIPTION ID { def_description ($2);}
148 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);}
149 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
150 | CODE attr_list { def_section ("CODE", $2);}
151 | DATAU attr_list { def_section ("DATA", $2);}
152 | SECTIONS seclist
153 | EXPORTS explist
154 | IMPORTS implist
155 | VERSIONK NUMBER { def_version ($2, 0);}
156 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
157 | DIRECTIVE ID { def_directive ($2);}
158 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);}
159 | EXCLUDE_SYMBOLS symbol_list
160 ;
161
162
163 explist:
164 /* EMPTY */
165 | expline
166 | explist expline
167 ;
168
169 expline:
170 /* The opt_comma is necessary to support both the usual
171 DEF file syntax as well as .drectve syntax which
172 mandates <expsym>,<expoptlist>. */
173 opt_name2 opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name
174 { def_exports ($1, $2, $3, $5, $7); }
175 ;
176 exp_opt_list:
177 /* The opt_comma is necessary to support both the usual
178 DEF file syntax as well as .drectve syntax which
179 allows for comma separated opt list. */
180 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
181 | { $$ = 0; }
182 ;
183 exp_opt:
184 NONAMEU { $$ = 1; }
185 | NONAMEL { $$ = 1; }
186 | CONSTANTU { $$ = 2; }
187 | CONSTANTL { $$ = 2; }
188 | DATAU { $$ = 4; }
189 | DATAL { $$ = 4; }
190 | PRIVATEU { $$ = 8; }
191 | PRIVATEL { $$ = 8; }
192 ;
193 implist:
194 implist impline
195 | impline
196 ;
197
198 impline:
199 ID '=' ID '.' ID '.' ID opt_equalequal_name
200 { def_import ($1, $3, $5, $7, -1, $8); }
201 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name
202 { def_import ($1, $3, $5, 0, $7, $8); }
203 | ID '=' ID '.' ID opt_equalequal_name
204 { def_import ($1, $3, 0, $5, -1, $6); }
205 | ID '=' ID '.' NUMBER opt_equalequal_name
206 { def_import ($1, $3, 0, 0, $5, $6); }
207 | ID '.' ID '.' ID opt_equalequal_name
208 { def_import( 0, $1, $3, $5, -1, $6); }
209 | ID '.' ID opt_equalequal_name
210 { def_import ( 0, $1, 0, $3, -1, $4); }
211 ;
212
213 seclist:
214 seclist secline
215 | secline
216 ;
217
218 secline:
219 ID attr_list { def_section ($1, $2);}
220 | ID ID { def_section_alt ($1, $2);}
221 ;
222
223 attr_list:
224 attr_list opt_comma attr { $$ = $1 | $3; }
225 | attr { $$ = $1; }
226 ;
227
228 opt_comma:
229 ','
230 |
231 ;
232 opt_number: ',' NUMBER { $$=$2;}
233 | { $$=-1;}
234 ;
235
236 attr:
237 READ { $$ = 1;}
238 | WRITE { $$ = 2;}
239 | EXECUTE { $$=4;}
240 | SHARED_K { $$=8;}
241 ;
242
243
244 keyword_as_name: BASE { $$ = "BASE"; }
245 | CODE { $$ = "CODE"; }
246 | CONSTANTU { $$ = "CONSTANT"; }
247 | CONSTANTL { $$ = "constant"; }
248 | DATAU { $$ = "DATA"; }
249 | DATAL { $$ = "data"; }
250 | DESCRIPTION { $$ = "DESCRIPTION"; }
251 | DIRECTIVE { $$ = "DIRECTIVE"; }
252 | EXCLUDE_SYMBOLS { $$ = "EXCLUDE_SYMBOLS"; }
253 | EXECUTE { $$ = "EXECUTE"; }
254 | EXPORTS { $$ = "EXPORTS"; }
255 | HEAPSIZE { $$ = "HEAPSIZE"; }
256 | IMPORTS { $$ = "IMPORTS"; }
257 /* Disable LIBRARY keyword as valid symbol-name. This is necessary
258 for libtool, which places this command after EXPORTS command.
259 This behavior is illegal by specification, but sadly required by
260 by compatibility reasons.
261 See PR binutils/13710
262 | LIBRARY { $$ = "LIBRARY"; } */
263 | NAME { $$ = "NAME"; }
264 | NONAMEU { $$ = "NONAME"; }
265 | NONAMEL { $$ = "noname"; }
266 | PRIVATEU { $$ = "PRIVATE"; }
267 | PRIVATEL { $$ = "private"; }
268 | READ { $$ = "READ"; }
269 | SHARED_K { $$ = "SHARED"; }
270 | STACKSIZE_K { $$ = "STACKSIZE"; }
271 | VERSIONK { $$ = "VERSION"; }
272 | WRITE { $$ = "WRITE"; }
273 ;
274
275 opt_name2: ID { $$ = $1; }
276 | '.' keyword_as_name
277 {
278 char *name = xmalloc (strlen ($2) + 2);
279 sprintf (name, ".%s", $2);
280 $$ = name;
281 }
282 | '.' opt_name2
283 {
284 char *name = def_pool_alloc (strlen ($2) + 2);
285 sprintf (name, ".%s", $2);
286 $$ = name;
287 }
288 | keyword_as_name '.' opt_name2
289 {
290 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
291 sprintf (name, "%s.%s", $1, $3);
292 $$ = name;
293 }
294 | ID '.' opt_name2
295 {
296 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
297 sprintf (name, "%s.%s", $1, $3);
298 $$ = name;
299 }
300 ;
301
302 opt_name: opt_name2 { $$ = $1; }
303 | { $$ = ""; }
304 ;
305
306 opt_equalequal_name: EQUAL ID { $$ = $2; }
307 | { $$ = 0; }
308 ;
309
310 opt_ordinal:
311 '@' NUMBER { $$ = $2;}
312 | { $$ = -1;}
313 ;
314
315 opt_equal_name:
316 '=' opt_name2 { $$ = $2; }
317 | { $$ = 0; }
318 ;
319
320 opt_base: BASE '=' VMA { $$ = $3;}
321 | { $$ = (bfd_vma) -1;}
322 ;
323
324 anylang_id: ID { $$ = $1; }
325 | '.' ID
326 {
327 char *id = def_pool_alloc (strlen ($2) + 2);
328 sprintf (id, ".%s", $2);
329 $$ = id;
330 }
331 | anylang_id '.' opt_digits opt_id
332 {
333 char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
334 sprintf (id, "%s.%s%s", $1, $3, $4);
335 $$ = id;
336 }
337 ;
338
339 symbol_list:
340 anylang_id { def_exclude_symbols ($1); }
341 | symbol_list anylang_id { def_exclude_symbols ($2); }
342 | symbol_list ',' anylang_id { def_exclude_symbols ($3); }
343 ;
344
345 opt_digits: DIGITS { $$ = $1; }
346 | { $$ = ""; }
347 ;
348
349 opt_id: ID { $$ = $1; }
350 | { $$ = ""; }
351 ;
352
353 NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); }
354 ;
355 VMA: DIGITS { $$ = (bfd_vma) strtoull ($1, 0, 0); }
356
357 %%
358
359 /*****************************************************************************
360 API
361 *****************************************************************************/
362
363 static FILE *the_file;
364 static const char *def_filename;
365 static int linenumber;
366 static def_file *def;
367 static int saw_newline;
368
369 struct directive
370 {
371 struct directive *next;
372 char *name;
373 int len;
374 };
375
376 static struct directive *directives = 0;
377
378 def_file *
379 def_file_empty (void)
380 {
381 def_file *rv = xmalloc (sizeof (def_file));
382 memset (rv, 0, sizeof (def_file));
383 rv->is_dll = -1;
384 rv->base_address = (bfd_vma) -1;
385 rv->stack_reserve = rv->stack_commit = -1;
386 rv->heap_reserve = rv->heap_commit = -1;
387 rv->version_major = rv->version_minor = -1;
388 return rv;
389 }
390
391 def_file *
392 def_file_parse (const char *filename, def_file *add_to)
393 {
394 struct directive *d;
395
396 the_file = fopen (filename, "r");
397 def_filename = filename;
398 linenumber = 1;
399 if (!the_file)
400 {
401 perror (filename);
402 return 0;
403 }
404 if (add_to)
405 {
406 def = add_to;
407 }
408 else
409 {
410 def = def_file_empty ();
411 }
412
413 saw_newline = 1;
414 if (def_parse ())
415 {
416 def_file_free (def);
417 fclose (the_file);
418 def_pool_free ();
419 return 0;
420 }
421
422 fclose (the_file);
423
424 while ((d = directives) != NULL)
425 {
426 #if TRACE
427 printf ("Adding directive %08x `%s'\n", d->name, d->name);
428 #endif
429 def_file_add_directive (def, d->name, d->len);
430 directives = d->next;
431 free (d->name);
432 free (d);
433 }
434 def_pool_free ();
435
436 return def;
437 }
438
439 void
440 def_file_free (def_file *fdef)
441 {
442 int i;
443
444 if (!fdef)
445 return;
446 free (fdef->name);
447 free (fdef->description);
448
449 if (fdef->section_defs)
450 {
451 for (i = 0; i < fdef->num_section_defs; i++)
452 {
453 free (fdef->section_defs[i].name);
454 free (fdef->section_defs[i].class);
455 }
456 free (fdef->section_defs);
457 }
458
459 if (fdef->exports)
460 {
461 for (i = 0; i < fdef->num_exports; i++)
462 {
463 if (fdef->exports[i].internal_name != fdef->exports[i].name)
464 free (fdef->exports[i].internal_name);
465 free (fdef->exports[i].name);
466 free (fdef->exports[i].its_name);
467 }
468 free (fdef->exports);
469 }
470
471 if (fdef->imports)
472 {
473 for (i = 0; i < fdef->num_imports; i++)
474 {
475 if (fdef->imports[i].internal_name != fdef->imports[i].name)
476 free (fdef->imports[i].internal_name);
477 free (fdef->imports[i].name);
478 free (fdef->imports[i].its_name);
479 }
480 free (fdef->imports);
481 }
482
483 while (fdef->modules)
484 {
485 def_file_module *m = fdef->modules;
486
487 fdef->modules = fdef->modules->next;
488 free (m);
489 }
490
491 while (fdef->aligncomms)
492 {
493 def_file_aligncomm *c = fdef->aligncomms;
494
495 fdef->aligncomms = fdef->aligncomms->next;
496 free (c->symbol_name);
497 free (c);
498 }
499
500 while (fdef->exclude_symbols)
501 {
502 def_file_exclude_symbol *e = fdef->exclude_symbols;
503
504 fdef->exclude_symbols = fdef->exclude_symbols->next;
505 free (e->symbol_name);
506 free (e);
507 }
508
509 free (fdef);
510 }
511
512 #ifdef DEF_FILE_PRINT
513 void
514 def_file_print (FILE *file, def_file *fdef)
515 {
516 int i;
517
518 fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
519 if (fdef->name)
520 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)");
521 if (fdef->is_dll != -1)
522 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no");
523 if (fdef->base_address != (bfd_vma) -1)
524 fprintf (file, " base address: 0x%" PRIx64 "\n",
525 (uint64_t) fdef->base_address);
526 if (fdef->description)
527 fprintf (file, " description: `%s'\n", fdef->description);
528 if (fdef->stack_reserve != -1)
529 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
530 if (fdef->stack_commit != -1)
531 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
532 if (fdef->heap_reserve != -1)
533 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
534 if (fdef->heap_commit != -1)
535 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
536
537 if (fdef->num_section_defs > 0)
538 {
539 fprintf (file, " section defs:\n");
540
541 for (i = 0; i < fdef->num_section_defs; i++)
542 {
543 fprintf (file, " name: `%s', class: `%s', flags:",
544 fdef->section_defs[i].name, fdef->section_defs[i].class);
545 if (fdef->section_defs[i].flag_read)
546 fprintf (file, " R");
547 if (fdef->section_defs[i].flag_write)
548 fprintf (file, " W");
549 if (fdef->section_defs[i].flag_execute)
550 fprintf (file, " X");
551 if (fdef->section_defs[i].flag_shared)
552 fprintf (file, " S");
553 fprintf (file, "\n");
554 }
555 }
556
557 if (fdef->num_exports > 0)
558 {
559 fprintf (file, " exports:\n");
560
561 for (i = 0; i < fdef->num_exports; i++)
562 {
563 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
564 fdef->exports[i].name, fdef->exports[i].internal_name,
565 fdef->exports[i].ordinal);
566 if (fdef->exports[i].flag_private)
567 fprintf (file, " P");
568 if (fdef->exports[i].flag_constant)
569 fprintf (file, " C");
570 if (fdef->exports[i].flag_noname)
571 fprintf (file, " N");
572 if (fdef->exports[i].flag_data)
573 fprintf (file, " D");
574 fprintf (file, "\n");
575 }
576 }
577
578 if (fdef->num_imports > 0)
579 {
580 fprintf (file, " imports:\n");
581
582 for (i = 0; i < fdef->num_imports; i++)
583 {
584 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
585 fdef->imports[i].internal_name,
586 fdef->imports[i].module,
587 fdef->imports[i].name,
588 fdef->imports[i].ordinal);
589 }
590 }
591
592 if (fdef->version_major != -1)
593 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
594
595 fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
596 }
597 #endif
598
599 /* Helper routine to check for identity of string pointers,
600 which might be NULL. */
601
602 static int
603 are_names_equal (const char *s1, const char *s2)
604 {
605 if (!s1 && !s2)
606 return 0;
607 if (!s1 || !s2)
608 return (!s1 ? -1 : 1);
609 return strcmp (s1, s2);
610 }
611
612 static int
613 cmp_export_elem (const def_file_export *e, const char *ex_name,
614 const char *in_name, const char *its_name,
615 int ord)
616 {
617 int r;
618
619 if ((r = are_names_equal (ex_name, e->name)) != 0)
620 return r;
621 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
622 return r;
623 if ((r = are_names_equal (its_name, e->its_name)) != 0)
624 return r;
625 return (ord - e->ordinal);
626 }
627
628 /* Search the position of the identical element, or returns the position
629 of the next higher element. If last valid element is smaller, then MAX
630 is returned. */
631
632 static int
633 find_export_in_list (def_file_export *b, int max,
634 const char *ex_name, const char *in_name,
635 const char *its_name, int ord, int *is_ident)
636 {
637 int e, l, r, p;
638
639 *is_ident = 0;
640 if (!max)
641 return 0;
642 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
643 {
644 if (!e)
645 *is_ident = 1;
646 return 0;
647 }
648 if (max == 1)
649 return 1;
650 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
651 return max;
652 else if (!e || max == 2)
653 {
654 if (!e)
655 *is_ident = 1;
656 return max - 1;
657 }
658 l = 0; r = max - 1;
659 while (l < r)
660 {
661 p = (l + r) / 2;
662 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
663 if (!e)
664 {
665 *is_ident = 1;
666 return p;
667 }
668 else if (e < 0)
669 r = p - 1;
670 else if (e > 0)
671 l = p + 1;
672 }
673 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
674 ++l;
675 else if (!e)
676 *is_ident = 1;
677 return l;
678 }
679
680 def_file_export *
681 def_file_add_export (def_file *fdef,
682 const char *external_name,
683 const char *internal_name,
684 int ordinal,
685 const char *its_name,
686 int *is_dup)
687 {
688 def_file_export *e;
689 int pos;
690 int max_exports = ROUND_UP(fdef->num_exports, 32);
691
692 if (internal_name && !external_name)
693 external_name = internal_name;
694 if (external_name && !internal_name)
695 internal_name = external_name;
696
697 /* We need to avoid duplicates. */
698 *is_dup = 0;
699 pos = find_export_in_list (fdef->exports, fdef->num_exports,
700 external_name, internal_name,
701 its_name, ordinal, is_dup);
702
703 if (*is_dup != 0)
704 return (fdef->exports + pos);
705
706 if (fdef->num_exports >= max_exports)
707 {
708 max_exports = ROUND_UP(fdef->num_exports + 1, 32);
709 if (fdef->exports)
710 fdef->exports = xrealloc (fdef->exports,
711 max_exports * sizeof (def_file_export));
712 else
713 fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
714 }
715
716 e = fdef->exports + pos;
717 if (pos != fdef->num_exports)
718 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
719 memset (e, 0, sizeof (def_file_export));
720 e->name = xstrdup (external_name);
721 e->internal_name = xstrdup (internal_name);
722 e->its_name = (its_name ? xstrdup (its_name) : NULL);
723 e->ordinal = ordinal;
724 fdef->num_exports++;
725 return e;
726 }
727
728 def_file_module *
729 def_get_module (def_file *fdef, const char *name)
730 {
731 def_file_module *s;
732
733 for (s = fdef->modules; s; s = s->next)
734 if (strcmp (s->name, name) == 0)
735 return s;
736
737 return NULL;
738 }
739
740 static def_file_module *
741 def_stash_module (def_file *fdef, const char *name)
742 {
743 def_file_module *s;
744
745 if ((s = def_get_module (fdef, name)) != NULL)
746 return s;
747 s = xmalloc (sizeof (def_file_module) + strlen (name));
748 s->next = fdef->modules;
749 fdef->modules = s;
750 s->user_data = 0;
751 strcpy (s->name, name);
752 return s;
753 }
754
755 static int
756 cmp_import_elem (const def_file_import *e, const char *ex_name,
757 const char *in_name, const char *module,
758 int ord)
759 {
760 int r;
761
762 if ((r = are_names_equal (module, (e->module ? e->module->name : NULL))))
763 return r;
764 if ((r = are_names_equal (ex_name, e->name)) != 0)
765 return r;
766 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
767 return r;
768 if (ord != e->ordinal)
769 return (ord < e->ordinal ? -1 : 1);
770 return 0;
771 }
772
773 /* Search the position of the identical element, or returns the position
774 of the next higher element. If last valid element is smaller, then MAX
775 is returned. */
776
777 static int
778 find_import_in_list (def_file_import *b, int max,
779 const char *ex_name, const char *in_name,
780 const char *module, int ord, int *is_ident)
781 {
782 int e, l, r, p;
783
784 *is_ident = 0;
785 if (!max)
786 return 0;
787 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
788 {
789 if (!e)
790 *is_ident = 1;
791 return 0;
792 }
793 if (max == 1)
794 return 1;
795 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
796 return max;
797 else if (!e || max == 2)
798 {
799 if (!e)
800 *is_ident = 1;
801 return max - 1;
802 }
803 l = 0; r = max - 1;
804 while (l < r)
805 {
806 p = (l + r) / 2;
807 e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
808 if (!e)
809 {
810 *is_ident = 1;
811 return p;
812 }
813 else if (e < 0)
814 r = p - 1;
815 else if (e > 0)
816 l = p + 1;
817 }
818 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
819 ++l;
820 else if (!e)
821 *is_ident = 1;
822 return l;
823 }
824
825 static void
826 fill_in_import (def_file_import *i,
827 const char *name,
828 def_file_module *module,
829 int ordinal,
830 const char *internal_name,
831 const char *its_name)
832 {
833 memset (i, 0, sizeof (def_file_import));
834 if (name)
835 i->name = xstrdup (name);
836 i->module = module;
837 i->ordinal = ordinal;
838 if (internal_name)
839 i->internal_name = xstrdup (internal_name);
840 else
841 i->internal_name = i->name;
842 i->its_name = (its_name ? xstrdup (its_name) : NULL);
843 }
844
845 def_file_import *
846 def_file_add_import (def_file *fdef,
847 const char *name,
848 const char *module,
849 int ordinal,
850 const char *internal_name,
851 const char *its_name,
852 int *is_dup)
853 {
854 def_file_import *i;
855 int pos;
856 int max_imports = ROUND_UP (fdef->num_imports, 16);
857
858 /* We need to avoid here duplicates. */
859 *is_dup = 0;
860 pos = find_import_in_list (fdef->imports, fdef->num_imports,
861 name,
862 (!internal_name ? name : internal_name),
863 module, ordinal, is_dup);
864 if (*is_dup != 0)
865 return fdef->imports + pos;
866
867 if (fdef->num_imports >= max_imports)
868 {
869 max_imports = ROUND_UP (fdef->num_imports+1, 16);
870
871 if (fdef->imports)
872 fdef->imports = xrealloc (fdef->imports,
873 max_imports * sizeof (def_file_import));
874 else
875 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
876 }
877 i = fdef->imports + pos;
878 if (pos != fdef->num_imports)
879 memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
880
881 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
882 internal_name, its_name);
883 fdef->num_imports++;
884
885 return i;
886 }
887
888 int
889 def_file_add_import_from (def_file *fdef,
890 int num_imports,
891 const char *name,
892 const char *module,
893 int ordinal,
894 const char *internal_name,
895 const char *its_name ATTRIBUTE_UNUSED)
896 {
897 def_file_import *i;
898 int is_dup;
899 int pos;
900 int max_imports = ROUND_UP (fdef->num_imports, 16);
901
902 /* We need to avoid here duplicates. */
903 is_dup = 0;
904 pos = find_import_in_list (fdef->imports, fdef->num_imports,
905 name, internal_name ? internal_name : name,
906 module, ordinal, &is_dup);
907 if (is_dup != 0)
908 return -1;
909 if (fdef->imports && pos != fdef->num_imports)
910 {
911 i = fdef->imports + pos;
912 if (i->module && strcmp (i->module->name, module) == 0)
913 return -1;
914 }
915
916 if (fdef->num_imports + num_imports - 1 >= max_imports)
917 {
918 max_imports = ROUND_UP (fdef->num_imports + num_imports, 16);
919
920 if (fdef->imports)
921 fdef->imports = xrealloc (fdef->imports,
922 max_imports * sizeof (def_file_import));
923 else
924 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
925 }
926 i = fdef->imports + pos;
927 if (pos != fdef->num_imports)
928 memmove (i + num_imports, i,
929 sizeof (def_file_import) * (fdef->num_imports - pos));
930
931 return pos;
932 }
933
934 def_file_import *
935 def_file_add_import_at (def_file *fdef,
936 int pos,
937 const char *name,
938 const char *module,
939 int ordinal,
940 const char *internal_name,
941 const char *its_name)
942 {
943 def_file_import *i = fdef->imports + pos;
944
945 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
946 internal_name, its_name);
947 fdef->num_imports++;
948
949 return i;
950 }
951
952 struct
953 {
954 char *param;
955 int token;
956 }
957 diropts[] =
958 {
959 { "-heap", HEAPSIZE },
960 { "-stack", STACKSIZE_K },
961 { "-attr", SECTIONS },
962 { "-export", EXPORTS },
963 { "-aligncomm", ALIGNCOMM },
964 { "-exclude-symbols", EXCLUDE_SYMBOLS },
965 { 0, 0 }
966 };
967
968 void
969 def_file_add_directive (def_file *my_def, const char *param, int len)
970 {
971 def_file *save_def = def;
972 const char *pend = param + len;
973 char * tend = (char *) param;
974 int i;
975
976 def = my_def;
977
978 while (param < pend)
979 {
980 while (param < pend
981 && (ISSPACE (*param) || *param == '\n' || *param == 0))
982 param++;
983
984 if (param == pend)
985 break;
986
987 /* Scan forward until we encounter any of:
988 - the end of the buffer
989 - the start of a new option
990 - a newline separating options
991 - a NUL separating options. */
992 for (tend = (char *) (param + 1);
993 (tend < pend
994 && !(ISSPACE (tend[-1]) && *tend == '-')
995 && *tend != '\n' && *tend != 0);
996 tend++)
997 ;
998
999 for (i = 0; diropts[i].param; i++)
1000 {
1001 len = strlen (diropts[i].param);
1002
1003 if (tend - param >= len
1004 && strncmp (param, diropts[i].param, len) == 0
1005 && (param[len] == ':' || param[len] == ' '))
1006 {
1007 lex_parse_string_end = tend;
1008 lex_parse_string = param + len + 1;
1009 lex_forced_token = diropts[i].token;
1010 saw_newline = 0;
1011 if (def_parse ())
1012 continue;
1013 break;
1014 }
1015 }
1016
1017 if (!diropts[i].param)
1018 {
1019 if (tend < pend)
1020 {
1021 char saved;
1022
1023 saved = * tend;
1024 * tend = 0;
1025 /* xgettext:c-format */
1026 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
1027 * tend = saved;
1028 }
1029 else
1030 {
1031 einfo (_("Warning: corrupt .drectve at end of def file\n"));
1032 }
1033 }
1034
1035 lex_parse_string = 0;
1036 param = tend;
1037 }
1038
1039 def = save_def;
1040 def_pool_free ();
1041 }
1042
1043 /* Parser Callbacks. */
1044
1045 static void
1046 def_image_name (const char *name, bfd_vma base, int is_dll)
1047 {
1048 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
1049 to do here. We retain the output filename specified on command line. */
1050 if (*name)
1051 {
1052 const char* image_name = lbasename (name);
1053
1054 if (image_name != name)
1055 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
1056 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
1057 name);
1058 free (def->name);
1059 /* Append the default suffix, if none specified. */
1060 if (strchr (image_name, '.') == 0)
1061 {
1062 const char * suffix = is_dll ? ".dll" : ".exe";
1063
1064 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
1065 sprintf (def->name, "%s%s", image_name, suffix);
1066 }
1067 else
1068 def->name = xstrdup (image_name);
1069 }
1070
1071 /* Honor a BASE address statement, even if LIBRARY string is empty. */
1072 def->base_address = base;
1073 def->is_dll = is_dll;
1074 }
1075
1076 static void
1077 def_description (const char *text)
1078 {
1079 int len = def->description ? strlen (def->description) : 0;
1080
1081 len += strlen (text) + 1;
1082 if (def->description)
1083 {
1084 def->description = xrealloc (def->description, len);
1085 strcat (def->description, text);
1086 }
1087 else
1088 {
1089 def->description = xmalloc (len);
1090 strcpy (def->description, text);
1091 }
1092 }
1093
1094 static void
1095 def_stacksize (int reserve, int commit)
1096 {
1097 def->stack_reserve = reserve;
1098 def->stack_commit = commit;
1099 }
1100
1101 static void
1102 def_heapsize (int reserve, int commit)
1103 {
1104 def->heap_reserve = reserve;
1105 def->heap_commit = commit;
1106 }
1107
1108 static void
1109 def_section (const char *name, int attr)
1110 {
1111 def_file_section *s;
1112 int max_sections = ROUND_UP (def->num_section_defs, 4);
1113
1114 if (def->num_section_defs >= max_sections)
1115 {
1116 max_sections = ROUND_UP (def->num_section_defs+1, 4);
1117
1118 if (def->section_defs)
1119 def->section_defs = xrealloc (def->section_defs,
1120 max_sections * sizeof (def_file_import));
1121 else
1122 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
1123 }
1124 s = def->section_defs + def->num_section_defs;
1125 memset (s, 0, sizeof (def_file_section));
1126 s->name = xstrdup (name);
1127 if (attr & 1)
1128 s->flag_read = 1;
1129 if (attr & 2)
1130 s->flag_write = 1;
1131 if (attr & 4)
1132 s->flag_execute = 1;
1133 if (attr & 8)
1134 s->flag_shared = 1;
1135
1136 def->num_section_defs++;
1137 }
1138
1139 static void
1140 def_section_alt (const char *name, const char *attr)
1141 {
1142 int aval = 0;
1143
1144 for (; *attr; attr++)
1145 {
1146 switch (*attr)
1147 {
1148 case 'R':
1149 case 'r':
1150 aval |= 1;
1151 break;
1152 case 'W':
1153 case 'w':
1154 aval |= 2;
1155 break;
1156 case 'X':
1157 case 'x':
1158 aval |= 4;
1159 break;
1160 case 'S':
1161 case 's':
1162 aval |= 8;
1163 break;
1164 }
1165 }
1166 def_section (name, aval);
1167 }
1168
1169 static void
1170 def_exports (const char *external_name,
1171 const char *internal_name,
1172 int ordinal,
1173 int flags,
1174 const char *its_name)
1175 {
1176 def_file_export *dfe;
1177 int is_dup = 0;
1178
1179 if (!internal_name && external_name)
1180 internal_name = external_name;
1181 #if TRACE
1182 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1183 #endif
1184
1185 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
1186 its_name, &is_dup);
1187
1188 /* We might check here for flag redefinition and warn. For now we
1189 ignore duplicates silently. */
1190 if (is_dup)
1191 return;
1192
1193 if (flags & 1)
1194 dfe->flag_noname = 1;
1195 if (flags & 2)
1196 dfe->flag_constant = 1;
1197 if (flags & 4)
1198 dfe->flag_data = 1;
1199 if (flags & 8)
1200 dfe->flag_private = 1;
1201 }
1202
1203 static void
1204 def_import (const char *internal_name,
1205 const char *module,
1206 const char *dllext,
1207 const char *name,
1208 int ordinal,
1209 const char *its_name)
1210 {
1211 char *buf = 0;
1212 const char *ext = dllext ? dllext : "dll";
1213 int is_dup = 0;
1214
1215 buf = xmalloc (strlen (module) + strlen (ext) + 2);
1216 sprintf (buf, "%s.%s", module, ext);
1217 module = buf;
1218
1219 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1220 &is_dup);
1221 free (buf);
1222 }
1223
1224 static void
1225 def_version (int major, int minor)
1226 {
1227 def->version_major = major;
1228 def->version_minor = minor;
1229 }
1230
1231 static void
1232 def_directive (char *str)
1233 {
1234 struct directive *d = xmalloc (sizeof (struct directive));
1235
1236 d->next = directives;
1237 directives = d;
1238 d->name = xstrdup (str);
1239 d->len = strlen (str);
1240 }
1241
1242 static void
1243 def_aligncomm (char *str, int align)
1244 {
1245 def_file_aligncomm *c, *p;
1246
1247 p = NULL;
1248 c = def->aligncomms;
1249 while (c != NULL)
1250 {
1251 int e = strcmp (c->symbol_name, str);
1252 if (!e)
1253 {
1254 /* Not sure if we want to allow here duplicates with
1255 different alignments, but for now we keep them. */
1256 e = (int) c->alignment - align;
1257 if (!e)
1258 return;
1259 }
1260 if (e > 0)
1261 break;
1262 c = (p = c)->next;
1263 }
1264
1265 c = xmalloc (sizeof (def_file_aligncomm));
1266 c->symbol_name = xstrdup (str);
1267 c->alignment = (unsigned int) align;
1268 if (!p)
1269 {
1270 c->next = def->aligncomms;
1271 def->aligncomms = c;
1272 }
1273 else
1274 {
1275 c->next = p->next;
1276 p->next = c;
1277 }
1278 }
1279
1280 static void
1281 def_exclude_symbols (char *str)
1282 {
1283 def_file_exclude_symbol *c, *p;
1284
1285 p = NULL;
1286 c = def->exclude_symbols;
1287 while (c != NULL)
1288 {
1289 int e = strcmp (c->symbol_name, str);
1290 if (!e)
1291 return;
1292 c = (p = c)->next;
1293 }
1294
1295 c = xmalloc (sizeof (def_file_exclude_symbol));
1296 c->symbol_name = xstrdup (str);
1297 if (!p)
1298 {
1299 c->next = def->exclude_symbols;
1300 def->exclude_symbols = c;
1301 }
1302 else
1303 {
1304 c->next = p->next;
1305 p->next = c;
1306 }
1307 }
1308
1309 static void
1310 def_error (const char *err)
1311 {
1312 einfo ("%P: %s:%d: %s\n",
1313 def_filename ? def_filename : "<unknown-file>", linenumber, err);
1314 }
1315
1316
1317 /* Lexical Scanner. */
1318
1319 #undef TRACE
1320 #define TRACE 0
1321
1322 /* Never freed, but always reused as needed, so no real leak. */
1323 static char *buffer = 0;
1324 static int buflen = 0;
1325 static int bufptr = 0;
1326
1327 static void
1328 put_buf (char c)
1329 {
1330 if (bufptr == buflen)
1331 {
1332 buflen += 50; /* overly reasonable, eh? */
1333 if (buffer)
1334 buffer = xrealloc (buffer, buflen + 1);
1335 else
1336 buffer = xmalloc (buflen + 1);
1337 }
1338 buffer[bufptr++] = c;
1339 buffer[bufptr] = 0; /* not optimal, but very convenient. */
1340 }
1341
1342 static struct
1343 {
1344 char *name;
1345 int token;
1346 }
1347 tokens[] =
1348 {
1349 { "BASE", BASE },
1350 { "CODE", CODE },
1351 { "CONSTANT", CONSTANTU },
1352 { "constant", CONSTANTL },
1353 { "DATA", DATAU },
1354 { "data", DATAL },
1355 { "DESCRIPTION", DESCRIPTION },
1356 { "DIRECTIVE", DIRECTIVE },
1357 { "EXCLUDE_SYMBOLS", EXCLUDE_SYMBOLS },
1358 { "EXECUTE", EXECUTE },
1359 { "EXPORTS", EXPORTS },
1360 { "HEAPSIZE", HEAPSIZE },
1361 { "IMPORTS", IMPORTS },
1362 { "LIBRARY", LIBRARY },
1363 { "NAME", NAME },
1364 { "NONAME", NONAMEU },
1365 { "noname", NONAMEL },
1366 { "PRIVATE", PRIVATEU },
1367 { "private", PRIVATEL },
1368 { "READ", READ },
1369 { "SECTIONS", SECTIONS },
1370 { "SEGMENTS", SECTIONS },
1371 { "SHARED", SHARED_K },
1372 { "STACKSIZE", STACKSIZE_K },
1373 { "VERSION", VERSIONK },
1374 { "WRITE", WRITE },
1375 { 0, 0 }
1376 };
1377
1378 static int
1379 def_getc (void)
1380 {
1381 int rv;
1382
1383 if (lex_parse_string)
1384 {
1385 if (lex_parse_string >= lex_parse_string_end)
1386 rv = EOF;
1387 else
1388 rv = *lex_parse_string++;
1389 }
1390 else
1391 {
1392 rv = fgetc (the_file);
1393 }
1394 if (rv == '\n')
1395 saw_newline = 1;
1396 return rv;
1397 }
1398
1399 static int
1400 def_ungetc (int c)
1401 {
1402 if (lex_parse_string)
1403 {
1404 lex_parse_string--;
1405 return c;
1406 }
1407 else
1408 return ungetc (c, the_file);
1409 }
1410
1411 static int
1412 def_lex (void)
1413 {
1414 int c, i, q;
1415
1416 if (lex_forced_token)
1417 {
1418 i = lex_forced_token;
1419 lex_forced_token = 0;
1420 #if TRACE
1421 printf ("lex: forcing token %d\n", i);
1422 #endif
1423 return i;
1424 }
1425
1426 c = def_getc ();
1427
1428 /* Trim leading whitespace. */
1429 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1430 c = def_getc ();
1431
1432 if (c == EOF)
1433 {
1434 #if TRACE
1435 printf ("lex: EOF\n");
1436 #endif
1437 return 0;
1438 }
1439
1440 if (saw_newline && c == ';')
1441 {
1442 do
1443 {
1444 c = def_getc ();
1445 }
1446 while (c != EOF && c != '\n');
1447 if (c == '\n')
1448 return def_lex ();
1449 return 0;
1450 }
1451
1452 /* Must be something else. */
1453 saw_newline = 0;
1454
1455 if (ISDIGIT (c))
1456 {
1457 bufptr = 0;
1458 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1459 {
1460 put_buf (c);
1461 c = def_getc ();
1462 }
1463 if (c != EOF)
1464 def_ungetc (c);
1465 yylval.digits = def_pool_strdup (buffer);
1466 #if TRACE
1467 printf ("lex: `%s' returns DIGITS\n", buffer);
1468 #endif
1469 return DIGITS;
1470 }
1471
1472 if (ISALPHA (c) || strchr ("$:-_?@", c))
1473 {
1474 bufptr = 0;
1475 q = c;
1476 put_buf (c);
1477 c = def_getc ();
1478
1479 if (q == '@')
1480 {
1481 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1482 return (q);
1483 else if (ISDIGIT (c)) /* '@' followed by digit. */
1484 {
1485 def_ungetc (c);
1486 return (q);
1487 }
1488 #if TRACE
1489 printf ("lex: @ returns itself\n");
1490 #endif
1491 }
1492
1493 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1494 {
1495 put_buf (c);
1496 c = def_getc ();
1497 }
1498 if (c != EOF)
1499 def_ungetc (c);
1500 if (ISALPHA (q)) /* Check for tokens. */
1501 {
1502 for (i = 0; tokens[i].name; i++)
1503 if (strcmp (tokens[i].name, buffer) == 0)
1504 {
1505 #if TRACE
1506 printf ("lex: `%s' is a string token\n", buffer);
1507 #endif
1508 return tokens[i].token;
1509 }
1510 }
1511 #if TRACE
1512 printf ("lex: `%s' returns ID\n", buffer);
1513 #endif
1514 yylval.id = def_pool_strdup (buffer);
1515 return ID;
1516 }
1517
1518 if (c == '\'' || c == '"')
1519 {
1520 q = c;
1521 c = def_getc ();
1522 bufptr = 0;
1523
1524 while (c != EOF && c != q)
1525 {
1526 put_buf (c);
1527 c = def_getc ();
1528 }
1529 yylval.id = def_pool_strdup (buffer);
1530 #if TRACE
1531 printf ("lex: `%s' returns ID\n", buffer);
1532 #endif
1533 return ID;
1534 }
1535
1536 if ( c == '=')
1537 {
1538 c = def_getc ();
1539 if (c == '=')
1540 {
1541 #if TRACE
1542 printf ("lex: `==' returns EQUAL\n");
1543 #endif
1544 return EQUAL;
1545 }
1546 def_ungetc (c);
1547 #if TRACE
1548 printf ("lex: `=' returns itself\n");
1549 #endif
1550 return '=';
1551 }
1552 if (c == '.' || c == ',')
1553 {
1554 #if TRACE
1555 printf ("lex: `%c' returns itself\n", c);
1556 #endif
1557 return c;
1558 }
1559
1560 if (c == '\n')
1561 {
1562 linenumber++;
1563 saw_newline = 1;
1564 }
1565
1566 /*printf ("lex: 0x%02x ignored\n", c); */
1567 return def_lex ();
1568 }
1569
1570 static char *
1571 def_pool_alloc (size_t sz)
1572 {
1573 def_pool_str *e;
1574
1575 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1576 e->next = pool_strs;
1577 pool_strs = e;
1578 return e->data;
1579 }
1580
1581 static char *
1582 def_pool_strdup (const char *str)
1583 {
1584 char *s;
1585 size_t len;
1586 if (!str)
1587 return NULL;
1588 len = strlen (str) + 1;
1589 s = def_pool_alloc (len);
1590 memcpy (s, str, len);
1591 return s;
1592 }
1593
1594 static void
1595 def_pool_free (void)
1596 {
1597 def_pool_str *p;
1598 while ((p = pool_strs) != NULL)
1599 {
1600 pool_strs = p->next;
1601 free (p);
1602 }
1603 }