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