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