S12Z: Emit uninitialized data in the .bss segment
[external/binutils.git] / ld / deffilep.y
1 %{ /* deffilep.y - parser for .def files */
2
3 /*   Copyright (C) 1995-2018 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 static void
820 fill_in_import (def_file_import *i,
821                 const char *name,
822                 def_file_module *module,
823                 int ordinal,
824                 const char *internal_name,
825                 const char *its_name)
826 {
827   memset (i, 0, sizeof (def_file_import));
828   if (name)
829     i->name = xstrdup (name);
830   i->module = module;
831   i->ordinal = ordinal;
832   if (internal_name)
833     i->internal_name = xstrdup (internal_name);
834   else
835     i->internal_name = i->name;
836   i->its_name = (its_name ? xstrdup (its_name) : NULL);
837 }
838
839 def_file_import *
840 def_file_add_import (def_file *fdef,
841                      const char *name,
842                      const char *module,
843                      int ordinal,
844                      const char *internal_name,
845                      const char *its_name,
846                      int *is_dup)
847 {
848   def_file_import *i;
849   int pos;
850   int max_imports = ROUND_UP (fdef->num_imports, 16);
851
852   /* We need to avoid here duplicates.  */
853   *is_dup = 0;
854   pos = find_import_in_list (fdef->imports, fdef->num_imports,
855                              name,
856                              (!internal_name ? name : internal_name),
857                              module, ordinal, is_dup);
858   if (*is_dup != 0)
859     return fdef->imports + pos;
860
861   if (fdef->num_imports >= max_imports)
862     {
863       max_imports = ROUND_UP (fdef->num_imports+1, 16);
864
865       if (fdef->imports)
866         fdef->imports = xrealloc (fdef->imports,
867                                  max_imports * sizeof (def_file_import));
868       else
869         fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
870     }
871   i = fdef->imports + pos;
872   if (pos != fdef->num_imports)
873     memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
874
875   fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
876                   internal_name, its_name);
877   fdef->num_imports++;
878
879   return i;
880 }
881
882 int
883 def_file_add_import_from (def_file *fdef,
884                           int num_imports,
885                           const char *name,
886                           const char *module,
887                           int ordinal,
888                           const char *internal_name,
889                           const char *its_name ATTRIBUTE_UNUSED)
890 {
891   def_file_import *i;
892   int is_dup;
893   int pos;
894   int max_imports = ROUND_UP (fdef->num_imports, 16);
895
896   /* We need to avoid here duplicates.  */
897   is_dup = 0;
898   pos = find_import_in_list (fdef->imports, fdef->num_imports,
899                              name, internal_name ? internal_name : name,
900                              module, ordinal, &is_dup);
901   if (is_dup != 0)
902     return -1;
903   if (fdef->imports && pos != fdef->num_imports)
904     {
905       i = fdef->imports + pos;
906       if (i->module && strcmp (i->module->name, module) == 0)
907         return -1;
908     }
909
910   if (fdef->num_imports + num_imports - 1 >= max_imports)
911     {
912       max_imports = ROUND_UP (fdef->num_imports + num_imports, 16);
913
914       if (fdef->imports)
915         fdef->imports = xrealloc (fdef->imports,
916                                  max_imports * sizeof (def_file_import));
917       else
918         fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
919     }
920   i = fdef->imports + pos;
921   if (pos != fdef->num_imports)
922     memmove (i + num_imports, i,
923              sizeof (def_file_import) * (fdef->num_imports - pos));
924
925   return pos;
926 }
927
928 def_file_import *
929 def_file_add_import_at (def_file *fdef,
930                         int pos,
931                         const char *name,
932                         const char *module,
933                         int ordinal,
934                         const char *internal_name,
935                         const char *its_name)
936 {
937   def_file_import *i = fdef->imports + pos;
938
939   fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
940                   internal_name, its_name);
941   fdef->num_imports++;
942
943   return i;
944 }
945
946 struct
947 {
948   char *param;
949   int token;
950 }
951 diropts[] =
952 {
953   { "-heap", HEAPSIZE },
954   { "-stack", STACKSIZE_K },
955   { "-attr", SECTIONS },
956   { "-export", EXPORTS },
957   { "-aligncomm", ALIGNCOMM },
958   { 0, 0 }
959 };
960
961 void
962 def_file_add_directive (def_file *my_def, const char *param, int len)
963 {
964   def_file *save_def = def;
965   const char *pend = param + len;
966   char * tend = (char *) param;
967   int i;
968
969   def = my_def;
970
971   while (param < pend)
972     {
973       while (param < pend
974              && (ISSPACE (*param) || *param == '\n' || *param == 0))
975         param++;
976
977       if (param == pend)
978         break;
979
980       /* Scan forward until we encounter any of:
981           - the end of the buffer
982           - the start of a new option
983           - a newline separating options
984           - a NUL separating options.  */
985       for (tend = (char *) (param + 1);
986            (tend < pend
987             && !(ISSPACE (tend[-1]) && *tend == '-')
988             && *tend != '\n' && *tend != 0);
989            tend++)
990         ;
991
992       for (i = 0; diropts[i].param; i++)
993         {
994           len = strlen (diropts[i].param);
995
996           if (tend - param >= len
997               && strncmp (param, diropts[i].param, len) == 0
998               && (param[len] == ':' || param[len] == ' '))
999             {
1000               lex_parse_string_end = tend;
1001               lex_parse_string = param + len + 1;
1002               lex_forced_token = diropts[i].token;
1003               saw_newline = 0;
1004               if (def_parse ())
1005                 continue;
1006               break;
1007             }
1008         }
1009
1010       if (!diropts[i].param)
1011         {
1012           if (tend < pend)
1013             {
1014               char saved;
1015
1016               saved = * tend;
1017               * tend = 0;
1018               /* xgettext:c-format */
1019               einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
1020               * tend = saved;
1021             }
1022           else
1023             {
1024               einfo (_("Warning: corrupt .drectve at end of def file\n"));
1025             }
1026         }
1027
1028       lex_parse_string = 0;
1029       param = tend;
1030     }
1031
1032   def = save_def;
1033   def_pool_free ();
1034 }
1035
1036 /* Parser Callbacks.  */
1037
1038 static void
1039 def_image_name (const char *name, bfd_vma base, int is_dll)
1040 {
1041   /* If a LIBRARY or NAME statement is specified without a name, there is nothing
1042      to do here.  We retain the output filename specified on command line.  */
1043   if (*name)
1044     {
1045       const char* image_name = lbasename (name);
1046
1047       if (image_name != name)
1048         einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
1049                def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
1050                name);
1051       if (def->name)
1052         free (def->name);
1053       /* Append the default suffix, if none specified.  */
1054       if (strchr (image_name, '.') == 0)
1055         {
1056           const char * suffix = is_dll ? ".dll" : ".exe";
1057
1058           def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
1059           sprintf (def->name, "%s%s", image_name, suffix);
1060         }
1061       else
1062         def->name = xstrdup (image_name);
1063     }
1064
1065   /* Honor a BASE address statement, even if LIBRARY string is empty.  */
1066   def->base_address = base;
1067   def->is_dll = is_dll;
1068 }
1069
1070 static void
1071 def_description (const char *text)
1072 {
1073   int len = def->description ? strlen (def->description) : 0;
1074
1075   len += strlen (text) + 1;
1076   if (def->description)
1077     {
1078       def->description = xrealloc (def->description, len);
1079       strcat (def->description, text);
1080     }
1081   else
1082     {
1083       def->description = xmalloc (len);
1084       strcpy (def->description, text);
1085     }
1086 }
1087
1088 static void
1089 def_stacksize (int reserve, int commit)
1090 {
1091   def->stack_reserve = reserve;
1092   def->stack_commit = commit;
1093 }
1094
1095 static void
1096 def_heapsize (int reserve, int commit)
1097 {
1098   def->heap_reserve = reserve;
1099   def->heap_commit = commit;
1100 }
1101
1102 static void
1103 def_section (const char *name, int attr)
1104 {
1105   def_file_section *s;
1106   int max_sections = ROUND_UP (def->num_section_defs, 4);
1107
1108   if (def->num_section_defs >= max_sections)
1109     {
1110       max_sections = ROUND_UP (def->num_section_defs+1, 4);
1111
1112       if (def->section_defs)
1113         def->section_defs = xrealloc (def->section_defs,
1114                                       max_sections * sizeof (def_file_import));
1115       else
1116         def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
1117     }
1118   s = def->section_defs + def->num_section_defs;
1119   memset (s, 0, sizeof (def_file_section));
1120   s->name = xstrdup (name);
1121   if (attr & 1)
1122     s->flag_read = 1;
1123   if (attr & 2)
1124     s->flag_write = 1;
1125   if (attr & 4)
1126     s->flag_execute = 1;
1127   if (attr & 8)
1128     s->flag_shared = 1;
1129
1130   def->num_section_defs++;
1131 }
1132
1133 static void
1134 def_section_alt (const char *name, const char *attr)
1135 {
1136   int aval = 0;
1137
1138   for (; *attr; attr++)
1139     {
1140       switch (*attr)
1141         {
1142         case 'R':
1143         case 'r':
1144           aval |= 1;
1145           break;
1146         case 'W':
1147         case 'w':
1148           aval |= 2;
1149           break;
1150         case 'X':
1151         case 'x':
1152           aval |= 4;
1153           break;
1154         case 'S':
1155         case 's':
1156           aval |= 8;
1157           break;
1158         }
1159     }
1160   def_section (name, aval);
1161 }
1162
1163 static void
1164 def_exports (const char *external_name,
1165              const char *internal_name,
1166              int ordinal,
1167              int flags,
1168              const char *its_name)
1169 {
1170   def_file_export *dfe;
1171   int is_dup = 0;
1172
1173   if (!internal_name && external_name)
1174     internal_name = external_name;
1175 #if TRACE
1176   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1177 #endif
1178
1179   dfe = def_file_add_export (def, external_name, internal_name, ordinal,
1180                              its_name, &is_dup);
1181
1182   /* We might check here for flag redefinition and warn.  For now we
1183      ignore duplicates silently.  */
1184   if (is_dup)
1185     return;
1186
1187   if (flags & 1)
1188     dfe->flag_noname = 1;
1189   if (flags & 2)
1190     dfe->flag_constant = 1;
1191   if (flags & 4)
1192     dfe->flag_data = 1;
1193   if (flags & 8)
1194     dfe->flag_private = 1;
1195 }
1196
1197 static void
1198 def_import (const char *internal_name,
1199             const char *module,
1200             const char *dllext,
1201             const char *name,
1202             int ordinal,
1203             const char *its_name)
1204 {
1205   char *buf = 0;
1206   const char *ext = dllext ? dllext : "dll";
1207   int is_dup = 0;
1208
1209   buf = xmalloc (strlen (module) + strlen (ext) + 2);
1210   sprintf (buf, "%s.%s", module, ext);
1211   module = buf;
1212
1213   def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1214                        &is_dup);
1215   free (buf);
1216 }
1217
1218 static void
1219 def_version (int major, int minor)
1220 {
1221   def->version_major = major;
1222   def->version_minor = minor;
1223 }
1224
1225 static void
1226 def_directive (char *str)
1227 {
1228   struct directive *d = xmalloc (sizeof (struct directive));
1229
1230   d->next = directives;
1231   directives = d;
1232   d->name = xstrdup (str);
1233   d->len = strlen (str);
1234 }
1235
1236 static void
1237 def_aligncomm (char *str, int align)
1238 {
1239   def_file_aligncomm *c, *p;
1240
1241   p = NULL;
1242   c = def->aligncomms;
1243   while (c != NULL)
1244     {
1245       int e = strcmp (c->symbol_name, str);
1246       if (!e)
1247         {
1248           /* Not sure if we want to allow here duplicates with
1249              different alignments, but for now we keep them.  */
1250           e = (int) c->alignment - align;
1251           if (!e)
1252             return;
1253         }
1254       if (e > 0)
1255         break;
1256       c = (p = c)->next;
1257     }
1258
1259   c = xmalloc (sizeof (def_file_aligncomm));
1260   c->symbol_name = xstrdup (str);
1261   c->alignment = (unsigned int) align;
1262   if (!p)
1263     {
1264       c->next = def->aligncomms;
1265       def->aligncomms = c;
1266     }
1267   else
1268     {
1269       c->next = p->next;
1270       p->next = c;
1271     }
1272 }
1273
1274 static int
1275 def_error (const char *err)
1276 {
1277   einfo ("%P: %s:%d: %s\n",
1278          def_filename ? def_filename : "<unknown-file>", linenumber, err);
1279   return 0;
1280 }
1281
1282
1283 /* Lexical Scanner.  */
1284
1285 #undef TRACE
1286 #define TRACE 0
1287
1288 /* Never freed, but always reused as needed, so no real leak.  */
1289 static char *buffer = 0;
1290 static int buflen = 0;
1291 static int bufptr = 0;
1292
1293 static void
1294 put_buf (char c)
1295 {
1296   if (bufptr == buflen)
1297     {
1298       buflen += 50;             /* overly reasonable, eh?  */
1299       if (buffer)
1300         buffer = xrealloc (buffer, buflen + 1);
1301       else
1302         buffer = xmalloc (buflen + 1);
1303     }
1304   buffer[bufptr++] = c;
1305   buffer[bufptr] = 0;           /* not optimal, but very convenient.  */
1306 }
1307
1308 static struct
1309 {
1310   char *name;
1311   int token;
1312 }
1313 tokens[] =
1314 {
1315   { "BASE", BASE },
1316   { "CODE", CODE },
1317   { "CONSTANT", CONSTANTU },
1318   { "constant", CONSTANTL },
1319   { "DATA", DATAU },
1320   { "data", DATAL },
1321   { "DESCRIPTION", DESCRIPTION },
1322   { "DIRECTIVE", DIRECTIVE },
1323   { "EXECUTE", EXECUTE },
1324   { "EXPORTS", EXPORTS },
1325   { "HEAPSIZE", HEAPSIZE },
1326   { "IMPORTS", IMPORTS },
1327   { "LIBRARY", LIBRARY },
1328   { "NAME", NAME },
1329   { "NONAME", NONAMEU },
1330   { "noname", NONAMEL },
1331   { "PRIVATE", PRIVATEU },
1332   { "private", PRIVATEL },
1333   { "READ", READ },
1334   { "SECTIONS", SECTIONS },
1335   { "SEGMENTS", SECTIONS },
1336   { "SHARED", SHARED },
1337   { "STACKSIZE", STACKSIZE_K },
1338   { "VERSION", VERSIONK },
1339   { "WRITE", WRITE },
1340   { 0, 0 }
1341 };
1342
1343 static int
1344 def_getc (void)
1345 {
1346   int rv;
1347
1348   if (lex_parse_string)
1349     {
1350       if (lex_parse_string >= lex_parse_string_end)
1351         rv = EOF;
1352       else
1353         rv = *lex_parse_string++;
1354     }
1355   else
1356     {
1357       rv = fgetc (the_file);
1358     }
1359   if (rv == '\n')
1360     saw_newline = 1;
1361   return rv;
1362 }
1363
1364 static int
1365 def_ungetc (int c)
1366 {
1367   if (lex_parse_string)
1368     {
1369       lex_parse_string--;
1370       return c;
1371     }
1372   else
1373     return ungetc (c, the_file);
1374 }
1375
1376 static int
1377 def_lex (void)
1378 {
1379   int c, i, q;
1380
1381   if (lex_forced_token)
1382     {
1383       i = lex_forced_token;
1384       lex_forced_token = 0;
1385 #if TRACE
1386       printf ("lex: forcing token %d\n", i);
1387 #endif
1388       return i;
1389     }
1390
1391   c = def_getc ();
1392
1393   /* Trim leading whitespace.  */
1394   while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1395     c = def_getc ();
1396
1397   if (c == EOF)
1398     {
1399 #if TRACE
1400       printf ("lex: EOF\n");
1401 #endif
1402       return 0;
1403     }
1404
1405   if (saw_newline && c == ';')
1406     {
1407       do
1408         {
1409           c = def_getc ();
1410         }
1411       while (c != EOF && c != '\n');
1412       if (c == '\n')
1413         return def_lex ();
1414       return 0;
1415     }
1416
1417   /* Must be something else.  */
1418   saw_newline = 0;
1419
1420   if (ISDIGIT (c))
1421     {
1422       bufptr = 0;
1423       while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1424         {
1425           put_buf (c);
1426           c = def_getc ();
1427         }
1428       if (c != EOF)
1429         def_ungetc (c);
1430       yylval.digits = def_pool_strdup (buffer);
1431 #if TRACE
1432       printf ("lex: `%s' returns DIGITS\n", buffer);
1433 #endif
1434       return DIGITS;
1435     }
1436
1437   if (ISALPHA (c) || strchr ("$:-_?@", c))
1438     {
1439       bufptr = 0;
1440       q = c;
1441       put_buf (c);
1442       c = def_getc ();
1443
1444       if (q == '@')
1445         {
1446           if (ISBLANK (c) ) /* '@' followed by whitespace.  */
1447             return (q);
1448           else if (ISDIGIT (c)) /* '@' followed by digit.  */
1449             {
1450               def_ungetc (c);
1451               return (q);
1452             }
1453 #if TRACE
1454           printf ("lex: @ returns itself\n");
1455 #endif
1456         }
1457
1458       while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1459         {
1460           put_buf (c);
1461           c = def_getc ();
1462         }
1463       if (c != EOF)
1464         def_ungetc (c);
1465       if (ISALPHA (q)) /* Check for tokens.  */
1466         {
1467           for (i = 0; tokens[i].name; i++)
1468             if (strcmp (tokens[i].name, buffer) == 0)
1469               {
1470 #if TRACE
1471                 printf ("lex: `%s' is a string token\n", buffer);
1472 #endif
1473                 return tokens[i].token;
1474               }
1475         }
1476 #if TRACE
1477       printf ("lex: `%s' returns ID\n", buffer);
1478 #endif
1479       yylval.id = def_pool_strdup (buffer);
1480       return ID;
1481     }
1482
1483   if (c == '\'' || c == '"')
1484     {
1485       q = c;
1486       c = def_getc ();
1487       bufptr = 0;
1488
1489       while (c != EOF && c != q)
1490         {
1491           put_buf (c);
1492           c = def_getc ();
1493         }
1494       yylval.id = def_pool_strdup (buffer);
1495 #if TRACE
1496       printf ("lex: `%s' returns ID\n", buffer);
1497 #endif
1498       return ID;
1499     }
1500
1501   if ( c == '=')
1502     {
1503       c = def_getc ();
1504       if (c == '=')
1505         {
1506 #if TRACE
1507           printf ("lex: `==' returns EQUAL\n");
1508 #endif
1509           return EQUAL;
1510         }
1511       def_ungetc (c);
1512 #if TRACE
1513       printf ("lex: `=' returns itself\n");
1514 #endif
1515       return '=';
1516     }
1517   if (c == '.' || c == ',')
1518     {
1519 #if TRACE
1520       printf ("lex: `%c' returns itself\n", c);
1521 #endif
1522       return c;
1523     }
1524
1525   if (c == '\n')
1526     {
1527       linenumber++;
1528       saw_newline = 1;
1529     }
1530
1531   /*printf ("lex: 0x%02x ignored\n", c); */
1532   return def_lex ();
1533 }
1534
1535 static char *
1536 def_pool_alloc (size_t sz)
1537 {
1538   def_pool_str *e;
1539
1540   e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1541   e->next = pool_strs;
1542   pool_strs = e;
1543   return e->data;
1544 }
1545
1546 static char *
1547 def_pool_strdup (const char *str)
1548 {
1549   char *s;
1550   size_t len;
1551   if (!str)
1552     return NULL;
1553   len = strlen (str) + 1;
1554   s = def_pool_alloc (len);
1555   memcpy (s, str, len);
1556   return s;
1557 }
1558
1559 static void
1560 def_pool_free (void)
1561 {
1562   def_pool_str *p;
1563   while ((p = pool_strs) != NULL)
1564     {
1565       pool_strs = p->next;
1566       free (p);
1567     }
1568 }