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