OSDN Git Service

Add code to prevent importing a dll multiple times.
[pf3gnuchains/pf3gnuchains4x.git] / ld / deffilep.y
1 %{ /* deffilep.y - parser for .def files */
2
3 /*   Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4      Free Software Foundation, Inc.
5
6      This file is part of GNU Binutils.
7
8      This program is free software; you can redistribute it and/or modify
9      it under the terms of the GNU General Public License as published by
10      the Free Software Foundation; either version 2 of the License, or
11      (at your option) any later version.
12
13      This program is distributed in the hope that it will be useful,
14      but WITHOUT ANY WARRANTY; without even the implied warranty of
15      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16      GNU General Public License for more details.
17
18      You should have received a copy of the GNU General Public License
19      along with this program; if not, write to the Free Software
20      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include <stdio.h>
23 #include "libiberty.h"
24 #include "safe-ctype.h"
25 #include "bfd.h"
26 #include "sysdep.h"
27 #include "ld.h"
28 #include "ldmisc.h"
29 #include "deffile.h"
30
31 #define TRACE 0
32
33 #define ROUND_UP(a, b) (((a)+((b)-1))&~((b)-1))
34
35 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
36    as well as gratuitiously global symbol names, so we can have multiple
37    yacc generated parsers in ld.  Note that these are only the variables
38    produced by yacc.  If other parser generators (bison, byacc, etc) produce
39    additional global names that conflict at link time, then those parser
40    generators need to be fixed instead of adding those names to this list.  */
41
42 #define yymaxdepth def_maxdepth
43 #define yyparse def_parse
44 #define yylex   def_lex
45 #define yyerror def_error
46 #define yylval  def_lval
47 #define yychar  def_char
48 #define yydebug def_debug
49 #define yypact  def_pact        
50 #define yyr1    def_r1                  
51 #define yyr2    def_r2                  
52 #define yydef   def_def         
53 #define yychk   def_chk         
54 #define yypgo   def_pgo         
55 #define yyact   def_act         
56 #define yyexca  def_exca
57 #define yyerrflag def_errflag
58 #define yynerrs def_nerrs
59 #define yyps    def_ps
60 #define yypv    def_pv
61 #define yys     def_s
62 #define yy_yys  def_yys
63 #define yystate def_state
64 #define yytmp   def_tmp
65 #define yyv     def_v
66 #define yy_yyv  def_yyv
67 #define yyval   def_val
68 #define yylloc  def_lloc
69 #define yyreds  def_reds                /* With YYDEBUG defined.  */
70 #define yytoks  def_toks                /* With YYDEBUG defined.  */
71 #define yylhs   def_yylhs
72 #define yylen   def_yylen
73 #define yydefred def_yydefred
74 #define yydgoto def_yydgoto
75 #define yysindex def_yysindex
76 #define yyrindex def_yyrindex
77 #define yygindex def_yygindex
78 #define yytable  def_yytable
79 #define yycheck  def_yycheck
80
81 static void def_description PARAMS ((const char *));
82 static void def_exports PARAMS ((const char *, const char *, int, int));
83 static void def_heapsize PARAMS ((int, int));
84 static void def_import PARAMS ((const char *, const char *, const char *, const char *, int));
85 static void def_library PARAMS ((const char *, int));
86 static def_file_module *def_stash_module PARAMS ((def_file *, const char *));
87 static void def_name PARAMS ((const char *, int));
88 static void def_section PARAMS ((const char *, int));
89 static void def_section_alt PARAMS ((const char *, const char *));
90 static void def_stacksize PARAMS ((int, int));
91 static void def_version PARAMS ((int, int));
92 static void def_directive PARAMS ((char *));
93 static int def_parse PARAMS ((void));
94 static int def_error PARAMS ((const char *));
95 static void put_buf PARAMS ((char));
96 static int def_getc PARAMS ((void));
97 static int def_ungetc PARAMS ((int));
98 static int def_lex PARAMS ((void));
99
100 static int lex_forced_token = 0;
101 static const char *lex_parse_string = 0;
102 static const char *lex_parse_string_end = 0;
103
104 %}
105
106 %union {
107   char *id;
108   int number;
109 };
110
111 %token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATAU, DATAL
112 %token SECTIONS, EXPORTS, IMPORTS, VERSIONK, BASE, CONSTANTU, CONSTANTL
113 %token PRIVATEU, PRIVATEL
114 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE
115 %token <id> ID
116 %token <number> NUMBER
117 %type  <number> opt_base opt_ordinal
118 %type  <number> attr attr_list opt_number exp_opt_list exp_opt
119 %type  <id> opt_name opt_equal_name 
120
121 %%
122
123 start: start command
124         | command
125         ;
126
127 command: 
128                 NAME opt_name opt_base { def_name ($2, $3); }
129         |       LIBRARY opt_name opt_base { def_library ($2, $3); }
130         |       DESCRIPTION ID { def_description ($2);}
131         |       STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);}
132         |       HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
133         |       CODE attr_list { def_section ("CODE", $2);}
134         |       DATAU attr_list  { def_section ("DATA", $2);}
135         |       SECTIONS seclist
136         |       EXPORTS explist 
137         |       IMPORTS implist
138         |       VERSIONK NUMBER { def_version ($2, 0);}
139         |       VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
140         |       DIRECTIVE ID { def_directive ($2);}
141         ;
142
143
144 explist:
145                 /* EMPTY */
146         |       expline
147         |       explist expline
148         ;
149
150 expline:
151                 /* The opt_comma is necessary to support both the usual
152                   DEF file syntax as well as .drectve syntax which
153                   mandates <expsym>,<expoptlist>.  */
154                 ID opt_equal_name opt_ordinal opt_comma exp_opt_list
155                         { def_exports ($1, $2, $3, $5); }
156         ;
157 exp_opt_list:
158                 /* The opt_comma is necessary to support both the usual
159                    DEF file syntax as well as .drectve syntax which
160                    allows for comma separated opt list.  */
161                 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
162         |       { $$ = 0; }
163         ;
164 exp_opt:
165                 NONAMEU         { $$ = 1; }
166         |       NONAMEL         { $$ = 1; }
167         |       CONSTANTU       { $$ = 2; }
168         |       CONSTANTL       { $$ = 2; }
169         |       DATAU           { $$ = 4; }
170         |       DATAL           { $$ = 4; }
171         |       PRIVATEU        { $$ = 8; }
172         |       PRIVATEL        { $$ = 8; }
173         ;
174 implist:        
175                 implist impline
176         |       impline
177         ;
178
179 impline:
180                ID '=' ID '.' ID '.' ID     { def_import ($1, $3, $5, $7, -1); }
181        |       ID '=' ID '.' ID '.' NUMBER { def_import ($1, $3, $5,  0, $7); }
182        |       ID '=' ID '.' ID            { def_import ($1, $3,  0, $5, -1); }
183        |       ID '=' ID '.' NUMBER        { def_import ($1, $3,  0,  0, $5); }
184        |       ID '.' ID '.' ID            { def_import ( 0, $1, $3, $5, -1); }
185        |       ID '.' ID                   { def_import ( 0, $1,  0, $3, -1); }
186 ;
187
188 seclist:
189                 seclist secline
190         |       secline
191         ;
192
193 secline:
194         ID attr_list { def_section ($1, $2);}
195         | ID ID { def_section_alt ($1, $2);}
196         ;
197
198 attr_list:
199         attr_list opt_comma attr { $$ = $1 | $3; }
200         | attr { $$ = $1; }
201         ;
202
203 opt_comma:
204         ','
205         | 
206         ;
207 opt_number: ',' NUMBER { $$=$2;}
208         |          { $$=-1;}
209         ;
210         
211 attr:
212                 READ    { $$ = 1;}
213         |       WRITE   { $$ = 2;}      
214         |       EXECUTE { $$=4;}
215         |       SHARED  { $$=8;}
216         ;
217
218 opt_name: ID            { $$ = $1; }
219         | ID '.' ID     
220           { 
221             char * name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
222             sprintf (name, "%s.%s", $1, $3);
223             $$ = name;
224           }
225         |               { $$ = ""; }
226         ;
227
228 opt_ordinal: 
229           '@' NUMBER     { $$ = $2;}
230         |                { $$ = -1;}
231         ;
232
233 opt_equal_name:
234           '=' ID        { $$ = $2; }
235         |               { $$ =  0; }                     
236         ;
237
238 opt_base: BASE  '=' NUMBER      { $$ = $3;}
239         |       { $$ = 0;}
240         ;
241
242         
243
244 %%
245
246 /*****************************************************************************
247  API
248  *****************************************************************************/
249
250 static FILE *the_file;
251 static const char *def_filename;
252 static int linenumber;
253 static def_file *def;
254 static int saw_newline;
255
256 struct directive
257   {
258     struct directive *next;
259     char *name;
260     int len;
261   };
262
263 static struct directive *directives = 0;
264
265 def_file *
266 def_file_empty ()
267 {
268   def_file *rv = (def_file *) xmalloc (sizeof (def_file));
269   memset (rv, 0, sizeof (def_file));
270   rv->is_dll = -1;
271   rv->base_address = (bfd_vma) (-1);
272   rv->stack_reserve = rv->stack_commit = -1;
273   rv->heap_reserve = rv->heap_commit = -1;
274   rv->version_major = rv->version_minor = -1;
275   return rv;
276 }
277
278 def_file *
279 def_file_parse (filename, add_to)
280      const char *filename;
281      def_file *add_to;
282 {
283   struct directive *d;
284
285   the_file = fopen (filename, "r");
286   def_filename = filename;
287   linenumber = 1;
288   if (!the_file)
289     {
290       perror (filename);
291       return 0;
292     }
293   if (add_to)
294     {
295       def = add_to;
296     }
297   else
298     {
299       def = def_file_empty ();
300     }
301
302   saw_newline = 1;
303   if (def_parse ())
304     {
305       def_file_free (def);
306       fclose (the_file);
307       return 0;
308     }
309
310   fclose (the_file);
311
312   for (d = directives; d; d = d->next)
313     {
314 #if TRACE
315       printf ("Adding directive %08x `%s'\n", d->name, d->name);
316 #endif
317       def_file_add_directive (def, d->name, d->len);
318     }
319
320   return def;
321 }
322
323 void
324 def_file_free (def)
325      def_file *def;
326 {
327   int i;
328
329   if (!def)
330     return;
331   if (def->name)
332     free (def->name);
333   if (def->description)
334     free (def->description);
335
336   if (def->section_defs)
337     {
338       for (i = 0; i < def->num_section_defs; i++)
339         {
340           if (def->section_defs[i].name)
341             free (def->section_defs[i].name);
342           if (def->section_defs[i].class)
343             free (def->section_defs[i].class);
344         }
345       free (def->section_defs);
346     }
347
348   if (def->exports)
349     {
350       for (i = 0; i < def->num_exports; i++)
351         {
352           if (def->exports[i].internal_name
353               && def->exports[i].internal_name != def->exports[i].name)
354             free (def->exports[i].internal_name);
355           if (def->exports[i].name)
356             free (def->exports[i].name);
357         }
358       free (def->exports);
359     }
360
361   if (def->imports)
362     {
363       for (i = 0; i < def->num_imports; i++)
364         {
365           if (def->imports[i].internal_name
366               && def->imports[i].internal_name != def->imports[i].name)
367             free (def->imports[i].internal_name);
368           if (def->imports[i].name)
369             free (def->imports[i].name);
370         }
371       free (def->imports);
372     }
373
374   while (def->modules)
375     {
376       def_file_module *m = def->modules;
377       def->modules = def->modules->next;
378       free (m);
379     }
380
381   free (def);
382 }
383
384 #ifdef DEF_FILE_PRINT
385 void
386 def_file_print (file, def)
387      FILE *file;
388      def_file *def;
389 {
390   int i;
391
392   fprintf (file, ">>>> def_file at 0x%08x\n", def);
393   if (def->name)
394     fprintf (file, "  name: %s\n", def->name ? def->name : "(unspecified)");
395   if (def->is_dll != -1)
396     fprintf (file, "  is dll: %s\n", def->is_dll ? "yes" : "no");
397   if (def->base_address != (bfd_vma) (-1))
398     fprintf (file, "  base address: 0x%08x\n", def->base_address);
399   if (def->description)
400     fprintf (file, "  description: `%s'\n", def->description);
401   if (def->stack_reserve != -1)
402     fprintf (file, "  stack reserve: 0x%08x\n", def->stack_reserve);
403   if (def->stack_commit != -1)
404     fprintf (file, "  stack commit: 0x%08x\n", def->stack_commit);
405   if (def->heap_reserve != -1)
406     fprintf (file, "  heap reserve: 0x%08x\n", def->heap_reserve);
407   if (def->heap_commit != -1)
408     fprintf (file, "  heap commit: 0x%08x\n", def->heap_commit);
409
410   if (def->num_section_defs > 0)
411     {
412       fprintf (file, "  section defs:\n");
413
414       for (i = 0; i < def->num_section_defs; i++)
415         {
416           fprintf (file, "    name: `%s', class: `%s', flags:",
417                    def->section_defs[i].name, def->section_defs[i].class);
418           if (def->section_defs[i].flag_read)
419             fprintf (file, " R");
420           if (def->section_defs[i].flag_write)
421             fprintf (file, " W");
422           if (def->section_defs[i].flag_execute)
423             fprintf (file, " X");
424           if (def->section_defs[i].flag_shared)
425             fprintf (file, " S");
426           fprintf (file, "\n");
427         }
428     }
429
430   if (def->num_exports > 0)
431     {
432       fprintf (file, "  exports:\n");
433
434       for (i = 0; i < def->num_exports; i++)
435         {
436           fprintf (file, "    name: `%s', int: `%s', ordinal: %d, flags:",
437                    def->exports[i].name, def->exports[i].internal_name,
438                    def->exports[i].ordinal);
439           if (def->exports[i].flag_private)
440             fprintf (file, " P");
441           if (def->exports[i].flag_constant)
442             fprintf (file, " C");
443           if (def->exports[i].flag_noname)
444             fprintf (file, " N");
445           if (def->exports[i].flag_data)
446             fprintf (file, " D");
447           fprintf (file, "\n");
448         }
449     }
450
451   if (def->num_imports > 0)
452     {
453       fprintf (file, "  imports:\n");
454
455       for (i = 0; i < def->num_imports; i++)
456         {
457           fprintf (file, "    int: %s, from: `%s', name: `%s', ordinal: %d\n",
458                    def->imports[i].internal_name,
459                    def->imports[i].module,
460                    def->imports[i].name,
461                    def->imports[i].ordinal);
462         }
463     }
464
465   if (def->version_major != -1)
466     fprintf (file, "  version: %d.%d\n", def->version_major, def->version_minor);
467
468   fprintf (file, "<<<< def_file at 0x%08x\n", def);
469 }
470 #endif
471
472 def_file_export *
473 def_file_add_export (def, external_name, internal_name, ordinal)
474      def_file *def;
475      const char *external_name;
476      const char *internal_name;
477      int ordinal;
478 {
479   def_file_export *e;
480   int max_exports = ROUND_UP(def->num_exports, 32);
481
482   if (def->num_exports >= max_exports)
483     {
484       max_exports = ROUND_UP(def->num_exports + 1, 32);
485       if (def->exports)
486         def->exports = (def_file_export *)
487           xrealloc (def->exports, max_exports * sizeof (def_file_export));
488       else
489         def->exports = (def_file_export *)
490           xmalloc (max_exports * sizeof (def_file_export));
491     }
492   e = def->exports + def->num_exports;
493   memset (e, 0, sizeof (def_file_export));
494   if (internal_name && !external_name)
495     external_name = internal_name;
496   if (external_name && !internal_name)
497     internal_name = external_name;
498   e->name = xstrdup (external_name);
499   e->internal_name = xstrdup (internal_name);
500   e->ordinal = ordinal;
501   def->num_exports++;
502   return e;
503 }
504
505 def_file_module *
506 def_get_module (def, name)
507      def_file *def;
508      const char *name;
509 {
510   def_file_module *s;
511
512   for (s = def->modules; s; s = s->next)
513     if (strcmp (s->name, name) == 0)
514       return s;
515
516   return (def_file_module *) 0;
517 }
518
519 static def_file_module *
520 def_stash_module (def, name)
521      def_file *def;
522      const char *name;
523 {
524   def_file_module *s;
525
526   if ((s = def_get_module (def, name)) != (def_file_module *) 0)
527       return s;
528   s = (def_file_module *) xmalloc (sizeof (def_file_module) + strlen (name));
529   s->next = def->modules;
530   def->modules = s;
531   s->user_data = 0;
532   strcpy (s->name, name);
533   return s;
534 }
535
536 def_file_import *
537 def_file_add_import (def, name, module, ordinal, internal_name)
538      def_file *def;
539      const char *name;
540      const char *module;
541      int ordinal;
542      const char *internal_name;
543 {
544   def_file_import *i;
545   int max_imports = ROUND_UP(def->num_imports, 16);
546
547   if (def->num_imports >= max_imports)
548     {
549       max_imports = ROUND_UP(def->num_imports+1, 16);
550
551       if (def->imports)
552         def->imports = (def_file_import *)
553           xrealloc (def->imports, max_imports * sizeof (def_file_import));
554       else
555         def->imports = (def_file_import *)
556           xmalloc (max_imports * sizeof (def_file_import));
557     }
558   i = def->imports + def->num_imports;
559   memset (i, 0, sizeof (def_file_import));
560   if (name)
561     i->name = xstrdup (name);
562   if (module)
563     i->module = def_stash_module (def, module);
564   i->ordinal = ordinal;
565   if (internal_name)
566     i->internal_name = xstrdup (internal_name);
567   else
568     i->internal_name = i->name;
569   def->num_imports++;
570
571   return i;
572 }
573
574 struct
575 {
576   char *param;
577   int token;
578 }
579 diropts[] =
580 {
581   { "-heap", HEAPSIZE },
582   { "-stack", STACKSIZE },
583   { "-attr", SECTIONS },
584   { "-export", EXPORTS },
585   { 0, 0 }
586 };
587
588 void
589 def_file_add_directive (my_def, param, len)
590      def_file *my_def;
591      const char *param;
592      int len;
593 {
594   def_file *save_def = def;
595   const char *pend = param + len;
596   const char *tend = param;
597   int i;
598
599   def = my_def;
600
601   while (param < pend)
602     {
603       while (param < pend && ISSPACE (*param))
604         param++;
605
606       for (tend = param + 1;
607            tend < pend && !(ISSPACE (tend[-1]) && *tend == '-');
608            tend++)
609         ;
610
611       for (i = 0; diropts[i].param; i++)
612         {
613           int len = strlen (diropts[i].param);
614
615           if (tend - param >= len
616               && strncmp (param, diropts[i].param, len) == 0
617               && (param[len] == ':' || param[len] == ' '))
618             {
619               lex_parse_string_end = tend;
620               lex_parse_string = param + len + 1;
621               lex_forced_token = diropts[i].token;
622               saw_newline = 0;
623               def_parse ();
624               break;
625             }
626         }
627
628       if (!diropts[i].param)
629         /* xgettext:c-format */
630         einfo (_("Warning: .drectve `%.*s' unrecognized\n"),
631                tend - param, param);
632
633       lex_parse_string = 0;
634       param = tend;
635     }
636
637   def = save_def;
638 }
639
640 /* Parser Callbacks.  */
641
642 static void
643 def_name (name, base)
644      const char *name;
645      int base;
646 {
647   if (def->name)
648     free (def->name);
649   def->name = xstrdup (name);
650   def->base_address = base;
651   def->is_dll = 0;
652 }
653
654 static void
655 def_library (name, base)
656      const char *name;
657      int base;
658 {
659   if (def->name)
660     free (def->name);
661   def->name = xstrdup (name);
662   def->base_address = base;
663   def->is_dll = 1;
664 }
665
666 static void
667 def_description (text)
668      const char *text;
669 {
670   int len = def->description ? strlen (def->description) : 0;
671
672   len += strlen (text) + 1;
673   if (def->description)
674     {
675       def->description = (char *) xrealloc (def->description, len);
676       strcat (def->description, text);
677     }
678   else
679     {
680       def->description = (char *) xmalloc (len);
681       strcpy (def->description, text);
682     }
683 }
684
685 static void
686 def_stacksize (reserve, commit)
687      int reserve;
688      int commit;
689 {
690   def->stack_reserve = reserve;
691   def->stack_commit = commit;
692 }
693
694 static void
695 def_heapsize (reserve, commit)
696      int reserve;
697      int commit;
698 {
699   def->heap_reserve = reserve;
700   def->heap_commit = commit;
701 }
702
703 static void
704 def_section (name, attr)
705      const char *name;
706      int attr;
707 {
708   def_file_section *s;
709   int max_sections = ROUND_UP(def->num_section_defs, 4);
710
711   if (def->num_section_defs >= max_sections)
712     {
713       max_sections = ROUND_UP(def->num_section_defs+1, 4);
714
715       if (def->section_defs)
716         def->section_defs = (def_file_section *) xrealloc (def->section_defs, max_sections * sizeof (def_file_import));
717       else
718         def->section_defs = (def_file_section *) xmalloc (max_sections * sizeof (def_file_import));
719     }
720   s = def->section_defs + def->num_section_defs;
721   memset (s, 0, sizeof (def_file_section));
722   s->name = xstrdup (name);
723   if (attr & 1)
724     s->flag_read = 1;
725   if (attr & 2)
726     s->flag_write = 1;
727   if (attr & 4)
728     s->flag_execute = 1;
729   if (attr & 8)
730     s->flag_shared = 1;
731
732   def->num_section_defs++;
733 }
734
735 static void
736 def_section_alt (name, attr)
737      const char *name;
738      const char *attr;
739 {
740   int aval = 0;
741
742   for (; *attr; attr++)
743     {
744       switch (*attr)
745         {
746         case 'R':
747         case 'r':
748           aval |= 1;
749           break;
750         case 'W':
751         case 'w':
752           aval |= 2;
753           break;
754         case 'X':
755         case 'x':
756           aval |= 4;
757           break;
758         case 'S':
759         case 's':
760           aval |= 8;
761           break;
762         }
763     }
764   def_section (name, aval);
765 }
766
767 static void
768 def_exports (external_name, internal_name, ordinal, flags)
769      const char *external_name;
770      const char *internal_name;
771      int ordinal;
772      int flags;
773 {
774   def_file_export *dfe;
775
776   if (!internal_name && external_name)
777     internal_name = external_name;
778 #if TRACE
779   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
780 #endif
781
782   dfe = def_file_add_export (def, external_name, internal_name, ordinal);
783   if (flags & 1)
784     dfe->flag_noname = 1;
785   if (flags & 2)
786     dfe->flag_constant = 1;
787   if (flags & 4)
788     dfe->flag_data = 1;
789   if (flags & 8)
790     dfe->flag_private = 1;
791 }
792
793 static void
794 def_import (internal_name, module, dllext, name, ordinal)
795      const char *internal_name;
796      const char *module;
797      const char *dllext;
798      const char *name;
799      int ordinal;
800 {
801   char *buf = 0;
802
803   if (dllext != NULL)
804     {
805       buf = (char *) xmalloc (strlen (module) + strlen (dllext) + 2);
806       sprintf (buf, "%s.%s", module, dllext);
807       module = buf;
808     }
809
810   def_file_add_import (def, name, module, ordinal, internal_name);
811   if (buf)
812     free (buf);
813 }
814
815 static void
816 def_version (major, minor)
817      int major;
818      int minor;
819 {
820   def->version_major = major;
821   def->version_minor = minor;
822 }
823
824 static void
825 def_directive (str)
826      char *str;
827 {
828   struct directive *d = (struct directive *) xmalloc (sizeof (struct directive));
829
830   d->next = directives;
831   directives = d;
832   d->name = xstrdup (str);
833   d->len = strlen (str);
834 }
835
836 static int
837 def_error (err)
838      const char *err;
839 {
840   einfo ("%P: %s:%d: %s\n", def_filename, linenumber, err);
841
842   return 0;
843 }
844
845
846 /* Lexical Scanner.  */
847
848 #undef TRACE
849 #define TRACE 0
850
851 /* Never freed, but always reused as needed, so no real leak.  */
852 static char *buffer = 0;
853 static int buflen = 0;
854 static int bufptr = 0;
855
856 static void
857 put_buf (c)
858      char c;
859 {
860   if (bufptr == buflen)
861     {
862       buflen += 50;             /* overly reasonable, eh?  */
863       if (buffer)
864         buffer = (char *) xrealloc (buffer, buflen + 1);
865       else
866         buffer = (char *) xmalloc (buflen + 1);
867     }
868   buffer[bufptr++] = c;
869   buffer[bufptr] = 0;           /* not optimal, but very convenient.  */
870 }
871
872 static struct
873 {
874   char *name;
875   int token;
876 }
877 tokens[] =
878 {
879   { "BASE", BASE },
880   { "CODE", CODE },
881   { "CONSTANT", CONSTANTU },
882   { "constant", CONSTANTL },
883   { "DATA", DATAU },
884   { "data", DATAL },
885   { "DESCRIPTION", DESCRIPTION },
886   { "DIRECTIVE", DIRECTIVE },
887   { "EXECUTE", EXECUTE },
888   { "EXPORTS", EXPORTS },
889   { "HEAPSIZE", HEAPSIZE },
890   { "IMPORTS", IMPORTS },
891   { "LIBRARY", LIBRARY },
892   { "NAME", NAME },
893   { "NONAME", NONAMEU },
894   { "noname", NONAMEL },
895   { "PRIVATE", PRIVATEU },
896   { "private", PRIVATEL },
897   { "READ", READ },
898   { "SECTIONS", SECTIONS },
899   { "SEGMENTS", SECTIONS },
900   { "SHARED", SHARED },
901   { "STACKSIZE", STACKSIZE },
902   { "VERSION", VERSIONK },
903   { "WRITE", WRITE },
904   { 0, 0 }
905 };
906
907 static int
908 def_getc ()
909 {
910   int rv;
911
912   if (lex_parse_string)
913     {
914       if (lex_parse_string >= lex_parse_string_end)
915         rv = EOF;
916       else
917         rv = *lex_parse_string++;
918     }
919   else
920     {
921       rv = fgetc (the_file);
922     }
923   if (rv == '\n')
924     saw_newline = 1;
925   return rv;
926 }
927
928 static int
929 def_ungetc (c)
930      int c;
931 {
932   if (lex_parse_string)
933     {
934       lex_parse_string--;
935       return c;
936     }
937   else
938     return ungetc (c, the_file);
939 }
940
941 static int
942 def_lex ()
943 {
944   int c, i, q;
945
946   if (lex_forced_token)
947     {
948       i = lex_forced_token;
949       lex_forced_token = 0;
950 #if TRACE
951       printf ("lex: forcing token %d\n", i);
952 #endif
953       return i;
954     }
955
956   c = def_getc ();
957
958   /* Trim leading whitespace.  */
959   while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
960     c = def_getc ();
961
962   if (c == EOF)
963     {
964 #if TRACE
965       printf ("lex: EOF\n");
966 #endif
967       return 0;
968     }
969
970   if (saw_newline && c == ';')
971     {
972       do
973         {
974           c = def_getc ();
975         }
976       while (c != EOF && c != '\n');
977       if (c == '\n')
978         return def_lex ();
979       return 0;
980     }
981
982   /* Must be something else.  */
983   saw_newline = 0;
984
985   if (ISDIGIT (c))
986     {
987       bufptr = 0;
988       while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
989         {
990           put_buf (c);
991           c = def_getc ();
992         }
993       if (c != EOF)
994         def_ungetc (c);
995       yylval.number = strtoul (buffer, 0, 0);
996 #if TRACE
997       printf ("lex: `%s' returns NUMBER %d\n", buffer, yylval.number);
998 #endif
999       return NUMBER;
1000     }
1001
1002   if (ISALPHA (c) || strchr ("$:-_?@", c))
1003     {
1004       bufptr = 0;
1005       q = c;
1006       put_buf (c);
1007       c = def_getc ();
1008
1009       if (q == '@')
1010         {
1011           if (ISBLANK (c) ) /* '@' followed by whitespace.  */
1012             return (q);
1013           else if (ISDIGIT (c)) /* '@' followed by digit.  */
1014             {
1015               def_ungetc (c);
1016               return (q);
1017             }
1018 #if TRACE
1019           printf ("lex: @ returns itself\n");
1020 #endif
1021         }
1022
1023       while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@", c)))
1024         {
1025           put_buf (c);
1026           c = def_getc ();
1027         }
1028       if (c != EOF)
1029         def_ungetc (c);
1030       if (ISALPHA (q)) /* Check for tokens.  */
1031         {
1032           for (i = 0; tokens[i].name; i++)
1033             if (strcmp (tokens[i].name, buffer) == 0)
1034               {
1035 #if TRACE
1036                 printf ("lex: `%s' is a string token\n", buffer);
1037 #endif
1038                 return tokens[i].token;
1039               }
1040         }
1041 #if TRACE
1042       printf ("lex: `%s' returns ID\n", buffer);
1043 #endif
1044       yylval.id = xstrdup (buffer);
1045       return ID;
1046     }
1047
1048   if (c == '\'' || c == '"')
1049     {
1050       q = c;
1051       c = def_getc ();
1052       bufptr = 0;
1053
1054       while (c != EOF && c != q)
1055         {
1056           put_buf (c);
1057           c = def_getc ();
1058         }
1059       yylval.id = xstrdup (buffer);
1060 #if TRACE
1061       printf ("lex: `%s' returns ID\n", buffer);
1062 #endif
1063       return ID;
1064     }
1065
1066   if (c == '=' || c == '.' || c == ',')
1067     {
1068 #if TRACE
1069       printf ("lex: `%c' returns itself\n", c);
1070 #endif
1071       return c;
1072     }
1073
1074   if (c == '\n')
1075     {
1076       linenumber++;
1077       saw_newline = 1;
1078     }
1079
1080   /*printf ("lex: 0x%02x ignored\n", c); */
1081   return def_lex ();
1082 }