1 %{ /* deffilep.y - parser for .def files */
2 
3 /*   Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21 
22 #include <stdio.h>
23 #include "libiberty.h"
24 #include "safe-ctype.h"
25 #include "bfd.h"
26 #include "sysdep.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 *
def_file_empty(void)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 *
def_file_parse(const char * filename,def_file * add_to)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
def_file_free(def_file * def)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
def_file_print(FILE * file,def_file * def)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 *
def_file_add_export(def_file * def,const char * external_name,const char * internal_name,int ordinal)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 *
def_get_module(def_file * def,const char * name)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 *
def_stash_module(def_file * def,const char * name)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 *
def_file_add_import(def_file * def,const char * name,const char * module,int ordinal,const char * internal_name)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
def_file_add_directive(def_file * my_def,const char * param,int len)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
def_image_name(const char * name,int base,int is_dll)649 def_image_name (const char *name, int base, int is_dll)
650 {
651   const char* image_name = lbasename (name);
652   if (image_name != name)
653     einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
654 	  def_filename, linenumber, is_dll ? "LIBRARY" : "NAME", name);
655   if (def->name)
656     free (def->name);
657   def->name = xstrdup (image_name);
658   def->base_address = base;
659   def->is_dll = is_dll;
660 }
661 
662 static void
def_description(const char * text)663 def_description (const char *text)
664 {
665   int len = def->description ? strlen (def->description) : 0;
666 
667   len += strlen (text) + 1;
668   if (def->description)
669     {
670       def->description = xrealloc (def->description, len);
671       strcat (def->description, text);
672     }
673   else
674     {
675       def->description = xmalloc (len);
676       strcpy (def->description, text);
677     }
678 }
679 
680 static void
def_stacksize(int reserve,int commit)681 def_stacksize (int reserve, int commit)
682 {
683   def->stack_reserve = reserve;
684   def->stack_commit = commit;
685 }
686 
687 static void
def_heapsize(int reserve,int commit)688 def_heapsize (int reserve, int commit)
689 {
690   def->heap_reserve = reserve;
691   def->heap_commit = commit;
692 }
693 
694 static void
def_section(const char * name,int attr)695 def_section (const char *name, int attr)
696 {
697   def_file_section *s;
698   int max_sections = ROUND_UP (def->num_section_defs, 4);
699 
700   if (def->num_section_defs >= max_sections)
701     {
702       max_sections = ROUND_UP (def->num_section_defs+1, 4);
703 
704       if (def->section_defs)
705 	def->section_defs = xrealloc (def->section_defs,
706 				      max_sections * sizeof (def_file_import));
707       else
708 	def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
709     }
710   s = def->section_defs + def->num_section_defs;
711   memset (s, 0, sizeof (def_file_section));
712   s->name = xstrdup (name);
713   if (attr & 1)
714     s->flag_read = 1;
715   if (attr & 2)
716     s->flag_write = 1;
717   if (attr & 4)
718     s->flag_execute = 1;
719   if (attr & 8)
720     s->flag_shared = 1;
721 
722   def->num_section_defs++;
723 }
724 
725 static void
def_section_alt(const char * name,const char * attr)726 def_section_alt (const char *name, const char *attr)
727 {
728   int aval = 0;
729 
730   for (; *attr; attr++)
731     {
732       switch (*attr)
733 	{
734 	case 'R':
735 	case 'r':
736 	  aval |= 1;
737 	  break;
738 	case 'W':
739 	case 'w':
740 	  aval |= 2;
741 	  break;
742 	case 'X':
743 	case 'x':
744 	  aval |= 4;
745 	  break;
746 	case 'S':
747 	case 's':
748 	  aval |= 8;
749 	  break;
750 	}
751     }
752   def_section (name, aval);
753 }
754 
755 static void
def_exports(const char * external_name,const char * internal_name,int ordinal,int flags)756 def_exports (const char *external_name,
757 	     const char *internal_name,
758 	     int ordinal,
759 	     int flags)
760 {
761   def_file_export *dfe;
762 
763   if (!internal_name && external_name)
764     internal_name = external_name;
765 #if TRACE
766   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
767 #endif
768 
769   dfe = def_file_add_export (def, external_name, internal_name, ordinal);
770   if (flags & 1)
771     dfe->flag_noname = 1;
772   if (flags & 2)
773     dfe->flag_constant = 1;
774   if (flags & 4)
775     dfe->flag_data = 1;
776   if (flags & 8)
777     dfe->flag_private = 1;
778 }
779 
780 static void
def_import(const char * internal_name,const char * module,const char * dllext,const char * name,int ordinal)781 def_import (const char *internal_name,
782 	    const char *module,
783 	    const char *dllext,
784 	    const char *name,
785 	    int ordinal)
786 {
787   char *buf = 0;
788   const char *ext = dllext ? dllext : "dll";
789 
790   buf = xmalloc (strlen (module) + strlen (ext) + 2);
791   sprintf (buf, "%s.%s", module, ext);
792   module = buf;
793 
794   def_file_add_import (def, name, module, ordinal, internal_name);
795   if (buf)
796     free (buf);
797 }
798 
799 static void
def_version(int major,int minor)800 def_version (int major, int minor)
801 {
802   def->version_major = major;
803   def->version_minor = minor;
804 }
805 
806 static void
def_directive(char * str)807 def_directive (char *str)
808 {
809   struct directive *d = xmalloc (sizeof (struct directive));
810 
811   d->next = directives;
812   directives = d;
813   d->name = xstrdup (str);
814   d->len = strlen (str);
815 }
816 
817 static int
def_error(const char * err)818 def_error (const char *err)
819 {
820   einfo ("%P: %s:%d: %s\n",
821 	 def_filename ? def_filename : "<unknown-file>", linenumber, err);
822   return 0;
823 }
824 
825 
826 /* Lexical Scanner.  */
827 
828 #undef TRACE
829 #define TRACE 0
830 
831 /* Never freed, but always reused as needed, so no real leak.  */
832 static char *buffer = 0;
833 static int buflen = 0;
834 static int bufptr = 0;
835 
836 static void
put_buf(char c)837 put_buf (char c)
838 {
839   if (bufptr == buflen)
840     {
841       buflen += 50;		/* overly reasonable, eh?  */
842       if (buffer)
843 	buffer = xrealloc (buffer, buflen + 1);
844       else
845 	buffer = xmalloc (buflen + 1);
846     }
847   buffer[bufptr++] = c;
848   buffer[bufptr] = 0;		/* not optimal, but very convenient.  */
849 }
850 
851 static struct
852 {
853   char *name;
854   int token;
855 }
856 tokens[] =
857 {
858   { "BASE", BASE },
859   { "CODE", CODE },
860   { "CONSTANT", CONSTANTU },
861   { "constant", CONSTANTL },
862   { "DATA", DATAU },
863   { "data", DATAL },
864   { "DESCRIPTION", DESCRIPTION },
865   { "DIRECTIVE", DIRECTIVE },
866   { "EXECUTE", EXECUTE },
867   { "EXPORTS", EXPORTS },
868   { "HEAPSIZE", HEAPSIZE },
869   { "IMPORTS", IMPORTS },
870   { "LIBRARY", LIBRARY },
871   { "NAME", NAME },
872   { "NONAME", NONAMEU },
873   { "noname", NONAMEL },
874   { "PRIVATE", PRIVATEU },
875   { "private", PRIVATEL },
876   { "READ", READ },
877   { "SECTIONS", SECTIONS },
878   { "SEGMENTS", SECTIONS },
879   { "SHARED", SHARED },
880   { "STACKSIZE", STACKSIZE },
881   { "VERSION", VERSIONK },
882   { "WRITE", WRITE },
883   { 0, 0 }
884 };
885 
886 static int
def_getc(void)887 def_getc (void)
888 {
889   int rv;
890 
891   if (lex_parse_string)
892     {
893       if (lex_parse_string >= lex_parse_string_end)
894 	rv = EOF;
895       else
896 	rv = *lex_parse_string++;
897     }
898   else
899     {
900       rv = fgetc (the_file);
901     }
902   if (rv == '\n')
903     saw_newline = 1;
904   return rv;
905 }
906 
907 static int
def_ungetc(int c)908 def_ungetc (int c)
909 {
910   if (lex_parse_string)
911     {
912       lex_parse_string--;
913       return c;
914     }
915   else
916     return ungetc (c, the_file);
917 }
918 
919 static int
def_lex(void)920 def_lex (void)
921 {
922   int c, i, q;
923 
924   if (lex_forced_token)
925     {
926       i = lex_forced_token;
927       lex_forced_token = 0;
928 #if TRACE
929       printf ("lex: forcing token %d\n", i);
930 #endif
931       return i;
932     }
933 
934   c = def_getc ();
935 
936   /* Trim leading whitespace.  */
937   while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
938     c = def_getc ();
939 
940   if (c == EOF)
941     {
942 #if TRACE
943       printf ("lex: EOF\n");
944 #endif
945       return 0;
946     }
947 
948   if (saw_newline && c == ';')
949     {
950       do
951 	{
952 	  c = def_getc ();
953 	}
954       while (c != EOF && c != '\n');
955       if (c == '\n')
956 	return def_lex ();
957       return 0;
958     }
959 
960   /* Must be something else.  */
961   saw_newline = 0;
962 
963   if (ISDIGIT (c))
964     {
965       bufptr = 0;
966       while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
967 	{
968 	  put_buf (c);
969 	  c = def_getc ();
970 	}
971       if (c != EOF)
972 	def_ungetc (c);
973       yylval.number = strtoul (buffer, 0, 0);
974 #if TRACE
975       printf ("lex: `%s' returns NUMBER %d\n", buffer, yylval.number);
976 #endif
977       return NUMBER;
978     }
979 
980   if (ISALPHA (c) || strchr ("$:-_?@", c))
981     {
982       bufptr = 0;
983       q = c;
984       put_buf (c);
985       c = def_getc ();
986 
987       if (q == '@')
988 	{
989           if (ISBLANK (c) ) /* '@' followed by whitespace.  */
990 	    return (q);
991           else if (ISDIGIT (c)) /* '@' followed by digit.  */
992             {
993 	      def_ungetc (c);
994               return (q);
995 	    }
996 #if TRACE
997 	  printf ("lex: @ returns itself\n");
998 #endif
999 	}
1000 
1001       while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@", c)))
1002 	{
1003 	  put_buf (c);
1004 	  c = def_getc ();
1005 	}
1006       if (c != EOF)
1007 	def_ungetc (c);
1008       if (ISALPHA (q)) /* Check for tokens.  */
1009 	{
1010           for (i = 0; tokens[i].name; i++)
1011 	    if (strcmp (tokens[i].name, buffer) == 0)
1012 	      {
1013 #if TRACE
1014 	        printf ("lex: `%s' is a string token\n", buffer);
1015 #endif
1016 	        return tokens[i].token;
1017 	      }
1018 	}
1019 #if TRACE
1020       printf ("lex: `%s' returns ID\n", buffer);
1021 #endif
1022       yylval.id = xstrdup (buffer);
1023       return ID;
1024     }
1025 
1026   if (c == '\'' || c == '"')
1027     {
1028       q = c;
1029       c = def_getc ();
1030       bufptr = 0;
1031 
1032       while (c != EOF && c != q)
1033 	{
1034 	  put_buf (c);
1035 	  c = def_getc ();
1036 	}
1037       yylval.id = xstrdup (buffer);
1038 #if TRACE
1039       printf ("lex: `%s' returns ID\n", buffer);
1040 #endif
1041       return ID;
1042     }
1043 
1044   if (c == '=' || c == '.' || c == ',')
1045     {
1046 #if TRACE
1047       printf ("lex: `%c' returns itself\n", c);
1048 #endif
1049       return c;
1050     }
1051 
1052   if (c == '\n')
1053     {
1054       linenumber++;
1055       saw_newline = 1;
1056     }
1057 
1058   /*printf ("lex: 0x%02x ignored\n", c); */
1059   return def_lex ();
1060 }
1061