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