Initial import from FreeBSD RELENG_4:
[games.git] / contrib / binutils / ld / deffilep.y
1 %{ /* deffilep.y - parser for .def files */
2
3 /*   Copyright 1995, 1997, 1998, 1999, 2000, 2001
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
85   PARAMS ((const char *, const char *, const char *, const char *, int));
86 static void def_library PARAMS ((const char *, int));
87 static def_file_module *def_stash_module PARAMS ((def_file *, const char *));
88 static void def_name PARAMS ((const char *, int));
89 static void def_section PARAMS ((const char *, int));
90 static void def_section_alt PARAMS ((const char *, const char *));
91 static void def_stacksize PARAMS ((int, int));
92 static void def_version PARAMS ((int, int));
93 static void def_directive PARAMS ((char *));
94 static int def_parse PARAMS ((void));
95 static int def_error PARAMS ((const char *));
96 static void put_buf PARAMS ((char));
97 static int def_getc PARAMS ((void));
98 static int def_ungetc PARAMS ((int));
99 static int def_lex PARAMS ((void));
100
101 static int lex_forced_token = 0;
102 static const char *lex_parse_string = 0;
103 static const char *lex_parse_string_end = 0;
104
105 %}
106
107 %union {
108   char *id;
109   int number;
110 };
111
112 %token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATAU, DATAL
113 %token SECTIONS, EXPORTS, IMPORTS, VERSIONK, BASE, CONSTANTU, CONSTANTL
114 %token PRIVATEU, PRIVATEL
115 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE
116 %token <id> ID
117 %token <number> NUMBER
118 %type  <number> opt_base opt_ordinal
119 %type  <number> attr attr_list opt_number exp_opt_list exp_opt
120 %type  <id> opt_name opt_equal_name 
121
122 %%
123
124 start: start command
125         | command
126         ;
127
128 command: 
129                 NAME opt_name opt_base { def_name ($2, $3); }
130         |       LIBRARY opt_name opt_base { def_library ($2, $3); }
131         |       DESCRIPTION ID { def_description ($2);}
132         |       STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);}
133         |       HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
134         |       CODE attr_list { def_section ("CODE", $2);}
135         |       DATAU attr_list  { def_section ("DATA", $2);}
136         |       SECTIONS seclist
137         |       EXPORTS explist 
138         |       IMPORTS implist
139         |       VERSIONK NUMBER { def_version ($2, 0);}
140         |       VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
141         |       DIRECTIVE ID { def_directive ($2);}
142         ;
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                 ID 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           '=' ID        { $$ = $2; }
236         |               { $$ =  0; }                     
237         ;
238
239 opt_base: BASE  '=' NUMBER      { $$ = $3;}
240         |       { $$ = 0;}
241         ;
242
243         
244
245 %%
246
247 /*****************************************************************************
248  API
249  *****************************************************************************/
250
251 static FILE *the_file;
252 static const char *def_filename;
253 static int linenumber;
254 static def_file *def;
255 static int saw_newline;
256
257 struct directive
258   {
259     struct directive *next;
260     char *name;
261     int len;
262   };
263
264 static struct directive *directives = 0;
265
266 def_file *
267 def_file_empty ()
268 {
269   def_file *rv = (def_file *) xmalloc (sizeof (def_file));
270   memset (rv, 0, sizeof (def_file));
271   rv->is_dll = -1;
272   rv->base_address = (bfd_vma) (-1);
273   rv->stack_reserve = rv->stack_commit = -1;
274   rv->heap_reserve = rv->heap_commit = -1;
275   rv->version_major = rv->version_minor = -1;
276   return rv;
277 }
278
279 def_file *
280 def_file_parse (filename, add_to)
281      const char *filename;
282      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)
326      def_file *def;
327 {
328   int i;
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, def)
387      FILE *file;
388      def_file *def;
389 {
390   int i;
391   fprintf (file, ">>>> def_file at 0x%08x\n", def);
392   if (def->name)
393     fprintf (file, "  name: %s\n", def->name ? def->name : "(unspecified)");
394   if (def->is_dll != -1)
395     fprintf (file, "  is dll: %s\n", def->is_dll ? "yes" : "no");
396   if (def->base_address != (bfd_vma) (-1))
397     fprintf (file, "  base address: 0x%08x\n", def->base_address);
398   if (def->description)
399     fprintf (file, "  description: `%s'\n", def->description);
400   if (def->stack_reserve != -1)
401     fprintf (file, "  stack reserve: 0x%08x\n", def->stack_reserve);
402   if (def->stack_commit != -1)
403     fprintf (file, "  stack commit: 0x%08x\n", def->stack_commit);
404   if (def->heap_reserve != -1)
405     fprintf (file, "  heap reserve: 0x%08x\n", def->heap_reserve);
406   if (def->heap_commit != -1)
407     fprintf (file, "  heap commit: 0x%08x\n", def->heap_commit);
408
409   if (def->num_section_defs > 0)
410     {
411       fprintf (file, "  section defs:\n");
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       for (i = 0; i < def->num_exports; i++)
432         {
433           fprintf (file, "    name: `%s', int: `%s', ordinal: %d, flags:",
434                    def->exports[i].name, def->exports[i].internal_name,
435                    def->exports[i].ordinal);
436           if (def->exports[i].flag_private)
437             fprintf (file, " P");
438           if (def->exports[i].flag_constant)
439             fprintf (file, " C");
440           if (def->exports[i].flag_noname)
441             fprintf (file, " N");
442           if (def->exports[i].flag_data)
443             fprintf (file, " D");
444           fprintf (file, "\n");
445         }
446     }
447
448   if (def->num_imports > 0)
449     {
450       fprintf (file, "  imports:\n");
451       for (i = 0; i < def->num_imports; i++)
452         {
453           fprintf (file, "    int: %s, from: `%s', name: `%s', ordinal: %d\n",
454                    def->imports[i].internal_name,
455                    def->imports[i].module,
456                    def->imports[i].name,
457                    def->imports[i].ordinal);
458         }
459     }
460   if (def->version_major != -1)
461     fprintf (file, "  version: %d.%d\n", def->version_major, def->version_minor);
462   fprintf (file, "<<<< def_file at 0x%08x\n", def);
463 }
464 #endif
465
466 def_file_export *
467 def_file_add_export (def, external_name, internal_name, ordinal)
468      def_file *def;
469      const char *external_name;
470      const char *internal_name;
471      int ordinal;
472 {
473   def_file_export *e;
474   int max_exports = ROUND_UP(def->num_exports, 32);
475   if (def->num_exports >= max_exports)
476     {
477       max_exports = ROUND_UP(def->num_exports+1, 32);
478       if (def->exports)
479         def->exports = (def_file_export *) xrealloc (def->exports, max_exports * sizeof (def_file_export));
480       else
481         def->exports = (def_file_export *) xmalloc (max_exports * sizeof (def_file_export));
482     }
483   e = def->exports + def->num_exports;
484   memset (e, 0, sizeof (def_file_export));
485   if (internal_name && !external_name)
486     external_name = internal_name;
487   if (external_name && !internal_name)
488     internal_name = external_name;
489   e->name = xstrdup (external_name);
490   e->internal_name = xstrdup (internal_name);
491   e->ordinal = ordinal;
492   def->num_exports++;
493   return e;
494 }
495
496 static def_file_module *
497 def_stash_module (def, name)
498      def_file *def;
499      const char *name;
500 {
501   def_file_module *s;
502   for (s=def->modules; s; s=s->next)
503     if (strcmp (s->name, name) == 0)
504       return s;
505   s = (def_file_module *) xmalloc (sizeof (def_file_module) + strlen (name));
506   s->next = def->modules;
507   def->modules = s;
508   s->user_data = 0;
509   strcpy (s->name, name);
510   return s;
511 }
512
513 def_file_import *
514 def_file_add_import (def, name, module, ordinal, internal_name)
515      def_file *def;
516      const char *name;
517      const char *module;
518      int ordinal;
519      const char *internal_name;
520 {
521   def_file_import *i;
522   int max_imports = ROUND_UP(def->num_imports, 16);
523   if (def->num_imports >= max_imports)
524     {
525       max_imports = ROUND_UP(def->num_imports+1, 16);
526       if (def->imports)
527         def->imports = (def_file_import *) xrealloc (def->imports, max_imports * sizeof (def_file_import));
528       else
529         def->imports = (def_file_import *) xmalloc (max_imports * sizeof (def_file_import));
530     }
531   i = def->imports + def->num_imports;
532   memset (i, 0, sizeof (def_file_import));
533   if (name)
534     i->name = xstrdup (name);
535   if (module)
536     i->module = def_stash_module (def, module);
537   i->ordinal = ordinal;
538   if (internal_name)
539     i->internal_name = xstrdup (internal_name);
540   else
541     i->internal_name = i->name;
542   def->num_imports++;
543   return i;
544 }
545
546 struct
547 {
548   char *param;
549   int token;
550 }
551 diropts[] =
552 {
553   { "-heap", HEAPSIZE },
554   { "-stack", STACKSIZE },
555   { "-attr", SECTIONS },
556   { "-export", EXPORTS },
557   { 0, 0 }
558 };
559
560 void
561 def_file_add_directive (my_def, param, len)
562      def_file *my_def;
563      const char *param;
564      int len;
565 {
566   def_file *save_def = def;
567   const char *pend = param + len;
568   const char *tend = param;
569   int i;
570
571   def = my_def;
572
573   while (param < pend)
574     {
575       while (param < pend && ISSPACE (*param))
576         param++;
577       for (tend = param + 1;
578            tend < pend && !(ISSPACE (tend[-1]) && *tend == '-');
579            tend++);
580
581       for (i = 0; diropts[i].param; i++)
582         {
583           int len = strlen (diropts[i].param);
584           if (tend - param >= len
585               && strncmp (param, diropts[i].param, len) == 0
586               && (param[len] == ':' || param[len] == ' '))
587             {
588               lex_parse_string_end = tend;
589               lex_parse_string = param + len + 1;
590               lex_forced_token = diropts[i].token;
591               saw_newline = 0;
592               def_parse ();
593               break;
594             }
595         }
596
597       if (!diropts[i].param)
598         {
599           /* xgettext:c-format */
600           einfo (_("Warning: .drectve `%.*s' unrecognized\n"),
601                  tend - param, param);
602         }
603       lex_parse_string = 0;
604       param = tend;
605     }
606
607   def = save_def;
608 }
609
610 /*****************************************************************************
611  Parser Callbacks
612  *****************************************************************************/
613
614 static void
615 def_name (name, base)
616      const char *name;
617      int base;
618 {
619   if (def->name)
620     free (def->name);
621   def->name = xstrdup (name);
622   def->base_address = base;
623   def->is_dll = 0;
624 }
625
626 static void
627 def_library (name, base)
628      const char *name;
629      int base;
630 {
631   if (def->name)
632     free (def->name);
633   def->name = xstrdup (name);
634   def->base_address = base;
635   def->is_dll = 1;
636 }
637
638 static void
639 def_description (text)
640      const char *text;
641 {
642   int len = def->description ? strlen (def->description) : 0;
643   len += strlen (text) + 1;
644   if (def->description)
645     {
646       def->description = (char *) xrealloc (def->description, len);
647       strcat (def->description, text);
648     }
649   else
650     {
651       def->description = (char *) xmalloc (len);
652       strcpy (def->description, text);
653     }
654 }
655
656 static void
657 def_stacksize (reserve, commit)
658      int reserve;
659      int commit;
660 {
661   def->stack_reserve = reserve;
662   def->stack_commit = commit;
663 }
664
665 static void
666 def_heapsize (reserve, commit)
667      int reserve;
668      int commit;
669 {
670   def->heap_reserve = reserve;
671   def->heap_commit = commit;
672 }
673
674 static void
675 def_section (name, attr)
676      const char *name;
677      int attr;
678 {
679   def_file_section *s;
680   int max_sections = ROUND_UP(def->num_section_defs, 4);
681   if (def->num_section_defs >= max_sections)
682     {
683       max_sections = ROUND_UP(def->num_section_defs+1, 4);
684       if (def->section_defs)
685         def->section_defs = (def_file_section *) xrealloc (def->section_defs, max_sections * sizeof (def_file_import));
686       else
687         def->section_defs = (def_file_section *) xmalloc (max_sections * sizeof (def_file_import));
688     }
689   s = def->section_defs + def->num_section_defs;
690   memset (s, 0, sizeof (def_file_section));
691   s->name = xstrdup (name);
692   if (attr & 1)
693     s->flag_read = 1;
694   if (attr & 2)
695     s->flag_write = 1;
696   if (attr & 4)
697     s->flag_execute = 1;
698   if (attr & 8)
699     s->flag_shared = 1;
700
701   def->num_section_defs++;
702 }
703
704 static void
705 def_section_alt (name, attr)
706      const char *name;
707      const char *attr;
708 {
709   int aval = 0;
710   for (; *attr; attr++)
711     {
712       switch (*attr)
713         {
714         case 'R':
715         case 'r':
716           aval |= 1;
717           break;
718         case 'W':
719         case 'w':
720           aval |= 2;
721           break;
722         case 'X':
723         case 'x':
724           aval |= 4;
725           break;
726         case 'S':
727         case 's':
728           aval |= 8;
729           break;
730         }
731     }
732   def_section (name, aval);
733 }
734
735 static void
736 def_exports (external_name, internal_name, ordinal, flags)
737      const char *external_name;
738      const char *internal_name;
739      int ordinal;
740      int flags;
741 {
742   def_file_export *dfe;
743
744   if (!internal_name && external_name)
745     internal_name = external_name;
746 #if TRACE
747   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
748 #endif
749
750   dfe = def_file_add_export (def, external_name, internal_name, ordinal);
751   if (flags & 1)
752     dfe->flag_noname = 1;
753   if (flags & 2)
754     dfe->flag_constant = 1;
755   if (flags & 4)
756     dfe->flag_data = 1;
757   if (flags & 8)
758     dfe->flag_private = 1;
759 }
760
761 static void
762 def_import (internal_name, module, dllext, name, ordinal)
763      const char *internal_name;
764      const char *module;
765      const char *dllext;
766      const char *name;
767      int ordinal;
768 {
769   char *buf = 0;
770
771   if (dllext != NULL)
772     {
773       buf = (char *) xmalloc (strlen (module) + strlen (dllext) + 2);
774       sprintf (buf, "%s.%s", module, dllext);
775       module = buf;
776     }
777
778   def_file_add_import (def, name, module, ordinal, internal_name);
779   if (buf)
780     free (buf);
781 }
782
783 static void
784 def_version (major, minor)
785      int major;
786      int minor;
787 {
788   def->version_major = major;
789   def->version_minor = minor;
790 }
791
792 static void
793 def_directive (str)
794      char *str;
795 {
796   struct directive *d = (struct directive *) xmalloc (sizeof (struct directive));
797   d->next = directives;
798   directives = d;
799   d->name = xstrdup (str);
800   d->len = strlen (str);
801 }
802
803 static int
804 def_error (err)
805      const char *err;
806 {
807   einfo ("%P: %s:%d: %s\n", def_filename, linenumber, err);
808
809   return 0;
810 }
811
812
813 /*****************************************************************************
814  Lexical Scanner
815  *****************************************************************************/
816
817 #undef TRACE
818 #define TRACE 0
819
820 /* Never freed, but always reused as needed, so no real leak */
821 static char *buffer = 0;
822 static int buflen = 0;
823 static int bufptr = 0;
824
825 static void
826 put_buf (c)
827      char c;
828 {
829   if (bufptr == buflen)
830     {
831       buflen += 50;             /* overly reasonable, eh? */
832       if (buffer)
833         buffer = (char *) xrealloc (buffer, buflen + 1);
834       else
835         buffer = (char *) xmalloc (buflen + 1);
836     }
837   buffer[bufptr++] = c;
838   buffer[bufptr] = 0;           /* not optimal, but very convenient */
839 }
840
841 static struct
842 {
843   char *name;
844   int token;
845 }
846 tokens[] =
847 {
848   { "BASE", BASE },
849   { "CODE", CODE },
850   { "CONSTANT", CONSTANTU },
851   { "constant", CONSTANTL },
852   { "DATA", DATAU },
853   { "data", DATAL },
854   { "DESCRIPTION", DESCRIPTION },
855   { "DIRECTIVE", DIRECTIVE },
856   { "EXECUTE", EXECUTE },
857   { "EXPORTS", EXPORTS },
858   { "HEAPSIZE", HEAPSIZE },
859   { "IMPORTS", IMPORTS },
860   { "LIBRARY", LIBRARY },
861   { "NAME", NAME },
862   { "NONAME", NONAMEU },
863   { "noname", NONAMEL },
864   { "PRIVATE", PRIVATEU },
865   { "private", PRIVATEL },
866   { "READ", READ },
867   { "SECTIONS", SECTIONS },
868   { "SEGMENTS", SECTIONS },
869   { "SHARED", SHARED },
870   { "STACKSIZE", STACKSIZE },
871   { "VERSION", VERSIONK },
872   { "WRITE", WRITE },
873   { 0, 0 }
874 };
875
876 static int
877 def_getc ()
878 {
879   int rv;
880   if (lex_parse_string)
881     {
882       if (lex_parse_string >= lex_parse_string_end)
883         rv = EOF;
884       else
885         rv = *lex_parse_string++;
886     }
887   else
888     {
889       rv = fgetc (the_file);
890     }
891   if (rv == '\n')
892     saw_newline = 1;
893   return rv;
894 }
895
896 static int
897 def_ungetc (c)
898      int c;
899 {
900   if (lex_parse_string)
901     {
902       lex_parse_string--;
903       return c;
904     }
905   else
906     return ungetc (c, the_file);
907 }
908
909 static int
910 def_lex ()
911 {
912   int c, i, q;
913
914   if (lex_forced_token)
915     {
916       i = lex_forced_token;
917       lex_forced_token = 0;
918 #if TRACE
919       printf ("lex: forcing token %d\n", i);
920 #endif
921       return i;
922     }
923
924   c = def_getc ();
925
926   /* trim leading whitespace */
927   while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
928     c = def_getc ();
929
930   if (c == EOF)
931     {
932 #if TRACE
933       printf ("lex: EOF\n");
934 #endif
935       return 0;
936     }
937
938   if (saw_newline && c == ';')
939     {
940       do
941         {
942           c = def_getc ();
943         }
944       while (c != EOF && c != '\n');
945       if (c == '\n')
946         return def_lex ();
947       return 0;
948     }
949   /* must be something else */
950   saw_newline = 0;
951
952   if (ISDIGIT (c))
953     {
954       bufptr = 0;
955       while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
956         {
957           put_buf (c);
958           c = def_getc ();
959         }
960       if (c != EOF)
961         def_ungetc (c);
962       yylval.number = strtoul (buffer, 0, 0);
963 #if TRACE
964       printf ("lex: `%s' returns NUMBER %d\n", buffer, yylval.number);
965 #endif
966       return NUMBER;
967     }
968
969   if (ISALPHA (c) || strchr ("$:-_?", c))
970     {
971       bufptr = 0;
972       while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@", c)))
973         {
974           put_buf (c);
975           c = def_getc ();
976         }
977       if (c != EOF)
978         def_ungetc (c);
979       for (i = 0; tokens[i].name; i++)
980         if (strcmp (tokens[i].name, buffer) == 0)
981           {
982 #if TRACE
983             printf ("lex: `%s' is a string token\n", buffer);
984 #endif
985             return tokens[i].token;
986           }
987 #if TRACE
988       printf ("lex: `%s' returns ID\n", buffer);
989 #endif
990       yylval.id = xstrdup (buffer);
991       return ID;
992     }
993
994   if (c == '\'' || c == '"')
995     {
996       q = c;
997       c = def_getc ();
998       bufptr = 0;
999       while (c != EOF && c != q)
1000         {
1001           put_buf (c);
1002           c = def_getc ();
1003         }
1004       yylval.id = xstrdup (buffer);
1005 #if TRACE
1006       printf ("lex: `%s' returns ID\n", buffer);
1007 #endif
1008       return ID;
1009     }
1010
1011   if (c == '=' || c == '.' || c == '@' || c == ',')
1012     {
1013 #if TRACE
1014       printf ("lex: `%c' returns itself\n", c);
1015 #endif
1016       return c;
1017     }
1018
1019   if (c == '\n')
1020     {
1021       linenumber++;
1022       saw_newline = 1;
1023     }
1024
1025   /*printf ("lex: 0x%02x ignored\n", c); */
1026   return def_lex ();
1027 }