PR ld/15957
[deliverable/binutils-gdb.git] / ld / deffilep.y
1 %{ /* deffilep.y - parser for .def files */
2
3 /* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
4 2007, 2009 Free Software Foundation, Inc.
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23 #include "sysdep.h"
24 #include "libiberty.h"
25 #include "safe-ctype.h"
26 #include "bfd.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 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
505 void
506 def_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
597 static int
598 are_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
607 static int
608 cmp_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
627 static int
628 find_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
675 def_file_export *
676 def_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
723 def_file_module *
724 def_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
735 static def_file_module *
736 def_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
750 static int
751 cmp_import_elem (const def_file_import *e, const char *ex_name,
752 const char *in_name, const char *module,
753 int ord)
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
772 static int
773 find_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
820 def_file_import *
821 def_file_add_import (def_file *fdef,
822 const char *name,
823 const char *module,
824 int ordinal,
825 const char *internal_name,
826 const char *its_name,
827 int *is_dup)
828 {
829 def_file_import *i;
830 int pos;
831 int max_imports = ROUND_UP (fdef->num_imports, 16);
832
833 /* We need to avoid here duplicates. */
834 *is_dup = 0;
835 pos = find_import_in_list (fdef->imports, fdef->num_imports,
836 name,
837 (!internal_name ? name : internal_name),
838 module, ordinal, is_dup);
839 if (*is_dup != 0)
840 return fdef->imports + pos;
841
842 if (fdef->num_imports >= max_imports)
843 {
844 max_imports = ROUND_UP (fdef->num_imports+1, 16);
845
846 if (fdef->imports)
847 fdef->imports = xrealloc (fdef->imports,
848 max_imports * sizeof (def_file_import));
849 else
850 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
851 }
852 i = fdef->imports + pos;
853 if (pos != fdef->num_imports)
854 memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos)));
855 memset (i, 0, sizeof (def_file_import));
856 if (name)
857 i->name = xstrdup (name);
858 if (module)
859 i->module = def_stash_module (fdef, module);
860 i->ordinal = ordinal;
861 if (internal_name)
862 i->internal_name = xstrdup (internal_name);
863 else
864 i->internal_name = i->name;
865 i->its_name = (its_name ? xstrdup (its_name) : NULL);
866 fdef->num_imports++;
867
868 return i;
869 }
870
871 struct
872 {
873 char *param;
874 int token;
875 }
876 diropts[] =
877 {
878 { "-heap", HEAPSIZE },
879 { "-stack", STACKSIZE_K },
880 { "-attr", SECTIONS },
881 { "-export", EXPORTS },
882 { "-aligncomm", ALIGNCOMM },
883 { 0, 0 }
884 };
885
886 void
887 def_file_add_directive (def_file *my_def, const char *param, int len)
888 {
889 def_file *save_def = def;
890 const char *pend = param + len;
891 char * tend = (char *) param;
892 int i;
893
894 def = my_def;
895
896 while (param < pend)
897 {
898 while (param < pend
899 && (ISSPACE (*param) || *param == '\n' || *param == 0))
900 param++;
901
902 if (param == pend)
903 break;
904
905 /* Scan forward until we encounter any of:
906 - the end of the buffer
907 - the start of a new option
908 - a newline seperating options
909 - a NUL seperating options. */
910 for (tend = (char *) (param + 1);
911 (tend < pend
912 && !(ISSPACE (tend[-1]) && *tend == '-')
913 && *tend != '\n' && *tend != 0);
914 tend++)
915 ;
916
917 for (i = 0; diropts[i].param; i++)
918 {
919 len = strlen (diropts[i].param);
920
921 if (tend - param >= len
922 && strncmp (param, diropts[i].param, len) == 0
923 && (param[len] == ':' || param[len] == ' '))
924 {
925 lex_parse_string_end = tend;
926 lex_parse_string = param + len + 1;
927 lex_forced_token = diropts[i].token;
928 saw_newline = 0;
929 if (def_parse ())
930 continue;
931 break;
932 }
933 }
934
935 if (!diropts[i].param)
936 {
937 if (tend < pend)
938 {
939 char saved;
940
941 saved = * tend;
942 * tend = 0;
943 /* xgettext:c-format */
944 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
945 * tend = saved;
946 }
947 else
948 {
949 einfo (_("Warning: corrupt .drectve at end of def file\n"));
950 }
951 }
952
953 lex_parse_string = 0;
954 param = tend;
955 }
956
957 def = save_def;
958 def_pool_free ();
959 }
960
961 /* Parser Callbacks. */
962
963 static void
964 def_image_name (const char *name, bfd_vma base, int is_dll)
965 {
966 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
967 to do here. We retain the output filename specified on command line. */
968 if (*name)
969 {
970 const char* image_name = lbasename (name);
971
972 if (image_name != name)
973 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
974 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
975 name);
976 if (def->name)
977 free (def->name);
978 /* Append the default suffix, if none specified. */
979 if (strchr (image_name, '.') == 0)
980 {
981 const char * suffix = is_dll ? ".dll" : ".exe";
982
983 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
984 sprintf (def->name, "%s%s", image_name, suffix);
985 }
986 else
987 def->name = xstrdup (image_name);
988 }
989
990 /* Honor a BASE address statement, even if LIBRARY string is empty. */
991 def->base_address = base;
992 def->is_dll = is_dll;
993 }
994
995 static void
996 def_description (const char *text)
997 {
998 int len = def->description ? strlen (def->description) : 0;
999
1000 len += strlen (text) + 1;
1001 if (def->description)
1002 {
1003 def->description = xrealloc (def->description, len);
1004 strcat (def->description, text);
1005 }
1006 else
1007 {
1008 def->description = xmalloc (len);
1009 strcpy (def->description, text);
1010 }
1011 }
1012
1013 static void
1014 def_stacksize (int reserve, int commit)
1015 {
1016 def->stack_reserve = reserve;
1017 def->stack_commit = commit;
1018 }
1019
1020 static void
1021 def_heapsize (int reserve, int commit)
1022 {
1023 def->heap_reserve = reserve;
1024 def->heap_commit = commit;
1025 }
1026
1027 static void
1028 def_section (const char *name, int attr)
1029 {
1030 def_file_section *s;
1031 int max_sections = ROUND_UP (def->num_section_defs, 4);
1032
1033 if (def->num_section_defs >= max_sections)
1034 {
1035 max_sections = ROUND_UP (def->num_section_defs+1, 4);
1036
1037 if (def->section_defs)
1038 def->section_defs = xrealloc (def->section_defs,
1039 max_sections * sizeof (def_file_import));
1040 else
1041 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
1042 }
1043 s = def->section_defs + def->num_section_defs;
1044 memset (s, 0, sizeof (def_file_section));
1045 s->name = xstrdup (name);
1046 if (attr & 1)
1047 s->flag_read = 1;
1048 if (attr & 2)
1049 s->flag_write = 1;
1050 if (attr & 4)
1051 s->flag_execute = 1;
1052 if (attr & 8)
1053 s->flag_shared = 1;
1054
1055 def->num_section_defs++;
1056 }
1057
1058 static void
1059 def_section_alt (const char *name, const char *attr)
1060 {
1061 int aval = 0;
1062
1063 for (; *attr; attr++)
1064 {
1065 switch (*attr)
1066 {
1067 case 'R':
1068 case 'r':
1069 aval |= 1;
1070 break;
1071 case 'W':
1072 case 'w':
1073 aval |= 2;
1074 break;
1075 case 'X':
1076 case 'x':
1077 aval |= 4;
1078 break;
1079 case 'S':
1080 case 's':
1081 aval |= 8;
1082 break;
1083 }
1084 }
1085 def_section (name, aval);
1086 }
1087
1088 static void
1089 def_exports (const char *external_name,
1090 const char *internal_name,
1091 int ordinal,
1092 int flags,
1093 const char *its_name)
1094 {
1095 def_file_export *dfe;
1096 int is_dup = 0;
1097
1098 if (!internal_name && external_name)
1099 internal_name = external_name;
1100 #if TRACE
1101 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1102 #endif
1103
1104 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
1105 its_name, &is_dup);
1106
1107 /* We might check here for flag redefinition and warn. For now we
1108 ignore duplicates silently. */
1109 if (is_dup)
1110 return;
1111
1112 if (flags & 1)
1113 dfe->flag_noname = 1;
1114 if (flags & 2)
1115 dfe->flag_constant = 1;
1116 if (flags & 4)
1117 dfe->flag_data = 1;
1118 if (flags & 8)
1119 dfe->flag_private = 1;
1120 }
1121
1122 static void
1123 def_import (const char *internal_name,
1124 const char *module,
1125 const char *dllext,
1126 const char *name,
1127 int ordinal,
1128 const char *its_name)
1129 {
1130 char *buf = 0;
1131 const char *ext = dllext ? dllext : "dll";
1132 int is_dup = 0;
1133
1134 buf = xmalloc (strlen (module) + strlen (ext) + 2);
1135 sprintf (buf, "%s.%s", module, ext);
1136 module = buf;
1137
1138 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1139 &is_dup);
1140 free (buf);
1141 }
1142
1143 static void
1144 def_version (int major, int minor)
1145 {
1146 def->version_major = major;
1147 def->version_minor = minor;
1148 }
1149
1150 static void
1151 def_directive (char *str)
1152 {
1153 struct directive *d = xmalloc (sizeof (struct directive));
1154
1155 d->next = directives;
1156 directives = d;
1157 d->name = xstrdup (str);
1158 d->len = strlen (str);
1159 }
1160
1161 static void
1162 def_aligncomm (char *str, int align)
1163 {
1164 def_file_aligncomm *c, *p;
1165
1166 p = NULL;
1167 c = def->aligncomms;
1168 while (c != NULL)
1169 {
1170 int e = strcmp (c->symbol_name, str);
1171 if (!e)
1172 {
1173 /* Not sure if we want to allow here duplicates with
1174 different alignments, but for now we keep them. */
1175 e = (int) c->alignment - align;
1176 if (!e)
1177 return;
1178 }
1179 if (e > 0)
1180 break;
1181 c = (p = c)->next;
1182 }
1183
1184 c = xmalloc (sizeof (def_file_aligncomm));
1185 c->symbol_name = xstrdup (str);
1186 c->alignment = (unsigned int) align;
1187 if (!p)
1188 {
1189 c->next = def->aligncomms;
1190 def->aligncomms = c;
1191 }
1192 else
1193 {
1194 c->next = p->next;
1195 p->next = c;
1196 }
1197 }
1198
1199 static int
1200 def_error (const char *err)
1201 {
1202 einfo ("%P: %s:%d: %s\n",
1203 def_filename ? def_filename : "<unknown-file>", linenumber, err);
1204 return 0;
1205 }
1206
1207
1208 /* Lexical Scanner. */
1209
1210 #undef TRACE
1211 #define TRACE 0
1212
1213 /* Never freed, but always reused as needed, so no real leak. */
1214 static char *buffer = 0;
1215 static int buflen = 0;
1216 static int bufptr = 0;
1217
1218 static void
1219 put_buf (char c)
1220 {
1221 if (bufptr == buflen)
1222 {
1223 buflen += 50; /* overly reasonable, eh? */
1224 if (buffer)
1225 buffer = xrealloc (buffer, buflen + 1);
1226 else
1227 buffer = xmalloc (buflen + 1);
1228 }
1229 buffer[bufptr++] = c;
1230 buffer[bufptr] = 0; /* not optimal, but very convenient. */
1231 }
1232
1233 static struct
1234 {
1235 char *name;
1236 int token;
1237 }
1238 tokens[] =
1239 {
1240 { "BASE", BASE },
1241 { "CODE", CODE },
1242 { "CONSTANT", CONSTANTU },
1243 { "constant", CONSTANTL },
1244 { "DATA", DATAU },
1245 { "data", DATAL },
1246 { "DESCRIPTION", DESCRIPTION },
1247 { "DIRECTIVE", DIRECTIVE },
1248 { "EXECUTE", EXECUTE },
1249 { "EXPORTS", EXPORTS },
1250 { "HEAPSIZE", HEAPSIZE },
1251 { "IMPORTS", IMPORTS },
1252 { "LIBRARY", LIBRARY },
1253 { "NAME", NAME },
1254 { "NONAME", NONAMEU },
1255 { "noname", NONAMEL },
1256 { "PRIVATE", PRIVATEU },
1257 { "private", PRIVATEL },
1258 { "READ", READ },
1259 { "SECTIONS", SECTIONS },
1260 { "SEGMENTS", SECTIONS },
1261 { "SHARED", SHARED },
1262 { "STACKSIZE", STACKSIZE_K },
1263 { "VERSION", VERSIONK },
1264 { "WRITE", WRITE },
1265 { 0, 0 }
1266 };
1267
1268 static int
1269 def_getc (void)
1270 {
1271 int rv;
1272
1273 if (lex_parse_string)
1274 {
1275 if (lex_parse_string >= lex_parse_string_end)
1276 rv = EOF;
1277 else
1278 rv = *lex_parse_string++;
1279 }
1280 else
1281 {
1282 rv = fgetc (the_file);
1283 }
1284 if (rv == '\n')
1285 saw_newline = 1;
1286 return rv;
1287 }
1288
1289 static int
1290 def_ungetc (int c)
1291 {
1292 if (lex_parse_string)
1293 {
1294 lex_parse_string--;
1295 return c;
1296 }
1297 else
1298 return ungetc (c, the_file);
1299 }
1300
1301 static int
1302 def_lex (void)
1303 {
1304 int c, i, q;
1305
1306 if (lex_forced_token)
1307 {
1308 i = lex_forced_token;
1309 lex_forced_token = 0;
1310 #if TRACE
1311 printf ("lex: forcing token %d\n", i);
1312 #endif
1313 return i;
1314 }
1315
1316 c = def_getc ();
1317
1318 /* Trim leading whitespace. */
1319 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1320 c = def_getc ();
1321
1322 if (c == EOF)
1323 {
1324 #if TRACE
1325 printf ("lex: EOF\n");
1326 #endif
1327 return 0;
1328 }
1329
1330 if (saw_newline && c == ';')
1331 {
1332 do
1333 {
1334 c = def_getc ();
1335 }
1336 while (c != EOF && c != '\n');
1337 if (c == '\n')
1338 return def_lex ();
1339 return 0;
1340 }
1341
1342 /* Must be something else. */
1343 saw_newline = 0;
1344
1345 if (ISDIGIT (c))
1346 {
1347 bufptr = 0;
1348 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1349 {
1350 put_buf (c);
1351 c = def_getc ();
1352 }
1353 if (c != EOF)
1354 def_ungetc (c);
1355 yylval.digits = def_pool_strdup (buffer);
1356 #if TRACE
1357 printf ("lex: `%s' returns DIGITS\n", buffer);
1358 #endif
1359 return DIGITS;
1360 }
1361
1362 if (ISALPHA (c) || strchr ("$:-_?@", c))
1363 {
1364 bufptr = 0;
1365 q = c;
1366 put_buf (c);
1367 c = def_getc ();
1368
1369 if (q == '@')
1370 {
1371 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1372 return (q);
1373 else if (ISDIGIT (c)) /* '@' followed by digit. */
1374 {
1375 def_ungetc (c);
1376 return (q);
1377 }
1378 #if TRACE
1379 printf ("lex: @ returns itself\n");
1380 #endif
1381 }
1382
1383 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1384 {
1385 put_buf (c);
1386 c = def_getc ();
1387 }
1388 if (c != EOF)
1389 def_ungetc (c);
1390 if (ISALPHA (q)) /* Check for tokens. */
1391 {
1392 for (i = 0; tokens[i].name; i++)
1393 if (strcmp (tokens[i].name, buffer) == 0)
1394 {
1395 #if TRACE
1396 printf ("lex: `%s' is a string token\n", buffer);
1397 #endif
1398 return tokens[i].token;
1399 }
1400 }
1401 #if TRACE
1402 printf ("lex: `%s' returns ID\n", buffer);
1403 #endif
1404 yylval.id = def_pool_strdup (buffer);
1405 return ID;
1406 }
1407
1408 if (c == '\'' || c == '"')
1409 {
1410 q = c;
1411 c = def_getc ();
1412 bufptr = 0;
1413
1414 while (c != EOF && c != q)
1415 {
1416 put_buf (c);
1417 c = def_getc ();
1418 }
1419 yylval.id = def_pool_strdup (buffer);
1420 #if TRACE
1421 printf ("lex: `%s' returns ID\n", buffer);
1422 #endif
1423 return ID;
1424 }
1425
1426 if ( c == '=')
1427 {
1428 c = def_getc ();
1429 if (c == '=')
1430 {
1431 #if TRACE
1432 printf ("lex: `==' returns EQUAL\n");
1433 #endif
1434 return EQUAL;
1435 }
1436 def_ungetc (c);
1437 #if TRACE
1438 printf ("lex: `=' returns itself\n");
1439 #endif
1440 return '=';
1441 }
1442 if (c == '.' || c == ',')
1443 {
1444 #if TRACE
1445 printf ("lex: `%c' returns itself\n", c);
1446 #endif
1447 return c;
1448 }
1449
1450 if (c == '\n')
1451 {
1452 linenumber++;
1453 saw_newline = 1;
1454 }
1455
1456 /*printf ("lex: 0x%02x ignored\n", c); */
1457 return def_lex ();
1458 }
1459
1460 static char *
1461 def_pool_alloc (size_t sz)
1462 {
1463 def_pool_str *e;
1464
1465 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1466 e->next = pool_strs;
1467 pool_strs = e;
1468 return e->data;
1469 }
1470
1471 static char *
1472 def_pool_strdup (const char *str)
1473 {
1474 char *s;
1475 size_t len;
1476 if (!str)
1477 return NULL;
1478 len = strlen (str) + 1;
1479 s = def_pool_alloc (len);
1480 memcpy (s, str, len);
1481 return s;
1482 }
1483
1484 static void
1485 def_pool_free (void)
1486 {
1487 def_pool_str *p;
1488 while ((p = pool_strs) != NULL)
1489 {
1490 pool_strs = p->next;
1491 free (p);
1492 }
1493 }
This page took 0.069832 seconds and 5 git commands to generate.