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