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