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