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