This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / binutils / nlmheader.y
1 %{/* nlmheader.y - parse NLM header specification keywords.
2      Copyright (C) 1993, 94, 95, 97, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 /* Written by Ian Lance Taylor <ian@cygnus.com>.
21
22    This bison file parses the commands recognized by the NetWare NLM
23    linker, except for lists of object files.  It stores the
24    information in global variables.
25
26    This implementation is based on the description in the NetWare Tool
27    Maker Specification manual, edition 1.0.  */
28
29 #include <ansidecl.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include "bfd.h"
33 #include "bucomm.h"
34 #include "nlm/common.h"
35 #include "nlm/internal.h"
36 #include "nlmconv.h"
37
38 /* Information is stored in the structures pointed to by these
39    variables.  */
40
41 Nlm_Internal_Fixed_Header *fixed_hdr;
42 Nlm_Internal_Variable_Header *var_hdr;
43 Nlm_Internal_Version_Header *version_hdr;
44 Nlm_Internal_Copyright_Header *copyright_hdr;
45 Nlm_Internal_Extended_Header *extended_hdr;
46
47 /* Procedure named by CHECK.  */
48 char *check_procedure;
49 /* File named by CUSTOM.  */
50 char *custom_file;
51 /* Whether to generate debugging information (DEBUG).  */
52 boolean debug_info;
53 /* Procedure named by EXIT.  */
54 char *exit_procedure;
55 /* Exported symbols (EXPORT).  */
56 struct string_list *export_symbols;
57 /* List of files from INPUT.  */
58 struct string_list *input_files;
59 /* Map file name (MAP, FULLMAP).  */
60 char *map_file;
61 /* Whether a full map has been requested (FULLMAP).  */
62 boolean full_map;
63 /* File named by HELP.  */
64 char *help_file;
65 /* Imported symbols (IMPORT).  */
66 struct string_list *import_symbols;
67 /* File named by MESSAGES.  */
68 char *message_file;
69 /* Autoload module list (MODULE).  */
70 struct string_list *modules;
71 /* File named by OUTPUT.  */
72 char *output_file;
73 /* File named by SHARELIB.  */
74 char *sharelib_file;
75 /* Start procedure name (START).  */
76 char *start_procedure;
77 /* VERBOSE.  */
78 boolean verbose;
79 /* RPC description file (XDCDATA).  */
80 char *rpc_file;
81
82 /* The number of serious errors that have occurred.  */
83 int parse_errors;
84
85 /* The current symbol prefix when reading a list of import or export
86    symbols.  */
87 static char *symbol_prefix;
88
89 /* Parser error message handler.  */
90 #define yyerror(msg) nlmheader_error (msg);
91
92 /* Local functions.  */
93 static int yylex PARAMS ((void));
94 static void nlmlex_file_push PARAMS ((const char *));
95 static boolean nlmlex_file_open PARAMS ((const char *));
96 static int nlmlex_buf_init PARAMS ((void));
97 static char nlmlex_buf_add PARAMS ((int));
98 static long nlmlex_get_number PARAMS ((const char *));
99 static void nlmheader_identify PARAMS ((void));
100 static void nlmheader_warn PARAMS ((const char *, int));
101 static void nlmheader_error PARAMS ((const char *));
102 static struct string_list * string_list_cons PARAMS ((char *,
103                                                       struct string_list *));
104 static struct string_list * string_list_append PARAMS ((struct string_list *,
105                                                         struct string_list *));
106 static struct string_list * string_list_append1 PARAMS ((struct string_list *,
107                                                          char *));
108 static char *xstrdup PARAMS ((const char *));
109
110 %}
111
112 %union
113 {
114   char *string;
115   struct string_list *list;
116 };
117
118 /* The reserved words.  */
119
120 %token CHECK CODESTART COPYRIGHT CUSTOM DATE DEBUG DESCRIPTION EXIT
121 %token EXPORT FLAG_ON FLAG_OFF FULLMAP HELP IMPORT INPUT MAP MESSAGES
122 %token MODULE MULTIPLE OS_DOMAIN OUTPUT PSEUDOPREEMPTION REENTRANT
123 %token SCREENNAME SHARELIB STACK START SYNCHRONIZE
124 %token THREADNAME TYPE VERBOSE VERSIONK XDCDATA
125
126 /* Arguments.  */
127
128 %token <string> STRING
129 %token <string> QUOTED_STRING
130
131 /* Typed non-terminals.  */
132 %type <list> symbol_list_opt symbol_list string_list
133 %type <string> symbol
134
135 %%
136
137 /* Keywords must start in the leftmost column of the file.  Arguments
138    may appear anywhere else.  The lexer uses this to determine what
139    token to return, so we don't have to worry about it here.  */
140
141 /* The entire file is just a list of commands.  */
142
143 file:   
144           commands
145         ;
146
147 /* A possibly empty list of commands.  */
148
149 commands:
150           /* May be empty.  */
151         | command commands
152         ;
153
154 /* A single command.  There is where most of the work takes place.  */
155
156 command:
157           CHECK STRING
158           {
159             check_procedure = $2;
160           }
161         | CODESTART STRING
162           {
163             nlmheader_warn (_("CODESTART is not implemented; sorry"), -1);
164             free ($2);
165           }
166         | COPYRIGHT QUOTED_STRING
167           {
168             int len;
169
170             strncpy (copyright_hdr->stamp, "CoPyRiGhT=", 10);
171             len = strlen ($2);
172             if (len >= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH)
173               {
174                 nlmheader_warn (_("copyright string is too long"),
175                                 NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1);
176                 len = NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1;
177               }
178             copyright_hdr->copyrightMessageLength = len;
179             strncpy (copyright_hdr->copyrightMessage, $2, len);
180             copyright_hdr->copyrightMessage[len] = '\0';
181             free ($2);
182           }
183         | CUSTOM STRING
184           {
185             custom_file = $2;
186           }
187         | DATE STRING STRING STRING
188           {
189             /* We don't set the version stamp here, because we use the
190                version stamp to detect whether the required VERSION
191                keyword was given.  */
192             version_hdr->month = nlmlex_get_number ($2);
193             version_hdr->day = nlmlex_get_number ($3);
194             version_hdr->year = nlmlex_get_number ($4);
195             free ($2);
196             free ($3);
197             free ($4);
198             if (version_hdr->month < 1 || version_hdr->month > 12)
199               nlmheader_warn (_("illegal month"), -1);
200             if (version_hdr->day < 1 || version_hdr->day > 31)
201               nlmheader_warn (_("illegal day"), -1);
202             if (version_hdr->year < 1900 || version_hdr->year > 3000)
203               nlmheader_warn (_("illegal year"), -1);
204           }
205         | DEBUG
206           {
207             debug_info = true;
208           }
209         | DESCRIPTION QUOTED_STRING
210           {
211             int len;
212
213             len = strlen ($2);
214             if (len > NLM_MAX_DESCRIPTION_LENGTH)
215               {
216                 nlmheader_warn (_("description string is too long"),
217                                 NLM_MAX_DESCRIPTION_LENGTH);
218                 len = NLM_MAX_DESCRIPTION_LENGTH;
219               }
220             var_hdr->descriptionLength = len;
221             strncpy (var_hdr->descriptionText, $2, len);
222             var_hdr->descriptionText[len] = '\0';
223             free ($2);
224           }
225         | EXIT STRING
226           {
227             exit_procedure = $2;
228           }
229         | EXPORT
230           {
231             symbol_prefix = NULL;
232           }
233           symbol_list_opt
234           {
235             export_symbols = string_list_append (export_symbols, $3);
236           }
237         | FLAG_ON STRING
238           {
239             fixed_hdr->flags |= nlmlex_get_number ($2);
240             free ($2);
241           }
242         | FLAG_OFF STRING
243           {
244             fixed_hdr->flags &=~ nlmlex_get_number ($2);
245             free ($2);
246           }
247         | FULLMAP
248           {
249             map_file = "";
250             full_map = true;
251           }
252         | FULLMAP STRING
253           {
254             map_file = $2;
255             full_map = true;
256           }
257         | HELP STRING
258           {
259             help_file = $2;
260           }
261         | IMPORT
262           {
263             symbol_prefix = NULL;
264           }
265           symbol_list_opt
266           {
267             import_symbols = string_list_append (import_symbols, $3);
268           }
269         | INPUT string_list
270           {
271             input_files = string_list_append (input_files, $2);
272           }
273         | MAP
274           {
275             map_file = "";
276           }
277         | MAP STRING
278           {
279             map_file = $2;
280           }
281         | MESSAGES STRING
282           {
283             message_file = $2;
284           }
285         | MODULE string_list
286           {
287             modules = string_list_append (modules, $2);
288           }
289         | MULTIPLE
290           {
291             fixed_hdr->flags |= 0x2;
292           }
293         | OS_DOMAIN
294           {
295             fixed_hdr->flags |= 0x10;
296           }
297         | OUTPUT STRING
298           {
299             if (output_file == NULL)
300               output_file = $2;
301             else
302               nlmheader_warn (_("ignoring duplicate OUTPUT statement"), -1);
303           }
304         | PSEUDOPREEMPTION
305           {
306             fixed_hdr->flags |= 0x8;
307           }
308         | REENTRANT
309           {
310             fixed_hdr->flags |= 0x1;
311           }
312         | SCREENNAME QUOTED_STRING
313           {
314             int len;
315
316             len = strlen ($2);
317             if (len >= NLM_MAX_SCREEN_NAME_LENGTH)
318               {
319                 nlmheader_warn (_("screen name is too long"),
320                                 NLM_MAX_SCREEN_NAME_LENGTH);
321                 len = NLM_MAX_SCREEN_NAME_LENGTH;
322               }
323             var_hdr->screenNameLength = len;
324             strncpy (var_hdr->screenName, $2, len);
325             var_hdr->screenName[NLM_MAX_SCREEN_NAME_LENGTH] = '\0';
326             free ($2);
327           }
328         | SHARELIB STRING
329           {
330             sharelib_file = $2;
331           }
332         | STACK STRING
333           {
334             var_hdr->stackSize = nlmlex_get_number ($2);
335             free ($2);
336           }
337         | START STRING
338           {
339             start_procedure = $2;
340           }
341         | SYNCHRONIZE
342           {
343             fixed_hdr->flags |= 0x4;
344           }
345         | THREADNAME QUOTED_STRING
346           {
347             int len;
348
349             len = strlen ($2);
350             if (len >= NLM_MAX_THREAD_NAME_LENGTH)
351               {
352                 nlmheader_warn (_("thread name is too long"),
353                                 NLM_MAX_THREAD_NAME_LENGTH);
354                 len = NLM_MAX_THREAD_NAME_LENGTH;
355               }
356             var_hdr->threadNameLength = len;
357             strncpy (var_hdr->threadName, $2, len);
358             var_hdr->threadName[len] = '\0';
359             free ($2);
360           }
361         | TYPE STRING
362           {
363             fixed_hdr->moduleType = nlmlex_get_number ($2);
364             free ($2);
365           }
366         | VERBOSE
367           {
368             verbose = true;
369           }
370         | VERSIONK STRING STRING STRING
371           {
372             long val;
373
374             strncpy (version_hdr->stamp, "VeRsIoN#", 8);
375             version_hdr->majorVersion = nlmlex_get_number ($2);
376             val = nlmlex_get_number ($3);
377             if (val < 0 || val > 99)
378               nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
379                               -1);
380             else
381               version_hdr->minorVersion = val;
382             val = nlmlex_get_number ($4);
383             if (val < 0)
384               nlmheader_warn (_("illegal revision number (must be between 0 and 26)"),
385                               -1);
386             else if (val > 26)
387               version_hdr->revision = 0;
388             else
389               version_hdr->revision = val;
390             free ($2);
391             free ($3);
392             free ($4);
393           }
394         | VERSIONK STRING STRING
395           {
396             long val;
397
398             strncpy (version_hdr->stamp, "VeRsIoN#", 8);
399             version_hdr->majorVersion = nlmlex_get_number ($2);
400             val = nlmlex_get_number ($3);
401             if (val < 0 || val > 99)
402               nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
403                               -1);
404             else
405               version_hdr->minorVersion = val;
406             version_hdr->revision = 0;
407             free ($2);
408             free ($3);
409           }
410         | XDCDATA STRING
411           {
412             rpc_file = $2;
413           }
414         ;
415
416 /* A possibly empty list of symbols.  */
417
418 symbol_list_opt:
419           /* Empty.  */
420           {
421             $$ = NULL;
422           }
423         | symbol_list
424           {
425             $$ = $1;
426           }
427         ;
428
429 /* A list of symbols in an import or export list.  Prefixes may appear
430    in parentheses.  We need to use left recursion here to avoid
431    building up a large import list on the parser stack.  */
432
433 symbol_list:
434           symbol
435           {
436             $$ = string_list_cons ($1, NULL);
437           }
438         | symbol_prefix
439           {
440             $$ = NULL;
441           }
442         | symbol_list symbol
443           {
444             $$ = string_list_append1 ($1, $2);
445           }
446         | symbol_list symbol_prefix
447           {
448             $$ = $1;
449           }
450         ;
451
452 /* A prefix for subsequent symbols.  */
453
454 symbol_prefix:
455           '(' STRING ')'
456           {
457             if (symbol_prefix != NULL)
458               free (symbol_prefix);
459             symbol_prefix = $2;
460           }
461         ;
462
463 /* A single symbol.  */
464
465 symbol:
466           STRING
467           {
468             if (symbol_prefix == NULL)
469               $$ = $1;
470             else
471               {
472                 $$ = xmalloc (strlen (symbol_prefix) + strlen ($1) + 2);
473                 sprintf ($$, "%s@%s", symbol_prefix, $1);
474                 free ($1);
475               }
476           }
477         ;
478
479 /* A list of strings.  */
480
481 string_list:
482           /* May be empty.  */
483           {
484             $$ = NULL;
485           }
486         | STRING string_list
487           {
488             $$ = string_list_cons ($1, $2);
489           }
490         ;
491
492 %%
493
494 /* If strerror is just a macro, we want to use the one from libiberty
495    since it will handle undefined values.  */
496 #undef strerror
497 extern char *strerror ();
498
499 /* The lexer is simple, too simple for flex.  Keywords are only
500    recognized at the start of lines.  Everything else must be an
501    argument.  A comma is treated as whitespace.  */
502
503 /* The states the lexer can be in.  */
504
505 enum lex_state
506 {
507   /* At the beginning of a line.  */
508   BEGINNING_OF_LINE,
509   /* In the middle of a line.  */
510   IN_LINE
511 };
512
513 /* We need to keep a stack of files to handle file inclusion.  */
514
515 struct input
516 {
517   /* The file to read from.  */
518   FILE *file;
519   /* The name of the file.  */
520   char *name;
521   /* The current line number.  */
522   int lineno;
523   /* The current state.  */
524   enum lex_state state;
525   /* The next file on the stack.  */
526   struct input *next;
527 };
528
529 /* The current input file.  */
530
531 static struct input current;
532
533 /* The character which introduces comments.  */
534 #define COMMENT_CHAR '#'
535 \f
536 /* Start the lexer going on the main input file.  */
537
538 boolean
539 nlmlex_file (name)
540      const char *name;
541 {
542   current.next = NULL;
543   return nlmlex_file_open (name);
544 }
545
546 /* Start the lexer going on a subsidiary input file.  */
547
548 static void
549 nlmlex_file_push (name)
550      const char *name;
551 {
552   struct input *push;
553
554   push = (struct input *) xmalloc (sizeof (struct input));
555   *push = current;
556   if (nlmlex_file_open (name))
557     current.next = push;
558   else
559     {
560       current = *push;
561       free (push);
562     }
563 }
564
565 /* Start lexing from a file.  */
566
567 static boolean
568 nlmlex_file_open (name)
569      const char *name;
570 {
571   current.file = fopen (name, "r");
572   if (current.file == NULL)
573     {
574       fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno));
575       ++parse_errors;
576       return false;
577     }
578   current.name = xstrdup (name);
579   current.lineno = 1;
580   current.state = BEGINNING_OF_LINE;
581   return true;
582 }
583 \f
584 /* Table used to turn keywords into tokens.  */
585
586 struct keyword_tokens_struct
587 {
588   const char *keyword;
589   int token;
590 };
591
592 struct keyword_tokens_struct keyword_tokens[] =
593 {
594   { "CHECK", CHECK },
595   { "CODESTART", CODESTART },
596   { "COPYRIGHT", COPYRIGHT },
597   { "CUSTOM", CUSTOM },
598   { "DATE", DATE },
599   { "DEBUG", DEBUG },
600   { "DESCRIPTION", DESCRIPTION },
601   { "EXIT", EXIT },
602   { "EXPORT", EXPORT },
603   { "FLAG_ON", FLAG_ON },
604   { "FLAG_OFF", FLAG_OFF },
605   { "FULLMAP", FULLMAP },
606   { "HELP", HELP },
607   { "IMPORT", IMPORT },
608   { "INPUT", INPUT },
609   { "MAP", MAP },
610   { "MESSAGES", MESSAGES },
611   { "MODULE", MODULE },
612   { "MULTIPLE", MULTIPLE },
613   { "OS_DOMAIN", OS_DOMAIN },
614   { "OUTPUT", OUTPUT },
615   { "PSEUDOPREEMPTION", PSEUDOPREEMPTION },
616   { "REENTRANT", REENTRANT },
617   { "SCREENNAME", SCREENNAME },
618   { "SHARELIB", SHARELIB },
619   { "STACK", STACK },
620   { "STACKSIZE", STACK },
621   { "START", START },
622   { "SYNCHRONIZE", SYNCHRONIZE },
623   { "THREADNAME", THREADNAME },
624   { "TYPE", TYPE },
625   { "VERBOSE", VERBOSE },
626   { "VERSION", VERSIONK },
627   { "XDCDATA", XDCDATA }
628 };
629
630 #define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0]))
631 \f
632 /* The lexer accumulates strings in these variables.  */
633 static char *lex_buf;
634 static int lex_size;
635 static int lex_pos;
636
637 /* Start accumulating strings into the buffer.  */
638 #define BUF_INIT() \
639   ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ()))
640
641 static int
642 nlmlex_buf_init ()
643 {
644   lex_size = 10;
645   lex_buf = xmalloc (lex_size + 1);
646   lex_pos = 0;
647   return 0;
648 }
649
650 /* Finish a string in the buffer.  */
651 #define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0'))
652
653 /* Accumulate a character into the buffer.  */
654 #define BUF_ADD(c) \
655   ((void) (lex_pos < lex_size \
656            ? lex_buf[lex_pos++] = (c) \
657            : nlmlex_buf_add (c)))
658
659 static char
660 nlmlex_buf_add (c)
661      int c;
662 {
663   if (lex_pos >= lex_size)
664     {
665       lex_size *= 2;
666       lex_buf = xrealloc (lex_buf, lex_size + 1);
667     }
668
669   return lex_buf[lex_pos++] = c;
670 }
671 \f
672 /* The lexer proper.  This is called by the bison generated parsing
673    code.  */
674
675 static int
676 yylex ()
677 {
678   int c;
679
680 tail_recurse:
681
682   c = getc (current.file);
683
684   /* Commas are treated as whitespace characters.  */
685   while (isspace ((unsigned char) c) || c == ',')
686     {
687       current.state = IN_LINE;
688       if (c == '\n')
689         {
690           ++current.lineno;
691           current.state = BEGINNING_OF_LINE;
692         }
693       c = getc (current.file);
694     }
695
696   /* At the end of the file we either pop to the previous file or
697      finish up.  */
698   if (c == EOF)
699     {
700       fclose (current.file);
701       free (current.name);
702       if (current.next == NULL)
703         return 0;
704       else
705         {
706           struct input *next;
707
708           next = current.next;
709           current = *next;
710           free (next);
711           goto tail_recurse;
712         }
713     }
714
715   /* A comment character always means to drop everything until the
716      next newline.  */
717   if (c == COMMENT_CHAR)
718     {
719       do
720         {
721           c = getc (current.file);
722         }
723       while (c != '\n');
724       ++current.lineno;
725       current.state = BEGINNING_OF_LINE;
726       goto tail_recurse;
727     }
728
729   /* An '@' introduces an include file.  */
730   if (c == '@')
731     {
732       do
733         {
734           c = getc (current.file);
735           if (c == '\n')
736             ++current.lineno;
737         }
738       while (isspace ((unsigned char) c));
739       BUF_INIT ();
740       while (! isspace ((unsigned char) c) && c != EOF)
741         {
742           BUF_ADD (c);
743           c = getc (current.file);
744         }
745       BUF_FINISH ();
746
747       ungetc (c, current.file);
748       
749       nlmlex_file_push (lex_buf);
750       goto tail_recurse;
751     }
752
753   /* A non-space character at the start of a line must be the start of
754      a keyword.  */
755   if (current.state == BEGINNING_OF_LINE)
756     {
757       BUF_INIT ();
758       while (isalnum ((unsigned char) c) || c == '_')
759         {
760           if (islower ((unsigned char) c))
761             BUF_ADD (toupper ((unsigned char) c));
762           else
763             BUF_ADD (c);
764           c = getc (current.file);
765         }
766       BUF_FINISH ();
767
768       if (c != EOF && ! isspace ((unsigned char) c) && c != ',')
769         {
770           nlmheader_identify ();
771           fprintf (stderr, _("%s:%d: illegal character in keyword: %c\n"),
772                    current.name, current.lineno, c);
773         }
774       else
775         {
776           unsigned int i;
777
778           for (i = 0; i < KEYWORD_COUNT; i++)
779             {
780               if (lex_buf[0] == keyword_tokens[i].keyword[0]
781                   && strcmp (lex_buf, keyword_tokens[i].keyword) == 0)
782                 {
783                   /* Pushing back the final whitespace avoids worrying
784                      about \n here.  */
785                   ungetc (c, current.file);
786                   current.state = IN_LINE;
787                   return keyword_tokens[i].token;
788                 }
789             }
790           
791           nlmheader_identify ();
792           fprintf (stderr, _("%s:%d: unrecognized keyword: %s\n"),
793                    current.name, current.lineno, lex_buf);
794         }
795
796       ++parse_errors;
797       /* Treat the rest of this line as a comment.  */
798       ungetc (COMMENT_CHAR, current.file);
799       goto tail_recurse;
800     }
801
802   /* Parentheses just represent themselves.  */
803   if (c == '(' || c == ')')
804     return c;
805
806   /* Handle quoted strings.  */
807   if (c == '"' || c == '\'')
808     {
809       int quote;
810       int start_lineno;
811
812       quote = c;
813       start_lineno = current.lineno;
814
815       c = getc (current.file);
816       BUF_INIT ();
817       while (c != quote && c != EOF)
818         {
819           BUF_ADD (c);
820           if (c == '\n')
821             ++current.lineno;
822           c = getc (current.file);
823         }
824       BUF_FINISH ();
825
826       if (c == EOF)
827         {
828           nlmheader_identify ();
829           fprintf (stderr, _("%s:%d: end of file in quoted string\n"),
830                    current.name, start_lineno);
831           ++parse_errors;
832         }
833
834       /* FIXME: Possible memory leak.  */
835       yylval.string = xstrdup (lex_buf);
836       return QUOTED_STRING;
837     }
838
839   /* Gather a generic argument.  */
840   BUF_INIT ();
841   while (! isspace (c)
842          && c != ','
843          && c != COMMENT_CHAR
844          && c != '('
845          && c != ')')
846     {
847       BUF_ADD (c);
848       c = getc (current.file);
849     }
850   BUF_FINISH ();
851
852   ungetc (c, current.file);
853
854   /* FIXME: Possible memory leak.  */
855   yylval.string = xstrdup (lex_buf);
856   return STRING;
857 }
858 \f
859 /* Get a number from a string.  */
860
861 static long
862 nlmlex_get_number (s)
863      const char *s;
864 {
865   long ret;
866   char *send;
867
868   ret = strtol (s, &send, 10);
869   if (*send != '\0')
870     nlmheader_warn (_("bad number"), -1);
871   return ret;
872 }
873
874 /* Prefix the nlmconv warnings with a note as to where they come from.
875    We don't use program_name on every warning, because then some
876    versions of the emacs next-error function can't recognize the line
877    number.  */
878
879 static void
880 nlmheader_identify ()
881 {
882   static int done;
883
884   if (! done)
885     {
886       fprintf (stderr, _("%s: problems in NLM command language input:\n"),
887                program_name);
888       done = 1;
889     }
890 }
891
892 /* Issue a warning.  */
893
894 static void
895 nlmheader_warn (s, imax)
896      const char *s;
897      int imax;
898 {
899   nlmheader_identify ();
900   fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s);
901   if (imax != -1)
902     fprintf (stderr, " (max %d)", imax);
903   fprintf (stderr, "\n");
904 }
905
906 /* Report an error.  */
907
908 static void
909 nlmheader_error (s)
910      const char *s;
911 {
912   nlmheader_warn (s, -1);
913   ++parse_errors;
914 }
915
916 /* Add a string to a string list.  */
917
918 static struct string_list *
919 string_list_cons (s, l)
920      char *s;
921      struct string_list *l;
922 {
923   struct string_list *ret;
924
925   ret = (struct string_list *) xmalloc (sizeof (struct string_list));
926   ret->next = l;
927   ret->string = s;
928   return ret;
929 }
930
931 /* Append a string list to another string list.  */
932
933 static struct string_list *
934 string_list_append (l1, l2)
935      struct string_list *l1;
936      struct string_list *l2;
937 {
938   register struct string_list **pp;
939
940   for (pp = &l1; *pp != NULL; pp = &(*pp)->next)
941     ;
942   *pp = l2;
943   return l1;
944 }
945
946 /* Append a string to a string list.  */
947
948 static struct string_list *
949 string_list_append1 (l, s)
950      struct string_list *l;
951      char *s;
952 {
953   struct string_list *n;
954   register struct string_list **pp;
955
956   n = (struct string_list *) xmalloc (sizeof (struct string_list));
957   n->next = NULL;
958   n->string = s;
959   for (pp = &l; *pp != NULL; pp = &(*pp)->next)
960     ;
961   *pp = n;
962   return l;
963 }
964
965 /* Duplicate a string in memory.  */
966
967 static char *
968 xstrdup (s)
969      const char *s;
970 {
971   unsigned long len;
972   char *ret;
973
974   len = strlen (s);
975   ret = xmalloc (len + 1);
976   strcpy (ret, s);
977   return ret;
978 }