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