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