exgram.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. /*
  14. * grammar support routines
  15. * stuffed in a header so exparse.y can work
  16. * with both yacc and bison
  17. */
  18. #if !defined(_EXGRAM_H) && ( defined(MINTOKEN) || defined(YYTOKENTYPE) )
  19. #define _EXGRAM_H
  20. #include <cgraph/gv_ctype.h>
  21. #include <expr/exlib.h>
  22. #include <stdbool.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <util/agxbuf.h>
  26. #define ex_lex() extoken_fn(expr.program)
  27. #define ALLOCATE(p,x) exalloc(p,sizeof(x))
  28. static int a2t[] = { 0, FLOATING, INTEGER, STRING };
  29. static Switch_t swstate;
  30. Exstate_t expr;
  31. static int T(long t) {
  32. if (expr.program->disc->types)
  33. return expr.program->disc->types[t & TMASK];
  34. else
  35. return a2t[t & TMASK];
  36. }
  37. /*
  38. * allocate and initialize a new expression node in the current program
  39. */
  40. Exnode_t *exnewnode(Expr_t *p, long op, bool binary, long type, Exnode_t *left,
  41. Exnode_t *right) {
  42. Exnode_t* x;
  43. x = ALLOCATE(p, Exnode_t);
  44. *x = (Exnode_t){0};
  45. x->op = op;
  46. x->type = type;
  47. x->binary = binary;
  48. x->data.operand.left = left;
  49. x->data.operand.right = right;
  50. return x;
  51. }
  52. /*
  53. * free node x and its children
  54. */
  55. void
  56. exfreenode(Expr_t* p, Exnode_t* x)
  57. {
  58. Print_t* pr;
  59. Exref_t* r;
  60. Print_t* pn;
  61. Exref_t* rn;
  62. switch (x->op)
  63. {
  64. case CALL:
  65. if (x->data.call.args)
  66. exfreenode(p, x->data.call.args);
  67. break;
  68. case CONSTANT:
  69. break;
  70. case DEFAULT:
  71. if (x->data.select.next)
  72. exfreenode(p, x->data.select.next);
  73. break;
  74. case DYNAMIC:
  75. if (x->data.variable.index)
  76. exfreenode(p, x->data.variable.index);
  77. if (x->data.variable.symbol->local)
  78. {
  79. dtclose(x->data.variable.symbol->local);
  80. x->data.variable.symbol->local = NULL;
  81. }
  82. break;
  83. case '#':
  84. if (x->data.variable.symbol->local) {
  85. dtclose(x->data.variable.symbol->local);
  86. x->data.variable.symbol->local = NULL;
  87. }
  88. break;
  89. // case IN_OP:
  90. case UNSET:
  91. if (x->data.variable.index)
  92. exfreenode(p, x->data.variable.index);
  93. if (x->data.variable.symbol->local) {
  94. dtclose(x->data.variable.symbol->local);
  95. x->data.variable.symbol->local = NULL;
  96. }
  97. break;
  98. case ITERATE:
  99. case ITERATOR:
  100. if (x->data.generate.statement)
  101. exfreenode(p, x->data.generate.statement);
  102. break;
  103. case ID:
  104. rn = x->data.variable.reference;
  105. while ((r = rn))
  106. {
  107. rn = r->next;
  108. vmfree(p->vm, r);
  109. }
  110. if (x->data.variable.index)
  111. exfreenode(p, x->data.variable.index);
  112. break;
  113. case GSUB:
  114. case SUB:
  115. case SUBSTR:
  116. exfreenode(p, x->data.string.base);
  117. exfreenode(p, x->data.string.pat);
  118. if (x->data.string.repl)
  119. exfreenode(p, x->data.string.repl);
  120. break;
  121. case TOKENS:
  122. case SPLIT:
  123. if (x->data.split.seps)
  124. exfreenode(p, x->data.split.seps);
  125. exfreenode(p, x->data.split.string);
  126. if (x->data.split.array->local) {
  127. dtclose(x->data.split.array->local);
  128. x->data.split.array->local = NULL;
  129. }
  130. break;
  131. case PRINT:
  132. exfreenode(p, x->data.operand.left);
  133. break;
  134. case PRINTF:
  135. case SPRINTF:
  136. if (x->data.print.descriptor)
  137. exfreenode(p, x->data.print.descriptor);
  138. pn = x->data.print.args;
  139. while ((pr = pn))
  140. {
  141. size_t i;
  142. for (i = 0; i < elementsof(pr->param) && pr->param[i]; i++)
  143. exfreenode(p, pr->param[i]);
  144. if (pr->arg)
  145. exfreenode(p, pr->arg);
  146. pn = pr->next;
  147. vmfree(p->vm, pr);
  148. }
  149. break;
  150. default:
  151. if (x->data.operand.left)
  152. exfreenode(p, x->data.operand.left);
  153. if (x->data.operand.right)
  154. exfreenode(p, x->data.operand.right);
  155. break;
  156. }
  157. vmfree(p->vm, x);
  158. }
  159. /* extract:
  160. * Given an argument list, extract first argument,
  161. * check its type, reset argument list, and
  162. * return first argument.
  163. * Return 0 on failure.
  164. */
  165. static Exnode_t *extract(Expr_t * p, Exnode_t ** argp, int type) {
  166. Exnode_t *args = *argp;
  167. Exnode_t *left;
  168. if (!args || (type != args->data.operand.left->type))
  169. return 0;
  170. *argp = args->data.operand.right;
  171. left = args->data.operand.left;
  172. args->data.operand.left = args->data.operand.right = 0;
  173. exfreenode(p, args);
  174. return left;
  175. }
  176. /* exnewsplit:
  177. * Generate split/tokens node.
  178. * Fifth argument is optional.
  179. */
  180. static Exnode_t *exnewsplit(Expr_t *p, long op, Exid_t *dyn, Exnode_t *s,
  181. Exnode_t *seps) {
  182. Exnode_t *ss = 0;
  183. if (dyn->local == NULL)
  184. exerror("cannot use non-array %s in %s", dyn->name, exopname(op));
  185. if ((dyn->index_type > 0) && (dyn->index_type != INTEGER))
  186. exerror("in %s, array %s must have integer index type, not %s",
  187. exopname(op), dyn->name, extypename(p, s->type));
  188. if (dyn->type != STRING)
  189. exerror("in %s, array %s entries must have string type, not %s",
  190. exopname(op), dyn->name, extypename(p, s->type));
  191. if (s->type != STRING)
  192. exerror("first argument to %s must have string type, not %s",
  193. exopname(op), extypename(p, s->type));
  194. if (seps && (seps->type != STRING))
  195. exerror("third argument to %s must have string type, not %s",
  196. exopname(op), extypename(p, seps->type));
  197. ss = exnewnode(p, op, false, INTEGER, NULL, NULL);
  198. ss->data.split.array = dyn;
  199. ss->data.split.string = s;
  200. ss->data.split.seps = seps;
  201. return ss;
  202. }
  203. /* exnewsub:
  204. * Generate sub node.
  205. * Third argument is optional.
  206. */
  207. static Exnode_t *exnewsub(Expr_t * p, Exnode_t * args, int op) {
  208. Exnode_t *base;
  209. Exnode_t *pat;
  210. Exnode_t *repl;
  211. Exnode_t *ss = 0;
  212. base = extract(p, &args, STRING);
  213. if (!base)
  214. exerror("invalid first argument to sub operator");
  215. pat = extract(p, &args, STRING);
  216. if (!pat)
  217. exerror("invalid second argument to sub operator");
  218. if (args) {
  219. repl = extract(p, &args, STRING);
  220. if (!repl)
  221. exerror("invalid third argument to sub operator");
  222. } else
  223. repl = 0;
  224. if (args)
  225. exerror("too many arguments to sub operator");
  226. ss = exnewnode(p, op, false, STRING, NULL, NULL);
  227. ss->data.string.base = base;
  228. ss->data.string.pat = pat;
  229. ss->data.string.repl = repl;
  230. return ss;
  231. }
  232. /* exnewsubstr:
  233. * Generate substr node.
  234. */
  235. static Exnode_t *exnewsubstr(Expr_t * p, Exnode_t * args) {
  236. Exnode_t *base;
  237. Exnode_t *pat;
  238. Exnode_t *repl;
  239. Exnode_t *ss = 0;
  240. base = extract(p, &args, STRING);
  241. if (!base)
  242. exerror("invalid first argument to substr operator");
  243. pat = extract(p, &args, INTEGER);
  244. if (!pat)
  245. exerror("invalid second argument to substr operator");
  246. if (args) {
  247. repl = extract(p, &args, INTEGER);
  248. if (!repl)
  249. exerror("invalid third argument to substr operator");
  250. } else
  251. repl = 0;
  252. if (args)
  253. exerror("too many arguments to substr operator");
  254. ss = exnewnode(p, SUBSTR, false, STRING, NULL, NULL);
  255. ss->data.string.base = base;
  256. ss->data.string.pat = pat;
  257. ss->data.string.repl = repl;
  258. return ss;
  259. }
  260. /* exstringOf:
  261. * Cast x to type STRING
  262. * Assume x->type != STRING
  263. */
  264. static Exnode_t *exstringOf(Expr_t * p, Exnode_t * x) {
  265. const long type = x->type;
  266. int cvt = 0;
  267. if (!type) {
  268. x->type = STRING;
  269. return x;
  270. }
  271. if (!BUILTIN(type) && !p->disc->stringof)
  272. exerror("cannot convert %s to STRING", extypename(p, type));
  273. if (x->op != CONSTANT) {
  274. if (!BUILTIN(type)) {
  275. if (p->disc->stringof(p, x, 1) < 0) {
  276. exerror("cannot convert %s to STRING",
  277. extypename(p, type));
  278. }
  279. cvt = XPRINT;
  280. } else
  281. switch (type) {
  282. case FLOATING:
  283. cvt = F2S;
  284. break;
  285. case INTEGER:
  286. cvt = I2S;
  287. break;
  288. }
  289. x = exnewnode(p, cvt, false, STRING, x, 0);
  290. } else if (!BUILTIN(type)) {
  291. if (p->disc->stringof(p, x, 0) < 0)
  292. exerror("cannot convert constant %s to STRING",
  293. extypename(p, x->type));
  294. } else
  295. switch (type) {
  296. case FLOATING:
  297. x->data.constant.value.string =
  298. exprintf(p->vm, "%g", x->data.constant.value.floating);
  299. break;
  300. case INTEGER:
  301. x->data.constant.value.string =
  302. exprintf(p->vm, "%lld", x->data.constant.value.integer);
  303. break;
  304. default:
  305. exerror("internal error: %ld: unknown type", type);
  306. break;
  307. }
  308. x->type = STRING;
  309. return x;
  310. }
  311. /* exprint:
  312. * Generate argument list of strings.
  313. */
  314. static Exnode_t *exprint(Expr_t * p, Exid_t * ex, Exnode_t * args) {
  315. Exnode_t *arg = args;
  316. Exnode_t *pr;
  317. while (arg) {
  318. if (arg->data.operand.left->type != STRING)
  319. arg->data.operand.left =
  320. exstringOf(p, arg->data.operand.left);
  321. arg = arg->data.operand.right;
  322. }
  323. pr = exnewnode(p, ex->index, true, ex->type, args, NULL);
  324. return pr;
  325. }
  326. /* makeVar:
  327. *
  328. * Create variable from s[idx].refs
  329. * If s is DYNAMIC, refs is non-empty and dyna represents s[idx].
  330. * The rightmost element in s[idx].refs becomes the dominant symbol,
  331. * and the prefix gets stored in refs. (This format is used to simplify
  332. * the yacc parser.)
  333. */
  334. static Exnode_t *makeVar(Expr_t * prog, Exid_t * s, Exnode_t * idx,
  335. Exnode_t * dyna, Exref_t * refs) {
  336. Exnode_t *nn;
  337. Exid_t *sym;
  338. /* parse components */
  339. if (refs) {
  340. if (refs->next) {
  341. sym = refs->next->symbol;
  342. refs->next->symbol = refs->symbol;
  343. } else
  344. sym = refs->symbol;
  345. refs->symbol = s;
  346. refs->index = idx;
  347. } else
  348. sym = s;
  349. const long kind = sym->type ? sym->type : STRING;
  350. nn = exnewnode(prog, ID, false, kind, NULL, NULL);
  351. nn->data.variable.symbol = sym;
  352. nn->data.variable.reference = refs;
  353. nn->data.variable.index = 0;
  354. nn->data.variable.dyna = dyna;
  355. if (!prog->disc->getf)
  356. exerror("%s: identifier references not supported", sym->name);
  357. else if (expr.program->disc->reff)
  358. expr.program->disc->reff(prog, nn, nn->data.variable.symbol, refs);
  359. return nn;
  360. }
  361. /*
  362. * cast x to type
  363. */
  364. static char* typename[] =
  365. {
  366. "external", "integer", "unsigned", "char", "float", "string"
  367. };
  368. static int typecast[6][6] =
  369. {
  370. {X2X, X2I, X2I, X2I, X2F, X2S},
  371. {I2X, 0, 0, 0, I2F, I2S},
  372. {I2X, 0, 0, 0, I2F, I2S},
  373. {I2X, 0, 0, 0, I2F, I2S},
  374. {F2X, F2I, F2I, F2I, 0, F2S},
  375. {S2X, S2I, S2I, S2I, S2F, 0},
  376. };
  377. #define TYPEINDEX(t) (((t)>=INTEGER&&(t)<=STRING)?((t)-INTEGER+1):0)
  378. #define TYPENAME(t) typename[TYPEINDEX(t)]
  379. #define TYPECAST(f,t) typecast[TYPEINDEX(f)][TYPEINDEX(t)]
  380. #define EXTERNAL(t) ((t)>=F2X)
  381. char *extypename(Expr_t *p, long type) {
  382. if (BUILTIN(type))
  383. return TYPENAME(type);
  384. return p->disc->typename(type);
  385. }
  386. /* exnoncast:
  387. * Return first non-cast node.
  388. */
  389. Exnode_t *exnoncast(Exnode_t * x) {
  390. while (x && (x->op >= F2I) && (x->op <= X2X))
  391. x = x->data.operand.left;
  392. return x;
  393. }
  394. Exnode_t *excast(Expr_t *p, Exnode_t *x, long type, Exnode_t *xref, int arg) {
  395. int t2t;
  396. char* s;
  397. char* e;
  398. if (x && x->type != type && type && type != VOIDTYPE)
  399. {
  400. if (!x->type)
  401. {
  402. x->type = type;
  403. return x;
  404. }
  405. if (!(t2t = TYPECAST(x->type, type)))
  406. return x;
  407. if (EXTERNAL(t2t) && !p->disc->convertf)
  408. exerror("cannot convert %s to %s", extypename(p, x->type), extypename(p, type));
  409. if (x->op != CONSTANT) {
  410. Exid_t *sym = (xref ? xref->data.variable.symbol : NULL);
  411. if (EXTERNAL(t2t)) {
  412. if (p->disc->convertf(x, type, 1) < 0) {
  413. if (xref) {
  414. if ((sym->lex == FUNCTION) && arg)
  415. exerror ("%s: cannot use value of type %s as argument %d in function %s",
  416. sym->name, extypename(p, x->type),
  417. arg, sym->name);
  418. else
  419. exerror("%s: cannot convert %s to %s",
  420. xref->data.variable.symbol->name,
  421. extypename(p, x->type),
  422. extypename(p, type));
  423. } else {
  424. exerror("cannot convert %s to %s",
  425. extypename(p, x->type), extypename(p, type));
  426. }
  427. }
  428. }
  429. x = exnewnode(p, t2t, false, type, x, xref);
  430. }
  431. else switch (t2t)
  432. {
  433. case F2X:
  434. case I2X:
  435. case S2X:
  436. case X2F:
  437. case X2I:
  438. case X2S:
  439. case X2X:
  440. if (xref && xref->op == ID)
  441. {
  442. if (p->disc->convertf(x, type, arg) < 0)
  443. exerror("%s: cannot cast constant %s to %s", xref->data.variable.symbol->name, extypename(p, x->type), extypename(p, type));
  444. }
  445. else if (p->disc->convertf(x, type, arg) < 0)
  446. exerror("cannot cast constant %s to %s", extypename(p, x->type), extypename(p, type));
  447. break;
  448. case F2I:
  449. x->data.constant.value.integer = x->data.constant.value.floating;
  450. break;
  451. case F2S:
  452. x->data.constant.value.string =
  453. exprintf(p->vm, "%g", x->data.constant.value.floating);
  454. break;
  455. case I2F:
  456. x->data.constant.value.floating = x->data.constant.value.integer;
  457. break;
  458. case I2S:
  459. x->data.constant.value.string =
  460. exprintf(p->vm, "%lld", x->data.constant.value.integer);
  461. break;
  462. case S2F:
  463. s = x->data.constant.value.string;
  464. x->data.constant.value.floating = strtod(s, &e);
  465. if (*e)
  466. x->data.constant.value.floating = (*s != 0);
  467. break;
  468. case S2I:
  469. s = x->data.constant.value.string;
  470. x->data.constant.value.integer = strtoll(s, &e, 0);
  471. if (*e)
  472. x->data.constant.value.integer = (*s != 0);
  473. break;
  474. default:
  475. exerror("internal error: %d: unknown cast op", t2t);
  476. break;
  477. }
  478. x->type = type;
  479. }
  480. return x;
  481. }
  482. /*
  483. * check function call arg types and count
  484. * return function identifier node
  485. */
  486. static Exnode_t*
  487. call(Exref_t* ref, Exid_t* fun, Exnode_t* args)
  488. {
  489. int type;
  490. Exnode_t* x;
  491. int num;
  492. x = exnewnode(expr.program, ID, false, 0, NULL, NULL);
  493. long t = fun->type;
  494. x->data.variable.symbol = fun;
  495. x->data.variable.reference = ref;
  496. num = 0;
  497. N(t);
  498. while ((type = T(t)))
  499. {
  500. if (!args)
  501. {
  502. exerror("%s: not enough args", fun->name);
  503. return args;
  504. }
  505. num++;
  506. if (type != args->data.operand.left->type)
  507. args->data.operand.left = excast(expr.program, args->data.operand.left, type, NULL, num);
  508. args = args->data.operand.right;
  509. N(t);
  510. }
  511. if (args)
  512. exerror("%s: too many args", fun->name);
  513. return x;
  514. }
  515. /*
  516. * precompile a printf/scanf call
  517. */
  518. static Print_t*
  519. preprint(Exnode_t* args)
  520. {
  521. Print_t* x;
  522. char* s;
  523. char c;
  524. int t;
  525. int i;
  526. int n;
  527. char* e;
  528. char* f;
  529. Print_t* p = 0;
  530. Print_t* q;
  531. if (!args || args->data.operand.left->type != STRING)
  532. exerror("format string argument expected");
  533. if (args->data.operand.left->op != CONSTANT)
  534. {
  535. x = ALLOCATE(expr.program, Print_t);
  536. *x = (Print_t){0};
  537. x->arg = args;
  538. return x;
  539. }
  540. f = args->data.operand.left->data.constant.value.string;
  541. args = args->data.operand.right;
  542. for (s = f; *s; s++)
  543. {
  544. agxbputc(&expr.program->tmp, *s);
  545. if (*s == '%')
  546. {
  547. if (!*++s)
  548. exerror("%s: trailing %% in format", f);
  549. if (*s != '%')
  550. break;
  551. if (args)
  552. agxbputc(&expr.program->tmp, '%');
  553. }
  554. }
  555. x = 0;
  556. for (;;)
  557. {
  558. q = ALLOCATE(expr.program, Print_t);
  559. if (x)
  560. x->next = q;
  561. else
  562. p = q;
  563. x = q;
  564. *x = (Print_t){0};
  565. if (*s)
  566. {
  567. i = 0;
  568. t = INTEGER;
  569. for (;;)
  570. {
  571. switch (c = *s++)
  572. {
  573. case 0:
  574. exerror("unterminated %%... in format");
  575. goto done;
  576. case '*':
  577. if (i >= (int)elementsof(x->param))
  578. {
  579. *s = 0;
  580. exerror("format %s has too many * arguments", f);
  581. goto done;
  582. }
  583. if (!args)
  584. {
  585. *s = 0;
  586. exerror("format %s * argument expected", f);
  587. goto done;
  588. }
  589. x->param[i++] = args->data.operand.left;
  590. args = args->data.operand.right;
  591. break;
  592. case '(':
  593. n = 1;
  594. for (;;)
  595. {
  596. agxbputc(&expr.program->tmp, c);
  597. switch (c = *s++)
  598. {
  599. case 0:
  600. s--;
  601. break;
  602. case '(':
  603. n++;
  604. continue;
  605. case ')':
  606. if (--n <= 0)
  607. break;
  608. continue;
  609. default:
  610. continue;
  611. }
  612. break;
  613. }
  614. break;
  615. case 'c':
  616. case 'd':
  617. goto specified;
  618. case 'e':
  619. case 'f':
  620. case 'g':
  621. t = FLOATING;
  622. goto specified;
  623. case 'h':
  624. exerror("short formats not supported");
  625. goto done;
  626. case 'l':
  627. t = INTEGER;
  628. break;
  629. case 'o':
  630. case 'u':
  631. case 'x':
  632. case 'T':
  633. t = UNSIGNED;
  634. goto specified;
  635. case 's':
  636. case 'S':
  637. t = STRING;
  638. goto specified;
  639. default:
  640. if (gv_isalpha(c))
  641. goto specified;
  642. break;
  643. }
  644. agxbputc(&expr.program->tmp, c);
  645. }
  646. specified:
  647. agxbputc(&expr.program->tmp, c);
  648. for (e = s; *s; s++)
  649. {
  650. if (*s == '%')
  651. {
  652. if (!*++s)
  653. {
  654. *e = 0;
  655. exerror("%s: trailing %% in format", f);
  656. goto done;
  657. }
  658. if (*s != '%')
  659. {
  660. s--;
  661. break;
  662. }
  663. }
  664. agxbputc(&expr.program->tmp, *s);
  665. }
  666. if (!args)
  667. {
  668. *e = 0;
  669. exerror("%s format argument expected", f);
  670. goto done;
  671. }
  672. x->arg = args->data.operand.left;
  673. switch (t)
  674. {
  675. case FLOATING:
  676. if (x->arg->type != FLOATING)
  677. x->arg = exnewnode(expr.program,
  678. x->arg->type == STRING ? S2F : INTEGRAL(x->arg->type) ? I2F : X2F,
  679. false, FLOATING, x->arg,
  680. x->arg->op == ID ? x->arg : NULL);
  681. break;
  682. case INTEGER:
  683. case UNSIGNED:
  684. if (!INTEGRAL(x->arg->type))
  685. x->arg = exnewnode(expr.program,
  686. x->arg->type == STRING ? S2I : x->arg->type == FLOATING ? F2I : X2I,
  687. false, INTEGER, x->arg,
  688. x->arg->op == ID ? x->arg : NULL);
  689. x->arg->type = t;
  690. break;
  691. case STRING:
  692. if (x->arg->type != STRING)
  693. {
  694. if (x->arg->op == CONSTANT && x->arg->data.constant.reference && expr.program->disc->convertf)
  695. {
  696. if (expr.program->disc->convertf(x->arg, STRING, 0) < 0)
  697. exerror("cannot convert string format argument");
  698. else x->arg->data.constant.value.string = vmstrdup(expr.program->vm, x->arg->data.constant.value.string);
  699. }
  700. else if (!expr.program->disc->convertf || (x->arg->op != ID && x->arg->op != DYNAMIC && x->arg->op != F2X && x->arg->op != I2X && x->arg->op != S2X))
  701. exerror("string format argument expected");
  702. else
  703. x->arg = exnewnode(expr.program,
  704. x->arg->type == FLOATING ? F2S : INTEGRAL(x->arg->type) ? I2S : X2S,
  705. false, STRING, x->arg,
  706. x->arg->op == ID ? x->arg : NULL);
  707. }
  708. break;
  709. }
  710. args = args->data.operand.right;
  711. }
  712. x->format = vmstrdup(expr.program->vm, agxbuse(&expr.program->tmp));
  713. if (x->format == NULL) {
  714. x->format = exnospace();
  715. }
  716. if (!*s)
  717. break;
  718. f = s;
  719. }
  720. if (args)
  721. exerror("too many format arguments");
  722. done:
  723. agxbclear(&expr.program->tmp);
  724. return p;
  725. }
  726. /*
  727. * push a new input stream and program
  728. */
  729. int expush(Expr_t *p, const char *name, int line, FILE *fp) {
  730. Exinput_t* in;
  731. if (!(in = calloc(1, sizeof(Exinput_t))))
  732. {
  733. exnospace();
  734. return -1;
  735. }
  736. if (!p->input)
  737. p->input = &expr.null;
  738. if ((in->fp = fp))
  739. in->close = 0;
  740. else if (name)
  741. {
  742. if (!(in->fp = fopen(name, "r")))
  743. {
  744. exerror("%s: file not found", name);
  745. }
  746. else
  747. {
  748. name = vmstrdup(p->vm, name);
  749. in->close = 1;
  750. }
  751. }
  752. if (!(in->next = p->input)->next)
  753. {
  754. p->errors = 0;
  755. if (line >= 0)
  756. error_info.line = line;
  757. }
  758. else if (line >= 0)
  759. error_info.line = line;
  760. setcontext(p);
  761. p->eof = 0;
  762. p->input = in;
  763. in->file = error_info.file;
  764. if (line >= 0)
  765. error_info.file = (char*)name;
  766. in->line = error_info.line;
  767. in->nesting = 0;
  768. in->unit = !name && !line;
  769. p->program = expr.program;
  770. expr.program = p;
  771. return 0;
  772. }
  773. /*
  774. * pop the current input stream
  775. */
  776. int
  777. expop(Expr_t* p)
  778. {
  779. int c;
  780. Exinput_t* in;
  781. if (!(in = p->input) || !in->next || in->unit)
  782. return -1;
  783. if (in->nesting)
  784. exerror("unbalanced quote or nesting construct");
  785. error_info.file = in->file;
  786. if (in->next->next)
  787. error_info.line = in->line;
  788. else
  789. {
  790. if (p->errors && in->fp && p->linep != p->line)
  791. while ((c = getc(in->fp)) != EOF)
  792. if (c == '\n')
  793. {
  794. error_info.line++;
  795. break;
  796. }
  797. error_info.line = in->line;
  798. }
  799. if (in->fp && in->close)
  800. fclose(in->fp);
  801. free(in->pushback);
  802. p->input = in->next;
  803. free(in);
  804. setcontext(p);
  805. if (p->program)
  806. expr.program = p->program;
  807. return 0;
  808. }
  809. /*
  810. * clear global state of stale pointers
  811. */
  812. void exinit(void) { expr = (Exstate_t){0}; }
  813. int excomp(Expr_t *p, const char *name, int line, FILE *fp, char *prefix) {
  814. int eof;
  815. eof = p->eof;
  816. if (expush(p, name, line, fp))
  817. return -1;
  818. p->input->unit = line >= 0;
  819. // insert prefix as pre-loaded pushback
  820. p->input->pushback = p->input->pp = prefix;
  821. ex_parse();
  822. p->input->unit = 0;
  823. expop(p);
  824. p->eof = eof;
  825. return 0;
  826. }
  827. /*
  828. * free the program p
  829. */
  830. void
  831. exclose(Expr_t* p, int all)
  832. {
  833. Exinput_t* in;
  834. if (p)
  835. {
  836. if (all)
  837. {
  838. size_t i;
  839. for (i = 3; i < elementsof(p->file); i++)
  840. if (p->file[i])
  841. fclose(p->file[i]);
  842. if (p->vm)
  843. vmclose(p->vm);
  844. if (p->ve)
  845. vmclose(p->ve);
  846. if (p->symbols)
  847. dtclose(p->symbols);
  848. agxbfree(&p->tmp);
  849. while ((in = p->input))
  850. {
  851. free(in->pushback);
  852. if (in->fp && in->close)
  853. fclose(in->fp);
  854. if ((p->input = in->next))
  855. free(in);
  856. }
  857. free(p);
  858. }
  859. else
  860. {
  861. vmclear(p->ve);
  862. p->main.value = 0;
  863. }
  864. }
  865. }
  866. /* checkBinary:
  867. * See if application wants to allow the given expression
  868. * combination. l and r give the operands; the operator
  869. * is given by ex. r may be NULL.
  870. */
  871. static void
  872. checkBinary(Expr_t * p, Exnode_t * l, Exnode_t * ex, Exnode_t * r)
  873. {
  874. if (p->disc->binaryf(l, ex, r, 1) < 0) {
  875. if (r)
  876. exerror
  877. ("cannot apply operator %s to expressions of types %s and %s",
  878. exopname(ex->op), extypename(p, l->type),
  879. extypename(p, r->type));
  880. else
  881. exerror
  882. ("cannot apply operator %s to expression of type %s",
  883. exopname(ex->op), extypename(p, l->type));
  884. }
  885. }
  886. /* checkName:
  887. * We allow parser to accept any name in a declaration, in
  888. * order to check that the name is undeclared and give a better
  889. * error message if it isn't.
  890. */
  891. static void checkName(Exid_t * id)
  892. {
  893. switch (id->lex) {
  894. case DYNAMIC:
  895. exerror("Variable \"%s\" already declared", id->name);
  896. break;
  897. case FUNCTION:
  898. exerror("Name \"%s\" already used as a function", id->name);
  899. break;
  900. case ID:
  901. exerror("Name \"%s\" already used as a keyword", id->name);
  902. break;
  903. case NAME:
  904. break;
  905. default:
  906. error(ERROR_PANIC,
  907. "Unexpected token \"%s\" as name in dcl_item", id->name);
  908. break;
  909. }
  910. }
  911. static int cmpKey(void *k1, void *k2) {
  912. const Extype_t *key1 = k1;
  913. const Extype_t *key2 = k2;
  914. if (key1->integer < key2->integer)
  915. return -1;
  916. else if (key1->integer > key2->integer)
  917. return 1;
  918. else
  919. return 0;
  920. }
  921. int
  922. exisAssign(Exnode_t * n)
  923. {
  924. return n->op == '=' && n->subop == '=';
  925. }
  926. #endif
  927. #ifdef __cplusplus
  928. }
  929. #endif