OSDN Git Service

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