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

/ifm-5.1/vars/src/vars-parser.y

#
Happy | 1434 lines | 1211 code | 223 blank | 0 comment | 0 complexity | be88564b6232d5130a2ed5004eee9b5a MD5 | raw file
Possible License(s): GPL-2.0, 0BSD, LGPL-2.1
  1. /*
  2. * This file is part of the Vars library, copyright (C) Glenn
  3. * Hutchings 1996-2003.
  4. *
  5. * The Vars library comes with ABSOLUTELY NO WARRANTY. This is free
  6. * software, and you are welcome to redistribute it under certain
  7. * conditions; see the file COPYING for details.
  8. */
  9. /*!
  10. @defgroup parser Parsers
  11. @ingroup types
  12. A parser is an object which is used to evaluate mathematical expressions.
  13. It stores variables, constants and functions which are used to perform
  14. the evaluations. Parsers get created with a set of builtin functions and
  15. constants, and you can define your own or override the builtin ones.
  16. */
  17. /*!
  18. @defgroup parser_create Creating and destroying parsers
  19. @ingroup parser
  20. */
  21. /*!
  22. @defgroup parser_exp Parsing expressions
  23. @ingroup parser
  24. */
  25. /*!
  26. @defgroup parser_custom Customizing parsers
  27. @ingroup parser
  28. */
  29. /*!
  30. @defgroup parser_access Accessing parser internals
  31. @ingroup parser
  32. */
  33. /*!
  34. @defgroup parser_syntax Parser input syntax
  35. @ingroup parser
  36. Input to a parser consists of a number of expressions. Each expression is
  37. terminated by a newline. Whitespace is ignored. Comments may also be
  38. included, starting with \c # and continuing to the end of the line.
  39. The following types of expression are allowed (where \c exp represents
  40. another expression):
  41. - <tt>number</tt> -- A number, with optional decimal part and exponent.
  42. - <tt>exp + exp, exp - exp, exp * exp, exp / exp</tt> -- The four
  43. standard arithmetic operations.
  44. - <tt>exp ^ exp</tt> -- Exponentiation. This function uses the \c pow(3)
  45. function internally, but cannot be overridden, as can the parser
  46. builtin "pow" function.
  47. - <tt>exp % exp</tt> -- The modulo function.
  48. - <tt>exp == exp, exp != exp, exp < exp, exp > exp, exp <= exp, exp >=
  49. exp</tt> -- Various tests. The return value is 1 if the expression is
  50. true, 0 if it is false.
  51. - <tt>exp && exp, exp || exp</tt> -- Boolean AND and OR. The return
  52. value is as above.
  53. - <tt>exp ? exp1 : exp2</tt> -- The C ternary operator. If \c exp is
  54. nonzero the return value is \c exp1, otherwise \c exp2.
  55. - <tt>exp ; exp</tt> -- Concatenation of expressions. This allows more
  56. than one expression per line. The return value is the rightmost
  57. expression.
  58. - <tt>(exp)</tt> -- Parentheses.
  59. - <tt>+ exp, - exp</tt> -- Unary plus and minus.
  60. - <tt>variable</tt> -- The name of a (possibly undefined) variable. The
  61. return value is the value of the variable (or 0 if undefined).
  62. - <tt>variable = exp</tt> -- Variable assignment. The return value is
  63. the value of the expression.
  64. - <tt>func([exp [, exp...]])</tt> -- Function call, where "func" is the
  65. name of a parser function.
  66. .
  67. */
  68. /*!
  69. @defgroup parser_builtin Builtin functions and constants
  70. @ingroup parser
  71. The following functions are builtin, and are described in \c math(3).
  72. - Trigonometric functions -- <tt>sin, cos, tan, asin, acos, atan, atan2</tt>
  73. - Exponent and log functions -- <tt>exp, log, log10, pow, sqrt, hypot</tt>
  74. - Rounding functions -- <tt>ceil, floor, trunc, abs, mod</tt>
  75. .
  76. The following functions are also defined:
  77. - <tt>min(val1, val2 [, val3...])</tt> -- Return the minimum of a list of
  78. values.
  79. - <tt>max(val1, val2 [, val3...])</tt> -- Return the maximum of a list of
  80. values.
  81. .
  82. The following constants are predefined:
  83. - \c pi -- 3.14159265...
  84. - \c e -- 2.7182818...
  85. - \c dtor -- Degrees to radians conversion factor.
  86. - \c rtod -- Radians to degrees conversion factor.
  87. .
  88. */
  89. %{
  90. #define __NO_MATH_INLINES
  91. #include <stdio.h>
  92. #include <string.h>
  93. #include <stdlib.h>
  94. #include <stdarg.h>
  95. #include <ctype.h>
  96. #include <errno.h>
  97. #include <math.h>
  98. #ifndef DOXYGEN_IGNORE
  99. #include "vars-config.h"
  100. #include "vars-buffer.h"
  101. #include "vars-hash.h"
  102. #include "vars-macros.h"
  103. #include "vars-memory.h"
  104. #include "vars-parser.h"
  105. #include "vars-regex.h"
  106. #endif
  107. /* Internalize yacc variables */
  108. #define yymaxdepth yy_vars_maxdepth
  109. #define yyparse yy_vars_parse
  110. #define yylex yy_vars_lex
  111. #define yyerror yy_vars_error
  112. #define yylval yy_vars_lval
  113. #define yychar yy_vars_char
  114. #define yydebug yy_vars_debug
  115. #define yypact yy_vars_pact
  116. #define yyr1 yy_vars_r1
  117. #define yyr2 yy_vars_r2
  118. #define yydef yy_vars_def
  119. #define yychk yy_vars_chk
  120. #define yypgo yy_vars_pgo
  121. #define yyact yy_vars_act
  122. #define yyexca yy_vars_exca
  123. #define yyerrflag yy_vars_errflag
  124. #define yynerrs yy_vars_nerrs
  125. #define yyps yy_vars_ps
  126. #define yypv yy_vars_pv
  127. #define yys yy_vars_s
  128. #define yy_yys yy_vars_yys
  129. #define yystate yy_vars_state
  130. #define yytmp yy_vars_tmp
  131. #define yyv yy_vars_v
  132. #define yy_yyv yy_vars_yyv
  133. #define yyval yy_vars_val
  134. #define yylloc yy_vars_lloc
  135. #define yyreds yy_vars_reds
  136. #define yytoks yy_vars_toks
  137. #define yylhs yy_vars_yylhs
  138. #define yylen yy_vars_yylen
  139. #define yydefred yy_vars_yydefred
  140. #define yydgoto yy_vars_yydgoto
  141. #define yysindex yy_vars_yysindex
  142. #define yyrindex yy_vars_yyrindex
  143. #define yygindex yy_vars_yygindex
  144. #define yytable yy_vars_yytable
  145. #define yycheck yy_vars_yycheck
  146. #define yyname yy_vars_yyname
  147. #define yyrule yy_vars_yyrule
  148. /* Convenience macros */
  149. #define COPY(s) vs_copy(s)
  150. #define PUSH(s) vl_push(vp_stack, s)
  151. #define NV(s) vs_dget(s)
  152. #define IV(s) vs_iget(s)
  153. #define SV(s) vs_sget_buf(s, buf)
  154. #define NSET(n) vs_dcreate(n)
  155. #define SSET(n) vs_screate(n)
  156. #define YYSTYPE vscalar *
  157. #define YYPRINT(fp, type, value) yyprint(fp, type, value)
  158. #define YYERROR_VERBOSE 1
  159. #define YYDEBUG 1
  160. #define CALL_MATH_1(func) \
  161. vs_dcreate(func(vl_dget(args, 0)))
  162. #define CALL_MATH_2(func) \
  163. vs_dcreate(func(vl_dget(args, 0), vl_dget(args, 1)))
  164. /* Type definition */
  165. struct v_parser {
  166. struct v_header id; /* Type marker */
  167. struct v_hash *constants; /* Constants */
  168. struct v_hash *variables; /* Variables */
  169. struct v_hash *functions; /* Functions */
  170. struct v_scalar *value; /* Last parse value */
  171. struct v_list *errors; /* List of parse errors */
  172. int undef_ok; /* OK to refer to undefined variables? */
  173. };
  174. /* Function attributes */
  175. struct v_pfunc {
  176. vscalar *(*func)(vlist *args);
  177. int minargs, maxargs;
  178. };
  179. /* Internal type abbreviations */
  180. typedef struct v_pfunc vpfunc;
  181. /* Type variable */
  182. vtype *vparser_type = NULL;
  183. /* Current parser for evaluation */
  184. static vparser *vp_parser = NULL;
  185. /* Current value stack */
  186. static vlist *vp_stack = NULL;
  187. /* Current function arg list */
  188. static vlist *vp_arglist = NULL;
  189. /* Current parse string */
  190. static char *vp_input = NULL;
  191. /* Current input line */
  192. static int vp_line_number = 0;
  193. /* Whether to report line numbers */
  194. static int report_line = 0;
  195. /* Internal arg list */
  196. static vlist *args = NULL;
  197. /* Scribble buffer */
  198. static char buf[BUFSIZ];
  199. /* Internal functions */
  200. static void vp_add_builtins(vparser *p);
  201. static vparser *vp_create_empty(void);
  202. static int yylex(void);
  203. static void yyprint(FILE *fp, int type, vscalar *s);
  204. static void yyerror(char *msg);
  205. static vscalar *builtin_acos(vlist *args);
  206. static vscalar *builtin_asin(vlist *args);
  207. static vscalar *builtin_atan(vlist *args);
  208. static vscalar *builtin_atan2(vlist *args);
  209. static vscalar *builtin_ceil(vlist *args);
  210. static vscalar *builtin_cos(vlist *args);
  211. static vscalar *builtin_exp(vlist *args);
  212. static vscalar *builtin_fabs(vlist *args);
  213. static vscalar *builtin_floor(vlist *args);
  214. static vscalar *builtin_fmod(vlist *args);
  215. static vscalar *builtin_hypot(vlist *args);
  216. static vscalar *builtin_log(vlist *args);
  217. static vscalar *builtin_log10(vlist *args);
  218. static vscalar *builtin_max(vlist *args);
  219. static vscalar *builtin_min(vlist *args);
  220. static vscalar *builtin_pow(vlist *args);
  221. static vscalar *builtin_sin(vlist *args);
  222. static vscalar *builtin_sqrt(vlist *args);
  223. static vscalar *builtin_tan(vlist *args);
  224. /* List of builtin functions */
  225. static struct builtin_func {
  226. char *name;
  227. vscalar *(*func)(vlist *args);
  228. int minargs, maxargs;
  229. } builtin_functions[] = {
  230. "abs", builtin_fabs, 1, 1,
  231. "acos", builtin_acos, 1, 1,
  232. "asin", builtin_asin, 1, 1,
  233. "atan", builtin_atan, 1, 1,
  234. "atan2", builtin_atan2, 2, 2,
  235. "ceil", builtin_ceil, 1, 1,
  236. "cos", builtin_cos, 1, 1,
  237. "exp", builtin_exp, 1, 1,
  238. "floor", builtin_floor, 1, 1,
  239. "hypot", builtin_hypot, 2, 2,
  240. "log", builtin_log, 1, 1,
  241. "log10", builtin_log10, 1, 1,
  242. "min", builtin_min, 2, VP_FUNC_NOLIMIT,
  243. "max", builtin_max, 2, VP_FUNC_NOLIMIT,
  244. "mod", builtin_fmod, 2, 2,
  245. "pow", builtin_pow, 2, 2,
  246. "sin", builtin_sin, 1, 1,
  247. "sqrt", builtin_sqrt, 1, 1,
  248. "tan", builtin_tan, 1, 1,
  249. NULL, NULL, 0
  250. };
  251. /* List of builtin constants */
  252. static struct builtin_const {
  253. char *name;
  254. double value;
  255. } builtin_constants[] = {
  256. "pi", M_PI, /* Pi */
  257. "e", M_E, /* E */
  258. "dtor", M_PI / 180, /* Degrees-to-radians */
  259. "rtod", 180 / M_PI, /* Radians-to-degrees */
  260. NULL, 0.0
  261. };
  262. %}
  263. %token VALUE ID
  264. %token EQ NE GE GT LE LT
  265. %token AND OR
  266. %left ';'
  267. %right '='
  268. %right '?' ':'
  269. %left OR
  270. %left AND
  271. %left EQ NE
  272. %left LT LE GT GE
  273. %left '+' '-'
  274. %left '*' '/' '%'
  275. %left PLUS MINUS
  276. %nonassoc '!'
  277. %right '^'
  278. %%
  279. input : /* empty */
  280. | input line
  281. ;
  282. line : '\n'
  283. | exp '\n'
  284. | error '\n'
  285. {
  286. yyerrok;
  287. }
  288. ;
  289. exp : VALUE
  290. {
  291. PUSH($1);
  292. }
  293. | ID
  294. {
  295. $$ = vp_get(vp_parser, SV($1));
  296. if ($$ != NULL)
  297. $$ = COPY($$);
  298. else
  299. $$ = vs_create(V_UNDEF);
  300. PUSH($1);
  301. PUSH($$);
  302. }
  303. | '+' exp %prec PLUS
  304. {
  305. $$ = NSET(NV($2)); PUSH($$);
  306. }
  307. | '-' exp %prec MINUS
  308. {
  309. $$ = NSET(-NV($2)); PUSH($$);
  310. }
  311. | exp '+' exp
  312. {
  313. $$ = NSET(NV($1) + NV($3)); PUSH($$);
  314. }
  315. | exp '-' exp
  316. {
  317. $$ = NSET(NV($1) - NV($3)); PUSH($$);
  318. }
  319. | exp '*' exp
  320. {
  321. $$ = NSET(NV($1) * NV($3)); PUSH($$);
  322. }
  323. | exp '/' exp
  324. {
  325. $$ = NSET(NV($1) / NV($3)); PUSH($$);
  326. }
  327. | exp '^' exp
  328. {
  329. errno = 0;
  330. $$ = NSET(pow(NV($1), NV($3))); PUSH($$);
  331. if (errno)
  332. vp_errno("^", errno);
  333. }
  334. | exp '%' exp
  335. {
  336. errno = 0;
  337. $$ = NSET(fmod(NV($1), NV($3))); PUSH($$);
  338. if (errno)
  339. vp_errno("%", errno);
  340. }
  341. | exp ';' exp
  342. {
  343. $$ = COPY($3); PUSH($$);
  344. }
  345. | '(' exp ')'
  346. {
  347. $$ = COPY($2); PUSH($$);
  348. }
  349. | exp EQ exp
  350. {
  351. $$ = NSET(NV($1) == NV($3)); PUSH($$);
  352. }
  353. | exp NE exp
  354. {
  355. $$ = NSET(NV($1) != NV($3)); PUSH($$);
  356. }
  357. | exp GT exp
  358. {
  359. $$ = NSET(NV($1) > NV($3)); PUSH($$);
  360. }
  361. | exp LT exp
  362. {
  363. $$ = NSET(NV($1) < NV($3)); PUSH($$);
  364. }
  365. | exp GE exp
  366. {
  367. $$ = NSET(NV($1) >= NV($3)); PUSH($$);
  368. }
  369. | exp LE exp
  370. {
  371. $$ = NSET(NV($1) <= NV($3)); PUSH($$);
  372. }
  373. | exp AND exp
  374. {
  375. $$ = NSET(IV($1) && IV($3)); PUSH($$);
  376. }
  377. | exp OR exp
  378. {
  379. $$ = NSET(IV($1) || IV($3)); PUSH($$);
  380. }
  381. | '!' exp
  382. {
  383. $$ = NSET(!IV($2)); PUSH($$);
  384. }
  385. | exp '?' exp ':' exp
  386. {
  387. $$ = COPY(IV($1) ? $3 : $5); PUSH($$);
  388. }
  389. | ID '=' exp
  390. {
  391. $$ = COPY($3);
  392. PUSH($1);
  393. PUSH($$);
  394. vp_store(vp_parser, SV($1), COPY($3));
  395. }
  396. | ID '('
  397. {
  398. PUSH($1);
  399. if (args != NULL)
  400. vl_ppush(vp_arglist, args);
  401. args = vl_create();
  402. }
  403. arglist ')'
  404. {
  405. if (($$ = vp_call(vp_parser, SV($1), args)) == NULL)
  406. $$ = vs_create(V_UNDEF);
  407. PUSH($$);
  408. vl_destroy(args);
  409. args = vl_ppop(vp_arglist);
  410. }
  411. ;
  412. arglist : /* empty */
  413. | arg
  414. | arglist ',' arg
  415. ;
  416. arg : exp
  417. {
  418. vl_push(args, COPY($1));
  419. }
  420. ;
  421. %%
  422. /* Add builtins to a parser */
  423. static void
  424. vp_add_builtins(vparser *p)
  425. {
  426. int i;
  427. /* Install builtin constants */
  428. for (i = 0; builtin_constants[i].name != NULL; i++)
  429. vp_dconst(p,
  430. builtin_constants[i].name,
  431. builtin_constants[i].value);
  432. /* Install builtin functions */
  433. for (i = 0; builtin_functions[i].name != NULL; i++)
  434. vp_func(p,
  435. builtin_functions[i].name,
  436. builtin_functions[i].func,
  437. builtin_functions[i].minargs,
  438. builtin_functions[i].maxargs);
  439. }
  440. /*!
  441. @brief Call a parser function.
  442. @ingroup parser_access
  443. @param p Parser.
  444. @param name Function name.
  445. @param args List of arguments (or \c NULL, meaning no args).
  446. @return Result.
  447. @retval NULL if the call failed.
  448. */
  449. vscalar *
  450. vp_call(vparser *p, char *name, vlist *args)
  451. {
  452. vscalar *result;
  453. int nargs = 0;
  454. vpfunc *f;
  455. VP_CHECK(p);
  456. if (args != NULL) {
  457. VL_CHECK(args);
  458. nargs = vl_length(args);
  459. }
  460. /* Get function info */
  461. if ((f = vh_pget(p->functions, name)) == NULL) {
  462. vp_err("function \"%s\" is undefined", name);
  463. return NULL;
  464. }
  465. /* Check no. of arguments */
  466. if (nargs < f->minargs || nargs > f->maxargs) {
  467. if (f->minargs == f->maxargs)
  468. vp_err("function \"%s\" requires %d argument%s",
  469. name, f->minargs, (f->minargs == 1 ? "" : "s"));
  470. else if (f->maxargs == VP_FUNC_NOLIMIT)
  471. vp_err("function \"%s\" requires at least %d argument%s",
  472. name, f->minargs, (f->minargs == 1 ? "" : "s"));
  473. else if (f->minargs == 0)
  474. vp_err("function \"%s\" requires at most %d argument%s",
  475. name, f->maxargs, (f->maxargs == 1 ? "" : "s"));
  476. else
  477. vp_err("function \"%s\" requires between %d and %d arguments",
  478. name, f->minargs, f->maxargs);
  479. return NULL;
  480. }
  481. /* Call function, checking for errors */
  482. errno = 0;
  483. result = (*f->func)(args);
  484. if (errno && vp_errno(name, errno)) {
  485. if (result != NULL)
  486. vs_destroy(result);
  487. return NULL;
  488. }
  489. return result;
  490. }
  491. /*!
  492. @brief Declare a parser constant.
  493. @ingroup parser_custom
  494. @param p Parser.
  495. @param name Constant name.
  496. @param val Its value.
  497. */
  498. void
  499. vp_const(vparser *p, char *name, vscalar *val)
  500. {
  501. VP_CHECK(p);
  502. vh_istore(p->constants, name, 1);
  503. vh_store(p->variables, name, val);
  504. }
  505. /*!
  506. @brief Return a copy of a parser.
  507. @ingroup parser_create
  508. @param p Parser to copy.
  509. @return Copy.
  510. Builtin functions and constants, and also current values of variables,
  511. are copied.
  512. */
  513. vparser *
  514. vp_copy(vparser *p)
  515. {
  516. vpfunc *cf, *f;
  517. vparser *copy;
  518. vscalar *elt;
  519. char *name;
  520. VP_CHECK(p);
  521. copy = vp_create_empty();
  522. vh_destroy(copy->constants);
  523. copy->constants = vh_copy(p->constants);
  524. vh_destroy(copy->variables);
  525. copy->variables = vh_copy(p->variables);
  526. vh_foreach(name, elt, p->functions) {
  527. f = vs_pget(elt);
  528. cf = V_ALLOC(vpfunc, 1);
  529. cf->func = f->func;
  530. cf->minargs = f->minargs;
  531. cf->maxargs = f->maxargs;
  532. vh_pstore(copy->functions, name, cf);
  533. }
  534. if (V_DEBUG(V_DBG_INFO))
  535. v_info("Copied %s to 0x%p", v_vinfo(p), copy);
  536. return copy;
  537. }
  538. /*!
  539. @brief Return a newly-created parser with builtins.
  540. @ingroup parser_create
  541. @return New parser.
  542. */
  543. vparser *
  544. vp_create(void)
  545. {
  546. vparser *p;
  547. p = vp_create_empty();
  548. vp_add_builtins(p);
  549. return p;
  550. }
  551. /* Return a newly-created empty parser */
  552. static vparser *
  553. vp_create_empty(void)
  554. {
  555. static vheader *id = NULL;
  556. vparser *p;
  557. if (id == NULL) {
  558. vp_declare();
  559. id = vt_header(vparser_type);
  560. }
  561. p = V_ALLOC(vparser, 1);
  562. p->id = *id;
  563. p->constants = vh_create();
  564. p->variables = vh_create();
  565. p->functions = vh_create();
  566. p->value = NULL;
  567. p->errors = NULL;
  568. p->undef_ok = 1;
  569. if (V_DEBUG(V_DBG_INFO))
  570. v_info("Created %s", v_vinfo(p));
  571. return p;
  572. }
  573. /* Declare parser type */
  574. vtype *
  575. vp_declare(void)
  576. {
  577. if (vparser_type == NULL) {
  578. vparser_type = vt_create("PARSER", "P");
  579. vt_copy_with(vparser_type, (void *(*)()) vp_copy);
  580. vt_read_with(vparser_type, (void *(*)()) vp_fread);
  581. vt_write_with(vparser_type, vp_fwrite);
  582. vt_print_with(vparser_type, vp_print);
  583. vt_destroy_with(vparser_type, vp_destroy);
  584. }
  585. return vparser_type;
  586. }
  587. /*!
  588. @brief Delete a builtin constant.
  589. @ingroup parser_custom
  590. @param p Parser.
  591. @param name Constant to delete.
  592. Does nothing if the constant doesn't exist.
  593. */
  594. void
  595. vp_delconst(vparser *p, char *name)
  596. {
  597. VP_CHECK(p);
  598. vh_delete(p->constants, name);
  599. vh_delete(p->variables, name);
  600. }
  601. /*!
  602. @brief Delete a builtin function.
  603. @ingroup parser_custom
  604. @param p Parser.
  605. @param name Function to delete.
  606. Does nothing if the function doesn't exist.
  607. */
  608. void
  609. vp_delfunc(vparser *p, char *name)
  610. {
  611. vpfunc *f;
  612. VP_CHECK(p);
  613. if ((f = vh_pget(p->functions, name)) != NULL) {
  614. vh_delete(p->functions, name);
  615. V_DEALLOC(f);
  616. }
  617. }
  618. /*!
  619. @brief Deallocate a parser.
  620. @ingroup parser_create
  621. @param p Parser.
  622. */
  623. void
  624. vp_destroy(vparser *p)
  625. {
  626. vscalar *elt;
  627. char *name;
  628. vpfunc *f;
  629. VP_CHECK(p);
  630. if (V_DEBUG(V_DBG_INFO))
  631. v_info("Destroyed %s", v_vinfo(p));
  632. /* Destroy builtin functions */
  633. vh_foreach(name, elt, p->functions) {
  634. f = vs_pget(elt);
  635. V_DEALLOC(f);
  636. }
  637. /* Destroy parser */
  638. vh_destroy(p->constants);
  639. vh_destroy(p->variables);
  640. vh_destroy(p->functions);
  641. if (p->value != NULL)
  642. vs_destroy(p->value);
  643. if (p->errors != NULL)
  644. vl_destroy(p->errors);
  645. V_DEALLOC(p);
  646. }
  647. /*!
  648. @brief Flag a parse error.
  649. @ingroup parser_custom
  650. @param fmt Format string.
  651. This function is for use inside a user-defined parser function to
  652. indicate that an error has occurred.
  653. */
  654. void
  655. vp_err(char *fmt, ...)
  656. {
  657. static vbuffer *err = NULL;
  658. char errbuf[BUFSIZ];
  659. if (err == NULL)
  660. err = vb_create();
  661. else
  662. vb_empty(err);
  663. if (vp_parser->errors == NULL)
  664. vp_parser->errors = vl_create();
  665. V_VPRINT(errbuf, fmt);
  666. if (report_line)
  667. vb_printf(err, "line %d: %s", vp_line_number, errbuf);
  668. else
  669. vb_puts(err, errbuf);
  670. vl_spush(vp_parser->errors, vb_get(err));
  671. }
  672. /* Flag an errno error */
  673. int
  674. vp_errno(char *name, int num)
  675. {
  676. char namebuf[80];
  677. strcpy(namebuf, name);
  678. vp_err("function \"%s\": %s", namebuf, strerror(num));
  679. return 1;
  680. }
  681. /*!
  682. @brief Return the last parser error.
  683. @ingroup parser_exp
  684. @param p Parser.
  685. @return Error string.
  686. @retval NULL if no errors occurred.
  687. */
  688. char *
  689. vp_error(vparser *p)
  690. {
  691. VP_CHECK(p);
  692. return (p->errors != NULL ? vl_shead(p->errors) : NULL);
  693. }
  694. /*!
  695. @brief Set whether undefined variable references cause an error.
  696. @ingroup parser_custom
  697. @param p Parser.
  698. @param flag Yes or no.
  699. By default all undefined variables have the value zero.
  700. */
  701. void
  702. vp_error_undef(vparser *p, int flag)
  703. {
  704. VP_CHECK(p);
  705. p->undef_ok = !flag;
  706. }
  707. /*!
  708. @brief Return the list of parser errors.
  709. @ingroup parser_exp
  710. @param p Parser.
  711. @return List of error strings.
  712. @retval NULL if no errors occurred.
  713. If an evaluation failed, then one or more errors occurred. This
  714. function returns the list of errors encountered during the last
  715. evaluation.
  716. */
  717. vlist *
  718. vp_errors(vparser *p)
  719. {
  720. VP_CHECK(p);
  721. return p->errors;
  722. }
  723. /*!
  724. @brief Evaluate an expression.
  725. @ingroup parser_exp
  726. @param p Parser.
  727. @param expr Expression.
  728. @return Whether successful.
  729. Use vp_value() to get the value of the expression.
  730. */
  731. int
  732. vp_eval(vparser *p, char *expr)
  733. {
  734. VP_CHECK(p);
  735. /* Initialise */
  736. if (vp_stack == NULL) {
  737. vp_stack = vl_create();
  738. v_cleanup(vp_stack);
  739. } else {
  740. vl_empty(vp_stack);
  741. }
  742. if (vp_arglist == NULL) {
  743. vp_arglist = vl_create();
  744. v_cleanup(vp_arglist);
  745. }
  746. if (p->value != NULL)
  747. vs_destroy(p->value);
  748. if (p->errors != NULL)
  749. vl_destroy(p->errors);
  750. p->errors = NULL;
  751. vp_parser = p;
  752. vp_input = expr;
  753. vp_line_number = 1;
  754. report_line = (strchr(expr, '\n') != NULL);
  755. /* Let's parse! */
  756. yyparse();
  757. vp_parser = NULL;
  758. /* Tidy up */
  759. report_line = 0;
  760. /* Save return value */
  761. if (vl_length(vp_stack) > 0)
  762. p->value = vl_pop(vp_stack);
  763. else
  764. p->value = vs_create(V_UNDEF);
  765. return (p->errors == NULL);
  766. }
  767. /*!
  768. @brief Return whether a variable exists.
  769. @ingroup parser_access
  770. @param p Parser.
  771. @param name Variable name.
  772. @return Yes or no.
  773. */
  774. int
  775. vp_exists(vparser *p, char *name)
  776. {
  777. VP_CHECK(p);
  778. return vh_exists(p->variables, name);
  779. }
  780. /* Read parser from a stream */
  781. vparser *
  782. vp_fread(FILE *fp)
  783. {
  784. vparser *p;
  785. /* Initialise */
  786. p = vp_create_empty();
  787. vp_add_builtins(p);
  788. /* Read variables */
  789. vh_destroy(p->variables);
  790. if ((p->variables = vh_fread(fp)) == NULL)
  791. return NULL;
  792. /* Read constant flags */
  793. vh_destroy(p->constants);
  794. if ((p->constants = vh_fread(fp)) == NULL)
  795. return NULL;
  796. if (V_DEBUG(V_DBG_IO))
  797. v_info("Read %s", v_vinfo(p));
  798. return p;
  799. }
  800. /*!
  801. @brief Declare a parser function.
  802. @ingroup parser_custom
  803. @param p Parser.
  804. @param name Function name.
  805. @param func Function.
  806. @param minargs Minimum no. of arguments.
  807. @param maxargs Maximum no. of arguments.
  808. @see vp_func_min(), vp_func_max(), vp_func_args(), vp_func_any()
  809. Declare a parser function with the given name, function and range of
  810. arguments. Overrides any previous definition.
  811. A parser function is one that accepts a list of scalars as arguments and
  812. returns a single scalar, which should be of type V_INT, V_DOUBLE or
  813. V_STRING. In vp_eval(), the number of arguments supplied to the function
  814. must be between \c minargs and \c maxargs or a parse error is given. If
  815. \c maxargs is VP_FUNC_NOLIMIT, then there is no upper limit to the number
  816. of arguments. If the function fails for any reason, it should call
  817. vp_err() and return NULL. The function should check for the case where
  818. \c args is \c NULL, and treat it as if an empty list of arguments was
  819. passed.
  820. */
  821. void
  822. vp_func(vparser *p, char *name, vscalar *(*func)(vlist *args),
  823. int minargs, int maxargs)
  824. {
  825. vpfunc *f, *oldf;
  826. VP_CHECK(p);
  827. f = V_ALLOC(vpfunc, 1);
  828. f->func = func;
  829. f->minargs = V_MIN(minargs, maxargs);
  830. f->maxargs = V_MAX(minargs, maxargs);
  831. if ((oldf = vh_pget(p->functions, name)) != NULL)
  832. V_DEALLOC(oldf);
  833. vh_pstore(p->functions, name, f);
  834. }
  835. /* Write parser to a stream */
  836. int
  837. vp_fwrite(vparser *p, FILE *fp)
  838. {
  839. VP_CHECK(p);
  840. if (V_DEBUG(V_DBG_IO))
  841. v_info("Writing %s", v_vinfo(p));
  842. /* Write variables */
  843. if (!vh_fwrite(p->variables, fp))
  844. return 0;
  845. /* Write constant flags */
  846. if (!vh_fwrite(p->constants, fp))
  847. return 0;
  848. return 1;
  849. }
  850. /*!
  851. @brief Return the value of a parser variable.
  852. @ingroup parser_access
  853. @param p Parser.
  854. @param name Variable name.
  855. @return Its value.
  856. */
  857. vscalar *
  858. vp_get(vparser *p, char *name)
  859. {
  860. vscalar *val;
  861. VP_CHECK(p);
  862. if ((val = vh_get(p->variables, name)) == NULL &&
  863. !p->undef_ok && vp_parser != NULL)
  864. vp_err("undefined variable \"%s\"", name);
  865. return val;
  866. }
  867. /*!
  868. @brief Return whether a name exists as a constant.
  869. @ingroup parser_access
  870. @param p Parser.
  871. @param name Name.
  872. @return Yes or no.
  873. */
  874. int
  875. vp_isconst(vparser *p, char *name)
  876. {
  877. VP_CHECK(p);
  878. return vh_exists(p->constants, name);
  879. }
  880. /*!
  881. @brief Return whether a name exists as a function.
  882. @ingroup parser_access
  883. @param p Parser.
  884. @param name Name.
  885. @return Yes or no.
  886. */
  887. int
  888. vp_isfunc(vparser *p, char *name)
  889. {
  890. VP_CHECK(p);
  891. return vh_exists(p->functions, name);
  892. }
  893. /* Print contents of a parser */
  894. void
  895. vp_print(vparser *p, FILE *fp)
  896. {
  897. vscalar *elt;
  898. vlist *list;
  899. char *name;
  900. vpfunc *f;
  901. VP_CHECK(p);
  902. v_print_start();
  903. v_push_indent();
  904. v_print_type(vparser_type, p, fp);
  905. /* Print variables */
  906. v_indent(fp);
  907. fprintf(fp, "VARIABLES => LIST\n");
  908. v_push_indent();
  909. list = vh_sortkeys(p->variables, NULL);
  910. vl_foreach(elt, list) {
  911. name = vs_sgetref(elt);
  912. v_indent(fp);
  913. fprintf(fp, "%s = %s", name, vh_sget(p->variables, name));
  914. if (vh_exists(p->constants, name))
  915. fprintf(fp, " (constant)");
  916. fprintf(fp, "\n");
  917. }
  918. v_pop_indent();
  919. /* Print functions */
  920. v_indent(fp);
  921. fprintf(fp, "FUNCTIONS => LIST\n");
  922. v_push_indent();
  923. list = vh_sortkeys(p->functions, NULL);
  924. vl_foreach(elt, list) {
  925. name = vs_sgetref(elt);
  926. f = vh_pget(p->functions, name);
  927. v_indent(fp);
  928. fprintf(fp, "%s", name);
  929. if (f->minargs == f->maxargs)
  930. fprintf(fp, " (%d arg%s)", f->minargs,
  931. (f->minargs == 1 ? "" : "s"));
  932. else if (f->maxargs == VP_FUNC_NOLIMIT)
  933. fprintf(fp, " (>= %d arg%s)", f->minargs,
  934. (f->minargs == 1 ? "" : "s"));
  935. else if (f->minargs == 0)
  936. fprintf(fp, " (<= %d arg%s)", f->maxargs,
  937. (f->maxargs == 1 ? "" : "s"));
  938. else
  939. fprintf(fp, " (%d-%d args)", f->minargs, f->maxargs);
  940. fprintf(fp, "\n");
  941. }
  942. v_pop_indent();
  943. /* That's it */
  944. v_pop_indent();
  945. v_print_finish();
  946. }
  947. /*!
  948. @brief Set the value of a parser variable.
  949. @ingroup parser_access
  950. @param p Parser.
  951. @param name Variable name.
  952. @param val Value to set.
  953. */
  954. void
  955. vp_store(vparser *p, char *name, vscalar *val)
  956. {
  957. VP_CHECK(p);
  958. if (!vh_exists(p->constants, name))
  959. vh_store(p->variables, name, val);
  960. else
  961. vp_err("attempt to modify constant \"%s\"", name);
  962. }
  963. /*!
  964. @brief Return the value of the last expression evaluated.
  965. @ingroup parser_exp
  966. @param p Parser.
  967. @return Expression value.
  968. */
  969. vscalar *
  970. vp_value(vparser *p)
  971. {
  972. VP_CHECK(p);
  973. return p->value;
  974. }
  975. /* Lexer function */
  976. static int
  977. yylex(void)
  978. {
  979. static vregex *re_int, *re_real, *re_intexp, *re_id, *re_token;
  980. extern vscalar *yylval;
  981. static int newline = 0;
  982. extern char *vp_input;
  983. static vhash *tokens;
  984. static int init = 0;
  985. static int eof = 0;
  986. vlist *keylist;
  987. vscalar *elt;
  988. vbuffer *b;
  989. char *key;
  990. int token;
  991. /* Initialise */
  992. if (!init) {
  993. init++;
  994. tokens = vh_create();
  995. vh_istore(tokens, "&&", AND);
  996. vh_istore(tokens, "==", EQ);
  997. vh_istore(tokens, ">=", GE);
  998. vh_istore(tokens, ">", GT);
  999. vh_istore(tokens, "<=", LE);
  1000. vh_istore(tokens, "<", LT);
  1001. vh_istore(tokens, "!=", NE);
  1002. vh_istore(tokens, "||", OR);
  1003. b = vb_create();
  1004. vb_puts(b, "\\`\\(");
  1005. keylist = vh_keys(tokens);
  1006. vb_puts(b, vl_join(keylist, "\\|"));
  1007. vl_destroy(keylist);
  1008. vb_puts(b, "\\)");
  1009. if ((re_token = vr_create(vb_get(b))) == NULL)
  1010. v_fatal("invalid token regexp: %s", vr_error());
  1011. v_cleanup(re_token);
  1012. vb_destroy(b);
  1013. if ((re_id = vr_create("\\`[A-Za-z_]\\w*")) == NULL)
  1014. v_fatal("invalid ID regexp: %s", vr_error());
  1015. v_cleanup(re_id);
  1016. if ((re_int = vr_create("\\`[0-9]+")) == NULL)
  1017. v_fatal("invalid integer regexp: %s", vr_error());
  1018. v_cleanup(re_int);
  1019. if ((re_intexp = vr_create("\\`[0-9]+[Ee]-?[0-9]+")) == NULL)
  1020. v_fatal("invalid integer-exponent regexp: %s", vr_error());
  1021. v_cleanup(re_intexp);
  1022. if ((re_real = vr_create("\\`[0-9]*\\.[0-9]+\\([Ee]-?[0-9]+\\)?")) == NULL)
  1023. v_fatal("invalid real regexp: %s", vr_error());
  1024. v_cleanup(re_real);
  1025. }
  1026. /* Check for end-of-input */
  1027. if (eof) {
  1028. eof = 0;
  1029. return 0;
  1030. }
  1031. /* Increment line number if required */
  1032. if (newline) {
  1033. vp_line_number++;
  1034. newline = 0;
  1035. }
  1036. /* Scan input */
  1037. while (1) {
  1038. if (*vp_input == '\0') {
  1039. /* End of input -- fake a final newline */
  1040. eof++;
  1041. return '\n';
  1042. } else if (*vp_input == '\n') {
  1043. /* Newline */
  1044. vp_input++;
  1045. newline++;
  1046. return '\n';
  1047. } else if (isspace(*vp_input)) {
  1048. /* Skip whitespace */
  1049. vp_input++;
  1050. } else if (*vp_input == '#') {
  1051. /* Skip comments */
  1052. while (*vp_input != '\n' && *vp_input != '\0')
  1053. vp_input++;
  1054. } else if (vr_match(vp_input, re_token)) {
  1055. /* Token */
  1056. char *val = vr_matched(0);
  1057. token = vh_iget(tokens, val);
  1058. vp_input += strlen(val);
  1059. return token;
  1060. } else if (vr_match(vp_input, re_id)) {
  1061. /* ID -- variable, constant or function */
  1062. char *val = vr_matched(0);
  1063. yylval = vs_screate(val);
  1064. vp_input += strlen(val);
  1065. return ID;
  1066. } else if (vr_match(vp_input, re_real)) {
  1067. /* Real with decimal point and optional exponent */
  1068. char *val = vr_matched(0);
  1069. yylval = vs_dcreate(atof(val));
  1070. vp_input += strlen(val);
  1071. return VALUE;
  1072. } else if (vr_match(vp_input, re_intexp)) {
  1073. /* Integer with exponent */
  1074. char *val = vr_matched(0);
  1075. yylval = vs_dcreate(atof(val));
  1076. vp_input += strlen(val);
  1077. return VALUE;
  1078. } else if (vr_match(vp_input, re_int)) {
  1079. /* Integer */
  1080. char *val = vr_matched(0);
  1081. yylval = vs_icreate(atoi(val));
  1082. vp_input += strlen(val);
  1083. return VALUE;
  1084. } else {
  1085. /* Single character */
  1086. return *vp_input++;
  1087. }
  1088. }
  1089. /* NOTREACHED */
  1090. }
  1091. /* Parser print function */
  1092. static void
  1093. yyprint(FILE *fp, int type, vscalar *s)
  1094. {
  1095. switch (type) {
  1096. case ID:
  1097. case VALUE:
  1098. fprintf(fp, " %s", vs_sget(s));
  1099. break;
  1100. }
  1101. }
  1102. /* Parser error function */
  1103. static void
  1104. yyerror(char *msg)
  1105. {
  1106. vp_err(msg);
  1107. }
  1108. /* Builtin functions */
  1109. static vscalar *
  1110. builtin_acos(vlist *args)
  1111. {
  1112. return CALL_MATH_1(acos);
  1113. }
  1114. static vscalar *
  1115. builtin_asin(vlist *args)
  1116. {
  1117. return CALL_MATH_1(asin);
  1118. }
  1119. static vscalar *
  1120. builtin_atan(vlist *args)
  1121. {
  1122. return CALL_MATH_1(atan);
  1123. }
  1124. static vscalar *
  1125. builtin_atan2(vlist *args)
  1126. {
  1127. return CALL_MATH_2(atan2);
  1128. }
  1129. static vscalar *
  1130. builtin_ceil(vlist *args)
  1131. {
  1132. return CALL_MATH_1(ceil);
  1133. }
  1134. static vscalar *
  1135. builtin_cos(vlist *args)
  1136. {
  1137. return CALL_MATH_1(cos);
  1138. }
  1139. static vscalar *
  1140. builtin_exp(vlist *args)
  1141. {
  1142. return CALL_MATH_1(exp);
  1143. }
  1144. static vscalar *
  1145. builtin_fabs(vlist *args)
  1146. {
  1147. return CALL_MATH_1(fabs);
  1148. }
  1149. static vscalar *
  1150. builtin_floor(vlist *args)
  1151. {
  1152. return CALL_MATH_1(floor);
  1153. }
  1154. static vscalar *
  1155. builtin_fmod(vlist *args)
  1156. {
  1157. return CALL_MATH_2(fmod);
  1158. }
  1159. static vscalar *
  1160. builtin_hypot(vlist *args)
  1161. {
  1162. return CALL_MATH_2(hypot);
  1163. }
  1164. static vscalar *
  1165. builtin_log(vlist *args)
  1166. {
  1167. return CALL_MATH_1(log);
  1168. }
  1169. static vscalar *
  1170. builtin_log10(vlist *args)
  1171. {
  1172. return CALL_MATH_1(log10);
  1173. }
  1174. static vscalar *
  1175. builtin_max(vlist *args)
  1176. {
  1177. double max = vl_dget(args, 0);
  1178. vscalar *elt;
  1179. vl_foreach(elt, args)
  1180. max = V_MAX(max, vs_dget(elt));
  1181. return vs_dcreate(max);
  1182. }
  1183. static vscalar *
  1184. builtin_min(vlist *args)
  1185. {
  1186. double min = vl_dget(args, 0);
  1187. vscalar *elt;
  1188. vl_foreach(elt, args)
  1189. min = V_MIN(min, vs_dget(elt));
  1190. return vs_dcreate(min);
  1191. }
  1192. static vscalar *
  1193. builtin_pow(vlist *args)
  1194. {
  1195. return CALL_MATH_2(pow);
  1196. }
  1197. static vscalar *
  1198. builtin_sin(vlist *args)
  1199. {
  1200. return CALL_MATH_1(sin);
  1201. }
  1202. static vscalar *
  1203. builtin_sqrt(vlist *args)
  1204. {
  1205. return CALL_MATH_1(sqrt);
  1206. }
  1207. static vscalar *
  1208. builtin_tan(vlist *args)
  1209. {
  1210. return CALL_MATH_1(tan);
  1211. }