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
81static void def_description (const char *);
82static void def_exports (const char *, const char *, int, int);
83static void def_heapsize (int, int);
84static void def_import (const char *, const char *, const char *, const char *,
85			int);
86static void def_library (const char *, int);
87static void def_name (const char *, int);
88static void def_section (const char *, int);
89static void def_section_alt (const char *, const char *);
90static void def_stacksize (int, int);
91static void def_version (int, int);
92static void def_directive (char *);
93static int def_parse (void);
94static int def_error (const char *);
95static int def_lex (void);
96
97static int lex_forced_token = 0;
98static const char *lex_parse_string = 0;
99static 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
120start: start command
121	| command
122	;
123
124command:
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
141explist:
142		/* EMPTY */
143	|	expline
144	|	explist expline
145	;
146
147expline:
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	;
154exp_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	;
161exp_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	;
171implist:
172		implist impline
173	|	impline
174	;
175
176impline:
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
185seclist:
186		seclist secline
187	|	secline
188	;
189
190secline:
191	ID attr_list { def_section ($1, $2);}
192	| ID ID { def_section_alt ($1, $2);}
193	;
194
195attr_list:
196	attr_list opt_comma attr { $$ = $1 | $3; }
197	| attr { $$ = $1; }
198	;
199
200opt_comma:
201	','
202	|
203	;
204opt_number: ',' NUMBER { $$=$2;}
205	|	   { $$=-1;}
206	;
207
208attr:
209		READ	{ $$ = 1;}
210	|	WRITE	{ $$ = 2;}
211	|	EXECUTE	{ $$=4;}
212	|	SHARED	{ $$=8;}
213	;
214
215opt_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
225opt_ordinal:
226	  '@' NUMBER     { $$ = $2;}
227	|                { $$ = -1;}
228	;
229
230opt_equal_name:
231          '=' dot_name	{ $$ = $2; }
232        | 		{ $$ =  0; }
233	;
234
235opt_base: BASE	'=' NUMBER	{ $$ = $3;}
236	|	{ $$ = -1;}
237	;
238
239dot_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
255static FILE *the_file;
256static const char *def_filename;
257static int linenumber;
258static def_file *def;
259static int saw_newline;
260
261struct directive
262  {
263    struct directive *next;
264    char *name;
265    int len;
266  };
267
268static struct directive *directives = 0;
269
270def_file *
271def_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
283def_file *
284def_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
326void
327def_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
387void
388def_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
472def_file_export *
473def_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
503def_file_module *
504def_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
515static def_file_module *
516def_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
530def_file_import *
531def_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
566struct
567{
568  char *param;
569  int token;
570}
571diropts[] =
572{
573  { "-heap", HEAPSIZE },
574  { "-stack", STACKSIZE },
575  { "-attr", SECTIONS },
576  { "-export", EXPORTS },
577  { 0, 0 }
578};
579
580void
581def_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
649static void
650def_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
659static void
660def_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
669static void
670def_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
687static void
688def_stacksize (int reserve, int commit)
689{
690  def->stack_reserve = reserve;
691  def->stack_commit = commit;
692}
693
694static void
695def_heapsize (int reserve, int commit)
696{
697  def->heap_reserve = reserve;
698  def->heap_commit = commit;
699}
700
701static void
702def_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
732static void
733def_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
762static void
763def_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
787static void
788def_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
806static void
807def_version (int major, int minor)
808{
809  def->version_major = major;
810  def->version_minor = minor;
811}
812
813static void
814def_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
824static int
825def_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.  */
839static char *buffer = 0;
840static int buflen = 0;
841static int bufptr = 0;
842
843static void
844put_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
858static struct
859{
860  char *name;
861  int token;
862}
863tokens[] =
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
893static int
894def_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
914static int
915def_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
926static int
927def_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