* nlmconv.c (debug, unlink_on_exit): New static variables.
[deliverable/binutils-gdb.git] / binutils / nlmheader.y
CommitLineData
627703f9
ILT
1%{/* nlmheader.y - parse NLM header specification keywords.
2 Copyright (C) 1993 Free Software Foundation, Inc.
3
4This file is part of GNU Binutils.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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
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). */
53boolean debug_info;
54/* Procedure named by EXIT. */
55char *exit_procedure;
56/* Exported symbols (EXPORT). */
57struct string_list *export_symbols;
0f6df2ee
ILT
58/* List of files from INPUT. */
59struct string_list *input_files;
627703f9
ILT
60/* Map file name (MAP, FULLMAP). */
61char *map_file;
62/* Whether a full map has been requested (FULLMAP). */
63boolean full_map;
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;
0f6df2ee
ILT
72/* File named by OUTPUT. */
73char *output_file;
627703f9
ILT
74/* File named by SHARELIB. */
75char *sharelib_file;
76/* Start procedure name (START). */
77char *start_procedure;
78/* VERBOSE. */
79boolean verbose;
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. */
94static int yylex PARAMS ((void));
95static void nlmlex_file_push PARAMS ((const char *));
96static boolean nlmlex_file_open PARAMS ((const char *));
97static int nlmlex_buf_init PARAMS ((void));
98static char nlmlex_buf_add PARAMS ((int));
99static long nlmlex_get_number PARAMS ((const char *));
100static void nlmheader_identify PARAMS ((void));
101static void nlmheader_warn PARAMS ((const char *, int));
102static void nlmheader_error PARAMS ((const char *));
103static struct string_list * string_list_cons PARAMS ((char *,
104 struct string_list *));
105static struct string_list * string_list_append PARAMS ((struct string_list *,
106 struct string_list *));
107static struct string_list * string_list_append1 PARAMS ((struct string_list *,
108 char *));
109static 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. */
0f6df2ee 133%type <list> symbol_list_opt symbol_list string_list
627703f9
ILT
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
144file:
145 commands
146 ;
147
148/* A possibly empty list of commands. */
149
150commands:
151 /* May be empty. */
152 | command commands
153 ;
154
155/* A single command. There is where most of the work takes place. */
156
157command:
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 }
0f6df2ee 259 | INPUT string_list
627703f9 260 {
0f6df2ee 261 input_files = string_list_append (input_files, $2);
627703f9
ILT
262 }
263 | MAP STRING
264 {
265 map_file = $2;
266 }
267 | MESSAGES STRING
268 {
269 message_file = $2;
270 }
0f6df2ee 271 | MODULE string_list
627703f9
ILT
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 {
0f6df2ee
ILT
285 if (output_file == NULL)
286 output_file = $2;
287 else
288 nlmheader_warn ("ignoring duplicate OUTPUT statement", -1);
627703f9
ILT
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
407symbol_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
422symbol_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
443symbol_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
454symbol:
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
0f6df2ee 468/* A list of strings. */
627703f9 469
0f6df2ee 470string_list:
627703f9
ILT
471 /* May be empty. */
472 {
473 $$ = NULL;
474 }
0f6df2ee 475 | STRING string_list
627703f9
ILT
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
486extern 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
494enum 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
504struct 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
520static 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
527boolean
528nlmlex_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
537static void
538nlmlex_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
556static boolean
557nlmlex_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
575struct keyword_tokens_struct
576{
577 const char *keyword;
578 int token;
579};
580
581struct 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. */
622static char *lex_buf;
623static int lex_size;
624static 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
630static int
631nlmlex_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
648static char
649nlmlex_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
664static int
665yylex ()
666{
667 int c;
668
669tail_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
850static long
851nlmlex_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
868static void
869nlmheader_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
883static void
884nlmheader_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
897static void
898nlmheader_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
907static struct string_list *
908string_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
922static struct string_list *
923string_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
937static struct string_list *
938string_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
956static char *
957xstrdup (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}
This page took 0.09041 seconds and 4 git commands to generate.