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