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