xref: /netbsd/external/gpl3/binutils/dist/ld/deffilep.y (revision 6550d01e)
1 %{ /* deffilep.y - parser for .def files */
2 
3 /*   Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
4      Free Software Foundation, Inc.
5 
6      This file is part of GNU Binutils.
7 
8      This program is free software; you can redistribute it and/or modify
9      it under the terms of the GNU General Public License as published by
10      the Free Software Foundation; either version 3 of the License, or
11      (at your option) any later version.
12 
13      This program is distributed in the hope that it will be useful,
14      but WITHOUT ANY WARRANTY; without even the implied warranty of
15      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16      GNU General Public License for more details.
17 
18      You should have received a copy of the GNU General Public License
19      along with this program; if not, write to the Free Software
20      Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21      MA 02110-1301, USA.  */
22 
23 #include "sysdep.h"
24 #include "libiberty.h"
25 #include "safe-ctype.h"
26 #include "bfd.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 static void def_description (const char *);
82 static void def_exports (const char *, const char *, int, int);
83 static void def_heapsize (int, int);
84 static void def_import (const char *, const char *, const char *, const char *,
85 			int);
86 static void def_image_name (const char *, int, int);
87 static void def_section (const char *, int);
88 static void def_section_alt (const char *, const char *);
89 static void def_stacksize (int, int);
90 static void def_version (int, int);
91 static void def_directive (char *);
92 static int def_parse (void);
93 static int def_error (const char *);
94 static int def_lex (void);
95 
96 static int lex_forced_token = 0;
97 static const char *lex_parse_string = 0;
98 static const char *lex_parse_string_end = 0;
99 
100 %}
101 
102 %union {
103   char *id;
104   int number;
105 };
106 
107 %token NAME LIBRARY DESCRIPTION STACKSIZE HEAPSIZE CODE DATAU DATAL
108 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
109 %token PRIVATEU PRIVATEL
110 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE
111 %token <id> ID
112 %token <number> NUMBER
113 %type  <number> opt_base opt_ordinal
114 %type  <number> attr attr_list opt_number exp_opt_list exp_opt
115 %type  <id> opt_name opt_equal_name dot_name
116 
117 %%
118 
119 start: start command
120 	| command
121 	;
122 
123 command:
124 		NAME opt_name opt_base { def_image_name ($2, $3, 0); }
125 	|	LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
126 	|	DESCRIPTION ID { def_description ($2);}
127 	|	STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);}
128 	|	HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
129 	|	CODE attr_list { def_section ("CODE", $2);}
130 	|	DATAU attr_list  { def_section ("DATA", $2);}
131 	|	SECTIONS seclist
132 	|	EXPORTS explist
133 	|	IMPORTS implist
134 	|	VERSIONK NUMBER { def_version ($2, 0);}
135 	|	VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
136 	|	DIRECTIVE ID { def_directive ($2);}
137 	;
138 
139 
140 explist:
141 		/* EMPTY */
142 	|	expline
143 	|	explist expline
144 	;
145 
146 expline:
147 		/* The opt_comma is necessary to support both the usual
148 		  DEF file syntax as well as .drectve syntax which
149 		  mandates <expsym>,<expoptlist>.  */
150 		dot_name opt_equal_name opt_ordinal opt_comma exp_opt_list
151 			{ def_exports ($1, $2, $3, $5); }
152 	;
153 exp_opt_list:
154 		/* The opt_comma is necessary to support both the usual
155 		   DEF file syntax as well as .drectve syntax which
156 		   allows for comma separated opt list.  */
157 		exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
158 	|	{ $$ = 0; }
159 	;
160 exp_opt:
161 		NONAMEU		{ $$ = 1; }
162 	|	NONAMEL		{ $$ = 1; }
163 	|	CONSTANTU	{ $$ = 2; }
164 	|	CONSTANTL	{ $$ = 2; }
165 	|	DATAU		{ $$ = 4; }
166 	|	DATAL		{ $$ = 4; }
167 	|	PRIVATEU	{ $$ = 8; }
168 	|	PRIVATEL	{ $$ = 8; }
169 	;
170 implist:
171 		implist impline
172 	|	impline
173 	;
174 
175 impline:
176                ID '=' ID '.' ID '.' ID     { def_import ($1, $3, $5, $7, -1); }
177        |       ID '=' ID '.' ID '.' NUMBER { def_import ($1, $3, $5,  0, $7); }
178        |       ID '=' ID '.' ID            { def_import ($1, $3,  0, $5, -1); }
179        |       ID '=' ID '.' NUMBER        { def_import ($1, $3,  0,  0, $5); }
180        |       ID '.' ID '.' ID            { def_import ( 0, $1, $3, $5, -1); }
181        |       ID '.' ID                   { def_import ( 0, $1,  0, $3, -1); }
182 ;
183 
184 seclist:
185 		seclist secline
186 	|	secline
187 	;
188 
189 secline:
190 	ID attr_list { def_section ($1, $2);}
191 	| ID ID { def_section_alt ($1, $2);}
192 	;
193 
194 attr_list:
195 	attr_list opt_comma attr { $$ = $1 | $3; }
196 	| attr { $$ = $1; }
197 	;
198 
199 opt_comma:
200 	','
201 	|
202 	;
203 opt_number: ',' NUMBER { $$=$2;}
204 	|	   { $$=-1;}
205 	;
206 
207 attr:
208 		READ	{ $$ = 1;}
209 	|	WRITE	{ $$ = 2;}
210 	|	EXECUTE	{ $$=4;}
211 	|	SHARED	{ $$=8;}
212 	;
213 
214 opt_name: ID		{ $$ = $1; }
215 	| ID '.' ID
216 	  {
217 	    char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
218 	    sprintf (name, "%s.%s", $1, $3);
219 	    $$ = name;
220 	  }
221 	|		{ $$ = ""; }
222 	;
223 
224 opt_ordinal:
225 	  '@' NUMBER     { $$ = $2;}
226 	|                { $$ = -1;}
227 	;
228 
229 opt_equal_name:
230           '=' dot_name	{ $$ = $2; }
231         | 		{ $$ =  0; }
232 	;
233 
234 opt_base: BASE	'=' NUMBER	{ $$ = $3;}
235 	|	{ $$ = -1;}
236 	;
237 
238 dot_name: ID		{ $$ = $1; }
239 	| dot_name '.' ID
240 	  {
241 	    char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
242 	    sprintf (name, "%s.%s", $1, $3);
243 	    $$ = name;
244 	  }
245 	;
246 
247 
248 %%
249 
250 /*****************************************************************************
251  API
252  *****************************************************************************/
253 
254 static FILE *the_file;
255 static const char *def_filename;
256 static int linenumber;
257 static def_file *def;
258 static int saw_newline;
259 
260 struct directive
261   {
262     struct directive *next;
263     char *name;
264     int len;
265   };
266 
267 static struct directive *directives = 0;
268 
269 def_file *
270 def_file_empty (void)
271 {
272   def_file *rv = xmalloc (sizeof (def_file));
273   memset (rv, 0, sizeof (def_file));
274   rv->is_dll = -1;
275   rv->base_address = (bfd_vma) -1;
276   rv->stack_reserve = rv->stack_commit = -1;
277   rv->heap_reserve = rv->heap_commit = -1;
278   rv->version_major = rv->version_minor = -1;
279   return rv;
280 }
281 
282 def_file *
283 def_file_parse (const char *filename, def_file *add_to)
284 {
285   struct directive *d;
286 
287   the_file = fopen (filename, "r");
288   def_filename = filename;
289   linenumber = 1;
290   if (!the_file)
291     {
292       perror (filename);
293       return 0;
294     }
295   if (add_to)
296     {
297       def = add_to;
298     }
299   else
300     {
301       def = def_file_empty ();
302     }
303 
304   saw_newline = 1;
305   if (def_parse ())
306     {
307       def_file_free (def);
308       fclose (the_file);
309       return 0;
310     }
311 
312   fclose (the_file);
313 
314   for (d = directives; d; d = d->next)
315     {
316 #if TRACE
317       printf ("Adding directive %08x `%s'\n", d->name, d->name);
318 #endif
319       def_file_add_directive (def, d->name, d->len);
320     }
321 
322   return def;
323 }
324 
325 void
326 def_file_free (def_file *def)
327 {
328   int i;
329 
330   if (!def)
331     return;
332   if (def->name)
333     free (def->name);
334   if (def->description)
335     free (def->description);
336 
337   if (def->section_defs)
338     {
339       for (i = 0; i < def->num_section_defs; i++)
340 	{
341 	  if (def->section_defs[i].name)
342 	    free (def->section_defs[i].name);
343 	  if (def->section_defs[i].class)
344 	    free (def->section_defs[i].class);
345 	}
346       free (def->section_defs);
347     }
348 
349   if (def->exports)
350     {
351       for (i = 0; i < def->num_exports; i++)
352 	{
353 	  if (def->exports[i].internal_name
354 	      && def->exports[i].internal_name != def->exports[i].name)
355 	    free (def->exports[i].internal_name);
356 	  if (def->exports[i].name)
357 	    free (def->exports[i].name);
358 	}
359       free (def->exports);
360     }
361 
362   if (def->imports)
363     {
364       for (i = 0; i < def->num_imports; i++)
365 	{
366 	  if (def->imports[i].internal_name
367 	      && def->imports[i].internal_name != def->imports[i].name)
368 	    free (def->imports[i].internal_name);
369 	  if (def->imports[i].name)
370 	    free (def->imports[i].name);
371 	}
372       free (def->imports);
373     }
374 
375   while (def->modules)
376     {
377       def_file_module *m = def->modules;
378       def->modules = def->modules->next;
379       free (m);
380     }
381 
382   free (def);
383 }
384 
385 #ifdef DEF_FILE_PRINT
386 void
387 def_file_print (FILE *file, def_file *def)
388 {
389   int i;
390 
391   fprintf (file, ">>>> def_file at 0x%08x\n", def);
392   if (def->name)
393     fprintf (file, "  name: %s\n", def->name ? def->name : "(unspecified)");
394   if (def->is_dll != -1)
395     fprintf (file, "  is dll: %s\n", def->is_dll ? "yes" : "no");
396   if (def->base_address != (bfd_vma) -1)
397     fprintf (file, "  base address: 0x%08x\n", def->base_address);
398   if (def->description)
399     fprintf (file, "  description: `%s'\n", def->description);
400   if (def->stack_reserve != -1)
401     fprintf (file, "  stack reserve: 0x%08x\n", def->stack_reserve);
402   if (def->stack_commit != -1)
403     fprintf (file, "  stack commit: 0x%08x\n", def->stack_commit);
404   if (def->heap_reserve != -1)
405     fprintf (file, "  heap reserve: 0x%08x\n", def->heap_reserve);
406   if (def->heap_commit != -1)
407     fprintf (file, "  heap commit: 0x%08x\n", def->heap_commit);
408 
409   if (def->num_section_defs > 0)
410     {
411       fprintf (file, "  section defs:\n");
412 
413       for (i = 0; i < def->num_section_defs; i++)
414 	{
415 	  fprintf (file, "    name: `%s', class: `%s', flags:",
416 		   def->section_defs[i].name, def->section_defs[i].class);
417 	  if (def->section_defs[i].flag_read)
418 	    fprintf (file, " R");
419 	  if (def->section_defs[i].flag_write)
420 	    fprintf (file, " W");
421 	  if (def->section_defs[i].flag_execute)
422 	    fprintf (file, " X");
423 	  if (def->section_defs[i].flag_shared)
424 	    fprintf (file, " S");
425 	  fprintf (file, "\n");
426 	}
427     }
428 
429   if (def->num_exports > 0)
430     {
431       fprintf (file, "  exports:\n");
432 
433       for (i = 0; i < def->num_exports; i++)
434 	{
435 	  fprintf (file, "    name: `%s', int: `%s', ordinal: %d, flags:",
436 		   def->exports[i].name, def->exports[i].internal_name,
437 		   def->exports[i].ordinal);
438 	  if (def->exports[i].flag_private)
439 	    fprintf (file, " P");
440 	  if (def->exports[i].flag_constant)
441 	    fprintf (file, " C");
442 	  if (def->exports[i].flag_noname)
443 	    fprintf (file, " N");
444 	  if (def->exports[i].flag_data)
445 	    fprintf (file, " D");
446 	  fprintf (file, "\n");
447 	}
448     }
449 
450   if (def->num_imports > 0)
451     {
452       fprintf (file, "  imports:\n");
453 
454       for (i = 0; i < def->num_imports; i++)
455 	{
456 	  fprintf (file, "    int: %s, from: `%s', name: `%s', ordinal: %d\n",
457 		   def->imports[i].internal_name,
458 		   def->imports[i].module,
459 		   def->imports[i].name,
460 		   def->imports[i].ordinal);
461 	}
462     }
463 
464   if (def->version_major != -1)
465     fprintf (file, "  version: %d.%d\n", def->version_major, def->version_minor);
466 
467   fprintf (file, "<<<< def_file at 0x%08x\n", def);
468 }
469 #endif
470 
471 def_file_export *
472 def_file_add_export (def_file *def,
473 		     const char *external_name,
474 		     const char *internal_name,
475 		     int ordinal)
476 {
477   def_file_export *e;
478   int max_exports = ROUND_UP(def->num_exports, 32);
479 
480   if (def->num_exports >= max_exports)
481     {
482       max_exports = ROUND_UP(def->num_exports + 1, 32);
483       if (def->exports)
484 	def->exports = xrealloc (def->exports,
485 				 max_exports * sizeof (def_file_export));
486       else
487 	def->exports = xmalloc (max_exports * sizeof (def_file_export));
488     }
489   e = def->exports + def->num_exports;
490   memset (e, 0, sizeof (def_file_export));
491   if (internal_name && !external_name)
492     external_name = internal_name;
493   if (external_name && !internal_name)
494     internal_name = external_name;
495   e->name = xstrdup (external_name);
496   e->internal_name = xstrdup (internal_name);
497   e->ordinal = ordinal;
498   def->num_exports++;
499   return e;
500 }
501 
502 def_file_module *
503 def_get_module (def_file *def, const char *name)
504 {
505   def_file_module *s;
506 
507   for (s = def->modules; s; s = s->next)
508     if (strcmp (s->name, name) == 0)
509       return s;
510 
511   return NULL;
512 }
513 
514 static def_file_module *
515 def_stash_module (def_file *def, const char *name)
516 {
517   def_file_module *s;
518 
519   if ((s = def_get_module (def, name)) != NULL)
520       return s;
521   s = xmalloc (sizeof (def_file_module) + strlen (name));
522   s->next = def->modules;
523   def->modules = s;
524   s->user_data = 0;
525   strcpy (s->name, name);
526   return s;
527 }
528 
529 def_file_import *
530 def_file_add_import (def_file *def,
531 		     const char *name,
532 		     const char *module,
533 		     int ordinal,
534 		     const char *internal_name)
535 {
536   def_file_import *i;
537   int max_imports = ROUND_UP (def->num_imports, 16);
538 
539   if (def->num_imports >= max_imports)
540     {
541       max_imports = ROUND_UP (def->num_imports+1, 16);
542 
543       if (def->imports)
544 	def->imports = xrealloc (def->imports,
545 				 max_imports * sizeof (def_file_import));
546       else
547 	def->imports = xmalloc (max_imports * sizeof (def_file_import));
548     }
549   i = def->imports + def->num_imports;
550   memset (i, 0, sizeof (def_file_import));
551   if (name)
552     i->name = xstrdup (name);
553   if (module)
554     i->module = def_stash_module (def, module);
555   i->ordinal = ordinal;
556   if (internal_name)
557     i->internal_name = xstrdup (internal_name);
558   else
559     i->internal_name = i->name;
560   def->num_imports++;
561 
562   return i;
563 }
564 
565 struct
566 {
567   char *param;
568   int token;
569 }
570 diropts[] =
571 {
572   { "-heap", HEAPSIZE },
573   { "-stack", STACKSIZE },
574   { "-attr", SECTIONS },
575   { "-export", EXPORTS },
576   { 0, 0 }
577 };
578 
579 void
580 def_file_add_directive (def_file *my_def, const char *param, int len)
581 {
582   def_file *save_def = def;
583   const char *pend = param + len;
584   char * tend = (char *) param;
585   int i;
586 
587   def = my_def;
588 
589   while (param < pend)
590     {
591       while (param < pend
592 	     && (ISSPACE (*param) || *param == '\n' || *param == 0))
593 	param++;
594 
595       if (param == pend)
596 	break;
597 
598       /* Scan forward until we encounter any of:
599           - the end of the buffer
600 	  - the start of a new option
601 	  - a newline seperating options
602           - a NUL seperating options.  */
603       for (tend = (char *) (param + 1);
604 	   (tend < pend
605 	    && !(ISSPACE (tend[-1]) && *tend == '-')
606 	    && *tend != '\n' && *tend != 0);
607 	   tend++)
608 	;
609 
610       for (i = 0; diropts[i].param; i++)
611 	{
612 	  int len = strlen (diropts[i].param);
613 
614 	  if (tend - param >= len
615 	      && strncmp (param, diropts[i].param, len) == 0
616 	      && (param[len] == ':' || param[len] == ' '))
617 	    {
618 	      lex_parse_string_end = tend;
619 	      lex_parse_string = param + len + 1;
620 	      lex_forced_token = diropts[i].token;
621 	      saw_newline = 0;
622 	      if (def_parse ())
623 		continue;
624 	      break;
625 	    }
626 	}
627 
628       if (!diropts[i].param)
629 	{
630 	  char saved;
631 
632 	  saved = * tend;
633 	  * tend = 0;
634 	  /* xgettext:c-format */
635 	  einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
636 	  * tend = saved;
637 	}
638 
639       lex_parse_string = 0;
640       param = tend;
641     }
642 
643   def = save_def;
644 }
645 
646 /* Parser Callbacks.  */
647 
648 static void
649 def_image_name (const char *name, int base, int is_dll)
650 {
651   /* If a LIBRARY or NAME statement is specified without a name, there is nothing
652      to do here.  We retain the output filename specified on command line.  */
653   if (*name)
654     {
655       const char* image_name = lbasename (name);
656       if (image_name != name)
657 	einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
658 	       def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
659 	       name);
660       if (def->name)
661 	free (def->name);
662       /* Append the default suffix, if none specified.  */
663       if (strchr (image_name, '.') == 0)
664 	{
665 	  const char * suffix = is_dll ? ".dll" : ".exe";
666 
667 	  def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
668 	  sprintf (def->name, "%s%s", image_name, suffix);
669         }
670       else
671 	def->name = xstrdup (image_name);
672     }
673 
674   /* Honor a BASE address statement, even if LIBRARY string is empty.  */
675   def->base_address = base;
676   def->is_dll = is_dll;
677 }
678 
679 static void
680 def_description (const char *text)
681 {
682   int len = def->description ? strlen (def->description) : 0;
683 
684   len += strlen (text) + 1;
685   if (def->description)
686     {
687       def->description = xrealloc (def->description, len);
688       strcat (def->description, text);
689     }
690   else
691     {
692       def->description = xmalloc (len);
693       strcpy (def->description, text);
694     }
695 }
696 
697 static void
698 def_stacksize (int reserve, int commit)
699 {
700   def->stack_reserve = reserve;
701   def->stack_commit = commit;
702 }
703 
704 static void
705 def_heapsize (int reserve, int commit)
706 {
707   def->heap_reserve = reserve;
708   def->heap_commit = commit;
709 }
710 
711 static void
712 def_section (const char *name, int attr)
713 {
714   def_file_section *s;
715   int max_sections = ROUND_UP (def->num_section_defs, 4);
716 
717   if (def->num_section_defs >= max_sections)
718     {
719       max_sections = ROUND_UP (def->num_section_defs+1, 4);
720 
721       if (def->section_defs)
722 	def->section_defs = xrealloc (def->section_defs,
723 				      max_sections * sizeof (def_file_import));
724       else
725 	def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
726     }
727   s = def->section_defs + def->num_section_defs;
728   memset (s, 0, sizeof (def_file_section));
729   s->name = xstrdup (name);
730   if (attr & 1)
731     s->flag_read = 1;
732   if (attr & 2)
733     s->flag_write = 1;
734   if (attr & 4)
735     s->flag_execute = 1;
736   if (attr & 8)
737     s->flag_shared = 1;
738 
739   def->num_section_defs++;
740 }
741 
742 static void
743 def_section_alt (const char *name, const char *attr)
744 {
745   int aval = 0;
746 
747   for (; *attr; attr++)
748     {
749       switch (*attr)
750 	{
751 	case 'R':
752 	case 'r':
753 	  aval |= 1;
754 	  break;
755 	case 'W':
756 	case 'w':
757 	  aval |= 2;
758 	  break;
759 	case 'X':
760 	case 'x':
761 	  aval |= 4;
762 	  break;
763 	case 'S':
764 	case 's':
765 	  aval |= 8;
766 	  break;
767 	}
768     }
769   def_section (name, aval);
770 }
771 
772 static void
773 def_exports (const char *external_name,
774 	     const char *internal_name,
775 	     int ordinal,
776 	     int flags)
777 {
778   def_file_export *dfe;
779 
780   if (!internal_name && external_name)
781     internal_name = external_name;
782 #if TRACE
783   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
784 #endif
785 
786   dfe = def_file_add_export (def, external_name, internal_name, ordinal);
787   if (flags & 1)
788     dfe->flag_noname = 1;
789   if (flags & 2)
790     dfe->flag_constant = 1;
791   if (flags & 4)
792     dfe->flag_data = 1;
793   if (flags & 8)
794     dfe->flag_private = 1;
795 }
796 
797 static void
798 def_import (const char *internal_name,
799 	    const char *module,
800 	    const char *dllext,
801 	    const char *name,
802 	    int ordinal)
803 {
804   char *buf = 0;
805   const char *ext = dllext ? dllext : "dll";
806 
807   buf = xmalloc (strlen (module) + strlen (ext) + 2);
808   sprintf (buf, "%s.%s", module, ext);
809   module = buf;
810 
811   def_file_add_import (def, name, module, ordinal, internal_name);
812   if (buf)
813     free (buf);
814 }
815 
816 static void
817 def_version (int major, int minor)
818 {
819   def->version_major = major;
820   def->version_minor = minor;
821 }
822 
823 static void
824 def_directive (char *str)
825 {
826   struct directive *d = xmalloc (sizeof (struct directive));
827 
828   d->next = directives;
829   directives = d;
830   d->name = xstrdup (str);
831   d->len = strlen (str);
832 }
833 
834 static int
835 def_error (const char *err)
836 {
837   einfo ("%P: %s:%d: %s\n",
838 	 def_filename ? def_filename : "<unknown-file>", linenumber, err);
839   return 0;
840 }
841 
842 
843 /* Lexical Scanner.  */
844 
845 #undef TRACE
846 #define TRACE 0
847 
848 /* Never freed, but always reused as needed, so no real leak.  */
849 static char *buffer = 0;
850 static int buflen = 0;
851 static int bufptr = 0;
852 
853 static void
854 put_buf (char c)
855 {
856   if (bufptr == buflen)
857     {
858       buflen += 50;		/* overly reasonable, eh?  */
859       if (buffer)
860 	buffer = xrealloc (buffer, buflen + 1);
861       else
862 	buffer = xmalloc (buflen + 1);
863     }
864   buffer[bufptr++] = c;
865   buffer[bufptr] = 0;		/* not optimal, but very convenient.  */
866 }
867 
868 static struct
869 {
870   char *name;
871   int token;
872 }
873 tokens[] =
874 {
875   { "BASE", BASE },
876   { "CODE", CODE },
877   { "CONSTANT", CONSTANTU },
878   { "constant", CONSTANTL },
879   { "DATA", DATAU },
880   { "data", DATAL },
881   { "DESCRIPTION", DESCRIPTION },
882   { "DIRECTIVE", DIRECTIVE },
883   { "EXECUTE", EXECUTE },
884   { "EXPORTS", EXPORTS },
885   { "HEAPSIZE", HEAPSIZE },
886   { "IMPORTS", IMPORTS },
887   { "LIBRARY", LIBRARY },
888   { "NAME", NAME },
889   { "NONAME", NONAMEU },
890   { "noname", NONAMEL },
891   { "PRIVATE", PRIVATEU },
892   { "private", PRIVATEL },
893   { "READ", READ },
894   { "SECTIONS", SECTIONS },
895   { "SEGMENTS", SECTIONS },
896   { "SHARED", SHARED },
897   { "STACKSIZE", STACKSIZE },
898   { "VERSION", VERSIONK },
899   { "WRITE", WRITE },
900   { 0, 0 }
901 };
902 
903 static int
904 def_getc (void)
905 {
906   int rv;
907 
908   if (lex_parse_string)
909     {
910       if (lex_parse_string >= lex_parse_string_end)
911 	rv = EOF;
912       else
913 	rv = *lex_parse_string++;
914     }
915   else
916     {
917       rv = fgetc (the_file);
918     }
919   if (rv == '\n')
920     saw_newline = 1;
921   return rv;
922 }
923 
924 static int
925 def_ungetc (int c)
926 {
927   if (lex_parse_string)
928     {
929       lex_parse_string--;
930       return c;
931     }
932   else
933     return ungetc (c, the_file);
934 }
935 
936 static int
937 def_lex (void)
938 {
939   int c, i, q;
940 
941   if (lex_forced_token)
942     {
943       i = lex_forced_token;
944       lex_forced_token = 0;
945 #if TRACE
946       printf ("lex: forcing token %d\n", i);
947 #endif
948       return i;
949     }
950 
951   c = def_getc ();
952 
953   /* Trim leading whitespace.  */
954   while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
955     c = def_getc ();
956 
957   if (c == EOF)
958     {
959 #if TRACE
960       printf ("lex: EOF\n");
961 #endif
962       return 0;
963     }
964 
965   if (saw_newline && c == ';')
966     {
967       do
968 	{
969 	  c = def_getc ();
970 	}
971       while (c != EOF && c != '\n');
972       if (c == '\n')
973 	return def_lex ();
974       return 0;
975     }
976 
977   /* Must be something else.  */
978   saw_newline = 0;
979 
980   if (ISDIGIT (c))
981     {
982       bufptr = 0;
983       while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
984 	{
985 	  put_buf (c);
986 	  c = def_getc ();
987 	}
988       if (c != EOF)
989 	def_ungetc (c);
990       yylval.number = strtoul (buffer, 0, 0);
991 #if TRACE
992       printf ("lex: `%s' returns NUMBER %d\n", buffer, yylval.number);
993 #endif
994       return NUMBER;
995     }
996 
997   if (ISALPHA (c) || strchr ("$:-_?@", c))
998     {
999       bufptr = 0;
1000       q = c;
1001       put_buf (c);
1002       c = def_getc ();
1003 
1004       if (q == '@')
1005 	{
1006           if (ISBLANK (c) ) /* '@' followed by whitespace.  */
1007 	    return (q);
1008           else if (ISDIGIT (c)) /* '@' followed by digit.  */
1009             {
1010 	      def_ungetc (c);
1011               return (q);
1012 	    }
1013 #if TRACE
1014 	  printf ("lex: @ returns itself\n");
1015 #endif
1016 	}
1017 
1018       while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@", c)))
1019 	{
1020 	  put_buf (c);
1021 	  c = def_getc ();
1022 	}
1023       if (c != EOF)
1024 	def_ungetc (c);
1025       if (ISALPHA (q)) /* Check for tokens.  */
1026 	{
1027           for (i = 0; tokens[i].name; i++)
1028 	    if (strcmp (tokens[i].name, buffer) == 0)
1029 	      {
1030 #if TRACE
1031 	        printf ("lex: `%s' is a string token\n", buffer);
1032 #endif
1033 	        return tokens[i].token;
1034 	      }
1035 	}
1036 #if TRACE
1037       printf ("lex: `%s' returns ID\n", buffer);
1038 #endif
1039       yylval.id = xstrdup (buffer);
1040       return ID;
1041     }
1042 
1043   if (c == '\'' || c == '"')
1044     {
1045       q = c;
1046       c = def_getc ();
1047       bufptr = 0;
1048 
1049       while (c != EOF && c != q)
1050 	{
1051 	  put_buf (c);
1052 	  c = def_getc ();
1053 	}
1054       yylval.id = xstrdup (buffer);
1055 #if TRACE
1056       printf ("lex: `%s' returns ID\n", buffer);
1057 #endif
1058       return ID;
1059     }
1060 
1061   if (c == '=' || c == '.' || c == ',')
1062     {
1063 #if TRACE
1064       printf ("lex: `%c' returns itself\n", c);
1065 #endif
1066       return c;
1067     }
1068 
1069   if (c == '\n')
1070     {
1071       linenumber++;
1072       saw_newline = 1;
1073     }
1074 
1075   /*printf ("lex: 0x%02x ignored\n", c); */
1076   return def_lex ();
1077 }
1078