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