PageRenderTime 52ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/expr/extoken.c

https://github.com/ekoontz/graphviz
C | 828 lines | 741 code | 35 blank | 52 comment | 167 complexity | 0d3f96415db0ac56317610b24c5313d8 MD5 | raw file
Possible License(s): CPL-1.0
  1. /* $Id: extoken.c,v 1.1.1.1 2004/12/23 04:05:07 ellson Exp $ $Revision: 1.1.1.1 $ */
  2. /* vim:set shiftwidth=4 ts=8: */
  3. /**********************************************************
  4. * This software is part of the graphviz package *
  5. * http://www.graphviz.org/ *
  6. * *
  7. * Copyright (c) 1994-2004 AT&T Corp. *
  8. * and is licensed under the *
  9. * Common Public License, Version 1.0 *
  10. * by AT&T Corp. *
  11. * *
  12. * Information and Software Systems Research *
  13. * AT&T Research, Florham Park NJ *
  14. **********************************************************/
  15. /*
  16. * Glenn Fowler
  17. * AT&T Research
  18. *
  19. * expression library default lexical analyzer
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include "exlib.h"
  25. #include <string.h>
  26. #if !defined(TRACE_lex) && _BLD_DEBUG
  27. #define TRACE_lex -10
  28. #endif
  29. #define TRACE_lex -10
  30. #if TRACE_lex
  31. int traceLex;
  32. /*
  33. * trace c for op
  34. */
  35. static void trace(Expr_t * ex, int lev, char *op, int c)
  36. {
  37. char *s = 0;
  38. char *t;
  39. char buf[16];
  40. void *x = 0;
  41. if (!traceLex)
  42. return;
  43. t = "";
  44. switch (c) {
  45. case 0:
  46. s = " EOF";
  47. break;
  48. case '=':
  49. s = t = buf;
  50. *t++ = ' ';
  51. if (!lev && exlval.op != c)
  52. *t++ = exlval.op;
  53. *t++ = c;
  54. *t = 0;
  55. break;
  56. case AND:
  57. s = " AND ";
  58. t = "&&";
  59. break;
  60. case DEC:
  61. s = " DEC ";
  62. t = "--";
  63. break;
  64. case DECLARE:
  65. s = " DECLARE ";
  66. t = exlval.id->name;
  67. break;
  68. case PROCEDURE:
  69. s = " PROCEDURE ";
  70. t = exlval.id->name;
  71. break;
  72. case DYNAMIC:
  73. s = " DYNAMIC ";
  74. t = exlval.id->name;
  75. x = (void *) (exlval.id);
  76. break;
  77. case EQ:
  78. s = " EQ ";
  79. t = "==";
  80. break;
  81. case FLOATING:
  82. s = " FLOATING ";
  83. sfsprintf(t = buf, sizeof(buf), "%f", exlval.floating);
  84. break;
  85. case GE:
  86. s = " GE ";
  87. t = ">=";
  88. break;
  89. case ID:
  90. s = " ID ";
  91. t = exlval.id->name;
  92. break;
  93. case INC:
  94. s = "INC ";
  95. t = "++";
  96. break;
  97. case INTEGER:
  98. s = " INTEGER ";
  99. sfsprintf(t =
  100. buf, sizeof(buf), "%I*d", sizeof(exlval.integer),
  101. exlval.integer);
  102. break;
  103. case LABEL:
  104. s = " LABEL ";
  105. t = exlval.id->name;
  106. break;
  107. case LE:
  108. s = " LE ";
  109. t = "<=";
  110. break;
  111. case LS:
  112. s = " LS ";
  113. t = "<<";
  114. break;
  115. case NAME:
  116. s = " NAME ";
  117. t = exlval.id->name;
  118. x = (void *) (exlval.id);
  119. break;
  120. case NE:
  121. s = " NE ";
  122. t = "!=";
  123. break;
  124. case OR:
  125. s = " OR ";
  126. t = "||";
  127. break;
  128. case RS:
  129. s = " RS ";
  130. t = ">>";
  131. break;
  132. case STRING:
  133. s = " STRING ";
  134. t = fmtesc(exlval.string);
  135. break;
  136. case UNSIGNED:
  137. s = " UNSIGNED ";
  138. sfsprintf(t =
  139. buf, sizeof(buf), "%I*u", sizeof(exlval.integer),
  140. exlval.integer);
  141. break;
  142. case BREAK:
  143. s = " break";
  144. break;
  145. case CASE:
  146. s = " case";
  147. break;
  148. case CONTINUE:
  149. s = " continue";
  150. break;
  151. case DEFAULT:
  152. s = " default";
  153. break;
  154. case ELSE:
  155. s = " else";
  156. break;
  157. case EXIT:
  158. s = " exit";
  159. break;
  160. case FOR:
  161. s = " for";
  162. break;
  163. case GSUB:
  164. s = " gsub";
  165. break;
  166. case IF:
  167. s = " if";
  168. break;
  169. case PRAGMA:
  170. s = " pragma";
  171. break;
  172. case PRINT:
  173. s = " print";
  174. break;
  175. case PRINTF:
  176. s = " printf";
  177. break;
  178. case QUERY:
  179. s = " query";
  180. break;
  181. case RAND:
  182. s = " rand";
  183. break;
  184. case RETURN:
  185. s = " return";
  186. break;
  187. case SPRINTF:
  188. s = " sprintf";
  189. break;
  190. case SRAND:
  191. s = " srand";
  192. break;
  193. case SUB:
  194. s = " sub";
  195. break;
  196. case SUBSTR:
  197. s = " substr";
  198. break;
  199. case SWITCH:
  200. s = " switch";
  201. break;
  202. case WHILE:
  203. s = " while";
  204. break;
  205. default:
  206. if (c < 0177) {
  207. s = buf;
  208. *s++ = c;
  209. *s = 0;
  210. t = fmtesc(buf);
  211. s = " ";
  212. }
  213. break;
  214. }
  215. if (x)
  216. error(TRACE_lex + lev, "%s: [%d] %04d%s%s (%x)",
  217. op, ex->input->nesting, c, s, t, x);
  218. else
  219. error(TRACE_lex + lev, "%s: [%d] %04d%s%s",
  220. op, ex->input->nesting, c, s, t);
  221. }
  222. /*
  223. * trace wrapper for extoken_fn()
  224. */
  225. int _extoken_fn_(register Expr_t * ex);
  226. int extoken_fn(Expr_t * ex)
  227. {
  228. int c;
  229. #define extoken_fn _extoken_fn_
  230. c = extoken_fn(ex);
  231. trace(ex, 0, "exlex", c);
  232. return c;
  233. }
  234. #else
  235. #define trace(p,a,b,c)
  236. #endif
  237. #ifdef OLD
  238. #define BUMP(l) if (l) l++; else l = 2
  239. #else
  240. #define BUMP(l) l++
  241. #endif
  242. /*
  243. * get the next expression char
  244. */
  245. static int lex(register Expr_t * ex)
  246. {
  247. register int c;
  248. for (;;) {
  249. if ((c = ex->input->peek))
  250. ex->input->peek = 0;
  251. else if (ex->input->pp) {
  252. if (!(c = *ex->input->pp++)) {
  253. ex->input->pp = 0;
  254. continue;
  255. }
  256. } else if (ex->input->sp) {
  257. if (!(c = *ex->input->sp++)) {
  258. if (!expop(ex))
  259. continue;
  260. else
  261. trace(ex, -1, "expop sp FAIL", 0);
  262. ex->input->sp--;
  263. }
  264. } else if (ex->input->fp) {
  265. if ((c = sfgetc(ex->input->fp)) == EOF) {
  266. if (!expop(ex))
  267. continue;
  268. else
  269. trace(ex, -1, "expop fp FAIL", 0);
  270. c = 0;
  271. } else if ((ex->disc->flags & EX_INTERACTIVE) && c == '\n'
  272. && ex->input->next && !ex->input->next->next
  273. && ex->input->nesting <= 0) {
  274. error_info.line++;
  275. expop(ex);
  276. trace(ex, -1, "expop sp FORCE", 0);
  277. c = 0;
  278. }
  279. } else
  280. c = 0;
  281. if (c == '\n')
  282. setcontext(ex);
  283. else if (c)
  284. putcontext(ex, c);
  285. /* trace(ex, -3, "ex--lex", c); */
  286. return c;
  287. }
  288. }
  289. /*
  290. * get the next expression token
  291. */
  292. int extoken_fn(register Expr_t * ex)
  293. {
  294. register int c;
  295. register char *s;
  296. register int q;
  297. char *e;
  298. if (ex->eof || ex->errors)
  299. return 0;
  300. again:
  301. for (;;)
  302. switch (c = lex(ex)) {
  303. case 0:
  304. goto eof;
  305. case '/':
  306. switch (q = lex(ex)) {
  307. case '*':
  308. for (;;)
  309. switch (lex(ex)) {
  310. case '\n':
  311. BUMP(error_info.line);
  312. continue;
  313. case '*':
  314. switch (lex(ex)) {
  315. case 0:
  316. goto eof;
  317. case '\n':
  318. BUMP(error_info.line);
  319. break;
  320. case '*':
  321. exunlex(ex, '*');
  322. break;
  323. case '/':
  324. goto again;
  325. }
  326. break;
  327. }
  328. break;
  329. case '/':
  330. while ((c = lex(ex)) != '\n')
  331. if (!c)
  332. goto eof;
  333. break;
  334. default:
  335. goto opeq;
  336. }
  337. /*FALLTHROUGH*/ case '\n':
  338. BUMP(error_info.line);
  339. /*FALLTHROUGH*/ case ' ':
  340. case '\t':
  341. break;
  342. case '(':
  343. case '{':
  344. case '[':
  345. ex->input->nesting++;
  346. return exlval.op = c;
  347. case ')':
  348. case '}':
  349. case ']':
  350. ex->input->nesting--;
  351. return exlval.op = c;
  352. case '+':
  353. case '-':
  354. if ((q = lex(ex)) == c)
  355. return exlval.op = c == '+' ? INC : DEC;
  356. goto opeq;
  357. case '*':
  358. case '%':
  359. case '^':
  360. q = lex(ex);
  361. opeq:
  362. exlval.op = c;
  363. if (q == '=')
  364. c = '=';
  365. else if (q == '%' && c == '%') {
  366. if (ex->input->fp)
  367. ex->more = (const char *) ex->input->fp;
  368. else
  369. ex->more = ex->input->sp;
  370. goto eof;
  371. } else
  372. exunlex(ex, q);
  373. return c;
  374. case '&':
  375. case '|':
  376. if ((q = lex(ex)) == '=') {
  377. exlval.op = c;
  378. return '=';
  379. }
  380. if (q == c)
  381. c = c == '&' ? AND : OR;
  382. else
  383. exunlex(ex, q);
  384. return exlval.op = c;
  385. case '<':
  386. case '>':
  387. if ((q = lex(ex)) == c) {
  388. exlval.op = c = c == '<' ? LS : RS;
  389. if ((q = lex(ex)) == '=')
  390. c = '=';
  391. else
  392. exunlex(ex, q);
  393. return c;
  394. }
  395. goto relational;
  396. case '=':
  397. case '!':
  398. q = lex(ex);
  399. relational:
  400. if (q == '=')
  401. switch (c) {
  402. case '<':
  403. c = LE;
  404. break;
  405. case '>':
  406. c = GE;
  407. break;
  408. case '=':
  409. c = EQ;
  410. break;
  411. case '!':
  412. c = NE;
  413. break;
  414. } else
  415. exunlex(ex, q);
  416. return exlval.op = c;
  417. case '#':
  418. if (!ex->linewrap && !(ex->disc->flags & EX_PURE)) {
  419. s = ex->linep - 1;
  420. while (s > ex->line && isspace(*(s - 1)))
  421. s--;
  422. if (s == ex->line) {
  423. switch (extoken_fn(ex)) {
  424. case DYNAMIC:
  425. case ID:
  426. case NAME:
  427. s = exlval.id->name;
  428. break;
  429. default:
  430. s = "";
  431. break;
  432. }
  433. if (streq(s, "include")) {
  434. if (extoken_fn(ex) != STRING)
  435. exerror("#%s: string argument expected", s);
  436. else if (!expush(ex, exlval.string, 1, NiL, NiL)) {
  437. setcontext(ex);
  438. goto again;
  439. }
  440. } else
  441. exerror("unknown directive");
  442. }
  443. }
  444. return exlval.op = c;
  445. case '\'':
  446. case '"':
  447. q = c;
  448. sfstrset(ex->tmp, 0);
  449. ex->input->nesting++;
  450. while ((c = lex(ex)) != q) {
  451. if (c == '\\') {
  452. sfputc(ex->tmp, c);
  453. c = lex(ex);
  454. }
  455. if (!c) {
  456. exerror("unterminated %c string", q);
  457. goto eof;
  458. }
  459. if (c == '\n') {
  460. BUMP(error_info.line);
  461. }
  462. sfputc(ex->tmp, c);
  463. }
  464. ex->input->nesting--;
  465. s = sfstruse(ex->tmp);
  466. if (q == '"' || (ex->disc->flags & EX_CHARSTRING)) {
  467. if (!(exlval.string = vmstrdup(ex->vm, s)))
  468. goto eof;
  469. stresc(exlval.string);
  470. return STRING;
  471. }
  472. exlval.integer = chrtoi(s);
  473. return INTEGER;
  474. case '.':
  475. if (isdigit(c = lex(ex))) {
  476. sfstrset(ex->tmp, 0);
  477. sfputc(ex->tmp, '0');
  478. sfputc(ex->tmp, '.');
  479. goto floating;
  480. }
  481. exunlex(ex, c);
  482. return exlval.op = '.';
  483. case '0':
  484. case '1':
  485. case '2':
  486. case '3':
  487. case '4':
  488. case '5':
  489. case '6':
  490. case '7':
  491. case '8':
  492. case '9':
  493. sfstrset(ex->tmp, 0);
  494. sfputc(ex->tmp, c);
  495. q = INTEGER;
  496. if ((c = lex(ex)) == 'x' || c == 'X') {
  497. sfputc(ex->tmp, c);
  498. for (;;) {
  499. switch (c = lex(ex)) {
  500. case '0':
  501. case '1':
  502. case '2':
  503. case '3':
  504. case '4':
  505. case '5':
  506. case '6':
  507. case '7':
  508. case '8':
  509. case '9':
  510. case 'a':
  511. case 'b':
  512. case 'c':
  513. case 'd':
  514. case 'e':
  515. case 'f':
  516. case 'A':
  517. case 'B':
  518. case 'C':
  519. case 'D':
  520. case 'E':
  521. case 'F':
  522. sfputc(ex->tmp, c);
  523. continue;
  524. }
  525. break;
  526. }
  527. } else {
  528. while (isdigit(c)) {
  529. sfputc(ex->tmp, c);
  530. c = lex(ex);
  531. }
  532. if (c == '#') {
  533. sfputc(ex->tmp, c);
  534. /* s = sfstruse(ex->tmp); */
  535. /* b = strtol(s, NiL, 10); */
  536. do {
  537. sfputc(ex->tmp, c);
  538. } while (isalnum(c = lex(ex)));
  539. } else {
  540. if (c == '.') {
  541. floating:
  542. q = FLOATING;
  543. sfputc(ex->tmp, c);
  544. while (isdigit(c = lex(ex)))
  545. sfputc(ex->tmp, c);
  546. }
  547. if (c == 'e' || c == 'E') {
  548. q = FLOATING;
  549. sfputc(ex->tmp, c);
  550. if ((c = lex(ex)) == '-' || c == '+') {
  551. sfputc(ex->tmp, c);
  552. c = lex(ex);
  553. }
  554. while (isdigit(c)) {
  555. sfputc(ex->tmp, c);
  556. c = lex(ex);
  557. }
  558. }
  559. }
  560. }
  561. s = sfstruse(ex->tmp);
  562. if (q == FLOATING)
  563. exlval.floating = strtod(s, &e);
  564. else {
  565. if (c == 'u' || c == 'U') {
  566. q = UNSIGNED;
  567. c = lex(ex);
  568. exlval.integer = strToL(s, &e);
  569. } else
  570. exlval.integer = strToL(s, &e);
  571. if (*e) {
  572. *--e = 1;
  573. exlval.integer *= strton(e, &e, NiL, 0);
  574. }
  575. }
  576. exunlex(ex, c);
  577. if (*e || isalpha(c) || c == '_' || c == '$') {
  578. exerror("%s: invalid numeric constant", s);
  579. goto eof;
  580. }
  581. return q;
  582. default:
  583. if (isalpha(c) || c == '_' || c == '$') {
  584. sfstrset(ex->tmp, 0);
  585. sfputc(ex->tmp, c);
  586. while (isalnum(c = lex(ex)) || c == '_' || c == '$')
  587. sfputc(ex->tmp, c);
  588. exunlex(ex, c);
  589. s = sfstruse(ex->tmp);
  590. if (!(exlval.id = (Exid_t *) dtmatch(ex->symbols, s))) {
  591. if (!
  592. (exlval.id =
  593. newof(0, Exid_t, 1,
  594. strlen(s) - EX_NAMELEN + 1))) {
  595. exerror("out of space");
  596. goto eof;
  597. }
  598. strcpy(exlval.id->name, s);
  599. exlval.id->lex = NAME;
  600. dtinsert((ex->formals
  601. || !ex->symbols->view) ? ex->symbols : ex->
  602. symbols->view, exlval.id);
  603. }
  604. /*
  605. * lexical analyzer state controlled by the grammar
  606. */
  607. switch (exlval.id->lex) {
  608. case DECLARE:
  609. if (exlval.id->index == CHAR) {
  610. /*
  611. * `char*' === `string'
  612. * the * must immediately follow char
  613. */
  614. if (c == '*') {
  615. lex(ex);
  616. exlval.id = id_string;
  617. }
  618. }
  619. break;
  620. case NAME:
  621. /*
  622. * action labels are disambiguated from ?:
  623. * through the expr.nolabel grammar hook
  624. * the : must immediately follow labels
  625. */
  626. if (c == ':' && !expr.nolabel)
  627. return LABEL;
  628. break;
  629. case PRAGMA:
  630. /*
  631. * user specific statement stripped and
  632. * passed as string
  633. */
  634. {
  635. int b;
  636. int n;
  637. int pc = 0;
  638. int po;
  639. int t;
  640. /*UNDENT... */
  641. sfstrset(ex->tmp, 0);
  642. b = 1;
  643. n = 0;
  644. po = 0;
  645. t = 0;
  646. for (c = t = lex(ex);; c = lex(ex)) {
  647. switch (c) {
  648. case 0:
  649. goto eof;
  650. case '/':
  651. switch (q = lex(ex)) {
  652. case '*':
  653. for (;;) {
  654. switch (lex(ex)) {
  655. case '\n':
  656. BUMP(error_info.line);
  657. continue;
  658. case '*':
  659. switch (lex(ex)) {
  660. case 0:
  661. goto eof;
  662. case '\n':
  663. BUMP(error_info.line);
  664. continue;
  665. case '*':
  666. exunlex(ex, '*');
  667. continue;
  668. case '/':
  669. break;
  670. default:
  671. continue;
  672. }
  673. break;
  674. }
  675. if (!b++)
  676. goto eof;
  677. sfputc(ex->tmp, ' ');
  678. break;
  679. }
  680. break;
  681. case '/':
  682. while ((c = lex(ex)) != '\n')
  683. if (!c)
  684. goto eof;
  685. BUMP(error_info.line);
  686. b = 1;
  687. sfputc(ex->tmp, '\n');
  688. break;
  689. default:
  690. b = 0;
  691. sfputc(ex->tmp, c);
  692. sfputc(ex->tmp, q);
  693. break;
  694. }
  695. continue;
  696. case '\n':
  697. BUMP(error_info.line);
  698. b = 1;
  699. sfputc(ex->tmp, '\n');
  700. continue;
  701. case ' ':
  702. case '\t':
  703. if (!b++)
  704. goto eof;
  705. sfputc(ex->tmp, ' ');
  706. continue;
  707. case '(':
  708. case '{':
  709. case '[':
  710. b = 0;
  711. if (!po) {
  712. switch (po = c) {
  713. case '(':
  714. pc = ')';
  715. break;
  716. case '{':
  717. pc = '}';
  718. break;
  719. case '[':
  720. pc = ']';
  721. break;
  722. }
  723. n++;
  724. } else if (c == po)
  725. n++;
  726. sfputc(ex->tmp, c);
  727. continue;
  728. case ')':
  729. case '}':
  730. case ']':
  731. b = 0;
  732. if (!po) {
  733. exunlex(ex, c);
  734. break;
  735. }
  736. sfputc(ex->tmp, c);
  737. if (c == pc && --n <= 0) {
  738. if (t == po)
  739. break;
  740. po = 0;
  741. }
  742. continue;
  743. case ';':
  744. b = 0;
  745. if (!n)
  746. break;
  747. sfputc(ex->tmp, c);
  748. continue;
  749. case '\'':
  750. case '"':
  751. b = 0;
  752. sfputc(ex->tmp, c);
  753. ex->input->nesting++;
  754. q = c;
  755. while ((c = lex(ex)) != q) {
  756. if (c == '\\') {
  757. sfputc(ex->tmp, c);
  758. c = lex(ex);
  759. }
  760. if (!c) {
  761. exerror("unterminated %c string",
  762. q);
  763. goto eof;
  764. }
  765. if (c == '\n') {
  766. BUMP(error_info.line);
  767. }
  768. sfputc(ex->tmp, c);
  769. }
  770. ex->input->nesting--;
  771. continue;
  772. default:
  773. b = 0;
  774. sfputc(ex->tmp, c);
  775. continue;
  776. }
  777. break;
  778. }
  779. (*ex->disc->reff) (ex, NiL, exlval.id, NiL,
  780. sfstruse(ex->tmp), 0, ex->disc);
  781. /*..INDENT */
  782. }
  783. goto again;
  784. }
  785. return exlval.id->lex;
  786. }
  787. return exlval.op = c;
  788. }
  789. eof:
  790. ex->eof = 1;
  791. return exlval.op = ';';
  792. }