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