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