📄 nlmheader.y
字号:
%%/* If strerror is just a macro, we want to use the one from libiberty since it will handle undefined values. */#undef strerrorextern char *strerror ();/* 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. */booleannlmlex_file (name) const char *name;{ current.next = NULL; return nlmlex_file_open (name);}/* Start the lexer going on a subsidiary input file. */static voidnlmlex_file_push (name) 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 booleannlmlex_file_open (name) 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;};struct keyword_tokens_struct keyword_tokens[] ={ { "CHECK", CHECK }, { "CODESTART", CODESTART }, { "COPYRIGHT", COPYRIGHT }, { "CUSTOM", CUSTOM }, { "DATE", DATE }, { "DEBUG", DEBUG }, { "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 intnlmlex_buf_init (){ 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 charnlmlex_buf_add (c) 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 intyylex (){ int c;tail_recurse: c = getc (current.file); /* Commas are treated as whitespace characters. */ while (isspace ((unsigned char) 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 ((unsigned char) c)); BUF_INIT (); while (! isspace ((unsigned char) 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 ((unsigned char) c) || c == '_') { if (islower ((unsigned char) c)) BUF_ADD (toupper ((unsigned char) c)); else BUF_ADD (c); c = getc (current.file); } BUF_FINISH (); if (c != EOF && ! isspace ((unsigned char) 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 longnlmlex_get_number (s) 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 voidnlmheader_identify (){ static int done; if (! done) { fprintf (stderr, _("%s: problems in NLM command language input:\n"), program_name); done = 1; }}/* Issue a warning. */static voidnlmheader_warn (s, imax) 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 voidnlmheader_error (s) const char *s;{ nlmheader_warn (s, -1); ++parse_errors;}/* Add a string to a string list. */static struct string_list *string_list_cons (s, l) 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 (l1, l2) 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 (l, s) 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 (s) const char *s;{ unsigned long len; char *ret; len = strlen (s); ret = xmalloc (len + 1); strcpy (ret, s); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -