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