]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/nlmheader.y
Change sources over to using GPLv3
[thirdparty/binutils-gdb.git] / binutils / nlmheader.y
CommitLineData
252b5132 1%{/* nlmheader.y - parse NLM header specification keywords.
3db64b00 2 Copyright 1993, 1994, 1995, 1997, 1998, 2001, 2002, 2003, 2007
02f6ffef 3 Free Software Foundation, Inc.
252b5132 4
32866df7
NC
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132
RH
21
22/* Written by Ian Lance Taylor <ian@cygnus.com>.
23
24 This bison file parses the commands recognized by the NetWare NLM
25 linker, except for lists of object files. It stores the
26 information in global variables.
27
28 This implementation is based on the description in the NetWare Tool
29 Maker Specification manual, edition 1.0. */
30
3db64b00 31#include "sysdep.h"
3882b010 32#include "safe-ctype.h"
252b5132 33#include "bfd.h"
252b5132
RH
34#include "nlm/common.h"
35#include "nlm/internal.h"
3db64b00 36#include "bucomm.h"
252b5132
RH
37#include "nlmconv.h"
38
39/* Information is stored in the structures pointed to by these
40 variables. */
41
42Nlm_Internal_Fixed_Header *fixed_hdr;
43Nlm_Internal_Variable_Header *var_hdr;
44Nlm_Internal_Version_Header *version_hdr;
45Nlm_Internal_Copyright_Header *copyright_hdr;
46Nlm_Internal_Extended_Header *extended_hdr;
47
48/* Procedure named by CHECK. */
49char *check_procedure;
50/* File named by CUSTOM. */
51char *custom_file;
52/* Whether to generate debugging information (DEBUG). */
b34976b6 53bfd_boolean debug_info;
252b5132
RH
54/* Procedure named by EXIT. */
55char *exit_procedure;
56/* Exported symbols (EXPORT). */
57struct string_list *export_symbols;
58/* List of files from INPUT. */
59struct string_list *input_files;
60/* Map file name (MAP, FULLMAP). */
61char *map_file;
62/* Whether a full map has been requested (FULLMAP). */
b34976b6 63bfd_boolean full_map;
252b5132
RH
64/* File named by HELP. */
65char *help_file;
66/* Imported symbols (IMPORT). */
67struct string_list *import_symbols;
68/* File named by MESSAGES. */
69char *message_file;
70/* Autoload module list (MODULE). */
71struct string_list *modules;
72/* File named by OUTPUT. */
73char *output_file;
74/* File named by SHARELIB. */
75char *sharelib_file;
76/* Start procedure name (START). */
77char *start_procedure;
78/* VERBOSE. */
b34976b6 79bfd_boolean verbose;
252b5132
RH
80/* RPC description file (XDCDATA). */
81char *rpc_file;
82
83/* The number of serious errors that have occurred. */
84int parse_errors;
85
86/* The current symbol prefix when reading a list of import or export
87 symbols. */
88static char *symbol_prefix;
89
90/* Parser error message handler. */
91#define yyerror(msg) nlmheader_error (msg);
92
93/* Local functions. */
2da42df6
AJ
94static int yylex (void);
95static void nlmlex_file_push (const char *);
96static bfd_boolean nlmlex_file_open (const char *);
97static int nlmlex_buf_init (void);
98static char nlmlex_buf_add (int);
99static long nlmlex_get_number (const char *);
100static void nlmheader_identify (void);
101static void nlmheader_warn (const char *, int);
102static void nlmheader_error (const char *);
103static struct string_list * string_list_cons (char *, struct string_list *);
104static struct string_list * string_list_append (struct string_list *,
105 struct string_list *);
106static struct string_list * string_list_append1 (struct string_list *,
107 char *);
108static char *xstrdup (const char *);
252b5132
RH
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
b34976b6 143file:
252b5132
RH
144 commands
145 ;
146
147/* A possibly empty list of commands. */
148
149commands:
150 /* May be empty. */
151 | command commands
152 ;
153
154/* A single command. There is where most of the work takes place. */
155
156command:
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 {
b34976b6 207 debug_info = TRUE;
252b5132
RH
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 = "";
b34976b6 250 full_map = TRUE;
252b5132
RH
251 }
252 | FULLMAP STRING
253 {
254 map_file = $2;
b34976b6 255 full_map = TRUE;
252b5132
RH
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 {
b34976b6 368 verbose = TRUE;
252b5132
RH
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
418symbol_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
433symbol_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
454symbol_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
465symbol:
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
481string_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
408f8db1 497extern char *strerror PARAMS ((int));
252b5132
RH
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
505enum 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
515struct 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
531static 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
b34976b6 538bfd_boolean
2da42df6 539nlmlex_file (const char *name)
252b5132
RH
540{
541 current.next = NULL;
542 return nlmlex_file_open (name);
543}
544
545/* Start the lexer going on a subsidiary input file. */
546
547static void
2da42df6 548nlmlex_file_push (const char *name)
252b5132
RH
549{
550 struct input *push;
551
552 push = (struct input *) xmalloc (sizeof (struct input));
553 *push = current;
554 if (nlmlex_file_open (name))
555 current.next = push;
556 else
557 {
558 current = *push;
559 free (push);
560 }
561}
562
563/* Start lexing from a file. */
564
b34976b6 565static bfd_boolean
2da42df6 566nlmlex_file_open (const char *name)
252b5132
RH
567{
568 current.file = fopen (name, "r");
569 if (current.file == NULL)
570 {
571 fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno));
572 ++parse_errors;
b34976b6 573 return FALSE;
252b5132
RH
574 }
575 current.name = xstrdup (name);
576 current.lineno = 1;
577 current.state = BEGINNING_OF_LINE;
b34976b6 578 return TRUE;
252b5132
RH
579}
580\f
581/* Table used to turn keywords into tokens. */
582
583struct keyword_tokens_struct
584{
585 const char *keyword;
586 int token;
587};
588
89b78896 589static struct keyword_tokens_struct keyword_tokens[] =
252b5132
RH
590{
591 { "CHECK", CHECK },
592 { "CODESTART", CODESTART },
593 { "COPYRIGHT", COPYRIGHT },
594 { "CUSTOM", CUSTOM },
595 { "DATE", DATE },
596 { "DEBUG", DEBUG },
597 { "DESCRIPTION", DESCRIPTION },
598 { "EXIT", EXIT },
599 { "EXPORT", EXPORT },
600 { "FLAG_ON", FLAG_ON },
601 { "FLAG_OFF", FLAG_OFF },
602 { "FULLMAP", FULLMAP },
603 { "HELP", HELP },
604 { "IMPORT", IMPORT },
605 { "INPUT", INPUT },
606 { "MAP", MAP },
607 { "MESSAGES", MESSAGES },
608 { "MODULE", MODULE },
609 { "MULTIPLE", MULTIPLE },
610 { "OS_DOMAIN", OS_DOMAIN },
611 { "OUTPUT", OUTPUT },
612 { "PSEUDOPREEMPTION", PSEUDOPREEMPTION },
613 { "REENTRANT", REENTRANT },
614 { "SCREENNAME", SCREENNAME },
615 { "SHARELIB", SHARELIB },
616 { "STACK", STACK },
617 { "STACKSIZE", STACK },
618 { "START", START },
619 { "SYNCHRONIZE", SYNCHRONIZE },
620 { "THREADNAME", THREADNAME },
621 { "TYPE", TYPE },
622 { "VERBOSE", VERBOSE },
623 { "VERSION", VERSIONK },
624 { "XDCDATA", XDCDATA }
625};
626
627#define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0]))
628\f
629/* The lexer accumulates strings in these variables. */
630static char *lex_buf;
631static int lex_size;
632static int lex_pos;
633
634/* Start accumulating strings into the buffer. */
635#define BUF_INIT() \
636 ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ()))
637
638static int
2da42df6 639nlmlex_buf_init (void)
252b5132
RH
640{
641 lex_size = 10;
642 lex_buf = xmalloc (lex_size + 1);
643 lex_pos = 0;
644 return 0;
645}
646
647/* Finish a string in the buffer. */
648#define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0'))
649
650/* Accumulate a character into the buffer. */
651#define BUF_ADD(c) \
652 ((void) (lex_pos < lex_size \
653 ? lex_buf[lex_pos++] = (c) \
654 : nlmlex_buf_add (c)))
655
656static char
2da42df6 657nlmlex_buf_add (int c)
252b5132
RH
658{
659 if (lex_pos >= lex_size)
660 {
661 lex_size *= 2;
662 lex_buf = xrealloc (lex_buf, lex_size + 1);
663 }
664
665 return lex_buf[lex_pos++] = c;
666}
667\f
668/* The lexer proper. This is called by the bison generated parsing
669 code. */
670
671static int
2da42df6 672yylex (void)
252b5132
RH
673{
674 int c;
675
676tail_recurse:
677
678 c = getc (current.file);
679
680 /* Commas are treated as whitespace characters. */
3882b010 681 while (ISSPACE (c) || c == ',')
252b5132
RH
682 {
683 current.state = IN_LINE;
684 if (c == '\n')
685 {
686 ++current.lineno;
687 current.state = BEGINNING_OF_LINE;
688 }
689 c = getc (current.file);
690 }
691
692 /* At the end of the file we either pop to the previous file or
693 finish up. */
694 if (c == EOF)
695 {
696 fclose (current.file);
697 free (current.name);
698 if (current.next == NULL)
699 return 0;
700 else
701 {
702 struct input *next;
703
704 next = current.next;
705 current = *next;
706 free (next);
707 goto tail_recurse;
708 }
709 }
710
711 /* A comment character always means to drop everything until the
712 next newline. */
713 if (c == COMMENT_CHAR)
714 {
715 do
716 {
717 c = getc (current.file);
718 }
719 while (c != '\n');
720 ++current.lineno;
721 current.state = BEGINNING_OF_LINE;
722 goto tail_recurse;
723 }
724
725 /* An '@' introduces an include file. */
726 if (c == '@')
727 {
728 do
729 {
730 c = getc (current.file);
731 if (c == '\n')
732 ++current.lineno;
733 }
3882b010 734 while (ISSPACE (c));
252b5132 735 BUF_INIT ();
3882b010 736 while (! ISSPACE (c) && c != EOF)
252b5132
RH
737 {
738 BUF_ADD (c);
739 c = getc (current.file);
740 }
741 BUF_FINISH ();
742
743 ungetc (c, current.file);
b34976b6 744
252b5132
RH
745 nlmlex_file_push (lex_buf);
746 goto tail_recurse;
747 }
748
749 /* A non-space character at the start of a line must be the start of
750 a keyword. */
751 if (current.state == BEGINNING_OF_LINE)
752 {
753 BUF_INIT ();
3882b010 754 while (ISALNUM (c) || c == '_')
252b5132 755 {
3882b010 756 BUF_ADD (TOUPPER (c));
252b5132
RH
757 c = getc (current.file);
758 }
759 BUF_FINISH ();
760
3882b010 761 if (c != EOF && ! ISSPACE (c) && c != ',')
252b5132
RH
762 {
763 nlmheader_identify ();
764 fprintf (stderr, _("%s:%d: illegal character in keyword: %c\n"),
765 current.name, current.lineno, c);
766 }
767 else
768 {
769 unsigned int i;
770
771 for (i = 0; i < KEYWORD_COUNT; i++)
772 {
773 if (lex_buf[0] == keyword_tokens[i].keyword[0]
774 && strcmp (lex_buf, keyword_tokens[i].keyword) == 0)
775 {
776 /* Pushing back the final whitespace avoids worrying
777 about \n here. */
778 ungetc (c, current.file);
779 current.state = IN_LINE;
780 return keyword_tokens[i].token;
781 }
782 }
b34976b6 783
252b5132
RH
784 nlmheader_identify ();
785 fprintf (stderr, _("%s:%d: unrecognized keyword: %s\n"),
786 current.name, current.lineno, lex_buf);
787 }
788
789 ++parse_errors;
790 /* Treat the rest of this line as a comment. */
791 ungetc (COMMENT_CHAR, current.file);
792 goto tail_recurse;
793 }
794
795 /* Parentheses just represent themselves. */
796 if (c == '(' || c == ')')
797 return c;
798
799 /* Handle quoted strings. */
800 if (c == '"' || c == '\'')
801 {
802 int quote;
803 int start_lineno;
804
805 quote = c;
806 start_lineno = current.lineno;
807
808 c = getc (current.file);
809 BUF_INIT ();
810 while (c != quote && c != EOF)
811 {
812 BUF_ADD (c);
813 if (c == '\n')
814 ++current.lineno;
815 c = getc (current.file);
816 }
817 BUF_FINISH ();
818
819 if (c == EOF)
820 {
821 nlmheader_identify ();
822 fprintf (stderr, _("%s:%d: end of file in quoted string\n"),
823 current.name, start_lineno);
824 ++parse_errors;
825 }
826
827 /* FIXME: Possible memory leak. */
828 yylval.string = xstrdup (lex_buf);
829 return QUOTED_STRING;
830 }
831
832 /* Gather a generic argument. */
833 BUF_INIT ();
3882b010 834 while (! ISSPACE (c)
252b5132
RH
835 && c != ','
836 && c != COMMENT_CHAR
837 && c != '('
838 && c != ')')
839 {
840 BUF_ADD (c);
841 c = getc (current.file);
842 }
843 BUF_FINISH ();
844
845 ungetc (c, current.file);
846
847 /* FIXME: Possible memory leak. */
848 yylval.string = xstrdup (lex_buf);
849 return STRING;
850}
851\f
852/* Get a number from a string. */
853
854static long
2da42df6 855nlmlex_get_number (const char *s)
252b5132
RH
856{
857 long ret;
858 char *send;
859
860 ret = strtol (s, &send, 10);
861 if (*send != '\0')
862 nlmheader_warn (_("bad number"), -1);
863 return ret;
864}
865
866/* Prefix the nlmconv warnings with a note as to where they come from.
867 We don't use program_name on every warning, because then some
868 versions of the emacs next-error function can't recognize the line
869 number. */
870
871static void
2da42df6 872nlmheader_identify (void)
252b5132
RH
873{
874 static int done;
875
876 if (! done)
877 {
878 fprintf (stderr, _("%s: problems in NLM command language input:\n"),
879 program_name);
880 done = 1;
881 }
882}
883
884/* Issue a warning. */
885
886static void
2da42df6 887nlmheader_warn (const char *s, int imax)
252b5132
RH
888{
889 nlmheader_identify ();
890 fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s);
891 if (imax != -1)
892 fprintf (stderr, " (max %d)", imax);
893 fprintf (stderr, "\n");
894}
895
896/* Report an error. */
897
898static void
2da42df6 899nlmheader_error (const char *s)
252b5132
RH
900{
901 nlmheader_warn (s, -1);
902 ++parse_errors;
903}
904
905/* Add a string to a string list. */
906
907static struct string_list *
2da42df6 908string_list_cons (char *s, struct string_list *l)
252b5132
RH
909{
910 struct string_list *ret;
911
912 ret = (struct string_list *) xmalloc (sizeof (struct string_list));
913 ret->next = l;
914 ret->string = s;
915 return ret;
916}
917
918/* Append a string list to another string list. */
919
920static struct string_list *
2da42df6 921string_list_append (struct string_list *l1, struct string_list *l2)
252b5132
RH
922{
923 register struct string_list **pp;
924
925 for (pp = &l1; *pp != NULL; pp = &(*pp)->next)
926 ;
927 *pp = l2;
928 return l1;
929}
930
931/* Append a string to a string list. */
932
933static struct string_list *
2da42df6 934string_list_append1 (struct string_list *l, char *s)
252b5132
RH
935{
936 struct string_list *n;
937 register struct string_list **pp;
938
939 n = (struct string_list *) xmalloc (sizeof (struct string_list));
940 n->next = NULL;
941 n->string = s;
942 for (pp = &l; *pp != NULL; pp = &(*pp)->next)
943 ;
944 *pp = n;
945 return l;
946}
947
948/* Duplicate a string in memory. */
949
950static char *
2da42df6 951xstrdup (const char *s)
252b5132
RH
952{
953 unsigned long len;
954 char *ret;
955
956 len = strlen (s);
957 ret = xmalloc (len + 1);
958 strcpy (ret, s);
959 return ret;
960}