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