xref: /netbsd-src/external/gpl3/binutils.old/dist/ld/deffilep.y (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1 %{ /* deffilep.y - parser for .def files */
2 
3 /*   Copyright (C) 1995-2022 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 void 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_K 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_K { $$=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_K  { $$ = "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 *
def_file_empty(void)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 *
def_file_parse(const char * filename,def_file * add_to)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
def_file_free(def_file * fdef)431 def_file_free (def_file *fdef)
432 {
433   int i;
434 
435   if (!fdef)
436     return;
437   free (fdef->name);
438   free (fdef->description);
439 
440   if (fdef->section_defs)
441     {
442       for (i = 0; i < fdef->num_section_defs; i++)
443 	{
444 	  free (fdef->section_defs[i].name);
445 	  free (fdef->section_defs[i].class);
446 	}
447       free (fdef->section_defs);
448     }
449 
450   if (fdef->exports)
451     {
452       for (i = 0; i < fdef->num_exports; i++)
453 	{
454 	  if (fdef->exports[i].internal_name != fdef->exports[i].name)
455 	    free (fdef->exports[i].internal_name);
456 	  free (fdef->exports[i].name);
457 	  free (fdef->exports[i].its_name);
458 	}
459       free (fdef->exports);
460     }
461 
462   if (fdef->imports)
463     {
464       for (i = 0; i < fdef->num_imports; i++)
465 	{
466 	  if (fdef->imports[i].internal_name != fdef->imports[i].name)
467 	    free (fdef->imports[i].internal_name);
468 	  free (fdef->imports[i].name);
469 	  free (fdef->imports[i].its_name);
470 	}
471       free (fdef->imports);
472     }
473 
474   while (fdef->modules)
475     {
476       def_file_module *m = fdef->modules;
477 
478       fdef->modules = fdef->modules->next;
479       free (m);
480     }
481 
482   while (fdef->aligncomms)
483     {
484       def_file_aligncomm *c = fdef->aligncomms;
485 
486       fdef->aligncomms = fdef->aligncomms->next;
487       free (c->symbol_name);
488       free (c);
489     }
490 
491   free (fdef);
492 }
493 
494 #ifdef DEF_FILE_PRINT
495 void
def_file_print(FILE * file,def_file * fdef)496 def_file_print (FILE *file, def_file *fdef)
497 {
498   int i;
499 
500   fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
501   if (fdef->name)
502     fprintf (file, "  name: %s\n", fdef->name ? fdef->name : "(unspecified)");
503   if (fdef->is_dll != -1)
504     fprintf (file, "  is dll: %s\n", fdef->is_dll ? "yes" : "no");
505   if (fdef->base_address != (bfd_vma) -1)
506     {
507       fprintf (file, "  base address: 0x");
508       fprintf_vma (file, fdef->base_address);
509       fprintf (file, "\n");
510     }
511   if (fdef->description)
512     fprintf (file, "  description: `%s'\n", fdef->description);
513   if (fdef->stack_reserve != -1)
514     fprintf (file, "  stack reserve: 0x%08x\n", fdef->stack_reserve);
515   if (fdef->stack_commit != -1)
516     fprintf (file, "  stack commit: 0x%08x\n", fdef->stack_commit);
517   if (fdef->heap_reserve != -1)
518     fprintf (file, "  heap reserve: 0x%08x\n", fdef->heap_reserve);
519   if (fdef->heap_commit != -1)
520     fprintf (file, "  heap commit: 0x%08x\n", fdef->heap_commit);
521 
522   if (fdef->num_section_defs > 0)
523     {
524       fprintf (file, "  section defs:\n");
525 
526       for (i = 0; i < fdef->num_section_defs; i++)
527 	{
528 	  fprintf (file, "    name: `%s', class: `%s', flags:",
529 		   fdef->section_defs[i].name, fdef->section_defs[i].class);
530 	  if (fdef->section_defs[i].flag_read)
531 	    fprintf (file, " R");
532 	  if (fdef->section_defs[i].flag_write)
533 	    fprintf (file, " W");
534 	  if (fdef->section_defs[i].flag_execute)
535 	    fprintf (file, " X");
536 	  if (fdef->section_defs[i].flag_shared)
537 	    fprintf (file, " S");
538 	  fprintf (file, "\n");
539 	}
540     }
541 
542   if (fdef->num_exports > 0)
543     {
544       fprintf (file, "  exports:\n");
545 
546       for (i = 0; i < fdef->num_exports; i++)
547 	{
548 	  fprintf (file, "    name: `%s', int: `%s', ordinal: %d, flags:",
549 		   fdef->exports[i].name, fdef->exports[i].internal_name,
550 		   fdef->exports[i].ordinal);
551 	  if (fdef->exports[i].flag_private)
552 	    fprintf (file, " P");
553 	  if (fdef->exports[i].flag_constant)
554 	    fprintf (file, " C");
555 	  if (fdef->exports[i].flag_noname)
556 	    fprintf (file, " N");
557 	  if (fdef->exports[i].flag_data)
558 	    fprintf (file, " D");
559 	  fprintf (file, "\n");
560 	}
561     }
562 
563   if (fdef->num_imports > 0)
564     {
565       fprintf (file, "  imports:\n");
566 
567       for (i = 0; i < fdef->num_imports; i++)
568 	{
569 	  fprintf (file, "    int: %s, from: `%s', name: `%s', ordinal: %d\n",
570 		   fdef->imports[i].internal_name,
571 		   fdef->imports[i].module,
572 		   fdef->imports[i].name,
573 		   fdef->imports[i].ordinal);
574 	}
575     }
576 
577   if (fdef->version_major != -1)
578     fprintf (file, "  version: %d.%d\n", fdef->version_major, fdef->version_minor);
579 
580   fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
581 }
582 #endif
583 
584 /* Helper routine to check for identity of string pointers,
585    which might be NULL.  */
586 
587 static int
are_names_equal(const char * s1,const char * s2)588 are_names_equal (const char *s1, const char *s2)
589 {
590   if (!s1 && !s2)
591     return 0;
592   if (!s1 || !s2)
593     return (!s1 ? -1 : 1);
594   return strcmp (s1, s2);
595 }
596 
597 static int
cmp_export_elem(const def_file_export * e,const char * ex_name,const char * in_name,const char * its_name,int ord)598 cmp_export_elem (const def_file_export *e, const char *ex_name,
599 		 const char *in_name, const char *its_name,
600 		 int ord)
601 {
602   int r;
603 
604   if ((r = are_names_equal (ex_name, e->name)) != 0)
605     return r;
606   if ((r = are_names_equal (in_name, e->internal_name)) != 0)
607     return r;
608   if ((r = are_names_equal (its_name, e->its_name)) != 0)
609     return r;
610   return (ord - e->ordinal);
611 }
612 
613 /* Search the position of the identical element, or returns the position
614    of the next higher element. If last valid element is smaller, then MAX
615    is returned.  */
616 
617 static int
find_export_in_list(def_file_export * b,int max,const char * ex_name,const char * in_name,const char * its_name,int ord,int * is_ident)618 find_export_in_list (def_file_export *b, int max,
619 		     const char *ex_name, const char *in_name,
620 		     const char *its_name, int ord, int *is_ident)
621 {
622   int e, l, r, p;
623 
624   *is_ident = 0;
625   if (!max)
626     return 0;
627   if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
628     {
629       if (!e)
630 	*is_ident = 1;
631       return 0;
632     }
633   if (max == 1)
634     return 1;
635   if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
636     return max;
637   else if (!e || max == 2)
638     {
639       if (!e)
640 	*is_ident = 1;
641       return max - 1;
642     }
643   l = 0; r = max - 1;
644   while (l < r)
645     {
646       p = (l + r) / 2;
647       e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
648       if (!e)
649 	{
650 	  *is_ident = 1;
651 	  return p;
652 	}
653       else if (e < 0)
654 	r = p - 1;
655       else if (e > 0)
656 	l = p + 1;
657     }
658   if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
659     ++l;
660   else if (!e)
661     *is_ident = 1;
662   return l;
663 }
664 
665 def_file_export *
def_file_add_export(def_file * fdef,const char * external_name,const char * internal_name,int ordinal,const char * its_name,int * is_dup)666 def_file_add_export (def_file *fdef,
667 		     const char *external_name,
668 		     const char *internal_name,
669 		     int ordinal,
670 		     const char *its_name,
671 		     int *is_dup)
672 {
673   def_file_export *e;
674   int pos;
675   int max_exports = ROUND_UP(fdef->num_exports, 32);
676 
677   if (internal_name && !external_name)
678     external_name = internal_name;
679   if (external_name && !internal_name)
680     internal_name = external_name;
681 
682   /* We need to avoid duplicates.  */
683   *is_dup = 0;
684   pos = find_export_in_list (fdef->exports, fdef->num_exports,
685 		     external_name, internal_name,
686 		     its_name, ordinal, is_dup);
687 
688   if (*is_dup != 0)
689     return (fdef->exports + pos);
690 
691   if (fdef->num_exports >= max_exports)
692     {
693       max_exports = ROUND_UP(fdef->num_exports + 1, 32);
694       if (fdef->exports)
695 	fdef->exports = xrealloc (fdef->exports,
696 				 max_exports * sizeof (def_file_export));
697       else
698 	fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
699     }
700 
701   e = fdef->exports + pos;
702   if (pos != fdef->num_exports)
703     memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
704   memset (e, 0, sizeof (def_file_export));
705   e->name = xstrdup (external_name);
706   e->internal_name = xstrdup (internal_name);
707   e->its_name = (its_name ? xstrdup (its_name) : NULL);
708   e->ordinal = ordinal;
709   fdef->num_exports++;
710   return e;
711 }
712 
713 def_file_module *
def_get_module(def_file * fdef,const char * name)714 def_get_module (def_file *fdef, const char *name)
715 {
716   def_file_module *s;
717 
718   for (s = fdef->modules; s; s = s->next)
719     if (strcmp (s->name, name) == 0)
720       return s;
721 
722   return NULL;
723 }
724 
725 static def_file_module *
def_stash_module(def_file * fdef,const char * name)726 def_stash_module (def_file *fdef, const char *name)
727 {
728   def_file_module *s;
729 
730   if ((s = def_get_module (fdef, name)) != NULL)
731       return s;
732   s = xmalloc (sizeof (def_file_module) + strlen (name));
733   s->next = fdef->modules;
734   fdef->modules = s;
735   s->user_data = 0;
736   strcpy (s->name, name);
737   return s;
738 }
739 
740 static int
cmp_import_elem(const def_file_import * e,const char * ex_name,const char * in_name,const char * module,int ord)741 cmp_import_elem (const def_file_import *e, const char *ex_name,
742 		 const char *in_name, const char *module,
743 		 int ord)
744 {
745   int r;
746 
747   if ((r = are_names_equal (module, (e->module ? e->module->name : NULL))))
748     return r;
749   if ((r = are_names_equal (ex_name, e->name)) != 0)
750     return r;
751   if ((r = are_names_equal (in_name, e->internal_name)) != 0)
752     return r;
753   if (ord != e->ordinal)
754     return (ord < e->ordinal ? -1 : 1);
755   return 0;
756 }
757 
758 /* Search the position of the identical element, or returns the position
759    of the next higher element. If last valid element is smaller, then MAX
760    is returned.  */
761 
762 static int
find_import_in_list(def_file_import * b,int max,const char * ex_name,const char * in_name,const char * module,int ord,int * is_ident)763 find_import_in_list (def_file_import *b, int max,
764 		     const char *ex_name, const char *in_name,
765 		     const char *module, int ord, int *is_ident)
766 {
767   int e, l, r, p;
768 
769   *is_ident = 0;
770   if (!max)
771     return 0;
772   if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
773     {
774       if (!e)
775 	*is_ident = 1;
776       return 0;
777     }
778   if (max == 1)
779     return 1;
780   if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
781     return max;
782   else if (!e || max == 2)
783     {
784       if (!e)
785 	*is_ident = 1;
786       return max - 1;
787     }
788   l = 0; r = max - 1;
789   while (l < r)
790     {
791       p = (l + r) / 2;
792       e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
793       if (!e)
794 	{
795 	  *is_ident = 1;
796 	  return p;
797 	}
798       else if (e < 0)
799 	r = p - 1;
800       else if (e > 0)
801 	l = p + 1;
802     }
803   if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
804     ++l;
805   else if (!e)
806     *is_ident = 1;
807   return l;
808 }
809 
810 static void
fill_in_import(def_file_import * i,const char * name,def_file_module * module,int ordinal,const char * internal_name,const char * its_name)811 fill_in_import (def_file_import *i,
812 		const char *name,
813 		def_file_module *module,
814 		int ordinal,
815 		const char *internal_name,
816 		const char *its_name)
817 {
818   memset (i, 0, sizeof (def_file_import));
819   if (name)
820     i->name = xstrdup (name);
821   i->module = module;
822   i->ordinal = ordinal;
823   if (internal_name)
824     i->internal_name = xstrdup (internal_name);
825   else
826     i->internal_name = i->name;
827   i->its_name = (its_name ? xstrdup (its_name) : NULL);
828 }
829 
830 def_file_import *
def_file_add_import(def_file * fdef,const char * name,const char * module,int ordinal,const char * internal_name,const char * its_name,int * is_dup)831 def_file_add_import (def_file *fdef,
832 		     const char *name,
833 		     const char *module,
834 		     int ordinal,
835 		     const char *internal_name,
836 		     const char *its_name,
837 		     int *is_dup)
838 {
839   def_file_import *i;
840   int pos;
841   int max_imports = ROUND_UP (fdef->num_imports, 16);
842 
843   /* We need to avoid here duplicates.  */
844   *is_dup = 0;
845   pos = find_import_in_list (fdef->imports, fdef->num_imports,
846 			     name,
847 			     (!internal_name ? name : internal_name),
848 			     module, ordinal, is_dup);
849   if (*is_dup != 0)
850     return fdef->imports + pos;
851 
852   if (fdef->num_imports >= max_imports)
853     {
854       max_imports = ROUND_UP (fdef->num_imports+1, 16);
855 
856       if (fdef->imports)
857 	fdef->imports = xrealloc (fdef->imports,
858 				 max_imports * sizeof (def_file_import));
859       else
860 	fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
861     }
862   i = fdef->imports + pos;
863   if (pos != fdef->num_imports)
864     memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
865 
866   fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
867 		  internal_name, its_name);
868   fdef->num_imports++;
869 
870   return i;
871 }
872 
873 int
def_file_add_import_from(def_file * fdef,int num_imports,const char * name,const char * module,int ordinal,const char * internal_name,const char * its_name ATTRIBUTE_UNUSED)874 def_file_add_import_from (def_file *fdef,
875 			  int num_imports,
876 			  const char *name,
877 			  const char *module,
878 			  int ordinal,
879 			  const char *internal_name,
880 			  const char *its_name ATTRIBUTE_UNUSED)
881 {
882   def_file_import *i;
883   int is_dup;
884   int pos;
885   int max_imports = ROUND_UP (fdef->num_imports, 16);
886 
887   /* We need to avoid here duplicates.  */
888   is_dup = 0;
889   pos = find_import_in_list (fdef->imports, fdef->num_imports,
890 			     name, internal_name ? internal_name : name,
891 			     module, ordinal, &is_dup);
892   if (is_dup != 0)
893     return -1;
894   if (fdef->imports && pos != fdef->num_imports)
895     {
896       i = fdef->imports + pos;
897       if (i->module && strcmp (i->module->name, module) == 0)
898 	return -1;
899     }
900 
901   if (fdef->num_imports + num_imports - 1 >= max_imports)
902     {
903       max_imports = ROUND_UP (fdef->num_imports + num_imports, 16);
904 
905       if (fdef->imports)
906 	fdef->imports = xrealloc (fdef->imports,
907 				 max_imports * sizeof (def_file_import));
908       else
909 	fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
910     }
911   i = fdef->imports + pos;
912   if (pos != fdef->num_imports)
913     memmove (i + num_imports, i,
914 	     sizeof (def_file_import) * (fdef->num_imports - pos));
915 
916   return pos;
917 }
918 
919 def_file_import *
def_file_add_import_at(def_file * fdef,int pos,const char * name,const char * module,int ordinal,const char * internal_name,const char * its_name)920 def_file_add_import_at (def_file *fdef,
921 			int pos,
922 			const char *name,
923 			const char *module,
924 			int ordinal,
925 			const char *internal_name,
926 			const char *its_name)
927 {
928   def_file_import *i = fdef->imports + pos;
929 
930   fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
931 		  internal_name, its_name);
932   fdef->num_imports++;
933 
934   return i;
935 }
936 
937 struct
938 {
939   char *param;
940   int token;
941 }
942 diropts[] =
943 {
944   { "-heap", HEAPSIZE },
945   { "-stack", STACKSIZE_K },
946   { "-attr", SECTIONS },
947   { "-export", EXPORTS },
948   { "-aligncomm", ALIGNCOMM },
949   { 0, 0 }
950 };
951 
952 void
def_file_add_directive(def_file * my_def,const char * param,int len)953 def_file_add_directive (def_file *my_def, const char *param, int len)
954 {
955   def_file *save_def = def;
956   const char *pend = param + len;
957   char * tend = (char *) param;
958   int i;
959 
960   def = my_def;
961 
962   while (param < pend)
963     {
964       while (param < pend
965 	     && (ISSPACE (*param) || *param == '\n' || *param == 0))
966 	param++;
967 
968       if (param == pend)
969 	break;
970 
971       /* Scan forward until we encounter any of:
972 	  - the end of the buffer
973 	  - the start of a new option
974 	  - a newline separating options
975 	  - a NUL separating options.  */
976       for (tend = (char *) (param + 1);
977 	   (tend < pend
978 	    && !(ISSPACE (tend[-1]) && *tend == '-')
979 	    && *tend != '\n' && *tend != 0);
980 	   tend++)
981 	;
982 
983       for (i = 0; diropts[i].param; i++)
984 	{
985 	  len = strlen (diropts[i].param);
986 
987 	  if (tend - param >= len
988 	      && strncmp (param, diropts[i].param, len) == 0
989 	      && (param[len] == ':' || param[len] == ' '))
990 	    {
991 	      lex_parse_string_end = tend;
992 	      lex_parse_string = param + len + 1;
993 	      lex_forced_token = diropts[i].token;
994 	      saw_newline = 0;
995 	      if (def_parse ())
996 		continue;
997 	      break;
998 	    }
999 	}
1000 
1001       if (!diropts[i].param)
1002 	{
1003 	  if (tend < pend)
1004 	    {
1005 	      char saved;
1006 
1007 	      saved = * tend;
1008 	      * tend = 0;
1009 	      /* xgettext:c-format */
1010 	      einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
1011 	      * tend = saved;
1012 	    }
1013 	  else
1014 	    {
1015 	      einfo (_("Warning: corrupt .drectve at end of def file\n"));
1016 	    }
1017 	}
1018 
1019       lex_parse_string = 0;
1020       param = tend;
1021     }
1022 
1023   def = save_def;
1024   def_pool_free ();
1025 }
1026 
1027 /* Parser Callbacks.  */
1028 
1029 static void
def_image_name(const char * name,bfd_vma base,int is_dll)1030 def_image_name (const char *name, bfd_vma base, int is_dll)
1031 {
1032   /* If a LIBRARY or NAME statement is specified without a name, there is nothing
1033      to do here.  We retain the output filename specified on command line.  */
1034   if (*name)
1035     {
1036       const char* image_name = lbasename (name);
1037 
1038       if (image_name != name)
1039 	einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
1040 	       def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
1041 	       name);
1042       free (def->name);
1043       /* Append the default suffix, if none specified.  */
1044       if (strchr (image_name, '.') == 0)
1045 	{
1046 	  const char * suffix = is_dll ? ".dll" : ".exe";
1047 
1048 	  def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
1049 	  sprintf (def->name, "%s%s", image_name, suffix);
1050 	}
1051       else
1052 	def->name = xstrdup (image_name);
1053     }
1054 
1055   /* Honor a BASE address statement, even if LIBRARY string is empty.  */
1056   def->base_address = base;
1057   def->is_dll = is_dll;
1058 }
1059 
1060 static void
def_description(const char * text)1061 def_description (const char *text)
1062 {
1063   int len = def->description ? strlen (def->description) : 0;
1064 
1065   len += strlen (text) + 1;
1066   if (def->description)
1067     {
1068       def->description = xrealloc (def->description, len);
1069       strcat (def->description, text);
1070     }
1071   else
1072     {
1073       def->description = xmalloc (len);
1074       strcpy (def->description, text);
1075     }
1076 }
1077 
1078 static void
def_stacksize(int reserve,int commit)1079 def_stacksize (int reserve, int commit)
1080 {
1081   def->stack_reserve = reserve;
1082   def->stack_commit = commit;
1083 }
1084 
1085 static void
def_heapsize(int reserve,int commit)1086 def_heapsize (int reserve, int commit)
1087 {
1088   def->heap_reserve = reserve;
1089   def->heap_commit = commit;
1090 }
1091 
1092 static void
def_section(const char * name,int attr)1093 def_section (const char *name, int attr)
1094 {
1095   def_file_section *s;
1096   int max_sections = ROUND_UP (def->num_section_defs, 4);
1097 
1098   if (def->num_section_defs >= max_sections)
1099     {
1100       max_sections = ROUND_UP (def->num_section_defs+1, 4);
1101 
1102       if (def->section_defs)
1103 	def->section_defs = xrealloc (def->section_defs,
1104 				      max_sections * sizeof (def_file_import));
1105       else
1106 	def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
1107     }
1108   s = def->section_defs + def->num_section_defs;
1109   memset (s, 0, sizeof (def_file_section));
1110   s->name = xstrdup (name);
1111   if (attr & 1)
1112     s->flag_read = 1;
1113   if (attr & 2)
1114     s->flag_write = 1;
1115   if (attr & 4)
1116     s->flag_execute = 1;
1117   if (attr & 8)
1118     s->flag_shared = 1;
1119 
1120   def->num_section_defs++;
1121 }
1122 
1123 static void
def_section_alt(const char * name,const char * attr)1124 def_section_alt (const char *name, const char *attr)
1125 {
1126   int aval = 0;
1127 
1128   for (; *attr; attr++)
1129     {
1130       switch (*attr)
1131 	{
1132 	case 'R':
1133 	case 'r':
1134 	  aval |= 1;
1135 	  break;
1136 	case 'W':
1137 	case 'w':
1138 	  aval |= 2;
1139 	  break;
1140 	case 'X':
1141 	case 'x':
1142 	  aval |= 4;
1143 	  break;
1144 	case 'S':
1145 	case 's':
1146 	  aval |= 8;
1147 	  break;
1148 	}
1149     }
1150   def_section (name, aval);
1151 }
1152 
1153 static void
def_exports(const char * external_name,const char * internal_name,int ordinal,int flags,const char * its_name)1154 def_exports (const char *external_name,
1155 	     const char *internal_name,
1156 	     int ordinal,
1157 	     int flags,
1158 	     const char *its_name)
1159 {
1160   def_file_export *dfe;
1161   int is_dup = 0;
1162 
1163   if (!internal_name && external_name)
1164     internal_name = external_name;
1165 #if TRACE
1166   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1167 #endif
1168 
1169   dfe = def_file_add_export (def, external_name, internal_name, ordinal,
1170 			     its_name, &is_dup);
1171 
1172   /* We might check here for flag redefinition and warn.  For now we
1173      ignore duplicates silently.  */
1174   if (is_dup)
1175     return;
1176 
1177   if (flags & 1)
1178     dfe->flag_noname = 1;
1179   if (flags & 2)
1180     dfe->flag_constant = 1;
1181   if (flags & 4)
1182     dfe->flag_data = 1;
1183   if (flags & 8)
1184     dfe->flag_private = 1;
1185 }
1186 
1187 static void
def_import(const char * internal_name,const char * module,const char * dllext,const char * name,int ordinal,const char * its_name)1188 def_import (const char *internal_name,
1189 	    const char *module,
1190 	    const char *dllext,
1191 	    const char *name,
1192 	    int ordinal,
1193 	    const char *its_name)
1194 {
1195   char *buf = 0;
1196   const char *ext = dllext ? dllext : "dll";
1197   int is_dup = 0;
1198 
1199   buf = xmalloc (strlen (module) + strlen (ext) + 2);
1200   sprintf (buf, "%s.%s", module, ext);
1201   module = buf;
1202 
1203   def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1204 		       &is_dup);
1205   free (buf);
1206 }
1207 
1208 static void
def_version(int major,int minor)1209 def_version (int major, int minor)
1210 {
1211   def->version_major = major;
1212   def->version_minor = minor;
1213 }
1214 
1215 static void
def_directive(char * str)1216 def_directive (char *str)
1217 {
1218   struct directive *d = xmalloc (sizeof (struct directive));
1219 
1220   d->next = directives;
1221   directives = d;
1222   d->name = xstrdup (str);
1223   d->len = strlen (str);
1224 }
1225 
1226 static void
def_aligncomm(char * str,int align)1227 def_aligncomm (char *str, int align)
1228 {
1229   def_file_aligncomm *c, *p;
1230 
1231   p = NULL;
1232   c = def->aligncomms;
1233   while (c != NULL)
1234     {
1235       int e = strcmp (c->symbol_name, str);
1236       if (!e)
1237 	{
1238 	  /* Not sure if we want to allow here duplicates with
1239 	     different alignments, but for now we keep them.  */
1240 	  e = (int) c->alignment - align;
1241 	  if (!e)
1242 	    return;
1243 	}
1244       if (e > 0)
1245 	break;
1246       c = (p = c)->next;
1247     }
1248 
1249   c = xmalloc (sizeof (def_file_aligncomm));
1250   c->symbol_name = xstrdup (str);
1251   c->alignment = (unsigned int) align;
1252   if (!p)
1253     {
1254       c->next = def->aligncomms;
1255       def->aligncomms = c;
1256     }
1257   else
1258     {
1259       c->next = p->next;
1260       p->next = c;
1261     }
1262 }
1263 
1264 static void
def_error(const char * err)1265 def_error (const char *err)
1266 {
1267   einfo ("%P: %s:%d: %s\n",
1268 	 def_filename ? def_filename : "<unknown-file>", linenumber, err);
1269 }
1270 
1271 
1272 /* Lexical Scanner.  */
1273 
1274 #undef TRACE
1275 #define TRACE 0
1276 
1277 /* Never freed, but always reused as needed, so no real leak.  */
1278 static char *buffer = 0;
1279 static int buflen = 0;
1280 static int bufptr = 0;
1281 
1282 static void
put_buf(char c)1283 put_buf (char c)
1284 {
1285   if (bufptr == buflen)
1286     {
1287       buflen += 50;		/* overly reasonable, eh?  */
1288       if (buffer)
1289 	buffer = xrealloc (buffer, buflen + 1);
1290       else
1291 	buffer = xmalloc (buflen + 1);
1292     }
1293   buffer[bufptr++] = c;
1294   buffer[bufptr] = 0;		/* not optimal, but very convenient.  */
1295 }
1296 
1297 static struct
1298 {
1299   char *name;
1300   int token;
1301 }
1302 tokens[] =
1303 {
1304   { "BASE", BASE },
1305   { "CODE", CODE },
1306   { "CONSTANT", CONSTANTU },
1307   { "constant", CONSTANTL },
1308   { "DATA", DATAU },
1309   { "data", DATAL },
1310   { "DESCRIPTION", DESCRIPTION },
1311   { "DIRECTIVE", DIRECTIVE },
1312   { "EXECUTE", EXECUTE },
1313   { "EXPORTS", EXPORTS },
1314   { "HEAPSIZE", HEAPSIZE },
1315   { "IMPORTS", IMPORTS },
1316   { "LIBRARY", LIBRARY },
1317   { "NAME", NAME },
1318   { "NONAME", NONAMEU },
1319   { "noname", NONAMEL },
1320   { "PRIVATE", PRIVATEU },
1321   { "private", PRIVATEL },
1322   { "READ", READ },
1323   { "SECTIONS", SECTIONS },
1324   { "SEGMENTS", SECTIONS },
1325   { "SHARED", SHARED_K },
1326   { "STACKSIZE", STACKSIZE_K },
1327   { "VERSION", VERSIONK },
1328   { "WRITE", WRITE },
1329   { 0, 0 }
1330 };
1331 
1332 static int
def_getc(void)1333 def_getc (void)
1334 {
1335   int rv;
1336 
1337   if (lex_parse_string)
1338     {
1339       if (lex_parse_string >= lex_parse_string_end)
1340 	rv = EOF;
1341       else
1342 	rv = *lex_parse_string++;
1343     }
1344   else
1345     {
1346       rv = fgetc (the_file);
1347     }
1348   if (rv == '\n')
1349     saw_newline = 1;
1350   return rv;
1351 }
1352 
1353 static int
def_ungetc(int c)1354 def_ungetc (int c)
1355 {
1356   if (lex_parse_string)
1357     {
1358       lex_parse_string--;
1359       return c;
1360     }
1361   else
1362     return ungetc (c, the_file);
1363 }
1364 
1365 static int
def_lex(void)1366 def_lex (void)
1367 {
1368   int c, i, q;
1369 
1370   if (lex_forced_token)
1371     {
1372       i = lex_forced_token;
1373       lex_forced_token = 0;
1374 #if TRACE
1375       printf ("lex: forcing token %d\n", i);
1376 #endif
1377       return i;
1378     }
1379 
1380   c = def_getc ();
1381 
1382   /* Trim leading whitespace.  */
1383   while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1384     c = def_getc ();
1385 
1386   if (c == EOF)
1387     {
1388 #if TRACE
1389       printf ("lex: EOF\n");
1390 #endif
1391       return 0;
1392     }
1393 
1394   if (saw_newline && c == ';')
1395     {
1396       do
1397 	{
1398 	  c = def_getc ();
1399 	}
1400       while (c != EOF && c != '\n');
1401       if (c == '\n')
1402 	return def_lex ();
1403       return 0;
1404     }
1405 
1406   /* Must be something else.  */
1407   saw_newline = 0;
1408 
1409   if (ISDIGIT (c))
1410     {
1411       bufptr = 0;
1412       while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1413 	{
1414 	  put_buf (c);
1415 	  c = def_getc ();
1416 	}
1417       if (c != EOF)
1418 	def_ungetc (c);
1419       yylval.digits = def_pool_strdup (buffer);
1420 #if TRACE
1421       printf ("lex: `%s' returns DIGITS\n", buffer);
1422 #endif
1423       return DIGITS;
1424     }
1425 
1426   if (ISALPHA (c) || strchr ("$:-_?@", c))
1427     {
1428       bufptr = 0;
1429       q = c;
1430       put_buf (c);
1431       c = def_getc ();
1432 
1433       if (q == '@')
1434 	{
1435 	  if (ISBLANK (c) ) /* '@' followed by whitespace.  */
1436 	    return (q);
1437 	  else if (ISDIGIT (c)) /* '@' followed by digit.  */
1438 	    {
1439 	      def_ungetc (c);
1440 	      return (q);
1441 	    }
1442 #if TRACE
1443 	  printf ("lex: @ returns itself\n");
1444 #endif
1445 	}
1446 
1447       while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1448 	{
1449 	  put_buf (c);
1450 	  c = def_getc ();
1451 	}
1452       if (c != EOF)
1453 	def_ungetc (c);
1454       if (ISALPHA (q)) /* Check for tokens.  */
1455 	{
1456 	  for (i = 0; tokens[i].name; i++)
1457 	    if (strcmp (tokens[i].name, buffer) == 0)
1458 	      {
1459 #if TRACE
1460 	        printf ("lex: `%s' is a string token\n", buffer);
1461 #endif
1462 	        return tokens[i].token;
1463 	      }
1464 	}
1465 #if TRACE
1466       printf ("lex: `%s' returns ID\n", buffer);
1467 #endif
1468       yylval.id = def_pool_strdup (buffer);
1469       return ID;
1470     }
1471 
1472   if (c == '\'' || c == '"')
1473     {
1474       q = c;
1475       c = def_getc ();
1476       bufptr = 0;
1477 
1478       while (c != EOF && c != q)
1479 	{
1480 	  put_buf (c);
1481 	  c = def_getc ();
1482 	}
1483       yylval.id = def_pool_strdup (buffer);
1484 #if TRACE
1485       printf ("lex: `%s' returns ID\n", buffer);
1486 #endif
1487       return ID;
1488     }
1489 
1490   if ( c == '=')
1491     {
1492       c = def_getc ();
1493       if (c == '=')
1494 	{
1495 #if TRACE
1496 	  printf ("lex: `==' returns EQUAL\n");
1497 #endif
1498 	  return EQUAL;
1499 	}
1500       def_ungetc (c);
1501 #if TRACE
1502       printf ("lex: `=' returns itself\n");
1503 #endif
1504       return '=';
1505     }
1506   if (c == '.' || c == ',')
1507     {
1508 #if TRACE
1509       printf ("lex: `%c' returns itself\n", c);
1510 #endif
1511       return c;
1512     }
1513 
1514   if (c == '\n')
1515     {
1516       linenumber++;
1517       saw_newline = 1;
1518     }
1519 
1520   /*printf ("lex: 0x%02x ignored\n", c); */
1521   return def_lex ();
1522 }
1523 
1524 static char *
def_pool_alloc(size_t sz)1525 def_pool_alloc (size_t sz)
1526 {
1527   def_pool_str *e;
1528 
1529   e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1530   e->next = pool_strs;
1531   pool_strs = e;
1532   return e->data;
1533 }
1534 
1535 static char *
def_pool_strdup(const char * str)1536 def_pool_strdup (const char *str)
1537 {
1538   char *s;
1539   size_t len;
1540   if (!str)
1541     return NULL;
1542   len = strlen (str) + 1;
1543   s = def_pool_alloc (len);
1544   memcpy (s, str, len);
1545   return s;
1546 }
1547 
1548 static void
def_pool_free(void)1549 def_pool_free (void)
1550 {
1551   def_pool_str *p;
1552   while ((p = pool_strs) != NULL)
1553     {
1554       pool_strs = p->next;
1555       free (p);
1556     }
1557 }
1558