1%{ /* deffilep.y - parser for .def files */
2
3/*   Copyright (C) 1995-2017 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
80typedef struct def_pool_str {
81  struct def_pool_str *next;
82  char data[1];
83} def_pool_str;
84
85static def_pool_str *pool_strs = NULL;
86
87static char *def_pool_alloc (size_t sz);
88static char *def_pool_strdup (const char *str);
89static void def_pool_free (void);
90
91static void def_description (const char *);
92static void def_exports (const char *, const char *, int, int, const char *);
93static void def_heapsize (int, int);
94static void def_import (const char *, const char *, const char *, const char *,
95			int, const char *);
96static void def_image_name (const char *, bfd_vma, int);
97static void def_section (const char *, int);
98static void def_section_alt (const char *, const char *);
99static void def_stacksize (int, int);
100static void def_version (int, int);
101static void def_directive (char *);
102static void def_aligncomm (char *str, int align);
103static int def_parse (void);
104static int def_error (const char *);
105static int def_lex (void);
106
107static int lex_forced_token = 0;
108static const char *lex_parse_string = 0;
109static 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
138start: start command
139	| command
140	;
141
142command:
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
160explist:
161		/* EMPTY */
162	|	expline
163	|	explist expline
164	;
165
166expline:
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	;
173exp_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	;
180exp_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	;
190implist:
191		implist impline
192	|	impline
193	;
194
195impline:
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
210seclist:
211		seclist secline
212	|	secline
213	;
214
215secline:
216	ID attr_list { def_section ($1, $2);}
217	| ID ID { def_section_alt ($1, $2);}
218	;
219
220attr_list:
221	attr_list opt_comma attr { $$ = $1 | $3; }
222	| attr { $$ = $1; }
223	;
224
225opt_comma:
226	','
227	|
228	;
229opt_number: ',' NUMBER { $$=$2;}
230	|	   { $$=-1;}
231	;
232
233attr:
234		READ	{ $$ = 1;}
235	|	WRITE	{ $$ = 2;}
236	|	EXECUTE	{ $$=4;}
237	|	SHARED	{ $$=8;}
238	;
239
240
241keyword_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
271opt_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
298opt_name: opt_name2 { $$ = $1; }
299	|		{ $$ = ""; }
300	;
301
302opt_equalequal_name: EQUAL ID	{ $$ = $2; }
303	|							{ $$ = 0; }
304	;
305
306opt_ordinal:
307	  '@' NUMBER     { $$ = $2;}
308	|                { $$ = -1;}
309	;
310
311opt_equal_name:
312          '=' opt_name2	{ $$ = $2; }
313        | 		{ $$ =  0; }
314	;
315
316opt_base: BASE	'=' VMA	{ $$ = $3;}
317	|	{ $$ = (bfd_vma) -1;}
318	;
319
320anylang_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
335opt_digits: DIGITS	{ $$ = $1; }
336	|		{ $$ = ""; }
337	;
338
339opt_id: ID		{ $$ = $1; }
340	|		{ $$ = ""; }
341	;
342
343NUMBER: DIGITS		{ $$ = strtoul ($1, 0, 0); }
344	;
345VMA: DIGITS		{ $$ = (bfd_vma) strtoull ($1, 0, 0); }
346
347%%
348
349/*****************************************************************************
350 API
351 *****************************************************************************/
352
353static FILE *the_file;
354static const char *def_filename;
355static int linenumber;
356static def_file *def;
357static int saw_newline;
358
359struct directive
360  {
361    struct directive *next;
362    char *name;
363    int len;
364  };
365
366static struct directive *directives = 0;
367
368def_file *
369def_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
381def_file *
382def_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
429void
430def_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
504void
505def_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
596static int
597are_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
606static int
607cmp_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
626static int
627find_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
674def_file_export *
675def_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
722def_file_module *
723def_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
734static def_file_module *
735def_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
749static int
750cmp_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
771static int
772find_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
819def_file_import *
820def_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
870struct
871{
872  char *param;
873  int token;
874}
875diropts[] =
876{
877  { "-heap", HEAPSIZE },
878  { "-stack", STACKSIZE_K },
879  { "-attr", SECTIONS },
880  { "-export", EXPORTS },
881  { "-aligncomm", ALIGNCOMM },
882  { 0, 0 }
883};
884
885void
886def_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 separating options
908          - a NUL separating 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
962static void
963def_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
994static void
995def_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
1012static void
1013def_stacksize (int reserve, int commit)
1014{
1015  def->stack_reserve = reserve;
1016  def->stack_commit = commit;
1017}
1018
1019static void
1020def_heapsize (int reserve, int commit)
1021{
1022  def->heap_reserve = reserve;
1023  def->heap_commit = commit;
1024}
1025
1026static void
1027def_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
1057static void
1058def_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
1087static void
1088def_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
1121static void
1122def_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
1142static void
1143def_version (int major, int minor)
1144{
1145  def->version_major = major;
1146  def->version_minor = minor;
1147}
1148
1149static void
1150def_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
1160static void
1161def_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
1198static int
1199def_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.  */
1213static char *buffer = 0;
1214static int buflen = 0;
1215static int bufptr = 0;
1216
1217static void
1218put_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
1232static struct
1233{
1234  char *name;
1235  int token;
1236}
1237tokens[] =
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
1267static int
1268def_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
1288static int
1289def_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
1300static int
1301def_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
1459static char *
1460def_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
1470static char *
1471def_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
1483static void
1484def_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}
1493