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