123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- %{/* nlmheader.y - parse NLM header specification keywords.
- Copyright (C) 1993-2015 Free Software Foundation, Inc.
- This file is part of GNU Binutils.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
- /* Written by Ian Lance Taylor <ian@cygnus.com>.
- This bison file parses the commands recognized by the NetWare NLM
- linker, except for lists of object files. It stores the
- information in global variables.
- This implementation is based on the description in the NetWare Tool
- Maker Specification manual, edition 1.0. */
- #include "sysdep.h"
- #include "safe-ctype.h"
- #include "bfd.h"
- #include "nlm/common.h"
- #include "nlm/internal.h"
- #include "bucomm.h"
- #include "nlmconv.h"
- /* Information is stored in the structures pointed to by these
- variables. */
- Nlm_Internal_Fixed_Header *fixed_hdr;
- Nlm_Internal_Variable_Header *var_hdr;
- Nlm_Internal_Version_Header *version_hdr;
- Nlm_Internal_Copyright_Header *copyright_hdr;
- Nlm_Internal_Extended_Header *extended_hdr;
- /* Procedure named by CHECK. */
- char *check_procedure;
- /* File named by CUSTOM. */
- char *custom_file;
- /* Whether to generate debugging information (DEBUG). */
- bfd_boolean debug_info;
- /* Procedure named by EXIT. */
- char *exit_procedure;
- /* Exported symbols (EXPORT). */
- struct string_list *export_symbols;
- /* List of files from INPUT. */
- struct string_list *input_files;
- /* Map file name (MAP, FULLMAP). */
- char *map_file;
- /* Whether a full map has been requested (FULLMAP). */
- bfd_boolean full_map;
- /* File named by HELP. */
- char *help_file;
- /* Imported symbols (IMPORT). */
- struct string_list *import_symbols;
- /* File named by MESSAGES. */
- char *message_file;
- /* Autoload module list (MODULE). */
- struct string_list *modules;
- /* File named by OUTPUT. */
- char *output_file;
- /* File named by SHARELIB. */
- char *sharelib_file;
- /* Start procedure name (START). */
- char *start_procedure;
- /* VERBOSE. */
- bfd_boolean verbose;
- /* RPC description file (XDCDATA). */
- char *rpc_file;
- /* The number of serious errors that have occurred. */
- int parse_errors;
- /* The current symbol prefix when reading a list of import or export
- symbols. */
- static char *symbol_prefix;
- /* Parser error message handler. */
- #define yyerror(msg) nlmheader_error (msg);
- /* Local functions. */
- static int yylex (void);
- static void nlmlex_file_push (const char *);
- static bfd_boolean nlmlex_file_open (const char *);
- static int nlmlex_buf_init (void);
- static char nlmlex_buf_add (int);
- static long nlmlex_get_number (const char *);
- static void nlmheader_identify (void);
- static void nlmheader_warn (const char *, int);
- static void nlmheader_error (const char *);
- static struct string_list * string_list_cons (char *, struct string_list *);
- static struct string_list * string_list_append (struct string_list *,
- struct string_list *);
- static struct string_list * string_list_append1 (struct string_list *,
- char *);
- static char *xstrdup (const char *);
- %}
- %union
- {
- char *string;
- struct string_list *list;
- };
- /* The reserved words. */
- %token CHECK CODESTART COPYRIGHT CUSTOM DATE DEBUG_K DESCRIPTION EXIT
- %token EXPORT FLAG_ON FLAG_OFF FULLMAP HELP IMPORT INPUT MAP MESSAGES
- %token MODULE MULTIPLE OS_DOMAIN OUTPUT PSEUDOPREEMPTION REENTRANT
- %token SCREENNAME SHARELIB STACK START SYNCHRONIZE
- %token THREADNAME TYPE VERBOSE VERSIONK XDCDATA
- /* Arguments. */
- %token <string> STRING
- %token <string> QUOTED_STRING
- /* Typed non-terminals. */
- %type <list> symbol_list_opt symbol_list string_list
- %type <string> symbol
- %%
- /* Keywords must start in the leftmost column of the file. Arguments
- may appear anywhere else. The lexer uses this to determine what
- token to return, so we don't have to worry about it here. */
- /* The entire file is just a list of commands. */
- file:
- commands
- ;
- /* A possibly empty list of commands. */
- commands:
- /* May be empty. */
- | command commands
- ;
- /* A single command. There is where most of the work takes place. */
- command:
- CHECK STRING
- {
- check_procedure = $2;
- }
- | CODESTART STRING
- {
- nlmheader_warn (_("CODESTART is not implemented; sorry"), -1);
- free ($2);
- }
- | COPYRIGHT QUOTED_STRING
- {
- int len;
- strncpy (copyright_hdr->stamp, "CoPyRiGhT=", 10);
- len = strlen ($2);
- if (len >= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH)
- {
- nlmheader_warn (_("copyright string is too long"),
- NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1);
- len = NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1;
- }
- copyright_hdr->copyrightMessageLength = len;
- strncpy (copyright_hdr->copyrightMessage, $2, len);
- copyright_hdr->copyrightMessage[len] = '\0';
- free ($2);
- }
- | CUSTOM STRING
- {
- custom_file = $2;
- }
- | DATE STRING STRING STRING
- {
- /* We don't set the version stamp here, because we use the
- version stamp to detect whether the required VERSION
- keyword was given. */
- version_hdr->month = nlmlex_get_number ($2);
- version_hdr->day = nlmlex_get_number ($3);
- version_hdr->year = nlmlex_get_number ($4);
- free ($2);
- free ($3);
- free ($4);
- if (version_hdr->month < 1 || version_hdr->month > 12)
- nlmheader_warn (_("illegal month"), -1);
- if (version_hdr->day < 1 || version_hdr->day > 31)
- nlmheader_warn (_("illegal day"), -1);
- if (version_hdr->year < 1900 || version_hdr->year > 3000)
- nlmheader_warn (_("illegal year"), -1);
- }
- | DEBUG_K
- {
- debug_info = TRUE;
- }
- | DESCRIPTION QUOTED_STRING
- {
- int len;
- len = strlen ($2);
- if (len > NLM_MAX_DESCRIPTION_LENGTH)
- {
- nlmheader_warn (_("description string is too long"),
- NLM_MAX_DESCRIPTION_LENGTH);
- len = NLM_MAX_DESCRIPTION_LENGTH;
- }
- var_hdr->descriptionLength = len;
- strncpy (var_hdr->descriptionText, $2, len);
- var_hdr->descriptionText[len] = '\0';
- free ($2);
- }
- | EXIT STRING
- {
- exit_procedure = $2;
- }
- | EXPORT
- {
- symbol_prefix = NULL;
- }
- symbol_list_opt
- {
- export_symbols = string_list_append (export_symbols, $3);
- }
- | FLAG_ON STRING
- {
- fixed_hdr->flags |= nlmlex_get_number ($2);
- free ($2);
- }
- | FLAG_OFF STRING
- {
- fixed_hdr->flags &=~ nlmlex_get_number ($2);
- free ($2);
- }
- | FULLMAP
- {
- map_file = "";
- full_map = TRUE;
- }
- | FULLMAP STRING
- {
- map_file = $2;
- full_map = TRUE;
- }
- | HELP STRING
- {
- help_file = $2;
- }
- | IMPORT
- {
- symbol_prefix = NULL;
- }
- symbol_list_opt
- {
- import_symbols = string_list_append (import_symbols, $3);
- }
- | INPUT string_list
- {
- input_files = string_list_append (input_files, $2);
- }
- | MAP
- {
- map_file = "";
- }
- | MAP STRING
- {
- map_file = $2;
- }
- | MESSAGES STRING
- {
- message_file = $2;
- }
- | MODULE string_list
- {
- modules = string_list_append (modules, $2);
- }
- | MULTIPLE
- {
- fixed_hdr->flags |= 0x2;
- }
- | OS_DOMAIN
- {
- fixed_hdr->flags |= 0x10;
- }
- | OUTPUT STRING
- {
- if (output_file == NULL)
- output_file = $2;
- else
- nlmheader_warn (_("ignoring duplicate OUTPUT statement"), -1);
- }
- | PSEUDOPREEMPTION
- {
- fixed_hdr->flags |= 0x8;
- }
- | REENTRANT
- {
- fixed_hdr->flags |= 0x1;
- }
- | SCREENNAME QUOTED_STRING
- {
- int len;
- len = strlen ($2);
- if (len >= NLM_MAX_SCREEN_NAME_LENGTH)
- {
- nlmheader_warn (_("screen name is too long"),
- NLM_MAX_SCREEN_NAME_LENGTH);
- len = NLM_MAX_SCREEN_NAME_LENGTH;
- }
- var_hdr->screenNameLength = len;
- strncpy (var_hdr->screenName, $2, len);
- var_hdr->screenName[NLM_MAX_SCREEN_NAME_LENGTH] = '\0';
- free ($2);
- }
- | SHARELIB STRING
- {
- sharelib_file = $2;
- }
- | STACK STRING
- {
- var_hdr->stackSize = nlmlex_get_number ($2);
- free ($2);
- }
- | START STRING
- {
- start_procedure = $2;
- }
- | SYNCHRONIZE
- {
- fixed_hdr->flags |= 0x4;
- }
- | THREADNAME QUOTED_STRING
- {
- int len;
- len = strlen ($2);
- if (len >= NLM_MAX_THREAD_NAME_LENGTH)
- {
- nlmheader_warn (_("thread name is too long"),
- NLM_MAX_THREAD_NAME_LENGTH);
- len = NLM_MAX_THREAD_NAME_LENGTH;
- }
- var_hdr->threadNameLength = len;
- strncpy (var_hdr->threadName, $2, len);
- var_hdr->threadName[len] = '\0';
- free ($2);
- }
- | TYPE STRING
- {
- fixed_hdr->moduleType = nlmlex_get_number ($2);
- free ($2);
- }
- | VERBOSE
- {
- verbose = TRUE;
- }
- | VERSIONK STRING STRING STRING
- {
- long val;
- strncpy (version_hdr->stamp, "VeRsIoN#", 8);
- version_hdr->majorVersion = nlmlex_get_number ($2);
- val = nlmlex_get_number ($3);
- if (val < 0 || val > 99)
- nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
- -1);
- else
- version_hdr->minorVersion = val;
- val = nlmlex_get_number ($4);
- if (val < 0)
- nlmheader_warn (_("illegal revision number (must be between 0 and 26)"),
- -1);
- else if (val > 26)
- version_hdr->revision = 0;
- else
- version_hdr->revision = val;
- free ($2);
- free ($3);
- free ($4);
- }
- | VERSIONK STRING STRING
- {
- long val;
- strncpy (version_hdr->stamp, "VeRsIoN#", 8);
- version_hdr->majorVersion = nlmlex_get_number ($2);
- val = nlmlex_get_number ($3);
- if (val < 0 || val > 99)
- nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
- -1);
- else
- version_hdr->minorVersion = val;
- version_hdr->revision = 0;
- free ($2);
- free ($3);
- }
- | XDCDATA STRING
- {
- rpc_file = $2;
- }
- ;
- /* A possibly empty list of symbols. */
- symbol_list_opt:
- /* Empty. */
- {
- $$ = NULL;
- }
- | symbol_list
- {
- $$ = $1;
- }
- ;
- /* A list of symbols in an import or export list. Prefixes may appear
- in parentheses. We need to use left recursion here to avoid
- building up a large import list on the parser stack. */
- symbol_list:
- symbol
- {
- $$ = string_list_cons ($1, NULL);
- }
- | symbol_prefix
- {
- $$ = NULL;
- }
- | symbol_list symbol
- {
- $$ = string_list_append1 ($1, $2);
- }
- | symbol_list symbol_prefix
- {
- $$ = $1;
- }
- ;
- /* A prefix for subsequent symbols. */
- symbol_prefix:
- '(' STRING ')'
- {
- if (symbol_prefix != NULL)
- free (symbol_prefix);
- symbol_prefix = $2;
- }
- ;
- /* A single symbol. */
- symbol:
- STRING
- {
- if (symbol_prefix == NULL)
- $$ = $1;
- else
- {
- $$ = xmalloc (strlen (symbol_prefix) + strlen ($1) + 2);
- sprintf ($$, "%s@%s", symbol_prefix, $1);
- free ($1);
- }
- }
- ;
- /* A list of strings. */
- string_list:
- /* May be empty. */
- {
- $$ = NULL;
- }
- | STRING string_list
- {
- $$ = string_list_cons ($1, $2);
- }
- ;
- %%
- /* If strerror is just a macro, we want to use the one from libiberty
- since it will handle undefined values. */
- #undef strerror
- extern char *strerror (int);
- /* The lexer is simple, too simple for flex. Keywords are only
- recognized at the start of lines. Everything else must be an
- argument. A comma is treated as whitespace. */
- /* The states the lexer can be in. */
- enum lex_state
- {
- /* At the beginning of a line. */
- BEGINNING_OF_LINE,
- /* In the middle of a line. */
- IN_LINE
- };
- /* We need to keep a stack of files to handle file inclusion. */
- struct input
- {
- /* The file to read from. */
- FILE *file;
- /* The name of the file. */
- char *name;
- /* The current line number. */
- int lineno;
- /* The current state. */
- enum lex_state state;
- /* The next file on the stack. */
- struct input *next;
- };
- /* The current input file. */
- static struct input current;
- /* The character which introduces comments. */
- #define COMMENT_CHAR '#'
- /* Start the lexer going on the main input file. */
- bfd_boolean
- nlmlex_file (const char *name)
- {
- current.next = NULL;
- return nlmlex_file_open (name);
- }
- /* Start the lexer going on a subsidiary input file. */
- static void
- nlmlex_file_push (const char *name)
- {
- struct input *push;
- push = (struct input *) xmalloc (sizeof (struct input));
- *push = current;
- if (nlmlex_file_open (name))
- current.next = push;
- else
- {
- current = *push;
- free (push);
- }
- }
- /* Start lexing from a file. */
- static bfd_boolean
- nlmlex_file_open (const char *name)
- {
- current.file = fopen (name, "r");
- if (current.file == NULL)
- {
- fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno));
- ++parse_errors;
- return FALSE;
- }
- current.name = xstrdup (name);
- current.lineno = 1;
- current.state = BEGINNING_OF_LINE;
- return TRUE;
- }
- /* Table used to turn keywords into tokens. */
- struct keyword_tokens_struct
- {
- const char *keyword;
- int token;
- };
- static struct keyword_tokens_struct keyword_tokens[] =
- {
- { "CHECK", CHECK },
- { "CODESTART", CODESTART },
- { "COPYRIGHT", COPYRIGHT },
- { "CUSTOM", CUSTOM },
- { "DATE", DATE },
- { "DEBUG", DEBUG_K },
- { "DESCRIPTION", DESCRIPTION },
- { "EXIT", EXIT },
- { "EXPORT", EXPORT },
- { "FLAG_ON", FLAG_ON },
- { "FLAG_OFF", FLAG_OFF },
- { "FULLMAP", FULLMAP },
- { "HELP", HELP },
- { "IMPORT", IMPORT },
- { "INPUT", INPUT },
- { "MAP", MAP },
- { "MESSAGES", MESSAGES },
- { "MODULE", MODULE },
- { "MULTIPLE", MULTIPLE },
- { "OS_DOMAIN", OS_DOMAIN },
- { "OUTPUT", OUTPUT },
- { "PSEUDOPREEMPTION", PSEUDOPREEMPTION },
- { "REENTRANT", REENTRANT },
- { "SCREENNAME", SCREENNAME },
- { "SHARELIB", SHARELIB },
- { "STACK", STACK },
- { "STACKSIZE", STACK },
- { "START", START },
- { "SYNCHRONIZE", SYNCHRONIZE },
- { "THREADNAME", THREADNAME },
- { "TYPE", TYPE },
- { "VERBOSE", VERBOSE },
- { "VERSION", VERSIONK },
- { "XDCDATA", XDCDATA }
- };
- #define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0]))
- /* The lexer accumulates strings in these variables. */
- static char *lex_buf;
- static int lex_size;
- static int lex_pos;
- /* Start accumulating strings into the buffer. */
- #define BUF_INIT() \
- ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ()))
- static int
- nlmlex_buf_init (void)
- {
- lex_size = 10;
- lex_buf = xmalloc (lex_size + 1);
- lex_pos = 0;
- return 0;
- }
- /* Finish a string in the buffer. */
- #define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0'))
- /* Accumulate a character into the buffer. */
- #define BUF_ADD(c) \
- ((void) (lex_pos < lex_size \
- ? lex_buf[lex_pos++] = (c) \
- : nlmlex_buf_add (c)))
- static char
- nlmlex_buf_add (int c)
- {
- if (lex_pos >= lex_size)
- {
- lex_size *= 2;
- lex_buf = xrealloc (lex_buf, lex_size + 1);
- }
- return lex_buf[lex_pos++] = c;
- }
- /* The lexer proper. This is called by the bison generated parsing
- code. */
- static int
- yylex (void)
- {
- int c;
- tail_recurse:
- c = getc (current.file);
- /* Commas are treated as whitespace characters. */
- while (ISSPACE (c) || c == ',')
- {
- current.state = IN_LINE;
- if (c == '\n')
- {
- ++current.lineno;
- current.state = BEGINNING_OF_LINE;
- }
- c = getc (current.file);
- }
- /* At the end of the file we either pop to the previous file or
- finish up. */
- if (c == EOF)
- {
- fclose (current.file);
- free (current.name);
- if (current.next == NULL)
- return 0;
- else
- {
- struct input *next;
- next = current.next;
- current = *next;
- free (next);
- goto tail_recurse;
- }
- }
- /* A comment character always means to drop everything until the
- next newline. */
- if (c == COMMENT_CHAR)
- {
- do
- {
- c = getc (current.file);
- }
- while (c != '\n');
- ++current.lineno;
- current.state = BEGINNING_OF_LINE;
- goto tail_recurse;
- }
- /* An '@' introduces an include file. */
- if (c == '@')
- {
- do
- {
- c = getc (current.file);
- if (c == '\n')
- ++current.lineno;
- }
- while (ISSPACE (c));
- BUF_INIT ();
- while (! ISSPACE (c) && c != EOF)
- {
- BUF_ADD (c);
- c = getc (current.file);
- }
- BUF_FINISH ();
- ungetc (c, current.file);
- nlmlex_file_push (lex_buf);
- goto tail_recurse;
- }
- /* A non-space character at the start of a line must be the start of
- a keyword. */
- if (current.state == BEGINNING_OF_LINE)
- {
- BUF_INIT ();
- while (ISALNUM (c) || c == '_')
- {
- BUF_ADD (TOUPPER (c));
- c = getc (current.file);
- }
- BUF_FINISH ();
- if (c != EOF && ! ISSPACE (c) && c != ',')
- {
- nlmheader_identify ();
- fprintf (stderr, _("%s:%d: illegal character in keyword: %c\n"),
- current.name, current.lineno, c);
- }
- else
- {
- unsigned int i;
- for (i = 0; i < KEYWORD_COUNT; i++)
- {
- if (lex_buf[0] == keyword_tokens[i].keyword[0]
- && strcmp (lex_buf, keyword_tokens[i].keyword) == 0)
- {
- /* Pushing back the final whitespace avoids worrying
- about \n here. */
- ungetc (c, current.file);
- current.state = IN_LINE;
- return keyword_tokens[i].token;
- }
- }
- nlmheader_identify ();
- fprintf (stderr, _("%s:%d: unrecognized keyword: %s\n"),
- current.name, current.lineno, lex_buf);
- }
- ++parse_errors;
- /* Treat the rest of this line as a comment. */
- ungetc (COMMENT_CHAR, current.file);
- goto tail_recurse;
- }
- /* Parentheses just represent themselves. */
- if (c == '(' || c == ')')
- return c;
- /* Handle quoted strings. */
- if (c == '"' || c == '\'')
- {
- int quote;
- int start_lineno;
- quote = c;
- start_lineno = current.lineno;
- c = getc (current.file);
- BUF_INIT ();
- while (c != quote && c != EOF)
- {
- BUF_ADD (c);
- if (c == '\n')
- ++current.lineno;
- c = getc (current.file);
- }
- BUF_FINISH ();
- if (c == EOF)
- {
- nlmheader_identify ();
- fprintf (stderr, _("%s:%d: end of file in quoted string\n"),
- current.name, start_lineno);
- ++parse_errors;
- }
- /* FIXME: Possible memory leak. */
- yylval.string = xstrdup (lex_buf);
- return QUOTED_STRING;
- }
- /* Gather a generic argument. */
- BUF_INIT ();
- while (! ISSPACE (c)
- && c != ','
- && c != COMMENT_CHAR
- && c != '('
- && c != ')')
- {
- BUF_ADD (c);
- c = getc (current.file);
- }
- BUF_FINISH ();
- ungetc (c, current.file);
- /* FIXME: Possible memory leak. */
- yylval.string = xstrdup (lex_buf);
- return STRING;
- }
- /* Get a number from a string. */
- static long
- nlmlex_get_number (const char *s)
- {
- long ret;
- char *send;
- ret = strtol (s, &send, 10);
- if (*send != '\0')
- nlmheader_warn (_("bad number"), -1);
- return ret;
- }
- /* Prefix the nlmconv warnings with a note as to where they come from.
- We don't use program_name on every warning, because then some
- versions of the emacs next-error function can't recognize the line
- number. */
- static void
- nlmheader_identify (void)
- {
- static int done;
- if (! done)
- {
- fprintf (stderr, _("%s: problems in NLM command language input:\n"),
- program_name);
- done = 1;
- }
- }
- /* Issue a warning. */
- static void
- nlmheader_warn (const char *s, int imax)
- {
- nlmheader_identify ();
- fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s);
- if (imax != -1)
- fprintf (stderr, " (max %d)", imax);
- fprintf (stderr, "\n");
- }
- /* Report an error. */
- static void
- nlmheader_error (const char *s)
- {
- nlmheader_warn (s, -1);
- ++parse_errors;
- }
- /* Add a string to a string list. */
- static struct string_list *
- string_list_cons (char *s, struct string_list *l)
- {
- struct string_list *ret;
- ret = (struct string_list *) xmalloc (sizeof (struct string_list));
- ret->next = l;
- ret->string = s;
- return ret;
- }
- /* Append a string list to another string list. */
- static struct string_list *
- string_list_append (struct string_list *l1, struct string_list *l2)
- {
- register struct string_list **pp;
- for (pp = &l1; *pp != NULL; pp = &(*pp)->next)
- ;
- *pp = l2;
- return l1;
- }
- /* Append a string to a string list. */
- static struct string_list *
- string_list_append1 (struct string_list *l, char *s)
- {
- struct string_list *n;
- register struct string_list **pp;
- n = (struct string_list *) xmalloc (sizeof (struct string_list));
- n->next = NULL;
- n->string = s;
- for (pp = &l; *pp != NULL; pp = &(*pp)->next)
- ;
- *pp = n;
- return l;
- }
- /* Duplicate a string in memory. */
- static char *
- xstrdup (const char *s)
- {
- unsigned long len;
- char *ret;
- len = strlen (s);
- ret = xmalloc (len + 1);
- strcpy (ret, s);
- return ret;
- }
|