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