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