home *** CD-ROM | disk | FTP | other *** search
- // -*- C++ -*-
- /* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.uucp)
-
- This file is part of groff.
-
- groff 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 1, or (at your option) any later
- version.
-
- groff 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 groff; see the file LICENSE. If not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "eqn.h"
- #include "eqn.tab.h"
- #include "stringclass.h"
- #include "ptable.h"
-
- struct definition {
- char is_macro;
- char is_simple;
- union {
- int tok;
- char *contents;
- };
- definition();
- ~definition();
- };
-
- definition::definition() : is_macro(1), contents(0), is_simple(0)
- {
- }
-
- definition::~definition()
- {
- if (is_macro)
- delete contents;
- }
-
- declare_ptable(definition)
- implement_ptable(definition)
-
- PTABLE(definition) macro_table;
-
- static struct {
- const char *name;
- int token;
- } token_table[] = {
- "over", OVER,
- "smallover", SMALLOVER,
- "sqrt", SQRT,
- "sub", SUB,
- "sup", SUP,
- "lpile", LPILE,
- "rpile", RPILE,
- "cpile", CPILE,
- "pile", PILE,
- "left", LEFT,
- "right", RIGHT,
- "to", TO,
- "from", FROM,
- "size", SIZE,
- "font", FONT,
- "roman", ROMAN,
- "bold", BOLD,
- "italic", ITALIC,
- "fat", FAT,
- "bar", BAR,
- "under", UNDER,
- "accent", ACCENT,
- "uaccent", UACCENT,
- "above", ABOVE,
- "fwd", FWD,
- "back", BACK,
- "down", DOWN,
- "up", UP,
- "matrix", MATRIX,
- "col", COL,
- "lcol", LCOL,
- "rcol", RCOL,
- "ccol", CCOL,
- "mark", MARK,
- "lineup", LINEUP,
- "space", SPACE,
- "gfont", GFONT,
- "gsize", GSIZE,
- "define", DEFINE,
- "sdefine", SDEFINE,
- "ndefine", NDEFINE,
- "tdefine", TDEFINE,
- "undef", UNDEF,
- "ifdef", IFDEF,
- "include", INCLUDE,
- "copy", INCLUDE,
- "delim", DELIM,
- "chartype", CHARTYPE,
- "type", TYPE,
- "vcenter", VCENTER,
- "set", SET,
- "opprime", PRIME,
- "grfont", GRFONT,
- "gbfont", GBFONT,
- "split", SPLIT,
- "nosplit", NOSPLIT,
- };
-
- static struct {
- const char *name;
- const char *def;
- } def_table[] = {
- "ALPHA", "\\(*A",
- "BETA", "\\(*B",
- "CHI", "\\(*X",
- "DELTA", "\\(*D",
- "EPSILON", "\\(*E",
- "ETA", "\\(*Y",
- "GAMMA", "\\(*G",
- "IOTA", "\\(*I",
- "KAPPA", "\\(*K",
- "LAMBDA", "\\(*L",
- "MU", "\\(*M",
- "NU", "\\(*N",
- "OMEGA", "\\(*W",
- "OMICRON", "\\(*O",
- "PHI", "\\(*F",
- "PI", "\\(*P",
- "PSI", "\\(*Q",
- "RHO", "\\(*R",
- "SIGMA", "\\(*S",
- "TAU", "\\(*T",
- "THETA", "\\(*H",
- "UPSILON", "\\(*U",
- "XI", "\\(*C",
- "ZETA", "\\(*Z",
- "Alpha", "\\(*A",
- "Beta", "\\(*B",
- "Chi", "\\(*X",
- "Delta", "\\(*D",
- "Epsilon", "\\(*E",
- "Eta", "\\(*Y",
- "Gamma", "\\(*G",
- "Iota", "\\(*I",
- "Kappa", "\\(*K",
- "Lambda", "\\(*L",
- "Mu", "\\(*M",
- "Nu", "\\(*N",
- "Omega", "\\(*W",
- "Omicron", "\\(*O",
- "Phi", "\\(*F",
- "Pi", "\\(*P",
- "Psi", "\\(*Q",
- "Rho", "\\(*R",
- "Sigma", "\\(*S",
- "Tau", "\\(*T",
- "Theta", "\\(*H",
- "Upsilon", "\\(*U",
- "Xi", "\\(*C",
- "Zeta", "\\(*Z",
- "alpha", "\\(*a",
- "beta", "\\(*b",
- "chi", "\\(*x",
- "delta", "\\(*d",
- "epsilon", "\\(*e",
- "eta", "\\(*y",
- "gamma", "\\(*g",
- "iota", "\\(*i",
- "kappa", "\\(*k",
- "lambda", "\\(*l",
- "mu", "\\(*m",
- "nu", "\\(*n",
- "omega", "\\(*w",
- "omicron", "\\(*o",
- "phi", "\\(*f",
- "pi", "\\(*p",
- "psi", "\\(*q",
- "rho", "\\(*r",
- "sigma", "\\(*s",
- "tau", "\\(*t",
- "theta", "\\(*h",
- "upsilon", "\\(*u",
- "xi", "\\(*c",
- "zeta", "\\(*z",
- "max", "{type \"operator\" roman \"max\"}",
- "min", "{type \"operator\" roman \"min\"}",
- "lim", "{type \"operator\" roman \"lim\"}",
- "sin", "{type \"operator\" roman \"sin\"}",
- "cos", "{type \"operator\" roman \"cos\"}",
- "tan", "{type \"operator\" roman \"tan\"}",
- "sinh", "{type \"operator\" roman \"sinh\"}",
- "cosh", "{type \"operator\" roman \"cosh\"}",
- "tanh", "{type \"operator\" roman \"tanh\"}",
- "arc", "{type \"operator\" roman \"arc\"}",
- "log", "{type \"operator\" roman \"log\"}",
- "ln", "{type \"operator\" roman \"ln\"}",
- "exp", "{type \"operator\" roman \"exp\"}",
- "Re", "{type \"operator\" roman \"Re\"}",
- "Im", "{type \"operator\" roman \"Im\"}",
- "det", "{type \"operator\" roman \"det\"}",
- "and", "{roman \"and\"}",
- "if", "{roman \"if\"}",
- "for", "{roman \"for\"}",
- "sum", "{type \"operator\" vcenter size +5 \\(*S}",
- "prod", "{type \"operator\" vcenter size +5 \\(*P}",
- "int", "{type \"operator\" vcenter size +8 \\(is}",
- "union", "{type \"operator\" vcenter size +5 \\(cu}",
- "inter", "{type \"operator\" vcenter size +5 \\(ca}",
- "times", "type \"binary\" \\(mu",
- "ldots", "type \"inner\" { . . . }",
- "inf", "\\(if",
- "partial", "\\(pd",
- "nothing", "\"\"",
- "half", "{1 smallover 2}",
- "hat_def", "\"^\"",
- "hat", "accent { hat_def }",
- "dot_def", "back 15 \"\\v'-52M'.\\v'52M'\"",
- "dot", "accent { dot_def }",
- "dotdot_def", "back 25 \"\\v'-52M'..\\v'52M'\"",
- "dotdot", "accent { dotdot_def }",
- "tilde_def", "\"~\"",
- "tilde", "accent { tilde_def }",
- "utilde_def", "\"\\v'75M'~\\v'-75M'\"",
- "utilde", "uaccent { utilde_def }",
- "vec_def", "up 52 size -5 \\(->",
- "vec", "accent { vec_def }",
- "dyad_def", "up 52 size -5 {\\(<- back 60 \\(->}",
- "dyad", "accent { dyad_def }",
- "==", "type \"relation\" \\(==",
- "!=", "type \"relation\" \\(!=",
- "+-", "type \"binary\" \\(+-",
- "->", "type \"relation\" \\(->",
- "<-", "type \"relation\" \\(<-",
- "<<", "{ < back 20 < }",
- ">>", "{ > back 20 > }",
- "...", "type \"inner\" vcenter { . . . }",
- "prime", "'",
- "approx", "type \"relation\" \"\\(~=\"",
- "grad", "\\(gr",
- "del", "\\(gr",
- "cdot", "type \"binary\" vcenter ."
- };
-
- void init_table(const char *device)
- {
- for (int i = 0; i < sizeof(token_table)/sizeof(token_table[0]); i++) {
- definition *def = new definition;
- def->is_macro = 0;
- def->tok = token_table[i].token;
- macro_table.define(token_table[i].name, def);
- }
- for (i = 0; i < sizeof(def_table)/sizeof(def_table[0]); i++) {
- definition *def = new definition;
- def->is_macro = 1;
- def->contents = strsave(def_table[i].def);
- def->is_simple = 1;
- macro_table.define(def_table[i].name, def);
- }
- definition *def = new definition;
- def->is_macro = 1;
- def->contents = strsave("1");
- macro_table.define(device, def);
- }
-
- class input {
- input *next;
- public:
- input(input *p);
- virtual ~input();
- virtual int get() = 0;
- virtual int peek() = 0;
- virtual int get_location(char **, int *);
-
- friend int get_char();
- friend int peek_char();
- friend int get_location(char **, int *);
- friend void init_lex(const char *str, const char *filename, int lineno);
- };
-
- class file_input : public input {
- FILE *fp;
- char *filename;
- int lineno;
- string line;
- const char *ptr;
- int read_line();
- public:
- file_input(FILE *, const char *, input *);
- ~file_input();
- int get();
- int peek();
- int get_location(char **, int *);
- };
-
-
- class macro_input : public input {
- char *s;
- char *p;
- public:
- macro_input(const char *, input *);
- ~macro_input();
- int get();
- int peek();
- };
-
- class top_input : public macro_input {
- char *filename;
- int lineno;
- public:
- top_input(const char *, const char *, int, input *);
- ~top_input();
- int get();
- int get_location(char **, int *);
- };
-
- class argument_macro_input: public input {
- char *s;
- char *p;
- char *ap;
- int argc;
- char *argv[9];
- public:
- argument_macro_input(const char *, int, char **, input *);
- ~argument_macro_input();
- int get();
- int peek();
- };
-
- input::input(input *x) : next(x)
- {
- }
-
- input::~input()
- {
- }
-
- int input::get_location(char **, int *)
- {
- return 0;
- }
-
- file_input::file_input(FILE *f, const char *fn, input *p)
- : input(p), lineno(0), ptr("")
- {
- fp = f;
- filename = strsave(fn);
- }
-
- file_input::~file_input()
- {
- delete filename;
- fclose(fp);
- }
-
- int file_input::read_line()
- {
- for (;;) {
- line.clear();
- lineno++;
- for (;;) {
- int c = getc(fp);
- if (c == EOF)
- break;
- else if (illegal_input_char(c))
- lex_error("illegal input character code %1", c);
- else {
- line += char(c);
- if (c == '\n')
- break;
- }
- }
- if (line.length() == 0)
- return 0;
- if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'E'
- && (line[2] == 'Q' || line[2] == 'N')
- && (line.length() == 3 || line[3] == ' ' || line[3] == '\n'
- || compatible_flag))) {
- line += '\0';
- ptr = line.contents();
- return 1;
- }
- }
- }
-
- int file_input::get()
- {
- if (*ptr != '\0' || read_line())
- return *ptr++ & 0377;
- else
- return EOF;
- }
-
- int file_input::peek()
- {
- if (*ptr != '\0' || read_line())
- return *ptr;
- else
- return EOF;
- }
-
- int file_input::get_location(char **fnp, int *lnp)
- {
- *fnp = filename;
- *lnp = lineno;
- return 1;
- }
-
- macro_input::macro_input(const char *str, input *x) : input(x)
- {
- p = s = strsave(str);
- }
-
- macro_input::~macro_input()
- {
- delete s;
- }
-
- int macro_input::get()
- {
- if (p == 0 || *p == '\0')
- return EOF;
- else
- return *p++ & 0377;
- }
-
- int macro_input::peek()
- {
- if (p == 0 || *p == '\0')
- return EOF;
- else
- return *p & 0377;
- }
-
- top_input::top_input(const char *str, const char *fn, int ln, input *x)
- : macro_input(str, x), lineno(ln)
- {
- filename = strsave(fn);
- }
-
- top_input::~top_input()
- {
- delete filename;
- }
-
- int top_input::get()
- {
- int c = macro_input::get();
- if (c == '\n')
- lineno++;
- return c;
- }
-
- int top_input::get_location(char **fnp, int *lnp)
- {
- *fnp = filename;
- *lnp = lineno;
- return 1;
- }
-
- #define ARG1 11
-
- argument_macro_input::argument_macro_input(const char *body, int ac,
- char **av, input *x)
- : input(x), argc(ac), ap(0)
- {
- for (int i = 0; i < argc; i++)
- argv[i] = av[i];
- p = s = strsave(body);
- int j = 0;
- for (i = 0; s[i] != '\0'; i++)
- if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') {
- if (s[i+1] != '0')
- s[j++] = ARG1 + s[++i] - '1';
- }
- else
- s[j++] = s[i];
- s[j] = '\0';
- }
-
-
- argument_macro_input::~argument_macro_input()
- {
- for (int i = 0; i < argc; i++)
- delete argv[i];
- delete s;
- }
-
- int argument_macro_input::get()
- {
- if (ap) {
- if (*ap != '\0')
- return *ap++ & 0377;
- ap = 0;
- }
- if (p == 0)
- return EOF;
- while (*p >= ARG1 && *p <= ARG1 + 8) {
- int i = *p++ - ARG1;
- if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
- ap = argv[i];
- return *ap++ & 0377;
- }
- }
- if (*p == '\0')
- return EOF;
- return *p++ & 0377;
- }
-
- int argument_macro_input::peek()
- {
- if (ap) {
- if (*ap != '\0')
- return *ap & 0377;
- ap = 0;
- }
- if (p == 0)
- return EOF;
- while (*p >= ARG1 && *p <= ARG1 + 8) {
- int i = *p++ - ARG1;
- if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
- ap = argv[i];
- return *ap & 0377;
- }
- }
- if (*p == '\0')
- return EOF;
- return *p & 0377;
- }
-
- static input *current_input = 0;
-
- /* we insert a newline between input from different levels */
-
- int get_char()
- {
- if (current_input == 0)
- return EOF;
- else {
- int c = current_input->get();
- if (c != EOF)
- return c;
- else {
- input *tem = current_input;
- current_input = current_input->next;
- delete tem;
- return '\n';
- }
- }
- }
-
- int peek_char()
- {
- if (current_input == 0)
- return EOF;
- else {
- int c = current_input->peek();
- if (c != EOF)
- return c;
- else
- return '\n';
- }
- }
-
- int get_location(char **fnp, int *lnp)
- {
- for (input *p = current_input; p; p = p->next)
- if (p->get_location(fnp, lnp))
- return 1;
- return 0;
- }
-
- string token_buffer;
- const int NCONTEXT = 4;
- string context_ring[NCONTEXT];
- int context_index = 0;
-
- void flush_context()
- {
- for (int i = 0; i < NCONTEXT; i++)
- context_ring[i] = "";
- context_index = 0;
- }
-
- void show_context()
- {
- int i = context_index;
- fputs(" context is\n\t", stderr);
- for (;;) {
- int j = (i + 1) % NCONTEXT;
- if (j == context_index) {
- fputs(">>> ", stderr);
- put_string(context_ring[i], stderr);
- fputs(" <<<", stderr);
- break;
- }
- else if (context_ring[i].length() > 0) {
- put_string(context_ring[i], stderr);
- putc(' ', stderr);
- }
- i = j;
- }
- putc('\n', stderr);
- }
-
- void add_context(const string &s)
- {
- context_ring[context_index] = s;
- context_index = (context_index + 1) % NCONTEXT;
- }
-
- void add_context(char c)
- {
- context_ring[context_index] = c;
- context_index = (context_index + 1) % NCONTEXT;
- }
-
- void add_quoted_context(const string &s)
- {
- string &r = context_ring[context_index];
- r = '"';
- for (int i = 0; i < s.length(); i++)
- if (s[i] == '"')
- r += "\\\"";
- else
- r += s[i];
- r += '"';
- context_index = (context_index + 1) % NCONTEXT;
- }
-
- void init_lex(const char *str, const char *filename, int lineno)
- {
- while (current_input != 0) {
- input *tem = current_input;
- current_input = current_input->next;
- delete tem;
- }
- current_input = new top_input(str, filename, lineno, 0);
- flush_context();
- }
-
-
- void get_delimited_text()
- {
- char *filename;
- int lineno;
- int got_location = get_location(&filename, &lineno);
- int start = get_char();
- while (start == ' ' || start == '\n')
- start = get_char();
- token_buffer.clear();
- if (start == EOF) {
- if (got_location)
- error_with_file_and_line(filename, lineno,
- "end of input while defining macro");
- else
- error("end of input while defining macro");
- return;
- }
- for (;;) {
- int c = get_char();
- if (c == EOF) {
- if (got_location)
- error_with_file_and_line(filename, lineno,
- "end of input while defining macro");
- else
- error("end of input while defining macro");
- add_context(start + token_buffer);
- return;
- }
- if (c == start)
- break;
- token_buffer += char(c);
- }
- add_context(start + token_buffer + start);
- }
-
- void interpolate_macro_with_args(const char *body)
- {
- char *argv[9];
- int argc = 0;
- for (int i = 0; i < 9; i++)
- argv[i] = 0;
- int level = 0;
- int c;
- do {
- token_buffer.clear();
- for (;;) {
- c = get_char();
- if (c == EOF) {
- lex_error("end of input while scanning macro arguments");
- break;
- }
- if (level == 0 && (c == ',' || c == ')')) {
- if (token_buffer.length() > 0) {
- token_buffer += '\0';
- argv[argc] = strsave(token_buffer.contents());
- }
- // for `foo()', argc = 0
- if (argc > 0 || c != ')' || i > 0)
- argc++;
- break;
- }
- token_buffer += char(c);
- if (c == '(')
- level++;
- else if (c == ')')
- level--;
- }
- } while (c != ')' && c != EOF);
- current_input = new argument_macro_input(body, argc, argv, current_input);
- }
-
- /* If lookup flag is non-zero the token will be looked up to see
- if it is macro. If it's 1, it will looked up to see if it's a token.
- */
-
- int get_token(int lookup_flag = 0)
- {
- for (;;) {
- int c = get_char();
- while (c == ' ' || c == '\n')
- c = get_char();
- switch (c) {
- case EOF:
- add_context("end of input");
- return 0;
- case '"':
- {
- int quoted = 0;
- token_buffer.clear();
- for (;;) {
- c = get_char();
- if (c == EOF) {
- lex_error("missing \"");
- break;
- }
- else if (c == '\n') {
- lex_error("newline before end of quoted text");
- break;
- }
- else if (c == '"') {
- if (!quoted)
- break;
- token_buffer[token_buffer.length() - 1] = '"';
- quoted = 0;
- }
- else {
- token_buffer += c;
- quoted = quoted ? 0 : c == '\\';
- }
- }
- }
- add_quoted_context(token_buffer);
- return QUOTED_TEXT;
- case '{':
- case '}':
- case '^':
- case '~':
- case '\t':
- add_context(c);
- return c;
- default:
- {
- int break_flag = 0;
- int quoted = 0;
- token_buffer.clear();
- if (c == '\\')
- quoted = 1;
- else
- token_buffer += c;
- int done = 0;
- while (!done) {
- c = peek_char();
- if (!quoted && lookup_flag != 0 && c == '(') {
- token_buffer += '\0';
- definition *def = macro_table.lookup(token_buffer.contents());
- if (def && def->is_macro && !def->is_simple) {
- (void)get_char(); // skip initial '('
- interpolate_macro_with_args(def->contents);
- break_flag = 1;
- break;
- }
- token_buffer.set_length(token_buffer.length() - 1);
- }
- if (quoted) {
- quoted = 0;
- switch (c) {
- case EOF:
- lex_error("`\\' ignored at end of equation");
- done = 1;
- break;
- case '\n':
- lex_error("`\\' ignored because followed by newline");
- done = 1;
- break;
- case '\t':
- lex_error("`\\' ignored because followed by tab");
- done = 1;
- break;
- case '"':
- (void)get_char();
- token_buffer += '"';
- break;
- default:
- (void)get_char();
- token_buffer += '\\';
- token_buffer += c;
- break;
- }
- }
- else {
- switch (c) {
- case EOF:
- case '{':
- case '}':
- case '^':
- case '~':
- case '"':
- case ' ':
- case '\t':
- case '\n':
- done = 1;
- break;
- case '\\':
- (void)get_char();
- quoted = 1;
- break;
- default:
- (void)get_char();
- token_buffer += char(c);
- break;
- }
- }
- }
- if (break_flag || token_buffer.length() == 0)
- break;
- if (lookup_flag != 0) {
- token_buffer += '\0';
- definition *def = macro_table.lookup(token_buffer.contents());
- token_buffer.set_length(token_buffer.length() - 1);
- if (def) {
- if (def->is_macro) {
- current_input = new macro_input(def->contents, current_input);
- break;
- }
- else if (lookup_flag == 1) {
- add_context(token_buffer);
- return def->tok;
- }
- }
- }
- add_context(token_buffer);
- return TEXT;
- }
- }
- }
- }
-
- void do_include()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad filename for include");
- return;
- }
- token_buffer += '\0';
- const char *filename = token_buffer.contents();
- FILE *fp = fopen(filename, "r");
- if (fp == 0) {
- lex_error("can't open included file `%1'", filename);
- return;
- }
- current_input = new file_input(fp, filename, current_input);
- }
-
- void ignore_definition()
- {
- int t = get_token();
- if (t != TEXT) {
- lex_error("bad definition");
- return;
- }
- get_delimited_text();
- }
-
- void do_definition(int is_simple)
- {
- int t = get_token();
- if (t != TEXT) {
- lex_error("bad definition");
- return;
- }
- token_buffer += '\0';
- const char *name = token_buffer.contents();
- definition *def = macro_table.lookup(name);
- if (def == 0) {
- def = new definition;
- macro_table.define(name, def);
- }
- else if (def->is_macro) {
- delete def->contents;
- }
- get_delimited_text();
- token_buffer += '\0';
- def->is_macro = 1;
- def->contents = strsave(token_buffer.contents());
- def->is_simple = is_simple;
- }
-
- void do_undef()
- {
- int t = get_token();
- if (t != TEXT) {
- lex_error("bad undef command");
- return;
- }
- token_buffer += '\0';
- macro_table.define(token_buffer.contents(), 0);
- }
-
- void do_gsize()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad argument to gsize command");
- return;
- }
- token_buffer += '\0';
- char *ptr;
- long n = strtol(token_buffer.contents(), &ptr, 10);
- if (n == 0 && ptr == token_buffer.contents())
- lex_error("bad argument `%1' to gsize command");
- else
- set_gsize(int(n));
- }
-
- void do_gfont()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad argument to gfont command");
- return;
- }
- token_buffer += '\0';
- set_gfont(token_buffer.contents());
- }
-
- void do_grfont()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad argument to grfont command");
- return;
- }
- token_buffer += '\0';
- set_grfont(token_buffer.contents());
- }
-
- void do_gbfont()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad argument to gbfont command");
- return;
- }
- token_buffer += '\0';
- set_gbfont(token_buffer.contents());
- }
-
- void do_space()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad argument to space command");
- return;
- }
- token_buffer += '\0';
- char *ptr;
- long n = strtol(token_buffer.contents(), &ptr, 10);
- if (n == 0 && ptr == token_buffer.contents())
- lex_error("bad argument `%1' to space command");
- else
- set_space(int(n));
- }
-
- void do_ifdef()
- {
- int t = get_token();
- if (t != TEXT) {
- lex_error("bad ifdef");
- return;
- }
- token_buffer += '\0';
- definition *def = macro_table.lookup(token_buffer.contents());
- int result = def && def->is_macro && !def->is_simple;
- get_delimited_text();
- if (result) {
- token_buffer += '\0';
- current_input = new macro_input(token_buffer.contents(), current_input);
- }
- }
-
- void do_delim()
- {
- int c = get_char();
- while (c == ' ' || c == '\n')
- c = get_char();
- int d;
- if (c == EOF || (d = get_char()) == EOF)
- lex_error("end of file while reading argument to `delim'");
- else {
- if (c == 'o' && d == 'f' && peek_char() == 'f') {
- (void)get_char();
- start_delim = end_delim = '\0';
- }
- else {
- start_delim = c;
- end_delim = d;
- }
- }
- }
-
- void do_chartype()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad chartype");
- return;
- }
- token_buffer += '\0';
- string type = token_buffer;
- t = get_token();
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad chartype");
- return;
- }
- token_buffer += '\0';
- set_char_type(type.contents(), strsave(token_buffer.contents()));
- }
-
- void do_set()
- {
- int t = get_token(2);
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad chartype");
- return;
- }
- token_buffer += '\0';
- string param = token_buffer;
- t = get_token();
- if (t != TEXT && t != QUOTED_TEXT) {
- lex_error("bad chartype");
- return;
- }
- token_buffer += '\0';
- int n;
- if (sscanf(&token_buffer[0], "%d", &n) != 1) {
- lex_error("bad number `%1'", token_buffer.contents());
- return;
- }
- set_param(param.contents(), n);
- }
-
- int yylex()
- {
- for (;;) {
- int tk = get_token(1);
- switch(tk) {
- case UNDEF:
- do_undef();
- break;
- case SDEFINE:
- do_definition(1);
- break;
- case TDEFINE:
- case DEFINE:
- do_definition(0);
- break;
- case NDEFINE:
- ignore_definition();
- break;
- case GSIZE:
- do_gsize();
- break;
- case GFONT:
- do_gfont();
- break;
- case GRFONT:
- do_grfont();
- break;
- case GBFONT:
- do_gbfont();
- break;
- case SPACE:
- do_space();
- break;
- case INCLUDE:
- do_include();
- break;
- case IFDEF:
- do_ifdef();
- break;
- case DELIM:
- do_delim();
- break;
- case CHARTYPE:
- do_chartype();
- break;
- case SET:
- do_set();
- break;
- case QUOTED_TEXT:
- case TEXT:
- token_buffer += '\0';
- yylval.str = strsave(token_buffer.contents());
- // fall through
- default:
- return tk;
- }
- }
- }
-
- void lex_error(const char *message,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
- {
- char *filename;
- int lineno;
- if (!get_location(&filename, &lineno))
- error(message, arg1, arg2, arg3);
- else
- error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
- }
-
- void yyerror(const char *s)
- {
- char *filename;
- int lineno;
- if (!get_location(&filename, &lineno))
- error(s);
- else
- error_with_file_and_line(filename, lineno, s);
- show_context();
- }
-
-