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