Home | History | Annotate | Download | only in ld
      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 }
   1493