123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259 |
- // -*- C++ -*-
- /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com) */
- /* Comment by rsm: shortly after label got_dot, there is a line that looks
- bogus:
- if (!c == EOF || !csdigit(c)) break;
- */
- #include "pic.h"
- #include "object.h"
- #include "gram.h"
- // Character representing $1. Must be illegal input character.
- #define ARG1 14
- declare_ptable(char)
- implement_ptable(char)
- PTABLE(char) macro_table;
- //////////////////////////////////////////////////////////////////////
- // Forward declarations for lexer
- //////////////////////////////////////////////////////////////////////
- // forward references to internal lexer functions
- static char * process_body(const char *body);
- static char * get_thru_arg(void);
- static int docmp(const char *s1, int n1, const char *s2, int n2);
- static int get_delimited(void);
- static int get_token(int lookup_flag);
- static int get_token_after_dot(int c);
- static int lookup_keyword(const char *str, int len);
- static void do_define(void);
- static void do_undef(void);
- static void interpolate_macro_with_args(const char *body);
- // lexer global variables
- static double token_double;
- static int lookahead_token = -1;
- static int token_int;
- static string context_buffer;
- static string old_context_buffer;
- static string token_buffer;
- //////////////////////////////////////////////////////////////////////
- // default function members for input classes
- //////////////////////////////////////////////////////////////////////
- input::input() : next(0)
- {
- }
- input::~input()
- {
- }
- int
- input::get_location (const char **, int *)
- {
- return 0;
- }
- //////////////////////////////////////////////////////////////////////
- // MACRO_INPUT class
- //////////////////////////////////////////////////////////////////////
- class macro_input : public input
- {
- public:
- // ctor, dtor
- macro_input(const char *);
- ~macro_input();
- // public functions
- int get (void);
- int peek (void);
- private:
- char *s;
- char *p;
- };
- macro_input::macro_input(const char *str)
- {
- p = s = strsave(str);
- }
- macro_input::~macro_input()
- {
- a_delete s;
- }
- int
- macro_input::get(void)
- {
- if (p == 0 || *p == '\0')
- return EOF;
- else
- return (unsigned char)*p++;
- }
- int
- macro_input::peek(void)
- {
- if (p == 0 || *p == '\0')
- return EOF;
- else
- return (unsigned char)*p;
- }
- //////////////////////////////////////////////////////////////////////
- // FILE_INPUT class
- //////////////////////////////////////////////////////////////////////
- file_input::file_input(FILE *f, const char *fn)
- : filename(fn), lineno(0), ptr("")
- {
- fp = f;
- }
- file_input::~file_input()
- {
- fclose(fp);
- }
- int
- file_input::get(void)
- {
- if (*ptr != '\0' || read_line())
- return (unsigned char)*ptr++;
- else
- return EOF;
- }
- int
- file_input::peek(void)
- {
- if (*ptr != '\0' || read_line())
- return (unsigned char)*ptr;
- else
- return EOF;
- }
- int
- file_input::get_location (const char **fnp, int *lnp)
- {
- *fnp = filename;
- *lnp = lineno;
- return 1;
- }
- int
- file_input::read_line(void)
- {
- 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] == 'P'
- && (line[2] == 'S' || line[2] == 'E' || line[2] == 'F')
- && (line.length() == 3 || line[3] == ' ' || line[3] == '\n'
- || compatible_flag)))
- {
- line += '\0';
- ptr = line.contents();
- return 1;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////
- // ARGUMENT_MACRO_INPUT class
- //////////////////////////////////////////////////////////////////////
- class argument_macro_input : public input
- {
- public:
- // ctor, dtor
- argument_macro_input(const char *, int, char **);
- ~argument_macro_input();
- // public functions
- int get (void);
- int peek (void);
- private:
- char *s;
- char *p;
- char *ap;
- int argc;
- char *argv[9];
- };
- argument_macro_input::argument_macro_input(const char *body, int ac, char **av)
- : ap(0), argc(ac)
- {
- for (int i = 0; i < argc; i++)
- argv[i] = av[i];
- p = s = process_body(body);
- }
- argument_macro_input::~argument_macro_input()
- {
- for (int i = 0; i < argc; i++)
- a_delete argv[i];
- a_delete s;
- }
- int
- argument_macro_input::get(void)
- {
- if (ap)
- {
- if (*ap != '\0')
- return (unsigned char)*ap++;
- 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 (unsigned char)*ap++;
- }
- }
- if (*p == '\0')
- return EOF;
- return (unsigned char)*p++;
- }
- int
- argument_macro_input::peek(void)
- {
- if (ap)
- {
- if (*ap != '\0')
- return (unsigned char)*ap;
- 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 (unsigned char)*ap;
- }
- }
- if (*p == '\0')
- return EOF;
- return (unsigned char)*p;
- }
- //////////////////////////////////////////////////////////////////////
- // CHAR_INPUT class
- //////////////////////////////////////////////////////////////////////
- class char_input : public input
- {
- public:
- // ctor
- char_input (int n);
- // public functions
- int get (void);
- int peek (void);
- private:
- int c;
- };
- char_input::char_input(int n) : c((unsigned char)n)
- {
- }
- int
- char_input::get (void)
- {
- int n = c;
- c = EOF;
- return n;
- }
- int
- char_input::peek (void)
- {
- return c;
- }
- //////////////////////////////////////////////////////////////////////
- // FOR_INPUT class
- //////////////////////////////////////////////////////////////////////
- class for_input : public input
- {
- public:
- //ctor, dtor
- for_input(char *, double, int, double, char *);
- ~for_input();
- // public functions
- int get (void);
- int peek (void);
- private:
- char *var;
- char *body;
- double to;
- int by_is_multiplicative;
- double by;
- const char *p;
- int done_newline;
- };
- for_input::for_input(char *vr, double t, int bim, double b, char *bd)
- : var(vr), body(bd), to(t), by_is_multiplicative(bim), by(b), p(body),
- done_newline(0)
- {
- }
- for_input::~for_input()
- {
- a_delete var;
- a_delete body;
- }
- int
- for_input::get(void)
- {
- if (p == 0)
- return EOF;
- for (;;)
- {
- if (*p != '\0')
- return (unsigned char)*p++;
- if (!done_newline)
- {
- done_newline = 1;
- return '\n';
- }
- double val;
- if (!lookup_variable(var, &val))
- {
- lex_error("body of `for' terminated enclosing block");
- return EOF;
- }
- if (by_is_multiplicative)
- val *= by;
- else
- val += by;
- define_variable(var, val);
- if (val > to)
- {
- p = 0;
- return EOF;
- }
- p = body;
- done_newline = 0;
- }
- }
- int
- for_input::peek(void)
- {
- if (p == 0)
- return EOF;
- if (*p != '\0')
- return (unsigned char)*p;
- if (!done_newline)
- return '\n';
- double val;
- if (!lookup_variable(var, &val))
- return EOF;
- if (by_is_multiplicative)
- {
- if (val * by > to)
- return EOF;
- }
- else
- {
- if (val + by > to)
- return EOF;
- }
- if (*body == '\0')
- return EOF;
- return (unsigned char)*body;
- }
- //////////////////////////////////////////////////////////////////////
- // COPY_THRU_INPUT class
- //////////////////////////////////////////////////////////////////////
- class copy_thru_input : public input
- {
- public:
- // ctor, dtor
- copy_thru_input(const char *b, const char *u);
- ~copy_thru_input();
- // public functions
- int get (void);
- int peek (void);
- private:
- int done;
- char *body;
- char *until;
- const char *p;
- const char *ap;
- int argv[9];
- int argc;
- string line;
- int get_line();
- virtual int inget() = 0;
- };
- copy_thru_input::copy_thru_input(const char *b, const char *u)
- : done(0)
- {
- ap = 0;
- body = process_body(b);
- p = 0;
- until = strsave(u);
- }
- copy_thru_input::~copy_thru_input()
- {
- a_delete body;
- a_delete until;
- }
- int
- copy_thru_input::get(void)
- {
- if (ap)
- {
- if (*ap != '\0')
- return (unsigned char)*ap++;
- ap = 0;
- }
- for (;;)
- {
- if (p == 0)
- {
- if (!get_line())
- break;
- p = body;
- }
- if (*p == '\0')
- {
- p = 0;
- return '\n';
- }
- while (*p >= ARG1 && *p <= ARG1 + 8)
- {
- int i = *p++ - ARG1;
- if (i < argc && line[argv[i]] != '\0')
- {
- ap = line.contents() + argv[i];
- return (unsigned char)*ap++;
- }
- }
- if (*p != '\0')
- return (unsigned char)*p++;
- }
- return EOF;
- }
- int
- copy_thru_input::peek(void)
- {
- if (ap)
- {
- if (*ap != '\0')
- return (unsigned char)*ap;
- ap = 0;
- }
- for (;;)
- {
- if (p == 0)
- {
- if (!get_line())
- break;
- p = body;
- }
- if (*p == '\0')
- return '\n';
- while (*p >= ARG1 && *p <= ARG1 + 8)
- {
- int i = *p++ - ARG1;
- if (i < argc && line[argv[i]] != '\0')
- {
- ap = line.contents() + argv[i];
- return (unsigned char)*ap;
- }
- }
- if (*p != '\0')
- return (unsigned char)*p;
- }
- return EOF;
- }
- int
- copy_thru_input::get_line(void)
- {
- if (done)
- return 0;
- line.clear();
- argc = 0;
- int c = inget();
- for (;;)
- {
- while (c == ' ')
- c = inget();
- if (c == EOF || c == '\n')
- break;
- if (argc == 9)
- {
- do
- {
- c = inget();
- } while (c != '\n' && c != EOF);
- break;
- }
- argv[argc++] = line.length();
- do
- {
- line += char(c);
- c = inget();
- } while (c != ' ' && c != '\n');
- line += '\0';
- }
- if (until != 0 && argc > 0 && strcmp(&line[argv[0]], until) == 0)
- {
- done = 1;
- return 0;
- }
- return argc > 0 || c == '\n';
- }
- //////////////////////////////////////////////////////////////////////
- // COPY_FILE_THRU_INPUT class (subclassed from COPY_THRU_INPUT)
- //////////////////////////////////////////////////////////////////////
- class copy_file_thru_input : public copy_thru_input
- {
- public:
- copy_file_thru_input(input *, const char *b, const char *u);
- ~copy_file_thru_input();
- int inget();
- private:
- input *in;
- };
- copy_file_thru_input::copy_file_thru_input(input *i, const char *b,
- const char *u)
- : copy_thru_input(b, u), in(i)
- {
- }
- copy_file_thru_input::~copy_file_thru_input()
- {
- delete in;
- }
- int
- copy_file_thru_input::inget(void)
- {
- if (!in)
- return EOF;
- else
- return in->get();
- }
- //////////////////////////////////////////////////////////////////////
- // COPY_REST_THRU_INPUT class (subclassed from COPY_THRU_INPUT)
- //////////////////////////////////////////////////////////////////////
- class copy_rest_thru_input : public copy_thru_input
- {
- public:
- // ctor
- copy_rest_thru_input (const char *, const char *u);
- // public functions
- int inget (void);
- };
- copy_rest_thru_input::copy_rest_thru_input(const char *b, const char *u)
- : copy_thru_input(b, u)
- {
- }
- int
- copy_rest_thru_input::inget(void)
- {
- while (next != 0)
- {
- int c = next->get();
- if (c != EOF)
- return c;
- if (next->next == 0)
- return EOF;
- input *tem = next;
- next = next->next;
- delete tem;
- }
- return EOF;
- }
- //////////////////////////////////////////////////////////////////////
- // SIMPLE_FILE_INPUT class
- //////////////////////////////////////////////////////////////////////
- class simple_file_input : public input
- {
- public:
- // ctor, dtor
- simple_file_input(FILE *, const char *);
- ~simple_file_input();
- // public functions
- int get (void);
- int peek (void);
- int get_location (const char **, int *);
- private:
- const char *filename;
- int lineno;
- FILE *fp;
- };
- simple_file_input::simple_file_input(FILE *p, const char *s)
- : filename(s), lineno(1), fp(p)
- {
- }
- simple_file_input::~simple_file_input(void)
- {
- // don't delete the filename
- fclose(fp);
- }
- int
- simple_file_input::get(void)
- {
- int c = getc(fp);
- while (illegal_input_char(c))
- {
- error("illegal input character code %1", c);
- c = getc(fp);
- }
- if (c == '\n')
- lineno++;
- return c;
- }
- int
- simple_file_input::peek(void)
- {
- int c = getc(fp);
- while (illegal_input_char(c))
- {
- error("illegal input character code %1", c);
- c = getc(fp);
- }
- if (c != EOF)
- ungetc(c, fp);
- return c;
- }
- int
- simple_file_input::get_location (const char **fnp, int *lnp)
- {
- *fnp = filename;
- *lnp = lineno;
- return 1;
- }
- //////////////////////////////////////////////////////////////////////
- // INPUT_STACK class (not subclassed from INPUT)
- //////////////////////////////////////////////////////////////////////
- class input_stack
- {
- public:
- static void push(input *);
- static void clear();
- static int get_char();
- static int peek_char();
- static int get_location (const char **fnp, int *lnp);
- static void push_back(unsigned char c, int was_bol = 0);
- static int bol();
- private:
- static input *current_input;
- static int bol_flag;
- };
- void
- input_stack::push(input *in)
- {
- in->next = current_input;
- current_input = in;
- }
- void
- input_stack::clear(void)
- {
- while (current_input != 0)
- {
- input *tem = current_input;
- current_input = current_input->next;
- delete tem;
- }
- bol_flag = 1;
- }
- int
- input_stack::get_char(void)
- {
- while (current_input != 0)
- {
- int c = current_input->get();
- if (c != EOF)
- {
- bol_flag = c == '\n';
- return c;
- }
- // don't pop the top-level input off the stack
- if (current_input->next == 0)
- return EOF;
- input *tem = current_input;
- current_input = current_input->next;
- delete tem;
- }
- return EOF;
- }
- int
- input_stack::peek_char(void)
- {
- while (current_input != 0)
- {
- int c = current_input->peek();
- if (c != EOF)
- return c;
- if (current_input->next == 0)
- return EOF;
- input *tem = current_input;
- current_input = current_input->next;
- delete tem;
- }
- return EOF;
- }
- int
- input_stack::get_location (const char **fnp, int *lnp)
- {
- for (input *p = current_input; p; p = p->next)
- if (p->get_location (fnp, lnp))
- return 1;
- return 0;
- }
- void
- input_stack::push_back(unsigned char c, int was_bol)
- {
- push(new char_input(c));
- bol_flag = was_bol;
- }
- inline int
- input_stack::bol(void)
- {
- return bol_flag;
- }
- input *input_stack::current_input = 0;
- int input_stack::bol_flag = 0;
- //////////////////////////////////////////////////////////////////////
- // PIC LEXER
- //
- // Public interface (declared in pic.h):
- //
- // lex_init(), lex_cleanup()
- // yylex(), yyerror()
- // lex_error(), lex_warning(),
- // do_copy(), do_for(), copy_file_thru(), copy_rest_thru(), push_body()
- // do_lookahead()
- //
- // The lexer accesses a read-only variable of the parser, `delim_flag',
- // and also calls the parser's define_variable() and lookup_variable()
- // functions [they're used in for loops].
- //////////////////////////////////////////////////////////////////////
- void
- lex_init(input *top)
- {
- input_stack::clear();
- input_stack::push(top);
- }
- void
- lex_cleanup(void)
- {
- while (input_stack::get_char() != EOF)
- ;
- }
- static void
- interpolate_macro_with_args(const char *body)
- {
- char *argv[9];
- int argc = 0;
- int i;
- for (i = 0; i < 9; i++)
- argv[i] = 0;
- int level = 0;
- int c;
- enum { NORMAL, IN_STRING, IN_STRING_QUOTED } state = NORMAL;
- do
- {
- token_buffer.clear();
- for (;;)
- {
- c = input_stack::get_char();
- if (c == EOF)
- {
- lex_error("end of input while scanning macro arguments");
- break;
- }
- if (state == NORMAL && 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);
- switch (state)
- {
- case NORMAL:
- if (c == '"')
- state = IN_STRING;
- else if (c == '(')
- level++;
- else if (c == ')')
- level--;
- break;
- case IN_STRING:
- if (c == '"')
- state = NORMAL;
- else if (c == '\\')
- state = IN_STRING_QUOTED;
- break;
- case IN_STRING_QUOTED:
- state = IN_STRING;
- break;
- }
- }
- } while (c != ')' && c != EOF);
- input_stack::push(new argument_macro_input(body, argc, argv));
- }
- static int
- docmp(const char *s1, int n1, const char *s2, int n2)
- {
- if (n1 < n2)
- {
- int r = memcmp(s1, s2, n1);
- return r ? r : -1;
- }
- else if (n1 > n2)
- {
- int r = memcmp(s1, s2, n2);
- return r ? r : 1;
- }
- else
- return memcmp(s1, s2, n1);
- }
- static int
- lookup_keyword(const char *str, int len)
- {
- static struct keyword
- {
- const char *name;
- int token;
- } table[] =
- {
- { "Here", HERE },
- { "above", ABOVE },
- { "aligned", ALIGNED },
- { "and", AND },
- { "arc", ARC },
- { "arrow", ARROW },
- { "at", AT },
- { "atan2", ATAN2 },
- { "below", BELOW },
- { "between", BETWEEN },
- { "bottom", BOTTOM },
- { "box", BOX },
- { "by", BY },
- { "ccw", CCW },
- { "center", CENTER },
- { "chop", CHOP },
- { "circle", CIRCLE },
- { "command", COMMAND },
- { "copy", COPY },
- { "cos", COS },
- { "cw", CW },
- { "dashed", DASHED },
- { "define", DEFINE },
- { "diam", DIAMETER },
- { "diameter", DIAMETER },
- { "do", DO },
- { "dotted", DOTTED },
- { "down", DOWN },
- { "ellipse", ELLIPSE },
- { "else", ELSE },
- { "end", END },
- { "exp", EXP },
- { "fill", FILL },
- { "filled", FILL },
- { "for", FOR },
- { "from", FROM },
- { "height", HEIGHT },
- { "ht", HEIGHT },
- { "if", IF },
- { "int", INT },
- { "invis", INVISIBLE },
- { "invisible", INVISIBLE },
- { "last", LAST },
- { "left", LEFT },
- { "line", LINE },
- { "ljust", LJUST },
- { "log", LOG },
- { "lower", LOWER },
- { "max", K_MAX },
- { "min", K_MIN },
- { "move", MOVE },
- { "of", OF },
- { "plot", PLOT },
- { "print", PRINT },
- { "rad", RADIUS },
- { "radius", RADIUS },
- { "rand", RAND },
- { "reset", RESET },
- { "right", RIGHT },
- { "rjust", RJUST },
- { "same", SAME },
- { "sh", SH },
- { "sin", SIN },
- { "spline", SPLINE },
- { "sprintf", SPRINTF },
- { "sqrt", SQRT },
- { "start", START },
- { "the", THE },
- { "then", THEN },
- { "thick", THICKNESS },
- { "thickness", THICKNESS },
- { "thru", THRU },
- { "to", TO },
- { "top", TOP },
- { "undef", UNDEF },
- { "until", UNTIL },
- { "up", UP },
- { "upper", UPPER },
- { "way", WAY },
- { "wid", WIDTH },
- { "width", WIDTH },
- { "with", WITH },
- };
-
- const keyword *start = table;
- const keyword *end = table + sizeof(table)/sizeof(table[0]);
- while (start < end)
- {
- // start <= target < end
- const keyword *mid = start + (end - start)/2;
-
- int cmp = docmp(str, len, mid->name, strlen(mid->name));
- if (cmp == 0)
- return mid->token;
- if (cmp < 0)
- end = mid;
- else
- start = mid + 1;
- }
- return 0;
- }
- static int
- get_token_after_dot(int c)
- {
- // get_token deals with the case where c is a digit
- switch (c)
- {
- case 'h':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- context_buffer = ".ht";
- return DOT_HT;
- }
- else if (c == 'e')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'i')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'g')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'h')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- context_buffer = ".height";
- return DOT_HT;
- }
- input_stack::push_back('h');
- }
- input_stack::push_back('g');
- }
- input_stack::push_back('i');
- }
- input_stack::push_back('e');
- }
- input_stack::push_back('h');
- return '.';
- case 'x':
- input_stack::get_char();
- context_buffer = ".x";
- return DOT_X;
- case 'y':
- input_stack::get_char();
- context_buffer = ".y";
- return DOT_Y;
- case 'c':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'e')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'n')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'e')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'r')
- {
- input_stack::get_char();
- context_buffer = ".center";
- return DOT_C;
- }
- input_stack::push_back('e');
- }
- input_stack::push_back('t');
- }
- input_stack::push_back('n');
- }
- input_stack::push_back('e');
- }
- context_buffer = ".c";
- return DOT_C;
- case 'n':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'e')
- {
- input_stack::get_char();
- context_buffer = ".ne";
- return DOT_NE;
- }
- else if (c == 'w')
- {
- input_stack::get_char();
- context_buffer = ".nw";
- return DOT_NW;
- }
- else
- {
- context_buffer = ".n";
- return DOT_N;
- }
- break;
- case 'e':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'n')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'd')
- {
- input_stack::get_char();
- context_buffer = ".end";
- return DOT_END;
- }
- input_stack::push_back('n');
- context_buffer = ".e";
- return DOT_E;
- }
- context_buffer = ".e";
- return DOT_E;
- case 'w':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'i')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'd')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'h')
- {
- input_stack::get_char();
- context_buffer = ".width";
- return DOT_WID;
- }
- input_stack::push_back('t');
- }
- context_buffer = ".wid";
- return DOT_WID;
- }
- input_stack::push_back('i');
- }
- context_buffer = ".w";
- return DOT_W;
- case 's':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'e')
- {
- input_stack::get_char();
- context_buffer = ".se";
- return DOT_SE;
- }
- else if (c == 'w')
- {
- input_stack::get_char();
- context_buffer = ".sw";
- return DOT_SW;
- }
- else
- {
- if (c == 't')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'a')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'r')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- context_buffer = ".start";
- return DOT_START;
- }
- input_stack::push_back('r');
- }
- input_stack::push_back('a');
- }
- input_stack::push_back('t');
- }
- context_buffer = ".s";
- return DOT_S;
- }
- break;
- case 't':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'o')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'p')
- {
- input_stack::get_char();
- context_buffer = ".top";
- return DOT_N;
- }
- input_stack::push_back('o');
- }
- context_buffer = ".t";
- return DOT_N;
- case 'l':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'e')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'f')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- context_buffer = ".left";
- return DOT_W;
- }
- input_stack::push_back('f');
- }
- input_stack::push_back('e');
- }
- context_buffer = ".l";
- return DOT_W;
- case 'r':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'a')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'd')
- {
- input_stack::get_char();
- context_buffer = ".rad";
- return DOT_RAD;
- }
- input_stack::push_back('a');
- }
- else if (c == 'i')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'g')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'h')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- context_buffer = ".right";
- return DOT_E;
- }
- input_stack::push_back('h');
- }
- input_stack::push_back('g');
- }
- input_stack::push_back('i');
- }
- context_buffer = ".r";
- return DOT_E;
- case 'b':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'o')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'o')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'm')
- {
- input_stack::get_char();
- context_buffer = ".bottom";
- return DOT_S;
- }
- input_stack::push_back('o');
- }
- input_stack::push_back('t');
- }
- context_buffer = ".bot";
- return DOT_S;
- }
- input_stack::push_back('o');
- }
- context_buffer = ".b";
- return DOT_S;
- default:
- context_buffer = '.';
- return '.';
- }
- }
- static int
- get_token(int lookup_flag)
- {
- context_buffer.clear();
- for (;;)
- {
- int n = 0;
- int bol = input_stack::bol();
- int c = input_stack::get_char();
- if (bol && c == command_char)
- {
- token_buffer.clear();
- token_buffer += c;
- // the newline is not part of the token
- for (;;)
- {
- c = input_stack::peek_char();
- if (c == EOF || c == '\n')
- break;
- input_stack::get_char();
- token_buffer += char(c);
- }
- context_buffer = token_buffer;
- return COMMAND_LINE;
- }
- switch (c)
- {
- case EOF:
- return EOF;
- case ' ':
- case '\t':
- break;
- case '\\':
- {
- int d = input_stack::peek_char();
- if (d != '\n')
- {
- context_buffer = '\\';
- return '\\';
- }
- input_stack::get_char();
- break;
- }
- case '#':
- do
- {
- c = input_stack::get_char();
- } while (c != '\n' && c != EOF);
- if (c == '\n')
- context_buffer = '\n';
- return c;
- case '"':
- context_buffer = '"';
- token_buffer.clear();
- for (;;)
- {
- c = input_stack::get_char();
- if (c == '\\')
- {
- context_buffer += '\\';
- c = input_stack::peek_char();
- if (c == '"')
- {
- input_stack::get_char();
- token_buffer += '"';
- context_buffer += '"';
- }
- else
- token_buffer += '\\';
- }
- else if (c == '\n')
- {
- error("newline in string");
- break;
- }
- else if (c == EOF)
- {
- error("missing `\"'");
- break;
- }
- else if (c == '"')
- {
- context_buffer += '"';
- break;
- }
- else
- {
- context_buffer += char(c);
- token_buffer += char(c);
- }
- }
- return TEXT;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- int overflow = 0;
- n = 0;
- for (;;)
- {
- if (n > (INT_MAX - 9)/10)
- {
- overflow = 1;
- break;
- }
- n *= 10;
- n += c - '0';
- context_buffer += char(c);
- c = input_stack::peek_char();
- if (c == EOF || !csdigit(c))
- break;
- c = input_stack::get_char();
- }
- token_double = n;
- if (overflow)
- {
- for (;;)
- {
- token_double *= 10.0;
- token_double += c - '0';
- context_buffer += char(c);
- c = input_stack::peek_char();
- if (c == EOF || !csdigit(c))
- break;
- c = input_stack::get_char();
- }
- // if somebody asks for 1000000000000th, we will silently
- // give them INT_MAXth
- double temp = token_double; // work around gas 1.34/sparc bug
- if (token_double > INT_MAX)
- n = INT_MAX;
- else
- n = int(temp);
- }
- }
- switch (c)
- {
- case 'i':
- case 'I':
- context_buffer += char(c);
- input_stack::get_char();
- return NUMBER;
- case '.':
- {
- context_buffer += '.';
- input_stack::get_char();
- got_dot:
- double factor = 1.0;
- for (;;)
- {
- c = input_stack::peek_char();
- if (!c == EOF || !csdigit(c))
- break;
- input_stack::get_char();
- context_buffer += char(c);
- factor /= 10.0;
- if (c != '0')
- token_double += factor*(c - '0');
- }
- if (c != 'e' && c != 'E')
- {
- if (c == 'i' || c == 'I')
- {
- context_buffer += char(c);
- input_stack::get_char();
- }
- return NUMBER;
- }
- }
- // fall through
- case 'e':
- case 'E':
- {
- int echar = c;
- input_stack::get_char();
- c = input_stack::peek_char();
- int sign = '+';
- if (c == '+' || c == '-')
- {
- sign = c;
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == EOF || !csdigit(c))
- {
- input_stack::push_back(sign);
- input_stack::push_back(echar);
- return NUMBER;
- }
- context_buffer += char(echar);
- context_buffer += char(sign);
- }
- else
- {
- if (c == EOF || !csdigit(c))
- {
- input_stack::push_back(echar);
- return NUMBER;
- }
- context_buffer += char(echar);
- }
- input_stack::get_char();
- context_buffer += char(c);
- n = c - '0';
- for (;;)
- {
- c = input_stack::peek_char();
- if (c == EOF || !csdigit(c))
- break;
- input_stack::get_char();
- context_buffer += char(c);
- n = n*10 + (c - '0');
- }
- if (sign == '-')
- n = -n;
- if (c == 'i' || c == 'I')
- {
- context_buffer += char(c);
- input_stack::get_char();
- }
- token_double *= pow(10.0, n);
- return NUMBER;
- }
- case 'n':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'd')
- {
- input_stack::get_char();
- token_int = n;
- context_buffer += "nd";
- return ORDINAL;
- }
- input_stack::push_back('n');
- return NUMBER;
- case 'r':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'd')
- {
- input_stack::get_char();
- token_int = n;
- context_buffer += "rd";
- return ORDINAL;
- }
- input_stack::push_back('r');
- return NUMBER;
- case 't':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'h')
- {
- input_stack::get_char();
- token_int = n;
- context_buffer += "th";
- return ORDINAL;
- }
- input_stack::push_back('t');
- return NUMBER;
- case 's':
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- token_int = n;
- context_buffer += "st";
- return ORDINAL;
- }
- input_stack::push_back('s');
- return NUMBER;
- default:
- return NUMBER;
- }
- break;
- case '\'':
- {
- c = input_stack::peek_char();
- if (c == 't')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == 'h')
- {
- input_stack::get_char();
- context_buffer = "'th";
- return TH;
- }
- else
- input_stack::push_back('t');
- }
- context_buffer = "'";
- return '\'';
- }
- case '.':
- {
- c = input_stack::peek_char();
- if (c != EOF && csdigit(c))
- {
- n = 0;
- token_double = 0.0;
- context_buffer = '.';
- goto got_dot;
- }
- return get_token_after_dot(c);
- }
- case '<':
- c = input_stack::peek_char();
- if (c == '-')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- if (c == '>')
- {
- input_stack::get_char();
- context_buffer = "<->";
- return DOUBLE_ARROW_HEAD;
- }
- context_buffer = "<-";
- return LEFT_ARROW_HEAD;
- }
- else if (c == '=')
- {
- input_stack::get_char();
- context_buffer = "<=";
- return LESSEQUAL;
- }
- context_buffer = "<";
- return '<';
- case '-':
- c = input_stack::peek_char();
- if (c == '>')
- {
- input_stack::get_char();
- context_buffer = "->";
- return RIGHT_ARROW_HEAD;
- }
- context_buffer = "-";
- return '-';
- case '!':
- c = input_stack::peek_char();
- if (c == '=')
- {
- input_stack::get_char();
- context_buffer = "!=";
- return NOTEQUAL;
- }
- context_buffer = "!";
- return '!';
- case '>':
- c = input_stack::peek_char();
- if (c == '=')
- {
- input_stack::get_char();
- context_buffer = ">=";
- return GREATEREQUAL;
- }
- context_buffer = ">";
- return '>';
- case '=':
- c = input_stack::peek_char();
- if (c == '=')
- {
- input_stack::get_char();
- context_buffer = "==";
- return EQUALEQUAL;
- }
- context_buffer = "=";
- return '=';
- case '&':
- c = input_stack::peek_char();
- if (c == '&')
- {
- input_stack::get_char();
- context_buffer = "&&";
- return ANDAND;
- }
- context_buffer = "&";
- return '&';
- case '|':
- c = input_stack::peek_char();
- if (c == '|')
- {
- input_stack::get_char();
- context_buffer = "||";
- return OROR;
- }
- context_buffer = "|";
- return '|';
- default:
- if (c != EOF && csalpha(c))
- {
- token_buffer.clear();
- token_buffer = c;
- for (;;)
- {
- c = input_stack::peek_char();
- if (c == EOF || (!csalnum(c) && c != '_'))
- break;
- input_stack::get_char();
- token_buffer += char(c);
- }
- int tok = lookup_keyword(token_buffer.contents(),
- token_buffer.length());
- if (tok != 0)
- {
- context_buffer = token_buffer;
- return tok;
- }
- char *def = 0;
- if (lookup_flag)
- {
- token_buffer += '\0';
- def = macro_table.lookup(token_buffer.contents());
- token_buffer.set_length(token_buffer.length() - 1);
- if (def)
- {
- if (c == '(')
- {
- input_stack::get_char();
- interpolate_macro_with_args(def);
- }
- else
- input_stack::push(new macro_input(def));
- }
- }
- if (!def)
- {
- context_buffer = token_buffer;
- if (csupper(token_buffer[0]))
- return LABEL;
- else
- return VARIABLE;
- }
- }
- else
- {
- context_buffer = char(c);
- return (unsigned char)c;
- }
- break;
- }
- }
- }
- static int
- get_delimited(void)
- {
- token_buffer.clear();
- int c = input_stack::get_char();
- while (c == ' ' || c == '\t' || c == '\n')
- c = input_stack::get_char();
- if (c == EOF)
- {
- lex_error("missing delimiter");
- return 0;
- }
- context_buffer = char(c);
- int had_newline = 0;
- int start = c;
- int level = 0;
- enum { NORMAL, IN_STRING, IN_STRING_QUOTED, DELIM_END } state = NORMAL;
- for (;;)
- {
- c = input_stack::get_char();
- if (c == EOF)
- {
- lex_error("missing closing delimiter");
- return 0;
- }
- if (c == '\n')
- had_newline = 1;
- else if (!had_newline)
- context_buffer += char(c);
- switch (state)
- {
- case NORMAL:
- if (start == '{')
- {
- if (c == '{')
- {
- level++;
- break;
- }
- if (c == '}')
- {
- if (--level < 0)
- state = DELIM_END;
- break;
- }
- }
- else
- {
- if (c == start)
- {
- state = DELIM_END;
- break;
- }
- }
- if (c == '"')
- state = IN_STRING;
- break;
- case IN_STRING_QUOTED:
- if (c == '\n')
- state = NORMAL;
- else
- state = IN_STRING;
- break;
- case IN_STRING:
- if (c == '"' || c == '\n')
- state = NORMAL;
- else if (c == '\\')
- state = IN_STRING_QUOTED;
- break;
- case DELIM_END:
- // This case is just to shut cfront 2.0 up.
- default:
- assert(0);
- }
- if (state == DELIM_END)
- break;
- token_buffer += c;
- }
- return 1;
- }
- static void
- do_define(void)
- {
- int t = get_token(0); // do not expand what we are defining
- if (t != VARIABLE && t != LABEL)
- {
- lex_error("can only define variable or placename");
- return;
- }
- token_buffer += '\0';
- string nm = token_buffer;
- const char *name = nm.contents();
- if (!get_delimited())
- return;
- token_buffer += '\0';
- macro_table.define(name, strsave(token_buffer.contents()));
- }
- static void
- do_undef(void)
- {
- int t = get_token(0); // do not expand what we are undefining
- if (t != VARIABLE && t != LABEL)
- {
- lex_error("can only define variable or placename");
- return;
- }
- token_buffer += '\0';
- macro_table.define(token_buffer.contents(), 0);
- }
- void
- do_for(char *var, double from, double to, int by_is_multiplicative,
- double by, char *body)
- {
- define_variable(var, from);
- if (from <= to)
- input_stack::push(new for_input(var, to, by_is_multiplicative, by, body));
- }
- void
- do_copy(const char *filename)
- {
- errno = 0;
- FILE *fp = fopen(filename, "r");
- if (fp == 0)
- {
- lex_error("can't open `%1': %2", filename, strerror(errno));
- return;
- }
- input_stack::push(new file_input(fp, filename));
- }
- void
- copy_file_thru(const char *filename, const char *body, const char *until)
- {
- errno = 0;
- FILE *fp = fopen(filename, "r");
- if (fp == 0)
- {
- lex_error("can't open `%1': %2", filename, strerror(errno));
- return;
- }
- input *in = new copy_file_thru_input(new simple_file_input(fp, filename),
- body, until);
- input_stack::push(in);
- }
- void
- copy_rest_thru(const char *body, const char *until)
- {
- input_stack::push(new copy_rest_thru_input(body, until));
- }
- void
- push_body(const char *s)
- {
- input_stack::push(new char_input('\n'));
- input_stack::push(new macro_input(s));
- }
- static char *
- get_thru_arg(void)
- {
- int c = input_stack::peek_char();
- while (c == ' ')
- {
- input_stack::get_char();
- c = input_stack::peek_char();
- }
- if (c != EOF && csalpha(c))
- {
- // looks like a macro
- input_stack::get_char();
- token_buffer = c;
- for (;;)
- {
- c = input_stack::peek_char();
- if (c == EOF || (!csalnum(c) && c != '_'))
- break;
- input_stack::get_char();
- token_buffer += char(c);
- }
- context_buffer = token_buffer;
- token_buffer += '\0';
- char *def = macro_table.lookup(token_buffer.contents());
- if (def)
- return strsave(def);
- // I guess it wasn't a macro after all; so push the macro name back.
- // -2 because we added a '\0'
- for (int i = token_buffer.length() - 2; i >= 0; i--)
- input_stack::push_back(token_buffer[i]);
- }
- if (get_delimited())
- {
- token_buffer += '\0';
- return strsave(token_buffer.contents());
- }
- else
- return 0;
- }
- static char *
- process_body(const char *body)
- {
- char *s = strsave(body);
- int j = 0;
- for (int 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';
- return s;
- }
- void
- do_lookahead(void)
- {
- if (lookahead_token == -1)
- {
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- }
- }
- int
- yylex(void)
- {
- if (delim_flag)
- {
- assert(lookahead_token == -1);
- if (delim_flag == 2)
- {
- if ((yylval.str = get_thru_arg()) != 0)
- return DELIMITED;
- else
- return 0;
- }
- else
- {
- if (get_delimited())
- {
- token_buffer += '\0';
- yylval.str = strsave(token_buffer.contents());
- return DELIMITED;
- }
- else
- return 0;
- }
- }
- for (;;)
- {
- int t;
- if (lookahead_token >= 0)
- {
- t = lookahead_token;
- lookahead_token = -1;
- }
- else
- t = get_token(1);
- switch (t)
- {
- case '\n':
- return ';';
- case EOF:
- return 0;
- case DEFINE:
- do_define();
- break;
- case UNDEF:
- do_undef();
- break;
- case ORDINAL:
- yylval.n = token_int;
- return t;
- case NUMBER:
- yylval.x = token_double;
- return t;
- case COMMAND_LINE:
- case TEXT:
- token_buffer += '\0';
- if (!input_stack::get_location (&yylval.lstr.filename,
- &yylval.lstr.lineno))
- {
- yylval.lstr.filename = 0;
- yylval.lstr.lineno = -1;
- }
- yylval.lstr.str = strsave(token_buffer.contents());
- return t;
- case LABEL:
- case VARIABLE:
- token_buffer += '\0';
- yylval.str = strsave(token_buffer.contents());
- return t;
- case LEFT:
- // change LEFT to LEFT_CORNER when followed by OF
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token == OF)
- return LEFT_CORNER;
- else
- return t;
- case RIGHT:
- // change RIGHT to RIGHT_CORNER when followed by OF
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token == OF)
- return RIGHT_CORNER;
- else
- return t;
- case UPPER:
- // recognise UPPER only before LEFT or RIGHT
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token != LEFT && lookahead_token != RIGHT)
- {
- yylval.str = strsave("upper");
- return VARIABLE;
- }
- else
- return t;
- case LOWER:
- // recognise LOWER only before LEFT or RIGHT
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token != LEFT && lookahead_token != RIGHT)
- {
- yylval.str = strsave("lower");
- return VARIABLE;
- }
- else
- return t;
- case TOP:
- // recognise TOP only before OF
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token != OF)
- {
- yylval.str = strsave("top");
- return VARIABLE;
- }
- else
- return t;
- case BOTTOM:
- // recognise BOTTOM only before OF
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token != OF)
- {
- yylval.str = strsave("bottom");
- return VARIABLE;
- }
- else
- return t;
- case CENTER:
- // recognise CENTER only before OF
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token != OF)
- {
- yylval.str = strsave("center");
- return VARIABLE;
- }
- else
- return t;
- case START:
- // recognise START only before OF
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token != OF)
- {
- yylval.str = strsave("start");
- return VARIABLE;
- }
- else
- return t;
- case END:
- // recognise END only before OF
- old_context_buffer = context_buffer;
- lookahead_token = get_token(1);
- if (lookahead_token != OF)
- {
- yylval.str = strsave("end");
- return VARIABLE;
- }
- else
- return t;
- default:
- return t;
- }
- }
- }
- void
- lex_error(const char *message, const errarg &arg1,
- const errarg &arg2, const errarg &arg3)
- {
- const char *filename;
- int lineno;
- if (!input_stack::get_location (&filename, &lineno))
- error(message, arg1, arg2, arg3);
- else
- error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
- }
- void
- lex_warning(const char *message, const errarg &arg1,
- const errarg &arg2, const errarg &arg3)
- {
- const char *filename;
- int lineno;
- if (!input_stack::get_location (&filename, &lineno))
- warning(message, arg1, arg2, arg3);
- else
- warning_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
- }
- void
- yyerror(const char *s)
- {
- const char *filename;
- int lineno;
- const char *context = 0;
- if (lookahead_token == -1)
- {
- if (context_buffer.length() > 0)
- {
- context_buffer += '\0';
- context = context_buffer.contents();
- }
- }
- else
- {
- if (old_context_buffer.length() > 0)
- {
- old_context_buffer += '\0';
- context = old_context_buffer.contents();
- }
- }
- if (!input_stack::get_location (&filename, &lineno))
- {
- if (context)
- {
- if (context[0] == '\n' && context[1] == '\0')
- error("%1 before newline", s);
- else
- error("%1 before `%2'", s, context);
- }
- else
- error("%1 at end of picture", s);
- }
- else
- {
- if (context)
- {
- if (context[0] == '\n' && context[1] == '\0')
- error_with_file_and_line(filename, lineno, "%1 before newline", s);
- else
- error_with_file_and_line(filename, lineno, "%1 before `%2'",
- s, context);
- }
- else
- error_with_file_and_line(filename, lineno, "%1 at end of picture", s);
- }
- }
|