commands.g 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. /* $Header$ */
  2. /* Command grammar */
  3. {
  4. #include <stdio.h>
  5. #include <alloc.h>
  6. #include <signal.h>
  7. #include "ops.h"
  8. #include "class.h"
  9. #include "position.h"
  10. #include "file.h"
  11. #include "idf.h"
  12. #include "symbol.h"
  13. #include "tree.h"
  14. #include "langdep.h"
  15. #include "token.h"
  16. #include "expr.h"
  17. extern char *Salloc();
  18. extern char *strindex();
  19. extern char *strcpy();
  20. extern FILE *db_in;
  21. extern int disable_intr;
  22. extern p_tree run_command, print_command;
  23. int errorgiven = 0;
  24. int child_interrupted = 0;
  25. int interrupted = 0;
  26. int eof_seen = 0;
  27. static int extended_charset = 0;
  28. static int in_expression = 0;
  29. struct token tok, aside;
  30. #define binprio(op) ((*(currlang->binop_prio))(op))
  31. #define unprio(op) ((*(currlang->unop_prio))(op))
  32. }
  33. %start Commands, commands;
  34. %lexical LLlex;
  35. commands
  36. { p_tree com, lastcom = 0;
  37. int give_prompt;
  38. }
  39. :
  40. { errorgiven = 0; }
  41. [ %persistent command_line(&com)
  42. [ '\n' { give_prompt = 1; }
  43. | %default ';' { give_prompt = 0; }
  44. ]
  45. { if (com) {
  46. if (lastcom) {
  47. freenode(lastcom);
  48. lastcom = 0;
  49. }
  50. if (errorgiven) {
  51. if (com != run_command) freenode(com);
  52. com = 0;
  53. }
  54. else {
  55. log(com);
  56. eval(com);
  57. if (repeatable(com)) {
  58. lastcom = com;
  59. }
  60. else if (! in_status(com) &&
  61. com != run_command &&
  62. com != print_command) {
  63. freenode(com);
  64. com = 0;
  65. }
  66. }
  67. } else if (lastcom && ! errorgiven) {
  68. log(lastcom);
  69. eval(lastcom);
  70. }
  71. if (give_prompt) {
  72. errorgiven = 0;
  73. interrupted = 0;
  74. prompt();
  75. }
  76. }
  77. ]*
  78. ;
  79. command_line(p_tree *p;)
  80. :
  81. { *p = 0; }
  82. [
  83. list_command(p)
  84. | file_command(p)
  85. | run_command(p)
  86. | stop_command(p)
  87. | when_command(p)
  88. | continue_command(p)
  89. | step_command(p)
  90. | next_command(p)
  91. | regs_command(p)
  92. | where_command(p)
  93. | STATUS { *p = mknode(OP_STATUS); }
  94. | DUMP { *p = mknode(OP_DUMP); }
  95. | RESTORE count(p)? { *p = mknode(OP_RESTORE, *p); }
  96. | delete_command(p)
  97. | print_command(p)
  98. | display_command(p)
  99. | trace_command(p)
  100. | set_command(p)
  101. | help_command(p)
  102. | FIND qualified_name(p){ *p = mknode(OP_FIND, *p); }
  103. | WHICH qualified_name(p){ *p = mknode(OP_WHICH, *p); }
  104. | able_command(p)
  105. | '!' { shellescape();
  106. *p = mknode(OP_SHELL);
  107. }
  108. | source_command(p)
  109. | log_command(p)
  110. | frame_command(p)
  111. |
  112. ]
  113. ;
  114. frame_command(p_tree *p;)
  115. :
  116. FRAME
  117. [ { *p = mknode(OP_FRAME, (p_tree) 0); }
  118. | count(p) { *p = mknode(OP_FRAME, *p); }
  119. | '-' count(p) { *p = mknode(OP_DOWN, *p); }
  120. | '+' count(p) { *p = mknode(OP_UP, *p); }
  121. ]
  122. ;
  123. source_command(p_tree *p;)
  124. :
  125. SOURCE { extended_charset = 1; }
  126. name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
  127. { *p = mknode(OP_SOURCE, *p);
  128. extended_charset = 0;
  129. }
  130. ;
  131. log_command(p_tree *p;)
  132. :
  133. LOG { extended_charset = 1; }
  134. [ name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
  135. | { *p = 0; }
  136. ]
  137. { *p = mknode(OP_LOG, *p);
  138. extended_charset = 0;
  139. }
  140. ;
  141. where_command(p_tree *p;)
  142. :
  143. WHERE opt_num(p) { *p = mknode(OP_WHERE, *p); }
  144. ;
  145. list_command(p_tree *p;)
  146. { p_tree t1 = 0, t2 = 0; }
  147. :
  148. LIST
  149. [
  150. | position(&t1)
  151. | qualified_name(&t1)
  152. ]
  153. [ ',' count(&t2)
  154. | '-'
  155. [ count(&t2) { t2->t_ival = - t2->t_ival; }
  156. | { t2 = mknode(OP_INTEGER, -100000000L); }
  157. ]
  158. |
  159. ]
  160. { *p = mknode(OP_LIST, t1, t2); }
  161. ;
  162. file_command(p_tree *p;)
  163. :
  164. XFILE { extended_charset = 1; }
  165. [ { *p = 0; }
  166. | name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
  167. ] { *p = mknode(OP_FILE, *p);
  168. extended_charset = 0;
  169. }
  170. ;
  171. help_command(p_tree *p;)
  172. :
  173. [ HELP | '?' ]
  174. { *p = mknode(OP_HELP, (p_tree) 0); }
  175. [ name(&(*p)->t_args[0])?
  176. | '?' { (*p)->t_args[0] = mknode(OP_NAME, str2idf("help",0), (char *) 0); }
  177. | '!' { (*p)->t_args[0] = mknode(OP_NAME, (struct idf *) 0, "!"); }
  178. ]
  179. ;
  180. run_command(p_tree *p;)
  181. :
  182. RUN { extended_charset = 1; }
  183. args(p) { *p = mknode(OP_RUN, *p);
  184. extended_charset = 0;
  185. }
  186. | RERUN { if (! run_command) {
  187. error("no run command given yet");
  188. }
  189. else *p = run_command;
  190. }
  191. [ '?' { *p = mknode(OP_PRCOMM, *p); }
  192. |
  193. ]
  194. ;
  195. stop_command(p_tree *p;)
  196. { p_tree whr = 0, cond = 0; }
  197. :
  198. STOP
  199. where(&whr)?
  200. condition(&cond)? { if (! whr && ! cond) {
  201. error("no position or condition");
  202. *p = 0;
  203. }
  204. else *p = mknode(OP_STOP, whr, cond);
  205. }
  206. ;
  207. trace_command(p_tree *p;)
  208. { p_tree whr = 0, cond = 0, exp = 0; }
  209. :
  210. TRACE
  211. [ ON expression(&exp, 0) ]?
  212. where(&whr)?
  213. condition(&cond)? { *p = mknode(OP_TRACE, whr, cond, exp); }
  214. ;
  215. continue_command(p_tree *p;)
  216. { long l; p_tree pos = 0; }
  217. :
  218. CONT
  219. [ INTEGER { l = tok.ival; }
  220. | { l = 1; }
  221. ]
  222. [ AT position(&pos) ]?
  223. { *p = mknode(OP_CONT, mknode(OP_INTEGER, l), pos); }
  224. ;
  225. when_command(p_tree *p;)
  226. { p_tree whr = 0, cond = 0; }
  227. :
  228. WHEN
  229. where(&whr)?
  230. condition(&cond)? { *p = mknode(OP_WHEN, whr, cond, (p_tree) 0);
  231. p = &(*p)->t_args[2];
  232. }
  233. '{'
  234. command_line(p)
  235. [ ';' { if (*p) {
  236. *p = mknode(OP_LINK, *p, (p_tree) 0);
  237. p = &((*p)->t_args[1]);
  238. }
  239. }
  240. command_line(p)
  241. ]*
  242. '}'
  243. { if (! whr && ! cond) {
  244. error("no position or condition");
  245. }
  246. else if (! *p) {
  247. error("no commands given");
  248. }
  249. }
  250. ;
  251. step_command(p_tree *p;)
  252. :
  253. STEP { *p = mknode(OP_STEP, (p_tree) 0); }
  254. count(&(*p)->t_args[0])?
  255. ;
  256. next_command(p_tree *p;)
  257. :
  258. NEXT { *p = mknode(OP_NEXT, (p_tree) 0); }
  259. count(&(*p)->t_args[0])?
  260. ;
  261. regs_command(p_tree *p;)
  262. :
  263. REGS { *p = mknode(OP_REGS, (p_tree) 0); }
  264. count(&(*p)->t_args[0])?
  265. ;
  266. delete_command(p_tree *p;)
  267. :
  268. DELETE count_list(p)? { *p = mknode(OP_DELETE, *p); }
  269. ;
  270. print_command(p_tree *p;)
  271. :
  272. PRINT
  273. [ format_expression_list(p)
  274. { *p = mknode(OP_PRINT, *p); }
  275. |
  276. { *p = mknode(OP_PRINT, (p_tree) 0); }
  277. ]
  278. ;
  279. display_command(p_tree *p;)
  280. :
  281. DISPLAY format_expression_list(p)
  282. { *p = mknode(OP_DISPLAY, *p); }
  283. ;
  284. format_expression_list(p_tree *p;)
  285. :
  286. format_expression(p)
  287. [ ',' { *p = mknode(OP_LINK, *p, (p_tree) 0);
  288. p = &((*p)->t_args[1]);
  289. }
  290. format_expression(p)
  291. ]*
  292. ;
  293. format_expression(p_tree *p;)
  294. { p_tree p1; }
  295. :
  296. expression(p, 0)
  297. [ '\\'
  298. [ name(&p1) { register char *c = p1->t_str;
  299. while (*c) {
  300. if (! strindex("doshcax", *c)) {
  301. error("illegal format: %c", *c);
  302. break;
  303. }
  304. c++;
  305. }
  306. *p = mknode(OP_FORMAT, *p, p1);
  307. }
  308. |
  309. ]
  310. |
  311. ]
  312. ;
  313. set_command(p_tree *p;)
  314. :
  315. SET expression(p, 0) { *p = mknode(OP_SET, *p, (p_tree) 0); }
  316. TO expression(&((*p)->t_args[1]), 0)
  317. ;
  318. able_command(p_tree *p;)
  319. :
  320. [ ENABLE { *p = mknode(OP_ENABLE, (p_tree) 0); }
  321. | DISABLE { *p = mknode(OP_DISABLE, (p_tree) 0); }
  322. ]
  323. count_list(&(*p)->t_args[0])?
  324. ;
  325. count_list(p_tree *p;)
  326. :
  327. count(p)
  328. [ ',' { *p = mknode(OP_LINK, *p, (p_tree) 0); }
  329. count(&(*p)->t_args[1])
  330. ]*
  331. ;
  332. condition(p_tree *p;)
  333. :
  334. IF expression(p, 0)
  335. ;
  336. where(p_tree *p;)
  337. :
  338. IN qualified_name(p) { *p = mknode(OP_IN, *p, (p_tree) 0); }
  339. [ AT position(&((*p)->t_args[1])) ]?
  340. |
  341. AT position(p)
  342. ;
  343. expression(p_tree *p; int level;)
  344. { int currprio, currop; }
  345. : { in_expression++; }
  346. factor(p)
  347. [ %while ((currprio = binprio(currop = (int) tok.ival)) > level)
  348. [ BIN_OP | PREF_OR_BIN_OP ]
  349. { *p = mknode(OP_BINOP, *p, (p_tree) 0);
  350. (*p)->t_whichoper = currop;
  351. }
  352. expression(&((*p)->t_args[1]), currprio)
  353. |
  354. SEL_OP { *p = mknode(OP_BINOP, *p, (p_tree) 0);
  355. (*p)->t_whichoper = (int) tok.ival;
  356. }
  357. name(&(*p)->t_args[1])
  358. |
  359. '[' { *p = mknode(OP_BINOP, *p, (p_tree) 0);
  360. (*p)->t_whichoper = E_ARRAY;
  361. }
  362. expression(&(*p)->t_args[1], 0)
  363. [ ',' { *p = mknode(OP_BINOP, *p, (p_tree) 0);
  364. (*p)->t_whichoper = E_ARRAY;
  365. }
  366. expression(&(*p)->t_args[1], 0)
  367. ]*
  368. ']'
  369. ]*
  370. { in_expression--; }
  371. ;
  372. factor(p_tree *p;)
  373. :
  374. [
  375. %default EXPRESSION /* lexical analyzer will never return this token */
  376. { *p = mknode(OP_INTEGER, 0L); }
  377. |
  378. '(' expression(p, 0) ')'
  379. |
  380. INTEGER { *p = mknode(OP_INTEGER, tok.ival); }
  381. |
  382. REAL { *p = mknode(OP_REAL, tok.fval); }
  383. |
  384. STRING { *p = mknode(OP_STRING, tok.str); }
  385. |
  386. qualified_name(p)
  387. |
  388. { *p = mknode(OP_UNOP, (p_tree) 0);
  389. (*p)->t_whichoper = (int) tok.ival;
  390. }
  391. [ PREF_OP
  392. | PREF_OR_BIN_OP
  393. { (*currlang->fix_bin_to_pref)(*p); }
  394. ]
  395. expression(&(*p)->t_args[0], unprio((*p)->t_whichoper))
  396. ]
  397. [ %while(1)
  398. POST_OP { *p = mknode(OP_UNOP, *p);
  399. (*p)->t_whichoper = (int) tok.ival;
  400. }
  401. ]*
  402. ;
  403. position(p_tree *p;)
  404. { p_tree lin;
  405. char *str;
  406. }
  407. :
  408. [ STRING { str = tok.str; }
  409. ':'
  410. | { if (! listfile) str = 0;
  411. else str = listfile->sy_idf->id_text;
  412. }
  413. ]
  414. count(&lin) { *p = mknode(OP_AT, lin->t_ival, str);
  415. freenode(lin);
  416. }
  417. ;
  418. args(p_tree *p;)
  419. { int first_time = 1; }
  420. :
  421. [ { if (! first_time) {
  422. *p = mknode(OP_LINK, *p, (p_tree) 0);
  423. p = &((*p)->t_args[1]);
  424. }
  425. first_time = 0;
  426. }
  427. arg(p)
  428. ]*
  429. ;
  430. arg(p_tree *p;)
  431. :
  432. name(p)
  433. |
  434. '>' name(p) { (*p)->t_oper = OP_OUTPUT; }
  435. |
  436. '<' name(p) { (*p)->t_oper = OP_INPUT; }
  437. ;
  438. count(p_tree *p;)
  439. :
  440. INTEGER { *p = mknode(OP_INTEGER, tok.ival); }
  441. ;
  442. opt_num(p_tree *p;)
  443. :
  444. count(p)
  445. |
  446. '-' count(p) { (*p)->t_ival = - (*p)->t_ival; }
  447. |
  448. { *p = 0; }
  449. ;
  450. qualified_name(p_tree *p;)
  451. :
  452. name(p)
  453. [ '`' { *p = mknode(OP_SELECT, *p, (p_tree) 0); }
  454. name(&((*p)->t_args[1]))
  455. ]*
  456. ;
  457. name(p_tree *p;)
  458. :
  459. [ XFILE
  460. | LIST
  461. | RUN
  462. | RERUN
  463. | STOP
  464. | WHEN
  465. | AT
  466. | IN
  467. | IF
  468. | %default NAME
  469. | CONT
  470. | STEP
  471. | NEXT
  472. | REGS
  473. | WHERE
  474. | STATUS
  475. | PRINT
  476. | DELETE
  477. | DUMP
  478. | RESTORE
  479. | TRACE
  480. | ON
  481. | SET
  482. | TO
  483. | FIND
  484. | DISPLAY
  485. | WHICH
  486. | HELP
  487. | DISABLE
  488. | ENABLE
  489. | SOURCE
  490. | FRAME
  491. | LOG
  492. ] { *p = mknode(OP_NAME, tok.idf, tok.str); }
  493. ;
  494. {
  495. int
  496. LLlex()
  497. {
  498. register int c;
  499. if (ASIDE) {
  500. tok = aside;
  501. ASIDE = 0;
  502. return TOK;
  503. }
  504. do {
  505. c = getc(db_in);
  506. } while (c != EOF && class(c) == STSKIP);
  507. if (c == EOF) {
  508. eof_seen = 1;
  509. return c;
  510. }
  511. if (extended_charset && in_ext(c)) {
  512. TOK = get_name(c);
  513. return TOK;
  514. }
  515. switch(class(c)) {
  516. case STSTR:
  517. TOK = (*currlang->get_string)(c);
  518. break;
  519. case STIDF:
  520. if (in_expression) TOK = (*currlang->get_name)(c);
  521. else TOK = get_name(c);
  522. break;
  523. case STNUM:
  524. TOK = (*currlang->get_number)(c);
  525. break;
  526. case STNL:
  527. TOK = c;
  528. break;
  529. case STSIMP:
  530. if (! in_expression) {
  531. TOK = c;
  532. break;
  533. }
  534. /* Fall through */
  535. default:
  536. TOK = (*currlang->get_token)(c);
  537. break;
  538. }
  539. return TOK;
  540. }
  541. int
  542. get_name(c)
  543. register int c;
  544. {
  545. char buf[512+1];
  546. register char *p = &buf[0];
  547. register struct idf *id;
  548. do {
  549. if (p - buf < 512) *p++ = c;
  550. c = getc(db_in);
  551. } while ((extended_charset && in_ext(c)) || in_idf(c));
  552. ungetc(c, db_in);
  553. *p++ = 0;
  554. if (extended_charset) {
  555. tok.idf = 0;
  556. tok.str = Salloc(buf, (unsigned) (p - buf));
  557. return NAME;
  558. }
  559. id = str2idf(buf, 1);
  560. tok.idf = id;
  561. tok.str = id->id_text;
  562. return id->id_reserved ? id->id_reserved : NAME;
  563. }
  564. extern char * symbol2str();
  565. LLmessage(t)
  566. {
  567. if (t > 0) {
  568. if (! errorgiven) {
  569. error("%s missing before %s", symbol2str(t), symbol2str(TOK));
  570. }
  571. aside = tok;
  572. }
  573. else if (t == 0) {
  574. if (! errorgiven) {
  575. error("%s unexpected", symbol2str(TOK));
  576. }
  577. }
  578. else if (! errorgiven) {
  579. error("EOF expected");
  580. }
  581. errorgiven = 1;
  582. }
  583. static int
  584. catch_del()
  585. {
  586. signal(SIGINT, catch_del);
  587. if (! disable_intr) {
  588. signal_child(SIGEMT);
  589. child_interrupted = 1;
  590. }
  591. interrupted = 1;
  592. }
  593. int
  594. init_del()
  595. {
  596. signal(SIGINT, catch_del);
  597. }
  598. static int
  599. ctch()
  600. {
  601. /* Only for shell escapes ... */
  602. signal(SIGINT, ctch);
  603. }
  604. #define SHBUFSIZ 512
  605. int
  606. shellescape()
  607. {
  608. register char *p; /* walks through command */
  609. static char previous[SHBUFSIZ]; /* previous command */
  610. char comm[SHBUFSIZ]; /* space for command */
  611. register int cnt; /* prevent array bound errors */
  612. register int c; /* current char */
  613. register int lastc = 0; /* will contain the previous char */
  614. p = comm;
  615. cnt = SHBUFSIZ-2;
  616. while (c = getc(db_in), c != '\n') {
  617. switch(c) {
  618. case '!':
  619. /*
  620. * An unescaped ! expands to the previous
  621. * command, but disappears if there is none
  622. */
  623. if (lastc != '\\') {
  624. if (*previous) {
  625. int len = strlen(previous);
  626. if ((cnt -= len) <= 0) break;
  627. strcpy(p,previous);
  628. p += len;
  629. }
  630. }
  631. else {
  632. *p++ = c;
  633. }
  634. continue;
  635. case '%':
  636. /*
  637. * An unescaped % will expand to the current
  638. * filename, but disappears is there is none
  639. */
  640. if (lastc != '\\') {
  641. if (listfile) {
  642. int len = strlen(listfile->sy_idf->id_text);
  643. if ((cnt -= len) <= 0) break;
  644. strcpy(p,listfile->sy_idf->id_text);
  645. p += len;
  646. }
  647. }
  648. else {
  649. *p++ = c;
  650. }
  651. continue;
  652. default:
  653. lastc = c;
  654. if (cnt-- <= 0) break;
  655. *p++ = c;
  656. continue;
  657. }
  658. break;
  659. }
  660. *p = '\0';
  661. if (c != '\n') {
  662. warning("shell command too long");
  663. while (c != '\n') c = getc(db_in);
  664. }
  665. ungetc(c, db_in);
  666. strcpy(previous, comm);
  667. signal(SIGINT, ctch);
  668. cnt = system(comm);
  669. signal(SIGINT, catch_del);
  670. return cnt;
  671. }
  672. }