commands.g 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /* $Header$ */
  2. /* Command grammar */
  3. {
  4. #include <stdio.h>
  5. #include <alloc.h>
  6. #include <setjmp.h>
  7. #include <signal.h>
  8. #include "ops.h"
  9. #include "class.h"
  10. #include "position.h"
  11. #include "file.h"
  12. #include "idf.h"
  13. #include "symbol.h"
  14. #include "tree.h"
  15. extern char *Salloc();
  16. extern t_lineno currline;
  17. extern FILE *db_in;
  18. int errorgiven;
  19. int extended_charset = 0;
  20. jmp_buf jmpbuf;
  21. static int init_del();
  22. static int skip_to_eol();
  23. static struct token {
  24. int tokno;
  25. long ival;
  26. char *str;
  27. double fval;
  28. struct idf *idf;
  29. } tok, aside;
  30. #define TOK tok.tokno
  31. #define ASIDE aside.tokno
  32. }
  33. %start Commands, commands;
  34. %lexical LLlex;
  35. commands
  36. { p_tree com, lastcom = 0;
  37. }
  38. :
  39. { if (! setjmp(jmpbuf)) {
  40. init_del();
  41. }
  42. else {
  43. skip_to_eol();
  44. goto prmpt;
  45. }
  46. }
  47. [ %persistent command_line(&com)
  48. { if (com) {
  49. if (errorgiven) {
  50. freenode(com);
  51. com = 0;
  52. }
  53. if (lastcom && !in_status(lastcom) &&
  54. lastcom != run_command) {
  55. freenode(lastcom);
  56. lastcom = 0;
  57. }
  58. if (com) {
  59. if (repeatable(com)) {
  60. lastcom = com;
  61. }
  62. eval(com);
  63. if (! repeatable(com) &&
  64. ! in_status(com) &&
  65. com != run_command) {
  66. freenode(com);
  67. }
  68. }
  69. } else if (lastcom && ! errorgiven) eval(lastcom);
  70. }
  71. [ '\n' { prmpt: prompt(); }
  72. | ';'
  73. ] { errorgiven = 0; }
  74. ]*
  75. { signal_child(SIGKILL); }
  76. ;
  77. command_line(p_tree *p;)
  78. :
  79. list_command(p)
  80. | file_command(p)
  81. | run_command(p)
  82. | stop_command(p)
  83. | when_command(p)
  84. | continue_command(p)
  85. | step_command(p)
  86. | next_command(p)
  87. | regs_command(p)
  88. | WHERE { *p = mknode(OP_WHERE); }
  89. | STATUS { *p = mknode(OP_STATUS); }
  90. | DUMP { *p = mknode(OP_DUMP); }
  91. | RESTORE INTEGER { *p = mknode(OP_RESTORE, tok.ival); }
  92. | delete_command(p)
  93. | print_command(p)
  94. | trace_command(p)
  95. | { *p = 0; }
  96. ;
  97. list_command(p_tree *p;)
  98. { p_tree t1 = 0, t2 = 0; }
  99. :
  100. LIST
  101. [
  102. | lin_num(&t1)
  103. [ ',' lin_num(&t2)
  104. | { t2 = mknode(OP_INTEGER, t1->t_ival); }
  105. ]
  106. ] { *p = mknode(OP_LIST, t1, t2); }
  107. ;
  108. file_command(p_tree *p;)
  109. :
  110. XFILE { extended_charset = 1; }
  111. [ { *p = 0; }
  112. | name(p) { (*p)->t_idf = str2idf((*p)->t_str, 0); }
  113. ] { *p = mknode(OP_FILE, *p);
  114. extended_charset = 0;
  115. }
  116. ;
  117. run_command(p_tree *p;)
  118. :
  119. RUN { extended_charset = 1; *p = 0; }
  120. args(p) { *p = mknode(OP_RUN, *p);
  121. extended_charset = 0;
  122. freenode(run_command);
  123. run_command = *p;
  124. }
  125. | RERUN { if (! run_command) {
  126. error("no run command given yet");
  127. }
  128. else *p = run_command;
  129. }
  130. ;
  131. stop_command(p_tree *p;)
  132. { p_tree whr = 0, cond = 0; }
  133. :
  134. STOP
  135. where(&whr)?
  136. condition(&cond)? { if (! whr && ! cond) {
  137. error("no position or condition");
  138. *p = 0;
  139. }
  140. else *p = mknode(OP_STOP, whr, cond);
  141. }
  142. ;
  143. trace_command(p_tree *p;)
  144. { p_tree whr = 0, cond = 0, exp = 0; }
  145. :
  146. TRACE
  147. [ ON expression(&exp) ]?
  148. where(&whr)?
  149. condition(&cond)? { *p = mknode(OP_TRACE, whr, cond, exp); }
  150. ;
  151. continue_command(p_tree *p;)
  152. { long l; p_tree pos = 0; }
  153. :
  154. CONT
  155. [ INTEGER { l = tok.ival; }
  156. | { l = 1; }
  157. ]
  158. position(&pos)?
  159. { *p = mknode(OP_CONT, mknode(OP_INTEGER, l), pos); }
  160. ;
  161. when_command(p_tree *p;)
  162. { p_tree whr = 0, cond = 0; }
  163. :
  164. WHEN
  165. where(&whr)?
  166. condition(&cond)?
  167. '{'
  168. command_line(p)
  169. [ ';' { *p = mknode(OP_LINK, *p, (p_tree) 0);
  170. p = &((*p)->t_args[1]);
  171. }
  172. command_line(p)
  173. ]*
  174. '}'
  175. { if (! whr && ! cond) {
  176. error("no position or condition");
  177. freenode(*p);
  178. *p = 0;
  179. }
  180. else *p = mknode(OP_WHEN, whr, cond, *p);
  181. }
  182. ;
  183. step_command(p_tree *p;)
  184. { long l; }
  185. :
  186. STEP
  187. [ INTEGER { l = tok.ival; }
  188. | { l = 1; }
  189. ] { *p = mknode(OP_STEP, l); }
  190. ;
  191. next_command(p_tree *p;)
  192. { long l; }
  193. :
  194. NEXT
  195. [ INTEGER { l = tok.ival; }
  196. | { l = 1; }
  197. ] { *p = mknode(OP_NEXT, l); }
  198. ;
  199. regs_command(p_tree *p;)
  200. { long l; }
  201. :
  202. REGS
  203. [ INTEGER { l = tok.ival; }
  204. | { l = 0; }
  205. ] { *p = mknode(OP_REGS, l); }
  206. ;
  207. delete_command(p_tree *p;)
  208. :
  209. DELETE
  210. INTEGER { *p = mknode(OP_DELETE, tok.ival); }
  211. ;
  212. print_command(p_tree *p;)
  213. :
  214. PRINT expression(p) { *p = mknode(OP_PRINT, *p);
  215. p = &((*p)->t_args[0]);
  216. }
  217. [ ',' { *p = mknode(OP_LINK, *p, (p_tree) 0);
  218. p = &((*p)->t_args[1]);
  219. }
  220. expression(p)
  221. ]*
  222. ;
  223. condition(p_tree *p;)
  224. :
  225. IF expression(p)
  226. ;
  227. where(p_tree *p;)
  228. :
  229. IN qualified_name(p) { *p = mknode(OP_IN, *p); }
  230. |
  231. position(p)
  232. ;
  233. expression(p_tree *p;)
  234. :
  235. qualified_name(p)
  236. ;
  237. position(p_tree *p;)
  238. { p_tree lin;
  239. char *str;
  240. }
  241. :
  242. AT
  243. [ STRING { str = tok.str; }
  244. ':'
  245. | { if (! currfile) str = 0;
  246. else str = currfile->sy_idf->id_text;
  247. }
  248. ]
  249. lin_num(&lin) { *p = mknode(OP_AT, lin->t_ival, str);
  250. freenode(lin);
  251. }
  252. ;
  253. args(p_tree *p;)
  254. { int first_time = 1; }
  255. :
  256. [ { if (! first_time) {
  257. *p = mknode(OP_LINK, *p, (p_tree) 0);
  258. p = &((*p)->t_args[1]);
  259. }
  260. first_time = 0;
  261. }
  262. arg(p)
  263. ]*
  264. ;
  265. arg(p_tree *p;)
  266. :
  267. name(p)
  268. |
  269. '>' name(p) { (*p)->t_oper = OP_OUTPUT; }
  270. |
  271. '<' name(p) { (*p)->t_oper = OP_INPUT; }
  272. ;
  273. lin_num(p_tree *p;)
  274. :
  275. INTEGER { *p = mknode(OP_INTEGER, tok.ival); }
  276. ;
  277. qualified_name(p_tree *p;)
  278. :
  279. name(p)
  280. [ '`' { *p = mknode(OP_SELECT, *p, (p_tree) 0); }
  281. name(&((*p)->t_args[1]))
  282. ]*
  283. ;
  284. name(p_tree *p;)
  285. :
  286. [ XFILE
  287. | LIST
  288. | RUN
  289. | RERUN
  290. | STOP
  291. | WHEN
  292. | AT
  293. | IN
  294. | IF
  295. | NAME
  296. | CONT
  297. | STEP
  298. | NEXT
  299. | REGS
  300. | WHERE
  301. | STATUS
  302. | PRINT
  303. | DELETE
  304. | DUMP
  305. | RESTORE
  306. | TRACE
  307. | ON
  308. ] { *p = mknode(OP_NAME, tok.idf, tok.str); }
  309. ;
  310. {
  311. int
  312. LLlex()
  313. {
  314. register int c;
  315. if (ASIDE) {
  316. tok = aside;
  317. ASIDE = 0;
  318. return TOK;
  319. }
  320. do {
  321. c = getc(db_in);
  322. } while (c != EOF && class(c) == STSKIP);
  323. if (c == EOF) return c;
  324. switch(class(c)) {
  325. case STSTR:
  326. TOK = get_string(c);
  327. break;
  328. case STIDF:
  329. TOK = get_name(c);
  330. break;
  331. case STDOT:
  332. c = getc(db_in);
  333. if (c == EOF || class(c) != STNUM) {
  334. ungetc(c,db_in);
  335. TOK = '.';
  336. break;
  337. }
  338. /* Fall through */
  339. case STNUM:
  340. TOK = get_number(c);
  341. break;
  342. case STNL:
  343. case STSIMP:
  344. TOK = c;
  345. break;
  346. default:
  347. error("illegal character '\\0%o'", c);
  348. return LLlex();
  349. }
  350. return TOK;
  351. }
  352. int
  353. get_name(c)
  354. register int c;
  355. {
  356. char buf[512+1];
  357. register char *p = &buf[0];
  358. register struct idf *id;
  359. do {
  360. if (p - buf < 512) *p++ = c;
  361. c = getc(db_in);
  362. } while ((extended_charset && in_ext(c)) || in_idf(c));
  363. ungetc(c, db_in);
  364. *p = 0;
  365. if (extended_charset) {
  366. tok.idf = 0;
  367. tok.str = Salloc(buf, (unsigned) (p - buf));
  368. return NAME;
  369. }
  370. id = str2idf(buf, 1);
  371. tok.idf = id;
  372. tok.str = id->id_text;
  373. return id->id_reserved ? id->id_reserved : NAME;
  374. }
  375. static int
  376. quoted(ch)
  377. int ch;
  378. {
  379. /* quoted() replaces an escaped character sequence by the
  380. character meant.
  381. */
  382. /* first char after backslash already in ch */
  383. if (!is_oct(ch)) { /* a quoted char */
  384. switch (ch) {
  385. case 'n':
  386. ch = '\n';
  387. break;
  388. case 't':
  389. ch = '\t';
  390. break;
  391. case 'b':
  392. ch = '\b';
  393. break;
  394. case 'r':
  395. ch = '\r';
  396. break;
  397. case 'f':
  398. ch = '\f';
  399. break;
  400. }
  401. }
  402. else { /* a quoted octal */
  403. register int oct = 0, cnt = 0;
  404. do {
  405. oct = oct*8 + (ch-'0');
  406. ch = getc(db_in);
  407. } while (is_oct(ch) && ++cnt < 3);
  408. ungetc(ch, db_in);
  409. ch = oct;
  410. }
  411. return ch&0377;
  412. }
  413. int get_string(c)
  414. int c;
  415. {
  416. register int ch;
  417. char buf[512];
  418. register int len = 0;
  419. while (ch = getc(db_in), ch != c) {
  420. if (ch == '\n') {
  421. error("newline in string");
  422. break;
  423. }
  424. if (ch == '\\') {
  425. ch = getc(db_in);
  426. ch = quoted(ch);
  427. }
  428. buf[len++] = ch;
  429. }
  430. buf[len++] = 0;
  431. tok.str = Salloc(buf, (unsigned) len);
  432. return STRING;
  433. }
  434. static int
  435. val_in_base(c, base)
  436. register int c;
  437. {
  438. return is_dig(c)
  439. ? c - '0'
  440. : base != 16
  441. ? -1
  442. : is_hex(c)
  443. ? (c - 'a' + 10) & 017
  444. : -1;
  445. }
  446. int
  447. get_number(c)
  448. register int c;
  449. {
  450. char buf[512+1];
  451. register int base = 10;
  452. register char *p = &buf[0];
  453. register long val = 0;
  454. register int val_c;
  455. if (c == '0') {
  456. /* check if next char is an 'x' or an 'X' */
  457. c = getc(db_in);
  458. if (c == 'x' || c == 'X') {
  459. base = 16;
  460. c = getc(db_in);
  461. }
  462. else base = 8;
  463. }
  464. while (val_c = val_in_base(c, base), val_c >= 0) {
  465. val = val * base + val_c;
  466. if (p - buf < 512) *p++ = c;
  467. c = getc(db_in);
  468. }
  469. if (base == 16 || !((c == '.' || c == 'e' || c == 'E'))) {
  470. ungetc(c, db_in);
  471. tok.ival = val;
  472. return INTEGER;
  473. }
  474. if (c == '.') {
  475. if (p - buf < 512) *p++ = c;
  476. c = getc(db_in);
  477. }
  478. while (is_dig(c)) {
  479. if (p - buf < 512) *p++ = c;
  480. c = getc(db_in);
  481. }
  482. if (c == 'e' || c == 'E') {
  483. if (p - buf < 512) *p++ = c;
  484. c = getc(db_in);
  485. if (c == '+' || c == '-') {
  486. if (p - buf < 512) *p++ = c;
  487. c = getc(db_in);
  488. }
  489. if (! is_dig(c)) {
  490. error("malformed floating constant");
  491. }
  492. while (is_dig(c)) {
  493. if (p - buf < 512) *p++ = c;
  494. c = getc(db_in);
  495. }
  496. }
  497. ungetc(c, db_in);
  498. *p++ = 0;
  499. if (p == &buf[512+1]) {
  500. error("floating point constant too long");
  501. }
  502. return REAL;
  503. }
  504. extern char * symbol2str();
  505. LLmessage(t)
  506. {
  507. if (t > 0) {
  508. if (! errorgiven) {
  509. error("%s missing before %s", symbol2str(t), symbol2str(TOK));
  510. }
  511. aside = tok;
  512. }
  513. else if (t == 0) {
  514. if (! errorgiven) {
  515. error("%s unexpected", symbol2str(TOK));
  516. }
  517. }
  518. else if (! errorgiven) {
  519. error("EOF expected");
  520. }
  521. errorgiven = 1;
  522. }
  523. static int
  524. catch_del()
  525. {
  526. signal(SIGINT, catch_del);
  527. signal_child(SIGEMT);
  528. longjmp(jmpbuf, 1);
  529. }
  530. static int
  531. init_del()
  532. {
  533. signal(SIGINT, catch_del);
  534. }
  535. static int
  536. skip_to_eol()
  537. {
  538. while (TOK != '\n' && TOK > 0) LLlex();
  539. wait_for_child("interrupted");
  540. }
  541. }