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