1 /* $Id: commands.g,v 1.19 1995/08/15 09:10:39 ceriel Exp $ */
21 extern char *Salloc();
22 extern char *strindex();
23 extern char *strcpy();
24 extern void signal_child();
26 extern int disable_intr;
27 extern p_tree run_command, print_command;
29 struct token tok, aside;
31 int child_interrupted = 0;
35 static int shellescape();
37 static int extended_charset = 0;
38 static int in_expression = 0;
40 #define binprio(op) ((*(currlang->binop_prio))(op))
41 #define unprio(op) ((*(currlang->unop_prio))(op))
43 %start Commands, commands;
48 { p_tree com, lastcom = 0;
53 [ %persistent command_line(&com)
54 [ '\n' { give_prompt = 1; }
55 | %default ';' { give_prompt = 0; }
63 if (com != run_command) freenode(com);
69 if (repeatable(com)) {
72 else if (! in_status(com) &&
74 com != print_command) {
79 } else if (lastcom && ! errorgiven) {
92 command_line(p_tree *p;)
101 | continue_command(p)
106 | STATUS { *p = mknode(OP_STATUS); }
107 | DUMP { *p = mknode(OP_DUMP); }
108 | RESTORE opt_num(p) { *p = mknode(OP_RESTORE, *p); }
115 | FIND qualified_name(p){ *p = mknode(OP_FIND, *p); }
116 | WHICH qualified_name(p){ *p = mknode(OP_WHICH, *p); }
118 | '!' { (void) shellescape();
119 *p = mknode(OP_SHELL);
128 frame_command(p_tree *p;)
131 [ { *p = mknode(OP_FRAME, (p_tree) 0); }
132 | count(p) { *p = mknode(OP_FRAME, *p); }
133 | '-' count(p) { *p = mknode(OP_DOWN, *p); }
134 | '+' count(p) { *p = mknode(OP_UP, *p); }
138 source_command(p_tree *p;)
140 SOURCE { extended_charset = 1; }
141 name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
142 { *p = mknode(OP_SOURCE, *p);
143 extended_charset = 0;
147 log_command(p_tree *p;)
149 LOG { extended_charset = 1; }
150 [ name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
153 { *p = mknode(OP_LOG, *p);
154 extended_charset = 0;
158 where_command(p_tree *p;)
160 WHERE opt_num(p) { *p = mknode(OP_WHERE, *p); }
163 list_command(p_tree *p;)
164 { p_tree t1 = 0, t2 = 0; }
169 | qualified_name(&t1)
173 [ count(&t2) { t2->t_ival = - t2->t_ival; }
174 | { t2 = mknode(OP_INTEGER, -100000000L); }
178 { *p = mknode(OP_LIST, t1, t2); }
181 file_command(p_tree *p;)
183 XFILE { extended_charset = 1; }
185 | name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
186 ] { *p = mknode(OP_FILE, *p);
187 extended_charset = 0;
191 help_command(p_tree *p;)
194 { *p = mknode(OP_HELP, (p_tree) 0); }
195 [ name(&(*p)->t_args[0])?
196 | '?' { (*p)->t_args[0] = mknode(OP_NAME, str2idf("help",0), (char *) 0); }
197 | '!' { (*p)->t_args[0] = mknode(OP_NAME, (struct idf *) 0, "!"); }
201 run_command(p_tree *p;)
203 RUN { extended_charset = 1; }
204 args(p) { *p = mknode(OP_RUN, *p);
205 extended_charset = 0;
207 | RERUN { if (! run_command) {
208 error("no run command given yet");
210 else *p = run_command;
212 [ '?' { *p = mknode(OP_PRCOMM, *p); }
217 stop_command(p_tree *p;)
218 { p_tree whr = 0, cond = 0; }
222 condition(&cond)? { if (! whr && ! cond) {
223 error("no position or condition");
226 else *p = mknode(OP_STOP, whr, cond);
230 trace_command(p_tree *p;)
231 { p_tree whr = 0, cond = 0, exp = 0; }
234 [ ON format_expression(&exp) ]?
236 condition(&cond)? { *p = mknode(OP_TRACE, whr, cond, exp); }
239 continue_command(p_tree *p;)
240 { long l; p_tree pos = 0; }
243 [ INTEGER { l = tok.ival; }
246 [ AT position(&pos) ]?
247 { *p = mknode(OP_CONT, mknode(OP_INTEGER, l), pos); }
250 when_command(p_tree *p;)
251 { p_tree whr = 0, cond = 0; }
255 condition(&cond)? { *p = mknode(OP_WHEN, whr, cond, (p_tree) 0);
256 p = &(*p)->t_args[2];
261 *p = mknode(OP_LINK, *p, (p_tree) 0);
262 p = &((*p)->t_args[1]);
268 { if (! whr && ! cond) {
269 error("no position or condition");
272 error("no commands given");
277 step_command(p_tree *p;)
279 STEP { *p = mknode(OP_STEP, (p_tree) 0); }
280 count(&(*p)->t_args[0])?
283 next_command(p_tree *p;)
285 NEXT { *p = mknode(OP_NEXT, (p_tree) 0); }
286 count(&(*p)->t_args[0])?
289 regs_command(p_tree *p;)
291 REGS { *p = mknode(OP_REGS, (p_tree) 0); }
292 count(&(*p)->t_args[0])?
295 delete_command(p_tree *p;)
297 DELETE num_list(p)? { *p = mknode(OP_DELETE, *p); }
300 print_command(p_tree *p;)
303 [ format_expression_list(p)
304 { *p = mknode(OP_PRINT, *p); }
306 { *p = mknode(OP_PRINT, (p_tree) 0); }
310 display_command(p_tree *p;)
312 DISPLAY format_expression_list(p)
313 { *p = mknode(OP_DISPLAY, *p); }
316 format_expression_list(p_tree *p;)
319 [ ',' { *p = mknode(OP_LINK, *p, (p_tree) 0);
320 p = &((*p)->t_args[1]);
326 format_expression(p_tree *p;)
330 [ '\\' name(&p1) { register char *c = p1->t_str;
332 if (! strindex("doshcax", *c)) {
333 error("illegal format: %c", *c);
338 *p = mknode(OP_FORMAT, *p, p1);
344 set_command(p_tree *p;)
346 SET expression(p, 0) { *p = mknode(OP_SET, *p, (p_tree) 0); }
347 TO expression(&((*p)->t_args[1]), 0)
350 able_command(p_tree *p;)
352 [ ENABLE { *p = mknode(OP_ENABLE, (p_tree) 0); }
353 | DISABLE { *p = mknode(OP_DISABLE, (p_tree) 0); }
355 num_list(&(*p)->t_args[0])?
361 [ ',' { *p = mknode(OP_LINK, *p, (p_tree) 0); }
362 num(&(*p)->t_args[1])
366 condition(p_tree *p;)
373 IN qualified_name(p) { *p = mknode(OP_IN, *p, (p_tree) 0); }
374 [ AT position(&((*p)->t_args[1])) ]?
379 expression(p_tree *p; int level;)
380 { int currprio, currop; }
381 : { in_expression++; }
383 [ %while ((currprio = binprio(currop = (int) tok.ival)) > level)
384 [ BIN_OP | PREF_OR_BIN_OP ]
385 { *p = mknode(OP_BINOP, *p, (p_tree) 0);
386 (*p)->t_whichoper = currop;
388 expression(&((*p)->t_args[1]), currprio)
390 SEL_OP { *p = mknode(OP_BINOP, *p, (p_tree) 0);
391 (*p)->t_whichoper = (int) tok.ival;
393 name(&(*p)->t_args[1])
395 '[' { *p = mknode(OP_BINOP, *p, (p_tree) 0);
396 (*p)->t_whichoper = E_ARRAY;
398 expression(&(*p)->t_args[1], 0)
399 [ ',' { *p = mknode(OP_BINOP, *p, (p_tree) 0);
400 (*p)->t_whichoper = E_ARRAY;
402 expression(&(*p)->t_args[1], 0)
412 %default EXPRESSION /* lexical analyzer will never return this token */
413 { *p = mknode(OP_INTEGER, 0L); }
415 '(' expression(p, 0) ')'
417 INTEGER { *p = mknode(OP_INTEGER, tok.ival); }
419 REAL { *p = mknode(OP_REAL, tok.fval); }
421 STRING { *p = mknode(OP_STRING, tok.str); }
425 { *p = mknode(OP_UNOP, (p_tree) 0);
426 (*p)->t_whichoper = (int) tok.ival;
430 { (*currlang->fix_bin_to_pref)(*p); }
432 expression(&(*p)->t_args[0], unprio((*p)->t_whichoper))
435 POST_OP { *p = mknode(OP_UNOP, *p);
436 (*p)->t_whichoper = (int) tok.ival;
446 [ STRING { str = tok.str; }
448 | { if (! listfile) str = 0;
449 else str = listfile->sy_idf->id_text;
452 count(&lin) { *p = mknode(OP_AT, lin->t_ival, str);
458 { int first_time = 1; }
460 [ { if (! first_time) {
461 *p = mknode(OP_LINK, *p, (p_tree) 0);
462 p = &((*p)->t_args[1]);
474 '>' name(p) { (*p)->t_oper = OP_OUTPUT; }
476 '<' name(p) { (*p)->t_oper = OP_INPUT; }
481 INTEGER { *p = mknode(OP_INTEGER, tok.ival); }
495 '-' count(p) { (*p)->t_ival = - (*p)->t_ival; }
498 qualified_name(p_tree *p;)
501 [ '`' { *p = mknode(OP_SELECT, *p, (p_tree) 0); }
502 name(&((*p)->t_args[1]))
541 ] { *p = mknode(OP_NAME, tok.idf, tok.str); }
557 if (interrupted && c == EOF) {
562 } while (c != EOF && class(c) == STSKIP);
567 if (extended_charset && in_ext(c)) {
573 TOK = (*currlang->get_string)(c);
576 if (in_expression) TOK = (*currlang->get_name)(c);
577 else TOK = get_name(c);
580 TOK = (*currlang->get_number)(c);
586 if (! in_expression) {
592 TOK = (*currlang->get_token)(c);
603 register char *p = &buf[0];
604 register struct idf *id;
607 if (p - buf < 512) *p++ = c;
609 } while ((extended_charset && in_ext(c)) || in_idf(c));
612 if (extended_charset) {
614 tok.str = Salloc(buf, (unsigned) (p - buf));
617 id = str2idf(buf, 1);
619 tok.str = id->id_text;
620 return id->id_reserved ? id->id_reserved : NAME;
623 extern char *symbol2str();
629 error("%s missing before %s", symbol2str(t), symbol2str(TOK));
635 error("%s unexpected", symbol2str(TOK));
638 else if (! errorgiven) {
639 error("EOF expected");
647 signal(SIGINT, catch_del);
648 if (! disable_intr) {
650 child_interrupted = 1;
658 signal(SIGINT, catch_del);
664 /* Only for shell escapes ... */
665 signal(SIGINT, ctch);
673 register char *p; /* walks through command */
674 static char previous[SHBUFSIZ]; /* previous command */
675 char comm[SHBUFSIZ]; /* space for command */
676 register int cnt; /* prevent array bound errors */
677 register int c; /* current char */
678 register int lastc = 0; /* will contain the previous char */
682 while (c = getc(db_in), c != '\n') {
686 * An unescaped ! expands to the previous
687 * command, but disappears if there is none
691 int len = strlen(previous);
692 if ((cnt -= len) <= 0) break;
703 * An unescaped % will expand to the current
704 * filename, but disappears is there is none
708 int len = strlen(listfile->sy_idf->id_text);
709 if ((cnt -= len) <= 0) break;
710 strcpy(p,listfile->sy_idf->id_text);
720 if (cnt-- <= 0) break;
728 warning("shell command too long");
729 while (c != '\n') c = getc(db_in);
732 strcpy(previous, comm);
733 signal(SIGINT, ctch);
735 signal(SIGINT, catch_del);