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 1993, 1994, 1995, 1997, 1998, 2001, 2002
3      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 /* Written by Ian Lance Taylor <ian@cygnus.com>.
22
23    This bison file parses the commands recognized by the NetWare NLM
24    linker, except for lists of object files.  It stores the
25    information in global variables.
26
27    This implementation is based on the description in the NetWare Tool
28    Maker Specification manual, edition 1.0.  */
29
30 #include "ansidecl.h"
31 #include <stdio.h>
32 #include "safe-ctype.h"
33 #include "bfd.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 START SYNCHRONIZE
125 %token THREADNAME TYPE VERBOSE VERSIONK 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         | START STRING
339           {
340             start_procedure = $2;
341           }
342         | SYNCHRONIZE
343           {
344             fixed_hdr->flags |= 0x4;
345           }
346         | THREADNAME QUOTED_STRING
347           {
348             int len;
349
350             len = strlen ($2);
351             if (len >= NLM_MAX_THREAD_NAME_LENGTH)
352               {
353                 nlmheader_warn (_("thread name is too long"),
354                                 NLM_MAX_THREAD_NAME_LENGTH);
355                 len = NLM_MAX_THREAD_NAME_LENGTH;
356               }
357             var_hdr->threadNameLength = len;
358             strncpy (var_hdr->threadName, $2, len);
359             var_hdr->threadName[len] = '\0';
360             free ($2);
361           }
362         | TYPE STRING
363           {
364             fixed_hdr->moduleType = nlmlex_get_number ($2);
365             free ($2);
366           }
367         | VERBOSE
368           {
369             verbose = true;
370           }
371         | VERSIONK STRING STRING STRING
372           {
373             long val;
374
375             strncpy (version_hdr->stamp, "VeRsIoN#", 8);
376             version_hdr->majorVersion = nlmlex_get_number ($2);
377             val = nlmlex_get_number ($3);
378             if (val < 0 || val > 99)
379               nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
380                               -1);
381             else
382               version_hdr->minorVersion = val;
383             val = nlmlex_get_number ($4);
384             if (val < 0)
385               nlmheader_warn (_("illegal revision number (must be between 0 and 26)"),
386                               -1);
387             else if (val > 26)
388               version_hdr->revision = 0;
389             else
390               version_hdr->revision = val;
391             free ($2);
392             free ($3);
393             free ($4);
394           }
395         | VERSIONK STRING STRING
396           {
397             long val;
398
399             strncpy (version_hdr->stamp, "VeRsIoN#", 8);
400             version_hdr->majorVersion = nlmlex_get_number ($2);
401             val = nlmlex_get_number ($3);
402             if (val < 0 || val > 99)
403               nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
404                               -1);
405             else
406               version_hdr->minorVersion = val;
407             version_hdr->revision = 0;
408             free ($2);
409             free ($3);
410           }
411         | XDCDATA STRING
412           {
413             rpc_file = $2;
414           }
415         ;
416
417 /* A possibly empty list of symbols.  */
418
419 symbol_list_opt:
420           /* Empty.  */
421           {
422             $$ = NULL;
423           }
424         | symbol_list
425           {
426             $$ = $1;
427           }
428         ;
429
430 /* A list of symbols in an import or export list.  Prefixes may appear
431    in parentheses.  We need to use left recursion here to avoid
432    building up a large import list on the parser stack.  */
433
434 symbol_list:
435           symbol
436           {
437             $$ = string_list_cons ($1, NULL);
438           }
439         | symbol_prefix
440           {
441             $$ = NULL;
442           }
443         | symbol_list symbol
444           {
445             $$ = string_list_append1 ($1, $2);
446           }
447         | symbol_list symbol_prefix
448           {
449             $$ = $1;
450           }
451         ;
452
453 /* A prefix for subsequent symbols.  */
454
455 symbol_prefix:
456           '(' STRING ')'
457           {
458             if (symbol_prefix != NULL)
459               free (symbol_prefix);
460             symbol_prefix = $2;
461           }
462         ;
463
464 /* A single symbol.  */
465
466 symbol:
467           STRING
468           {
469             if (symbol_prefix == NULL)
470               $$ = $1;
471             else
472               {
473                 $$ = xmalloc (strlen (symbol_prefix) + strlen ($1) + 2);
474                 sprintf ($$, "%s@%s", symbol_prefix, $1);
475                 free ($1);
476               }
477           }
478         ;
479
480 /* A list of strings.  */
481
482 string_list:
483           /* May be empty.  */
484           {
485             $$ = NULL;
486           }
487         | STRING string_list
488           {
489             $$ = string_list_cons ($1, $2);
490           }
491         ;
492
493 %%
494
495 /* If strerror is just a macro, we want to use the one from libiberty
496    since it will handle undefined values.  */
497 #undef strerror
498 extern char *strerror PARAMS ((int));
499
500 /* The lexer is simple, too simple for flex.  Keywords are only
501    recognized at the start of lines.  Everything else must be an
502    argument.  A comma is treated as whitespace.  */
503
504 /* The states the lexer can be in.  */
505
506 enum lex_state
507 {
508   /* At the beginning of a line.  */
509   BEGINNING_OF_LINE,
510   /* In the middle of a line.  */
511   IN_LINE
512 };
513
514 /* We need to keep a stack of files to handle file inclusion.  */
515
516 struct input
517 {
518   /* The file to read from.  */
519   FILE *file;
520   /* The name of the file.  */
521   char *name;
522   /* The current line number.  */
523   int lineno;
524   /* The current state.  */
525   enum lex_state state;
526   /* The next file on the stack.  */
527   struct input *next;
528 };
529
530 /* The current input file.  */
531
532 static struct input current;
533
534 /* The character which introduces comments.  */
535 #define COMMENT_CHAR '#'
536 \f
537 /* Start the lexer going on the main input file.  */
538
539 boolean
540 nlmlex_file (name)
541      const char *name;
542 {
543   current.next = NULL;
544   return nlmlex_file_open (name);
545 }
546
547 /* Start the lexer going on a subsidiary input file.  */
548
549 static void
550 nlmlex_file_push (name)
551      const char *name;
552 {
553   struct input *push;
554
555   push = (struct input *) xmalloc (sizeof (struct input));
556   *push = current;
557   if (nlmlex_file_open (name))
558     current.next = push;
559   else
560     {
561       current = *push;
562       free (push);
563     }
564 }
565
566 /* Start lexing from a file.  */
567
568 static boolean
569 nlmlex_file_open (name)
570      const char *name;
571 {
572   current.file = fopen (name, "r");
573   if (current.file == NULL)
574     {
575       fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno));
576       ++parse_errors;
577       return false;
578     }
579   current.name = xstrdup (name);
580   current.lineno = 1;
581   current.state = BEGINNING_OF_LINE;
582   return true;
583 }
584 \f
585 /* Table used to turn keywords into tokens.  */
586
587 struct keyword_tokens_struct
588 {
589   const char *keyword;
590   int token;
591 };
592
593 struct keyword_tokens_struct keyword_tokens[] =
594 {
595   { "CHECK", CHECK },
596   { "CODESTART", CODESTART },
597   { "COPYRIGHT", COPYRIGHT },
598   { "CUSTOM", CUSTOM },
599   { "DATE", DATE },
600   { "DEBUG", DEBUG },
601   { "DESCRIPTION", DESCRIPTION },
602   { "EXIT", EXIT },
603   { "EXPORT", EXPORT },
604   { "FLAG_ON", FLAG_ON },
605   { "FLAG_OFF", FLAG_OFF },
606   { "FULLMAP", FULLMAP },
607   { "HELP", HELP },
608   { "IMPORT", IMPORT },
609   { "INPUT", INPUT },
610   { "MAP", MAP },
611   { "MESSAGES", MESSAGES },
612   { "MODULE", MODULE },
613   { "MULTIPLE", MULTIPLE },
614   { "OS_DOMAIN", OS_DOMAIN },
615   { "OUTPUT", OUTPUT },
616   { "PSEUDOPREEMPTION", PSEUDOPREEMPTION },
617   { "REENTRANT", REENTRANT },
618   { "SCREENNAME", SCREENNAME },
619   { "SHARELIB", SHARELIB },
620   { "STACK", STACK },
621   { "STACKSIZE", STACK },
622   { "START", START },
623   { "SYNCHRONIZE", SYNCHRONIZE },
624   { "THREADNAME", THREADNAME },
625   { "TYPE", TYPE },
626   { "VERBOSE", VERBOSE },
627   { "VERSION", VERSIONK },
628   { "XDCDATA", XDCDATA }
629 };
630
631 #define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0]))
632 \f
633 /* The lexer accumulates strings in these variables.  */
634 static char *lex_buf;
635 static int lex_size;
636 static int lex_pos;
637
638 /* Start accumulating strings into the buffer.  */
639 #define BUF_INIT() \
640   ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ()))
641
642 static int
643 nlmlex_buf_init ()
644 {
645   lex_size = 10;
646   lex_buf = xmalloc (lex_size + 1);
647   lex_pos = 0;
648   return 0;
649 }
650
651 /* Finish a string in the buffer.  */
652 #define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0'))
653
654 /* Accumulate a character into the buffer.  */
655 #define BUF_ADD(c) \
656   ((void) (lex_pos < lex_size \
657            ? lex_buf[lex_pos++] = (c) \
658            : nlmlex_buf_add (c)))
659
660 static char
661 nlmlex_buf_add (c)
662      int c;
663 {
664   if (lex_pos >= lex_size)
665     {
666       lex_size *= 2;
667       lex_buf = xrealloc (lex_buf, lex_size + 1);
668     }
669
670   return lex_buf[lex_pos++] = c;
671 }
672 \f
673 /* The lexer proper.  This is called by the bison generated parsing
674    code.  */
675
676 static int
677 yylex ()
678 {
679   int c;
680
681 tail_recurse:
682
683   c = getc (current.file);
684
685   /* Commas are treated as whitespace characters.  */
686   while (ISSPACE (c) || c == ',')
687     {
688       current.state = IN_LINE;
689       if (c == '\n')
690         {
691           ++current.lineno;
692           current.state = BEGINNING_OF_LINE;
693         }
694       c = getc (current.file);
695     }
696
697   /* At the end of the file we either pop to the previous file or
698      finish up.  */
699   if (c == EOF)
700     {
701       fclose (current.file);
702       free (current.name);
703       if (current.next == NULL)
704         return 0;
705       else
706         {
707           struct input *next;
708
709           next = current.next;
710           current = *next;
711           free (next);
712           goto tail_recurse;
713         }
714     }
715
716   /* A comment character always means to drop everything until the
717      next newline.  */
718   if (c == COMMENT_CHAR)
719     {
720       do
721         {
722           c = getc (current.file);
723         }
724       while (c != '\n');
725       ++current.lineno;
726       current.state = BEGINNING_OF_LINE;
727       goto tail_recurse;
728     }
729
730   /* An '@' introduces an include file.  */
731   if (c == '@')
732     {
733       do
734         {
735           c = getc (current.file);
736           if (c == '\n')
737             ++current.lineno;
738         }
739       while (ISSPACE (c));
740       BUF_INIT ();
741       while (! ISSPACE (c) && c != EOF)
742         {
743           BUF_ADD (c);
744           c = getc (current.file);
745         }
746       BUF_FINISH ();
747
748       ungetc (c, current.file);
749       
750       nlmlex_file_push (lex_buf);
751       goto tail_recurse;
752     }
753
754   /* A non-space character at the start of a line must be the start of
755      a keyword.  */
756   if (current.state == BEGINNING_OF_LINE)
757     {
758       BUF_INIT ();
759       while (ISALNUM (c) || c == '_')
760         {
761           BUF_ADD (TOUPPER (c));
762           c = getc (current.file);
763         }
764       BUF_FINISH ();
765
766       if (c != EOF && ! ISSPACE (c) && c != ',')
767         {
768           nlmheader_identify ();
769           fprintf (stderr, _("%s:%d: illegal character in keyword: %c\n"),
770                    current.name, current.lineno, c);
771         }
772       else
773         {
774           unsigned int i;
775
776           for (i = 0; i < KEYWORD_COUNT; i++)
777             {
778               if (lex_buf[0] == keyword_tokens[i].keyword[0]
779                   && strcmp (lex_buf, keyword_tokens[i].keyword) == 0)
780                 {
781                   /* Pushing back the final whitespace avoids worrying
782                      about \n here.  */
783                   ungetc (c, current.file);
784                   current.state = IN_LINE;
785                   return keyword_tokens[i].token;
786                 }
787             }
788           
789           nlmheader_identify ();
790           fprintf (stderr, _("%s:%d: unrecognized keyword: %s\n"),
791                    current.name, current.lineno, lex_buf);
792         }
793
794       ++parse_errors;
795       /* Treat the rest of this line as a comment.  */
796       ungetc (COMMENT_CHAR, current.file);
797       goto tail_recurse;
798     }
799
800   /* Parentheses just represent themselves.  */
801   if (c == '(' || c == ')')
802     return c;
803
804   /* Handle quoted strings.  */
805   if (c == '"' || c == '\'')
806     {
807       int quote;
808       int start_lineno;
809
810       quote = c;
811       start_lineno = current.lineno;
812
813       c = getc (current.file);
814       BUF_INIT ();
815       while (c != quote && c != EOF)
816         {
817           BUF_ADD (c);
818           if (c == '\n')
819             ++current.lineno;
820           c = getc (current.file);
821         }
822       BUF_FINISH ();
823
824       if (c == EOF)
825         {
826           nlmheader_identify ();
827           fprintf (stderr, _("%s:%d: end of file in quoted string\n"),
828                    current.name, start_lineno);
829           ++parse_errors;
830         }
831
832       /* FIXME: Possible memory leak.  */
833       yylval.string = xstrdup (lex_buf);
834       return QUOTED_STRING;
835     }
836
837   /* Gather a generic argument.  */
838   BUF_INIT ();
839   while (! ISSPACE (c)
840          && c != ','
841          && c != COMMENT_CHAR
842          && c != '('
843          && c != ')')
844     {
845       BUF_ADD (c);
846       c = getc (current.file);
847     }
848   BUF_FINISH ();
849
850   ungetc (c, current.file);
851
852   /* FIXME: Possible memory leak.  */
853   yylval.string = xstrdup (lex_buf);
854   return STRING;
855 }
856 \f
857 /* Get a number from a string.  */
858
859 static long
860 nlmlex_get_number (s)
861      const char *s;
862 {
863   long ret;
864   char *send;
865
866   ret = strtol (s, &send, 10);
867   if (*send != '\0')
868     nlmheader_warn (_("bad number"), -1);
869   return ret;
870 }
871
872 /* Prefix the nlmconv warnings with a note as to where they come from.
873    We don't use program_name on every warning, because then some
874    versions of the emacs next-error function can't recognize the line
875    number.  */
876
877 static void
878 nlmheader_identify ()
879 {
880   static int done;
881
882   if (! done)
883     {
884       fprintf (stderr, _("%s: problems in NLM command language input:\n"),
885                program_name);
886       done = 1;
887     }
888 }
889
890 /* Issue a warning.  */
891
892 static void
893 nlmheader_warn (s, imax)
894      const char *s;
895      int imax;
896 {
897   nlmheader_identify ();
898   fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s);
899   if (imax != -1)
900     fprintf (stderr, " (max %d)", imax);
901   fprintf (stderr, "\n");
902 }
903
904 /* Report an error.  */
905
906 static void
907 nlmheader_error (s)
908      const char *s;
909 {
910   nlmheader_warn (s, -1);
911   ++parse_errors;
912 }
913
914 /* Add a string to a string list.  */
915
916 static struct string_list *
917 string_list_cons (s, l)
918      char *s;
919      struct string_list *l;
920 {
921   struct string_list *ret;
922
923   ret = (struct string_list *) xmalloc (sizeof (struct string_list));
924   ret->next = l;
925   ret->string = s;
926   return ret;
927 }
928
929 /* Append a string list to another string list.  */
930
931 static struct string_list *
932 string_list_append (l1, l2)
933      struct string_list *l1;
934      struct string_list *l2;
935 {
936   register struct string_list **pp;
937
938   for (pp = &l1; *pp != NULL; pp = &(*pp)->next)
939     ;
940   *pp = l2;
941   return l1;
942 }
943
944 /* Append a string to a string list.  */
945
946 static struct string_list *
947 string_list_append1 (l, s)
948      struct string_list *l;
949      char *s;
950 {
951   struct string_list *n;
952   register struct string_list **pp;
953
954   n = (struct string_list *) xmalloc (sizeof (struct string_list));
955   n->next = NULL;
956   n->string = s;
957   for (pp = &l; *pp != NULL; pp = &(*pp)->next)
958     ;
959   *pp = n;
960   return l;
961 }
962
963 /* Duplicate a string in memory.  */
964
965 static char *
966 xstrdup (s)
967      const char *s;
968 {
969   unsigned long len;
970   char *ret;
971
972   len = strlen (s);
973   ret = xmalloc (len + 1);
974   strcpy (ret, s);
975   return ret;
976 }