]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/binutils/ld/deffilep.y
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / binutils / ld / deffilep.y
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 *
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 *
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
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
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 *
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 *
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 *
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 *
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
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
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
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
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
688 def_stacksize (int reserve, int commit)
689 {
690   def->stack_reserve = reserve;
691   def->stack_commit = commit;
692 }
693
694 static void
695 def_heapsize (int reserve, int commit)
696 {
697   def->heap_reserve = reserve;
698   def->heap_commit = commit;
699 }
700
701 static void
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
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
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
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
807 def_version (int major, int minor)
808 {
809   def->version_major = major;
810   def->version_minor = minor;
811 }
812
813 static void
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
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
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
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
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
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 }