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