commands.g 12 KB

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