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