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