123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- /* $Id$ */
- /* Command grammar */
- {
- #include <stdio.h>
- #include <alloc.h>
- #include <signal.h>
- #include "ops.h"
- #include "class.h"
- #include "position.h"
- #include "file.h"
- #include "idf.h"
- #include "symbol.h"
- #include "tree.h"
- #include "langdep.h"
- #include "token.h"
- #include "expr.h"
- #include "misc.h"
- extern char *Salloc();
- extern char *strchr();
- extern char *strcpy();
- extern void signal_child();
- extern FILE *db_in;
- extern int disable_intr;
- extern p_tree run_command, print_command;
- struct token tok, aside;
- int errorgiven = 0;
- int child_interrupted = 0;
- int interrupted = 0;
- int eof_seen = 0;
- static int shellescape();
- static int extended_charset = 0;
- static int in_expression = 0;
- #define binprio(op) ((*(currlang->binop_prio))(op))
- #define unprio(op) ((*(currlang->unop_prio))(op))
- }
- %start Commands, commands;
- %lexical LLlex;
- commands
- { p_tree com, lastcom = 0;
- int give_prompt;
- }
- :
- { errorgiven = 0; }
- [ %persistent command_line(&com)
- [ '\n' { give_prompt = 1; }
- | %default ';' { give_prompt = 0; }
- ]
- { if (com) {
- if (lastcom) {
- freenode(lastcom);
- lastcom = 0;
- }
- if (errorgiven) {
- if (com != run_command) freenode(com);
- com = 0;
- }
- else {
- enterlog(com);
- eval(com);
- if (repeatable(com)) {
- lastcom = com;
- }
- else if (! in_status(com) &&
- com != run_command &&
- com != print_command) {
- freenode(com);
- com = 0;
- }
- }
- } else if (lastcom && ! errorgiven) {
- enterlog(lastcom);
- eval(lastcom);
- }
- if (give_prompt) {
- errorgiven = 0;
- interrupted = 0;
- prompt();
- }
- }
- ]*
- ;
- command_line(p_tree *p;)
- :
- { *p = 0; }
- [
- list_command(p)
- | file_command(p)
- | run_command(p)
- | stop_command(p)
- | when_command(p)
- | continue_command(p)
- | step_command(p)
- | next_command(p)
- | regs_command(p)
- | where_command(p)
- | STATUS { *p = mknode(OP_STATUS); }
- | DUMP { *p = mknode(OP_DUMP); }
- | RESTORE opt_num(p) { *p = mknode(OP_RESTORE, *p); }
- | delete_command(p)
- | print_command(p)
- | display_command(p)
- | trace_command(p)
- | set_command(p)
- | help_command(p)
- | FIND qualified_name(p){ *p = mknode(OP_FIND, *p); }
- | WHICH qualified_name(p){ *p = mknode(OP_WHICH, *p); }
- | able_command(p)
- | '!' { (void) shellescape();
- *p = mknode(OP_SHELL);
- }
- | source_command(p)
- | log_command(p)
- | frame_command(p)
- |
- ]
- ;
- frame_command(p_tree *p;)
- :
- FRAME
- [ { *p = mknode(OP_FRAME, (p_tree) 0); }
- | count(p) { *p = mknode(OP_FRAME, *p); }
- | '-' count(p) { *p = mknode(OP_DOWN, *p); }
- | '+' count(p) { *p = mknode(OP_UP, *p); }
- ]
- ;
- source_command(p_tree *p;)
- :
- SOURCE { extended_charset = 1; }
- name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
- { *p = mknode(OP_SOURCE, *p);
- extended_charset = 0;
- }
- ;
- log_command(p_tree *p;)
- :
- LOG { extended_charset = 1; }
- [ name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
- | { *p = 0; }
- ]
- { *p = mknode(OP_LOG, *p);
- extended_charset = 0;
- }
- ;
- where_command(p_tree *p;)
- :
- WHERE opt_num(p) { *p = mknode(OP_WHERE, *p); }
- ;
- list_command(p_tree *p;)
- { p_tree t1 = 0, t2 = 0; }
- :
- LIST
- [
- | position(&t1)
- | qualified_name(&t1)
- ]
- [ ',' count(&t2)
- | '-'
- [ count(&t2) { t2->t_ival = - t2->t_ival; }
- | { t2 = mknode(OP_INTEGER, -100000000L); }
- ]
- |
- ]
- { *p = mknode(OP_LIST, t1, t2); }
- ;
- file_command(p_tree *p;)
- :
- XFILE { extended_charset = 1; }
- [ { *p = 0; }
- | name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
- ] { *p = mknode(OP_FILE, *p);
- extended_charset = 0;
- }
- ;
- help_command(p_tree *p;)
- :
- [ HELP | '?' ]
- { *p = mknode(OP_HELP, (p_tree) 0); }
- [ name(&(*p)->t_args[0])?
- | '?' { (*p)->t_args[0] = mknode(OP_NAME, str2idf("help",0), (char *) 0); }
- | '!' { (*p)->t_args[0] = mknode(OP_NAME, (struct idf *) 0, "!"); }
- ]
- ;
- run_command(p_tree *p;)
- :
- RUN { extended_charset = 1; }
- args(p) { *p = mknode(OP_RUN, *p);
- extended_charset = 0;
- }
- | RERUN { if (! run_command) {
- error("no run command given yet");
- }
- else *p = run_command;
- }
- [ '?' { *p = mknode(OP_PRCOMM, *p); }
- |
- ]
- ;
- stop_command(p_tree *p;)
- { p_tree whr = 0, cond = 0; }
- :
- STOP
- where(&whr)?
- condition(&cond)? { if (! whr && ! cond) {
- error("no position or condition");
- *p = 0;
- }
- else *p = mknode(OP_STOP, whr, cond);
- }
- ;
- trace_command(p_tree *p;)
- { p_tree whr = 0, cond = 0, exp = 0; }
- :
- TRACE
- [ ON format_expression(&exp) ]?
- where(&whr)?
- condition(&cond)? { *p = mknode(OP_TRACE, whr, cond, exp); }
- ;
- continue_command(p_tree *p;)
- { long l; p_tree pos = 0; }
- :
- CONT
- [ INTEGER { l = tok.ival; }
- | { l = 1; }
- ]
- [ AT position(&pos) ]?
- { *p = mknode(OP_CONT, mknode(OP_INTEGER, l), pos); }
- ;
- when_command(p_tree *p;)
- { p_tree whr = 0, cond = 0; }
- :
- WHEN
- where(&whr)?
- condition(&cond)? { *p = mknode(OP_WHEN, whr, cond, (p_tree) 0);
- p = &(*p)->t_args[2];
- }
- '{'
- command_line(p)
- [ ';' { if (*p) {
- *p = mknode(OP_LINK, *p, (p_tree) 0);
- p = &((*p)->t_args[1]);
- }
- }
- command_line(p)
- ]*
- '}'
- { if (! whr && ! cond) {
- error("no position or condition");
- }
- else if (! *p) {
- error("no commands given");
- }
- }
- ;
- step_command(p_tree *p;)
- :
- STEP { *p = mknode(OP_STEP, (p_tree) 0); }
- count(&(*p)->t_args[0])?
- ;
- next_command(p_tree *p;)
- :
- NEXT { *p = mknode(OP_NEXT, (p_tree) 0); }
- count(&(*p)->t_args[0])?
- ;
- regs_command(p_tree *p;)
- :
- REGS { *p = mknode(OP_REGS, (p_tree) 0); }
- count(&(*p)->t_args[0])?
- ;
- delete_command(p_tree *p;)
- :
- DELETE num_list(p)? { *p = mknode(OP_DELETE, *p); }
- ;
- print_command(p_tree *p;)
- :
- PRINT
- [ format_expression_list(p)
- { *p = mknode(OP_PRINT, *p); }
- |
- { *p = mknode(OP_PRINT, (p_tree) 0); }
- ]
- ;
- display_command(p_tree *p;)
- :
- DISPLAY format_expression_list(p)
- { *p = mknode(OP_DISPLAY, *p); }
- ;
- format_expression_list(p_tree *p;)
- :
- format_expression(p)
- [ ',' { *p = mknode(OP_LINK, *p, (p_tree) 0);
- p = &((*p)->t_args[1]);
- }
- format_expression(p)
- ]*
- ;
- format_expression(p_tree *p;)
- { p_tree p1; }
- :
- expression(p, 0)
- [ '\\' name(&p1) { register char *c = p1->t_str;
- while (*c) {
- if (! strchr("doshcax", *c)) {
- error("illegal format: %c", *c);
- break;
- }
- c++;
- }
- *p = mknode(OP_FORMAT, *p, p1);
- }
- |
- ]
- ;
- set_command(p_tree *p;)
- :
- SET expression(p, 0) { *p = mknode(OP_SET, *p, (p_tree) 0); }
- TO expression(&((*p)->t_args[1]), 0)
- ;
- able_command(p_tree *p;)
- :
- [ ENABLE { *p = mknode(OP_ENABLE, (p_tree) 0); }
- | DISABLE { *p = mknode(OP_DISABLE, (p_tree) 0); }
- ]
- num_list(&(*p)->t_args[0])?
- ;
- num_list(p_tree *p;)
- :
- num(p)
- [ ',' { *p = mknode(OP_LINK, *p, (p_tree) 0); }
- num(&(*p)->t_args[1])
- ]*
- ;
- condition(p_tree *p;)
- :
- IF expression(p, 0)
- ;
- where(p_tree *p;)
- :
- IN qualified_name(p) { *p = mknode(OP_IN, *p, (p_tree) 0); }
- [ AT position(&((*p)->t_args[1])) ]?
- |
- AT position(p)
- ;
- expression(p_tree *p; int level;)
- { int currprio, currop; }
- : { in_expression++; }
- factor(p)
- [ %while ((currprio = binprio(currop = (int) tok.ival)) > level)
- [ BIN_OP | PREF_OR_BIN_OP ]
- { *p = mknode(OP_BINOP, *p, (p_tree) 0);
- (*p)->t_whichoper = currop;
- }
- expression(&((*p)->t_args[1]), currprio)
- |
- SEL_OP { *p = mknode(OP_BINOP, *p, (p_tree) 0);
- (*p)->t_whichoper = (int) tok.ival;
- }
- name(&(*p)->t_args[1])
- |
- '[' { *p = mknode(OP_BINOP, *p, (p_tree) 0);
- (*p)->t_whichoper = E_ARRAY;
- }
- expression(&(*p)->t_args[1], 0)
- [ ',' { *p = mknode(OP_BINOP, *p, (p_tree) 0);
- (*p)->t_whichoper = E_ARRAY;
- }
- expression(&(*p)->t_args[1], 0)
- ]*
- ']'
- ]*
- { in_expression--; }
- ;
- factor(p_tree *p;)
- :
- [
- %default EXPRESSION /* lexical analyzer will never return this token */
- { *p = mknode(OP_INTEGER, 0L); }
- |
- '(' expression(p, 0) ')'
- |
- INTEGER { *p = mknode(OP_INTEGER, tok.ival); }
- |
- REAL { *p = mknode(OP_REAL, tok.fval); }
- |
- STRING { *p = mknode(OP_STRING, tok.str); }
- |
- qualified_name(p)
- |
- { *p = mknode(OP_UNOP, (p_tree) 0);
- (*p)->t_whichoper = (int) tok.ival;
- }
- [ PREF_OP
- | PREF_OR_BIN_OP
- { (*currlang->fix_bin_to_pref)(*p); }
- ]
- expression(&(*p)->t_args[0], unprio((*p)->t_whichoper))
- ]
- [ %while(1)
- POST_OP { *p = mknode(OP_UNOP, *p);
- (*p)->t_whichoper = (int) tok.ival;
- }
- ]*
- ;
- position(p_tree *p;)
- { p_tree lin;
- char *str;
- }
- :
- [ STRING { str = tok.str; }
- ':'
- | { if (! listfile) str = 0;
- else str = listfile->sy_idf->id_text;
- }
- ]
- count(&lin) { *p = mknode(OP_AT, lin->t_ival, str);
- freenode(lin);
- }
- ;
- args(p_tree *p;)
- { int first_time = 1; }
- :
- [ { if (! first_time) {
- *p = mknode(OP_LINK, *p, (p_tree) 0);
- p = &((*p)->t_args[1]);
- }
- first_time = 0;
- }
- arg(p)
- ]*
- ;
- arg(p_tree *p;)
- :
- name(p)
- |
- '>' name(p) { (*p)->t_oper = OP_OUTPUT; }
- |
- '<' name(p) { (*p)->t_oper = OP_INPUT; }
- ;
- count(p_tree *p;)
- :
- INTEGER { *p = mknode(OP_INTEGER, tok.ival); }
- ;
- opt_num(p_tree *p;)
- :
- num(p)
- |
- { *p = 0; }
- ;
- num(p_tree *p;)
- :
- count(p)
- |
- '-' count(p) { (*p)->t_ival = - (*p)->t_ival; }
- ;
- qualified_name(p_tree *p;)
- :
- name(p)
- [ '`' { *p = mknode(OP_SELECT, *p, (p_tree) 0); }
- name(&((*p)->t_args[1]))
- ]*
- ;
- name(p_tree *p;)
- :
- [ XFILE
- | LIST
- | RUN
- | RERUN
- | STOP
- | WHEN
- | AT
- | IN
- | IF
- | %default NAME
- | CONT
- | STEP
- | NEXT
- | REGS
- | WHERE
- | STATUS
- | PRINT
- | DELETE
- | DUMP
- | RESTORE
- | TRACE
- | ON
- | SET
- | TO
- | FIND
- | DISPLAY
- | WHICH
- | HELP
- | DISABLE
- | ENABLE
- | SOURCE
- | FRAME
- | LOG
- ] { *p = mknode(OP_NAME, tok.idf, tok.str); }
- ;
- {
- int
- LLlex()
- {
- register int c;
- if (ASIDE) {
- tok = aside;
- ASIDE = 0;
- return TOK;
- }
- do {
- c = getc(db_in);
- if (interrupted && c == EOF) {
- c = ' ';
- interrupted = 0;
- continue;
- }
- } while (c != EOF && class(c) == STSKIP);
- if (c == EOF) {
- eof_seen = 1;
- return c;
- }
- if (extended_charset && in_ext(c)) {
- TOK = get_name(c);
- return TOK;
- }
- switch(class(c)) {
- case STSTR:
- TOK = (*currlang->get_string)(c);
- break;
- case STIDF:
- if (in_expression) TOK = (*currlang->get_name)(c);
- else TOK = get_name(c);
- break;
- case STNUM:
- TOK = (*currlang->get_number)(c);
- break;
- case STNL:
- TOK = c;
- break;
- case STSIMP:
- if (! in_expression) {
- TOK = c;
- break;
- }
- /* Fall through */
- default:
- TOK = (*currlang->get_token)(c);
- break;
- }
- return TOK;
- }
- int
- get_name(c)
- register int c;
- {
- char buf[512+1];
- register char *p = &buf[0];
- register struct idf *id;
- do {
- if (p - buf < 512) *p++ = c;
- c = getc(db_in);
- } while ((extended_charset && in_ext(c)) || in_idf(c));
- ungetc(c, db_in);
- *p++ = 0;
- if (extended_charset) {
- tok.idf = 0;
- tok.str = Salloc(buf, (unsigned) (p - buf));
- return NAME;
- }
- id = str2idf(buf, 1);
- tok.idf = id;
- tok.str = id->id_text;
- return id->id_reserved ? id->id_reserved : NAME;
- }
- extern char *symbol2str();
- LLmessage(t)
- {
- if (t > 0) {
- if (! errorgiven) {
- error("%s missing before %s", symbol2str(t), symbol2str(TOK));
- }
- aside = tok;
- }
- else if (t == 0) {
- if (! errorgiven) {
- error("%s unexpected", symbol2str(TOK));
- }
- }
- else if (! errorgiven) {
- error("EOF expected");
- }
- errorgiven = 1;
- }
- static void
- catch_del()
- {
- signal(SIGINT, catch_del);
- if (! disable_intr) {
- signal_child(7);
- child_interrupted = 1;
- }
- interrupted = 1;
- }
- void
- init_del()
- {
- signal(SIGINT, catch_del);
- }
- static void
- ctch()
- {
- /* Only for shell escapes ... */
- signal(SIGINT, ctch);
- }
- #define SHBUFSIZ 512
- static int
- shellescape()
- {
- register char *p; /* walks through command */
- static char previous[SHBUFSIZ]; /* previous command */
- char comm[SHBUFSIZ]; /* space for command */
- register int cnt; /* prevent array bound errors */
- register int c; /* current char */
- register int lastc = 0; /* will contain the previous char */
- p = comm;
- cnt = SHBUFSIZ-2;
- while (c = getc(db_in), c != '\n') {
- switch(c) {
- case '!':
- /*
- * An unescaped ! expands to the previous
- * command, but disappears if there is none
- */
- if (lastc != '\\') {
- if (*previous) {
- int len = strlen(previous);
- if ((cnt -= len) <= 0) break;
- strcpy(p,previous);
- p += len;
- }
- }
- else {
- *p++ = c;
- }
- continue;
- case '%':
- /*
- * An unescaped % will expand to the current
- * filename, but disappears is there is none
- */
- if (lastc != '\\') {
- if (listfile) {
- int len = strlen(listfile->sy_idf->id_text);
- if ((cnt -= len) <= 0) break;
- strcpy(p,listfile->sy_idf->id_text);
- p += len;
- }
- }
- else {
- *p++ = c;
- }
- continue;
- default:
- lastc = c;
- if (cnt-- <= 0) break;
- *p++ = c;
- continue;
- }
- break;
- }
- *p = '\0';
- if (c != '\n') {
- warning("shell command too long");
- while (c != '\n') c = getc(db_in);
- }
- ungetc(c, db_in);
- strcpy(previous, comm);
- signal(SIGINT, ctch);
- cnt = system(comm);
- signal(SIGINT, catch_del);
- return cnt;
- }
- }
|