OSDN Git Service

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