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