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