Apply patch from Mumit Khan to fix bugs generating dll names.
[external/binutils.git] / ld / deffilep.y
1 %{ /* deffilep.y - parser for .def files */
2
3 /*   Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
4
5 This file is part of GNU Binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include <stdio.h>
22 #include <ctype.h>
23 #include "libiberty.h"
24 #include "bfd.h"
25 #include "sysdep.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 int def_lex ();
81
82 static void def_description PARAMS ((const char *));
83 static void def_exports PARAMS ((const char *, const char *, int, int));
84 static void def_heapsize PARAMS ((int, int));
85 static void def_import
86   PARAMS ((const char *, const char *, const char *, const char *, int));
87 static void def_library PARAMS ((const char *, int));
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 int def_lex PARAMS ((void));
97
98 static int lex_forced_token = 0;
99 static const char *lex_parse_string = 0;
100 static const char *lex_parse_string_end = 0;
101
102 %}
103
104 %union {
105   char *id;
106   int number;
107 };
108
109 %token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATAU, DATAL
110 %token SECTIONS, EXPORTS, IMPORTS, VERSIONK, BASE, CONSTANTU, CONSTANTL
111 %token PRIVATEU, PRIVATEL
112 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE
113 %token <id> ID
114 %token <number> NUMBER
115 %type  <number> opt_base opt_ordinal
116 %type  <number> attr attr_list opt_number exp_opt_list exp_opt
117 %type  <id> opt_name opt_equal_name 
118
119 %%
120
121 start: start command
122         | command
123         ;
124
125 command: 
126                 NAME opt_name opt_base { def_name ($2, $3); }
127         |       LIBRARY opt_name opt_base { def_library ($2, $3); }
128         |       DESCRIPTION ID { def_description ($2);}
129         |       STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);}
130         |       HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
131         |       CODE attr_list { def_section ("CODE", $2);}
132         |       DATAU attr_list  { def_section ("DATA", $2);}
133         |       SECTIONS seclist
134         |       EXPORTS explist 
135         |       IMPORTS implist
136         |       VERSIONK NUMBER { def_version ($2, 0);}
137         |       VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
138         |       DIRECTIVE ID { def_directive ($2);}
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                 ID 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           '=' ID        { $$ = $2; }
233         |               { $$ =  0; }                     
234         ;
235
236 opt_base: BASE  '=' NUMBER      { $$ = $3;}
237         |       { $$ = 0;}
238         ;
239
240         
241
242 %%
243
244 /*****************************************************************************
245  API
246  *****************************************************************************/
247
248 static FILE *the_file;
249 static const char *def_filename;
250 static int linenumber;
251 static def_file *def;
252 static int saw_newline;
253
254 struct directive
255   {
256     struct directive *next;
257     char *name;
258     int len;
259   };
260
261 static struct directive *directives = 0;
262
263 def_file *
264 def_file_empty ()
265 {
266   def_file *rv = (def_file *) xmalloc (sizeof (def_file));
267   memset (rv, 0, sizeof (def_file));
268   rv->is_dll = -1;
269   rv->base_address = (bfd_vma) (-1);
270   rv->stack_reserve = rv->stack_commit = -1;
271   rv->heap_reserve = rv->heap_commit = -1;
272   rv->version_major = rv->version_minor = -1;
273   return rv;
274 }
275
276 def_file *
277 def_file_parse (filename, add_to)
278      const char *filename;
279      def_file *add_to;
280 {
281   struct directive *d;
282
283   the_file = fopen (filename, "r");
284   def_filename = filename;
285   linenumber = 1;
286   if (!the_file)
287     {
288       perror (filename);
289       return 0;
290     }
291   if (add_to)
292     {
293       def = add_to;
294     }
295   else
296     {
297       def = def_file_empty ();
298     }
299
300   saw_newline = 1;
301   if (def_parse ())
302     {
303       def_file_free (def);
304       fclose (the_file);
305       return 0;
306     }
307
308   fclose (the_file);
309
310   for (d = directives; d; d = d->next)
311     {
312 #if TRACE
313       printf ("Adding directive %08x `%s'\n", d->name, d->name);
314 #endif
315       def_file_add_directive (def, d->name, d->len);
316     }
317
318   return def;
319 }
320
321 void
322 def_file_free (def)
323      def_file *def;
324 {
325   int i;
326   if (!def)
327     return;
328   if (def->name)
329     free (def->name);
330   if (def->description)
331     free (def->description);
332
333   if (def->section_defs)
334     {
335       for (i = 0; i < def->num_section_defs; i++)
336         {
337           if (def->section_defs[i].name)
338             free (def->section_defs[i].name);
339           if (def->section_defs[i].class)
340             free (def->section_defs[i].class);
341         }
342       free (def->section_defs);
343     }
344
345   if (def->exports)
346     {
347       for (i = 0; i < def->num_exports; i++)
348         {
349           if (def->exports[i].internal_name
350               && def->exports[i].internal_name != def->exports[i].name)
351             free (def->exports[i].internal_name);
352           if (def->exports[i].name)
353             free (def->exports[i].name);
354         }
355       free (def->exports);
356     }
357
358   if (def->imports)
359     {
360       for (i = 0; i < def->num_imports; i++)
361         {
362           if (def->imports[i].internal_name
363               && def->imports[i].internal_name != def->imports[i].name)
364             free (def->imports[i].internal_name);
365           if (def->imports[i].name)
366             free (def->imports[i].name);
367         }
368       free (def->imports);
369     }
370
371   while (def->modules)
372     {
373       def_file_module *m = def->modules;
374       def->modules = def->modules->next;
375       free (m);
376     }
377
378   free (def);
379 }
380
381 #ifdef DEF_FILE_PRINT
382 void
383 def_file_print (file, def)
384      FILE *file;
385      def_file *def;
386 {
387   int i;
388   fprintf (file, ">>>> def_file at 0x%08x\n", def);
389   if (def->name)
390     fprintf (file, "  name: %s\n", def->name ? def->name : "(unspecified)");
391   if (def->is_dll != -1)
392     fprintf (file, "  is dll: %s\n", def->is_dll ? "yes" : "no");
393   if (def->base_address != (bfd_vma) (-1))
394     fprintf (file, "  base address: 0x%08x\n", def->base_address);
395   if (def->description)
396     fprintf (file, "  description: `%s'\n", def->description);
397   if (def->stack_reserve != -1)
398     fprintf (file, "  stack reserve: 0x%08x\n", def->stack_reserve);
399   if (def->stack_commit != -1)
400     fprintf (file, "  stack commit: 0x%08x\n", def->stack_commit);
401   if (def->heap_reserve != -1)
402     fprintf (file, "  heap reserve: 0x%08x\n", def->heap_reserve);
403   if (def->heap_commit != -1)
404     fprintf (file, "  heap commit: 0x%08x\n", def->heap_commit);
405
406   if (def->num_section_defs > 0)
407     {
408       fprintf (file, "  section defs:\n");
409       for (i = 0; i < def->num_section_defs; i++)
410         {
411           fprintf (file, "    name: `%s', class: `%s', flags:",
412                    def->section_defs[i].name, def->section_defs[i].class);
413           if (def->section_defs[i].flag_read)
414             fprintf (file, " R");
415           if (def->section_defs[i].flag_write)
416             fprintf (file, " W");
417           if (def->section_defs[i].flag_execute)
418             fprintf (file, " X");
419           if (def->section_defs[i].flag_shared)
420             fprintf (file, " S");
421           fprintf (file, "\n");
422         }
423     }
424
425   if (def->num_exports > 0)
426     {
427       fprintf (file, "  exports:\n");
428       for (i = 0; i < def->num_exports; i++)
429         {
430           fprintf (file, "    name: `%s', int: `%s', ordinal: %d, flags:",
431                    def->exports[i].name, def->exports[i].internal_name,
432                    def->exports[i].ordinal);
433           if (def->exports[i].flag_private)
434             fprintf (file, " P");
435           if (def->exports[i].flag_constant)
436             fprintf (file, " C");
437           if (def->exports[i].flag_noname)
438             fprintf (file, " N");
439           if (def->exports[i].flag_data)
440             fprintf (file, " D");
441           fprintf (file, "\n");
442         }
443     }
444
445   if (def->num_imports > 0)
446     {
447       fprintf (file, "  imports:\n");
448       for (i = 0; i < def->num_imports; i++)
449         {
450           fprintf (file, "    int: %s, from: `%s', name: `%s', ordinal: %d\n",
451                    def->imports[i].internal_name,
452                    def->imports[i].module,
453                    def->imports[i].name,
454                    def->imports[i].ordinal);
455         }
456     }
457   if (def->version_major != -1)
458     fprintf (file, "  version: %d.%d\n", def->version_major, def->version_minor);
459   fprintf (file, "<<<< def_file at 0x%08x\n", def);
460 }
461 #endif
462
463 def_file_export *
464 def_file_add_export (def, external_name, internal_name, ordinal)
465      def_file *def;
466      const char *external_name;
467      const char *internal_name;
468      int ordinal;
469 {
470   def_file_export *e;
471   int max_exports = ROUND_UP(def->num_exports, 32);
472   if (def->num_exports >= max_exports)
473     {
474       max_exports = ROUND_UP(def->num_exports+1, 32);
475       if (def->exports)
476         def->exports = (def_file_export *) xrealloc (def->exports, max_exports * sizeof (def_file_export));
477       else
478         def->exports = (def_file_export *) xmalloc (max_exports * sizeof (def_file_export));
479     }
480   e = def->exports + def->num_exports;
481   memset (e, 0, sizeof (def_file_export));
482   if (internal_name && !external_name)
483     external_name = internal_name;
484   if (external_name && !internal_name)
485     internal_name = external_name;
486   e->name = xstrdup (external_name);
487   e->internal_name = xstrdup (internal_name);
488   e->ordinal = ordinal;
489   def->num_exports++;
490   return e;
491 }
492
493 static def_file_module *
494 def_stash_module (def, name)
495      def_file *def;
496      char *name;
497 {
498   def_file_module *s;
499   for (s=def->modules; s; s=s->next)
500     if (strcmp (s->name, name) == 0)
501       return s;
502   s = (def_file_module *) xmalloc (sizeof (def_file_module) + strlen (name));
503   s->next = def->modules;
504   def->modules = s;
505   s->user_data = 0;
506   strcpy (s->name, name);
507   return s;
508 }
509
510 def_file_import *
511 def_file_add_import (def, name, module, ordinal, internal_name)
512      def_file *def;
513      const char *name;
514      const char *module;
515      int ordinal;
516      const char *internal_name;
517 {
518   def_file_import *i;
519   int max_imports = ROUND_UP(def->num_imports, 16);
520   if (def->num_imports >= max_imports)
521     {
522       max_imports = ROUND_UP(def->num_imports+1, 16);
523       if (def->imports)
524         def->imports = (def_file_import *) xrealloc (def->imports, max_imports * sizeof (def_file_import));
525       else
526         def->imports = (def_file_import *) xmalloc (max_imports * sizeof (def_file_import));
527     }
528   i = def->imports + def->num_imports;
529   memset (i, 0, sizeof (def_file_import));
530   if (name)
531     i->name = xstrdup (name);
532   if (module)
533     i->module = def_stash_module(def, module);
534   i->ordinal = ordinal;
535   if (internal_name)
536     i->internal_name = xstrdup (internal_name);
537   else
538     i->internal_name = i->name;
539   def->num_imports++;
540   return i;
541 }
542
543 struct
544 {
545   char *param;
546   int token;
547 }
548 diropts[] =
549 {
550   { "-heap", HEAPSIZE },
551   { "-stack", STACKSIZE },
552   { "-attr", SECTIONS },
553   { "-export", EXPORTS },
554   { 0, 0 }
555 };
556
557 void
558 def_file_add_directive (my_def, param, len)
559      def_file *my_def;
560      const char *param;
561      int len;
562 {
563   def_file *save_def = def;
564   const char *pend = param + len;
565   const char *tend = param;
566   int i;
567
568   def = my_def;
569
570   while (param < pend)
571     {
572       while (param < pend && isspace (*param))
573         param++;
574       for (tend = param + 1;
575            tend < pend && !(isspace (tend[-1]) && *tend == '-');
576            tend++);
577
578       for (i = 0; diropts[i].param; i++)
579         {
580           int len = strlen (diropts[i].param);
581           if (tend - param >= len
582               && strncmp (param, diropts[i].param, len) == 0
583               && (param[len] == ':' || param[len] == ' '))
584             {
585               lex_parse_string_end = tend;
586               lex_parse_string = param + len + 1;
587               lex_forced_token = diropts[i].token;
588               saw_newline = 0;
589               def_parse ();
590               break;
591             }
592         }
593
594       if (!diropts[i].param)
595         {
596           /* xgettext:c-format */
597           einfo (_("Warning: .drectve `%.*s' unrecognized\n"),
598                  tend - param, param);
599         }
600       lex_parse_string = 0;
601       param = tend;
602     }
603
604   def = save_def;
605 }
606
607 /*****************************************************************************
608  Parser Callbacks
609  *****************************************************************************/
610
611 static void
612 def_name (name, base)
613      const char *name;
614      int base;
615 {
616   if (def->name)
617     free (def->name);
618   def->name = xstrdup (name);
619   def->base_address = base;
620   def->is_dll = 0;
621 }
622
623 static void
624 def_library (name, base)
625      const char *name;
626      int base;
627 {
628   if (def->name)
629     free (def->name);
630   def->name = xstrdup (name);
631   def->base_address = base;
632   def->is_dll = 1;
633 }
634
635 static void
636 def_description (text)
637      const char *text;
638 {
639   int len = def->description ? strlen (def->description) : 0;
640   len += strlen (text) + 1;
641   if (def->description)
642     {
643       def->description = (char *) xrealloc (def->description, len);
644       strcat (def->description, text);
645     }
646   else
647     {
648       def->description = (char *) xmalloc (len);
649       strcpy (def->description, text);
650     }
651 }
652
653 static void
654 def_stacksize (reserve, commit)
655      int reserve;
656      int commit;
657 {
658   def->stack_reserve = reserve;
659   def->stack_commit = commit;
660 }
661
662 static void
663 def_heapsize (reserve, commit)
664      int reserve;
665      int commit;
666 {
667   def->heap_reserve = reserve;
668   def->heap_commit = commit;
669 }
670
671 static void
672 def_section (name, attr)
673      const char *name;
674      int attr;
675 {
676   def_file_section *s;
677   int max_sections = ROUND_UP(def->num_section_defs, 4);
678   if (def->num_section_defs >= max_sections)
679     {
680       max_sections = ROUND_UP(def->num_section_defs+1, 4);
681       if (def->section_defs)
682         def->section_defs = (def_file_section *) xrealloc (def->section_defs, max_sections * sizeof (def_file_import));
683       else
684         def->section_defs = (def_file_section *) xmalloc (max_sections * sizeof (def_file_import));
685     }
686   s = def->section_defs + def->num_section_defs;
687   memset (s, 0, sizeof (def_file_section));
688   s->name = xstrdup (name);
689   if (attr & 1)
690     s->flag_read = 1;
691   if (attr & 2)
692     s->flag_write = 1;
693   if (attr & 4)
694     s->flag_execute = 1;
695   if (attr & 8)
696     s->flag_shared = 1;
697
698   def->num_section_defs++;
699 }
700
701 static void
702 def_section_alt (name, attr)
703      const char *name;
704      const char *attr;
705 {
706   int aval = 0;
707   for (; *attr; attr++)
708     {
709       switch (*attr)
710         {
711         case 'R':
712         case 'r':
713           aval |= 1;
714           break;
715         case 'W':
716         case 'w':
717           aval |= 2;
718           break;
719         case 'X':
720         case 'x':
721           aval |= 4;
722           break;
723         case 'S':
724         case 's':
725           aval |= 8;
726           break;
727         }
728     }
729   def_section (name, aval);
730 }
731
732 static void
733 def_exports (external_name, internal_name, ordinal, flags)
734      const char *external_name;
735      const char *internal_name;
736      int ordinal;
737      int flags;
738 {
739   def_file_export *dfe;
740
741   if (!internal_name && external_name)
742     internal_name = external_name;
743 #if TRACE
744   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
745 #endif
746
747   dfe = def_file_add_export (def, external_name, internal_name, ordinal);
748   if (flags & 1)
749     dfe->flag_noname = 1;
750   if (flags & 2)
751     dfe->flag_constant = 1;
752   if (flags & 4)
753     dfe->flag_data = 1;
754   if (flags & 8)
755     dfe->flag_private = 1;
756 }
757
758 static void
759 def_import (internal_name, module, dllext, name, ordinal)
760      const char *internal_name;
761      const char *module;
762      const char *dllext;
763      const char *name;
764      int ordinal;
765 {
766   char *buf = 0;
767
768   if (dllext != NULL)
769     {
770       buf = (char *) xmalloc (strlen (module) + strlen (dllext) + 2);
771       sprintf (buf, "%s.%s", module, dllext);
772       module = buf;
773     }
774
775   def_file_add_import (def, name, module, ordinal, internal_name);
776   if (buf)
777     free (buf);
778 }
779
780 static void
781 def_version (major, minor)
782      int major;
783      int minor;
784 {
785   def->version_major = major;
786   def->version_minor = minor;
787 }
788
789 static void
790 def_directive (str)
791      char *str;
792 {
793   struct directive *d = (struct directive *) xmalloc (sizeof (struct directive));
794   d->next = directives;
795   directives = d;
796   d->name = xstrdup (str);
797   d->len = strlen (str);
798 }
799
800 static int
801 def_error (err)
802      const char *err;
803 {
804   einfo ("%P: %s:%d: %s\n", def_filename, linenumber, err);
805
806   return 0;
807 }
808
809
810 /*****************************************************************************
811  Lexical Scanner
812  *****************************************************************************/
813
814 #undef TRACE
815 #define TRACE 0
816
817 /* Never freed, but always reused as needed, so no real leak */
818 static char *buffer = 0;
819 static int buflen = 0;
820 static int bufptr = 0;
821
822 static void
823 put_buf (c)
824      char c;
825 {
826   if (bufptr == buflen)
827     {
828       buflen += 50;             /* overly reasonable, eh? */
829       if (buffer)
830         buffer = (char *) xrealloc (buffer, buflen + 1);
831       else
832         buffer = (char *) xmalloc (buflen + 1);
833     }
834   buffer[bufptr++] = c;
835   buffer[bufptr] = 0;           /* not optimal, but very convenient */
836 }
837
838 static struct
839 {
840   char *name;
841   int token;
842 }
843 tokens[] =
844 {
845   { "BASE", BASE },
846   { "CODE", CODE },
847   { "CONSTANT", CONSTANTU },
848   { "constant", CONSTANTL },
849   { "DATA", DATAU },
850   { "data", DATAL },
851   { "DESCRIPTION", DESCRIPTION },
852   { "DIRECTIVE", DIRECTIVE },
853   { "EXECUTE", EXECUTE },
854   { "EXPORTS", EXPORTS },
855   { "HEAPSIZE", HEAPSIZE },
856   { "IMPORTS", IMPORTS },
857   { "LIBRARY", LIBRARY },
858   { "NAME", NAME },
859   { "NONAME", NONAMEU },
860   { "noname", NONAMEL },
861   { "PRIVATE", PRIVATEU },
862   { "private", PRIVATEL },
863   { "READ", READ },
864   { "SECTIONS", SECTIONS },
865   { "SEGMENTS", SECTIONS },
866   { "SHARED", SHARED },
867   { "STACKSIZE", STACKSIZE },
868   { "VERSION", VERSIONK },
869   { "WRITE", WRITE },
870   { 0, 0 }
871 };
872
873 static int
874 def_getc ()
875 {
876   int rv;
877   if (lex_parse_string)
878     {
879       if (lex_parse_string >= lex_parse_string_end)
880         rv = EOF;
881       else
882         rv = *lex_parse_string++;
883     }
884   else
885     {
886       rv = fgetc (the_file);
887     }
888   if (rv == '\n')
889     saw_newline = 1;
890   return rv;
891 }
892
893 static int
894 def_ungetc (c)
895      int c;
896 {
897   if (lex_parse_string)
898     {
899       lex_parse_string--;
900       return c;
901     }
902   else
903     return ungetc (c, the_file);
904 }
905
906 static int
907 def_lex ()
908 {
909   int c, i, q;
910
911   if (lex_forced_token)
912     {
913       i = lex_forced_token;
914       lex_forced_token = 0;
915 #if TRACE
916       printf ("lex: forcing token %d\n", i);
917 #endif
918       return i;
919     }
920
921   c = def_getc ();
922
923   /* trim leading whitespace */
924   while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
925     c = def_getc ();
926
927   if (c == EOF)
928     {
929 #if TRACE
930       printf ("lex: EOF\n");
931 #endif
932       return 0;
933     }
934
935   if (saw_newline && c == ';')
936     {
937       do
938         {
939           c = def_getc ();
940         }
941       while (c != EOF && c != '\n');
942       if (c == '\n')
943         return def_lex ();
944       return 0;
945     }
946   /* must be something else */
947   saw_newline = 0;
948
949   if (isdigit (c))
950     {
951       bufptr = 0;
952       while (c != EOF && (isxdigit (c) || (c == 'x')))
953         {
954           put_buf (c);
955           c = def_getc ();
956         }
957       if (c != EOF)
958         def_ungetc (c);
959       yylval.number = strtoul (buffer, 0, 0);
960 #if TRACE
961       printf ("lex: `%s' returns NUMBER %d\n", buffer, yylval.number);
962 #endif
963       return NUMBER;
964     }
965
966   if (isalpha (c) || strchr ("$:-_?", c))
967     {
968       bufptr = 0;
969       while (c != EOF && (isalnum (c) || strchr ("$:-_?/@", c)))
970         {
971           put_buf (c);
972           c = def_getc ();
973         }
974       if (c != EOF)
975         def_ungetc (c);
976       for (i = 0; tokens[i].name; i++)
977         if (strcmp (tokens[i].name, buffer) == 0)
978           {
979 #if TRACE
980             printf ("lex: `%s' is a string token\n", buffer);
981 #endif
982             return tokens[i].token;
983           }
984 #if TRACE
985       printf ("lex: `%s' returns ID\n", buffer);
986 #endif
987       yylval.id = xstrdup (buffer);
988       return ID;
989     }
990
991   if (c == '\'' || c == '"')
992     {
993       q = c;
994       c = def_getc ();
995       bufptr = 0;
996       while (c != EOF && c != q)
997         {
998           put_buf (c);
999           c = def_getc ();
1000         }
1001       yylval.id = xstrdup (buffer);
1002 #if TRACE
1003       printf ("lex: `%s' returns ID\n", buffer);
1004 #endif
1005       return ID;
1006     }
1007
1008   if (c == '=' || c == '.' || c == '@' || c == ',')
1009     {
1010 #if TRACE
1011       printf ("lex: `%c' returns itself\n", c);
1012 #endif
1013       return c;
1014     }
1015
1016   if (c == '\n')
1017     {
1018       linenumber++;
1019       saw_newline = 1;
1020     }
1021
1022   /*printf ("lex: 0x%02x ignored\n", c); */
1023   return def_lex ();
1024 }