PageRenderTime 76ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/radiusd/rewrite.y

#
Happy | 6359 lines | 5568 code | 791 blank | 0 comment | 0 complexity | 746087d6a8925f92c839b6c7df700828 MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-SA-3.0, LGPL-3.0
  1. %{
  2. /* This file is part of GNU Radius.
  3. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  4. 2010, 2013 Free Software Foundation, Inc.
  5. Written by Sergey Poznyakoff
  6. GNU Radius is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3 of the License, or
  9. (at your option) any later version.
  10. GNU Radius is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with GNU Radius. If not, see <http://www.gnu.org/licenses/>. */
  16. #if defined(HAVE_CONFIG_H)
  17. # include <config.h>
  18. #endif
  19. #include <sys/types.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #include <errno.h>
  24. #include <radiusd.h>
  25. #include <setjmp.h>
  26. #include <rewrite.h>
  27. #ifdef USE_SERVER_GUILE
  28. # include <libguile.h>
  29. # include <radius/radscm.h>
  30. #endif
  31. typedef long RWSTYPE;
  32. #define RW_MIN(a,b) ((a)<(b)) ? (a) : (b)
  33. /*
  34. * Generalized list structure
  35. */
  36. typedef struct rw_list RWLIST;
  37. #define RWLIST(type) \
  38. type *next;\
  39. type *prev
  40. struct rw_list {
  41. RWLIST(RWLIST);
  42. };
  43. /*
  44. * Generalized object
  45. */
  46. typedef struct object_t OBJECT ;
  47. #define OBJ(type) \
  48. RWLIST(type);\
  49. type *alloc
  50. struct object_t {
  51. OBJ(OBJECT);
  52. };
  53. typedef struct {
  54. size_t size; /* Size of an element */
  55. void (*free)(); /* deallocator */
  56. OBJECT *alloc_list; /* list of allocated elements */
  57. } OBUCKET;
  58. /* ************************************************************
  59. * Basic data types
  60. */
  61. typedef int stkoff_t; /* Offset on stack */
  62. typedef unsigned int pctr_t; /* Program counter */
  63. #define RW_REG ('z'-'a'+1)
  64. typedef struct {
  65. RWSTYPE reg[RW_REG]; /* Registers */
  66. #define rA reg[0]
  67. char *sA; /* String accumulator */
  68. pctr_t pc; /* Program counter */
  69. RWSTYPE *stack; /* Stack+heap space */
  70. int stacksize; /* Size of stack */
  71. int st; /* Top of stack */
  72. int sb; /* Stack base */
  73. int ht; /* Top of heap */
  74. int nmatch;
  75. regmatch_t *pmatch;
  76. grad_request_t *req;
  77. jmp_buf jmp;
  78. } RWMACH;
  79. typedef void (*INSTR)(); /* program instruction */
  80. /* Compiled regular expression
  81. */
  82. typedef struct comp_regex COMP_REGEX;
  83. struct comp_regex {
  84. OBJ(COMP_REGEX);
  85. regex_t regex; /* compiled regex itself */
  86. int nmatch; /* number of \( ... \) groups */
  87. };
  88. /*
  89. * Binary Operations
  90. */
  91. typedef enum {
  92. Eq,
  93. Ne,
  94. Lt,
  95. Le,
  96. Gt,
  97. Ge,
  98. BAnd,
  99. BXor,
  100. BOr,
  101. And,
  102. Or,
  103. Shl,
  104. Shr,
  105. Add,
  106. Sub,
  107. Mul,
  108. Div,
  109. Rem,
  110. Max_opcode
  111. } Bopcode;
  112. /*
  113. * Unary operations
  114. */
  115. typedef enum {
  116. Neg,
  117. Not,
  118. Max_unary
  119. } Uopcode;
  120. /*
  121. * Matrix types
  122. */
  123. typedef enum {
  124. Generic,
  125. Nop,
  126. Enter,
  127. Leave,
  128. Stop,
  129. Constant,
  130. Matchref,
  131. Variable,
  132. Unary,
  133. Binary,
  134. Cond,
  135. Asgn,
  136. Match,
  137. Coercion,
  138. Expression,
  139. Return,
  140. Jump,
  141. Branch,
  142. Target,
  143. Call,
  144. Builtin,
  145. Pop,
  146. Pusha,
  147. Popa,
  148. Attr,
  149. Attr_asgn,
  150. Attr_check,
  151. Attr_delete,
  152. Max_mtxtype
  153. } Mtxtype;
  154. /*
  155. * Function parameter
  156. */
  157. typedef struct parm_t PARAMETER;
  158. struct parm_t {
  159. PARAMETER *prev; /* Previous parameter */
  160. PARAMETER *next; /* Next parameter */
  161. grad_data_type_t datatype; /* type */
  162. stkoff_t offset; /* Offset on stack */
  163. };
  164. /*
  165. * Local variable
  166. */
  167. typedef struct variable VAR;
  168. struct variable {
  169. OBJ(VAR);
  170. VAR *dcllink; /* Link to the next variable vithin the
  171. * same declaration
  172. */
  173. char *name; /* name of the variable */
  174. int level; /* nesting level */
  175. int offset; /* offset on stack */
  176. grad_data_type_t datatype; /* type */
  177. int constant; /* true if assigned a constant value */
  178. grad_datum_t datum; /* constant value itself */
  179. };
  180. /*
  181. * Function definition
  182. */
  183. typedef struct function_def {
  184. struct function_def *next;
  185. char *name; /* Function name */
  186. grad_data_type_t rettype; /* Return type */
  187. pctr_t entry; /* Code entry */
  188. COMP_REGEX *rx_list; /* List of compiled regexps */
  189. int nparm; /* Number of parameters */
  190. PARAMETER *parm; /* List of parameters */
  191. stkoff_t stack_alloc; /* required stack allocation */
  192. grad_locus_t loc; /* source location where the function
  193. * was declared
  194. */
  195. } FUNCTION;
  196. #define STACK_BASE 2
  197. /*
  198. * Built-in function
  199. */
  200. typedef struct {
  201. INSTR handler; /* Function itself */
  202. char *name; /* Function name */
  203. grad_data_type_t rettype; /* Return type */
  204. char *parms; /* coded parameter types */
  205. } builtin_t;
  206. /*
  207. * Operation matrices
  208. */
  209. typedef union mtx MTX;
  210. /*
  211. * All matrices contain the following common fields:
  212. * alloc- link to the previously allocated matrix.
  213. * It is used at the end of code generation
  214. * pass to free all allocated matrices.
  215. * next - link to the next matrix in the subexpression
  216. * prev - link to the previous matrix in the subexpression
  217. * Additionally, all expression matrices contain the field
  218. * `datatype' which contains the data type for this matrix.
  219. */
  220. #if defined(MAINTAINER_MODE)
  221. # define COMMON_MTX \
  222. OBJ(MTX);\
  223. int id;\
  224. grad_locus_t loc;\
  225. Mtxtype type;
  226. #else
  227. # define COMMON_MTX \
  228. OBJ(MTX);\
  229. grad_locus_t loc;\
  230. Mtxtype type;
  231. #endif
  232. #define COMMON_EXPR_MTX \
  233. COMMON_MTX\
  234. grad_data_type_t datatype;\
  235. MTX *uplink;\
  236. MTX *arglink;
  237. /*
  238. * Generic matrix: nothing special
  239. * Type: Generic
  240. */
  241. typedef struct {
  242. COMMON_EXPR_MTX
  243. } GEN_MTX;
  244. /*
  245. * Constant matrix
  246. * Type: Constant
  247. */
  248. typedef struct {
  249. COMMON_EXPR_MTX
  250. grad_datum_t datum; /* Constant value */
  251. } CONST_MTX;
  252. /*
  253. * Reference to a previous regexp: corresponds to a \N construct
  254. * Type: Matchref
  255. */
  256. typedef struct {
  257. COMMON_EXPR_MTX
  258. int num; /* Number of \( ... \) to be referenced */
  259. } MATCHREF_MTX;
  260. /*
  261. * Reference to a variable
  262. * Type: Variable
  263. */
  264. typedef struct {
  265. COMMON_EXPR_MTX
  266. VAR *var; /* Variable being referenced */
  267. } VAR_MTX;
  268. /*
  269. * Unary operation matrix
  270. * Type: Unary
  271. */
  272. typedef struct {
  273. COMMON_EXPR_MTX
  274. Uopcode opcode; /* Operation code */
  275. MTX *arg; /* Argument */
  276. } UN_MTX;
  277. /*
  278. * Binary operation matrix
  279. * Type: Binary
  280. */
  281. typedef struct {
  282. COMMON_EXPR_MTX
  283. Bopcode opcode; /* Operation code */
  284. MTX *arg[2]; /* Arguments */
  285. } BIN_MTX;
  286. /*
  287. * Assignment matrix
  288. * Type: Asgn
  289. */
  290. typedef struct {
  291. COMMON_EXPR_MTX
  292. VAR *lval; /* Lvalue */
  293. MTX *arg; /* Rvalue */
  294. } ASGN_MTX;
  295. /*
  296. * Conditional expression matrix
  297. * Type: Cond
  298. */
  299. typedef struct {
  300. COMMON_MTX
  301. MTX *expr; /* Conditional expression */
  302. MTX *if_true; /* Branch if true */
  303. MTX *if_false; /* Branch if false */
  304. } COND_MTX;
  305. /*
  306. * Regexp match
  307. * Type: Match
  308. */
  309. typedef struct {
  310. COMMON_EXPR_MTX
  311. int negated; /* Is the match negated ? */
  312. MTX *arg; /* Argument (lhs) */
  313. COMP_REGEX *rx; /* Regexp (rhs) */
  314. } MATCH_MTX;
  315. /*
  316. * Type coercion
  317. * Type: Coerce
  318. */
  319. typedef struct {
  320. COMMON_EXPR_MTX
  321. MTX *arg; /* Argument of the coercion */
  322. } COERCE_MTX;
  323. /*
  324. * Expression
  325. * Type: Expression
  326. */
  327. typedef struct {
  328. COMMON_EXPR_MTX
  329. MTX *expr;
  330. } EXPR_MTX;
  331. /*
  332. * Return from function
  333. * Type: Return
  334. */
  335. typedef struct {
  336. COMMON_EXPR_MTX
  337. MTX *expr; /* Return value */
  338. } RET_MTX;
  339. /*
  340. * Unconditional branch (jump)
  341. * Type: Jump
  342. */
  343. typedef struct {
  344. COMMON_MTX
  345. MTX *link; /* Link to the next jump matrix
  346. * (for break and continue matrices)
  347. */
  348. MTX *dest; /* Jump destination (usually a NOP matrix) */
  349. } JUMP_MTX;
  350. /*
  351. * Conditional branch
  352. * Type: Branch
  353. */
  354. typedef struct {
  355. COMMON_MTX
  356. int cond; /* Condition: 1 - equal, 0 - not equal */
  357. MTX *dest; /* Jump destination (usually a NOP matrix) */
  358. } BRANCH_MTX;
  359. /*
  360. * Stack frame matrix
  361. * Type: Enter, Leave
  362. */
  363. typedef struct {
  364. COMMON_MTX
  365. stkoff_t stacksize;/* Required stack size */
  366. } FRAME_MTX;
  367. /*
  368. * Jump target
  369. * Type: Target
  370. */
  371. typedef struct {
  372. COMMON_MTX
  373. pctr_t pc; /* Target's program counter */
  374. } TGT_MTX;
  375. /*
  376. * No-op matrix. It is always inserted at the branch destination
  377. * points. Its purpose is to keep a singly-linked list of jump
  378. * locations for fixing up jump statements.
  379. * Type: Nop
  380. */
  381. typedef struct {
  382. COMMON_MTX
  383. TGT_MTX *tgt; /* Target list */
  384. pctr_t pc; /* Program counter for backward
  385. references */
  386. } NOP_MTX;
  387. /*
  388. * Function call
  389. * Type: Call
  390. */
  391. typedef struct {
  392. COMMON_EXPR_MTX
  393. FUNCTION *fun; /* Called function */
  394. int nargs; /* Number of arguments */
  395. MTX *args; /* Arguments */
  396. } CALL_MTX;
  397. /*
  398. * Builtin function call
  399. * Type: Builtin
  400. */
  401. typedef struct {
  402. COMMON_EXPR_MTX
  403. INSTR fun; /* Handler function */
  404. int nargs; /* Number of arguments */
  405. MTX *args; /* Arguments */
  406. } BTIN_MTX;
  407. /*
  408. * Attribute matrix
  409. * Type: Attr, Attr_asgn, Attr_check
  410. */
  411. typedef struct {
  412. COMMON_EXPR_MTX
  413. int attrno; /* Attribute number */
  414. MTX *index; /* Index expression */
  415. MTX *rval; /* Rvalue */
  416. } ATTR_MTX;
  417. union mtx {
  418. GEN_MTX gen;
  419. NOP_MTX nop;
  420. FRAME_MTX frame;
  421. CONST_MTX cnst;
  422. MATCHREF_MTX ref;
  423. VAR_MTX var;
  424. UN_MTX un;
  425. BIN_MTX bin;
  426. COND_MTX cond;
  427. ASGN_MTX asgn;
  428. MATCH_MTX match;
  429. COERCE_MTX coerce;
  430. RET_MTX ret;
  431. JUMP_MTX jump;
  432. BRANCH_MTX branch;
  433. TGT_MTX tgt;
  434. CALL_MTX call;
  435. BTIN_MTX btin;
  436. ATTR_MTX attr;
  437. };
  438. /*
  439. * Stack frame
  440. */
  441. typedef struct frame_t FRAME;
  442. struct frame_t {
  443. OBJ(FRAME);
  444. int level; /* nesting level */
  445. stkoff_t stack_offset; /* offset in the stack */
  446. };
  447. /* *****************************************************************
  448. * Static data
  449. */
  450. /*
  451. * Stack Frame list
  452. */
  453. static OBUCKET frame_bkt = { sizeof(FRAME), NULL };
  454. static FRAME *frame_first, *frame_last;
  455. #define curframe frame_last
  456. static int errcnt; /* Number of errors detected */
  457. static FUNCTION *function; /* Function being compiled */
  458. static grad_symtab_t *rewrite_tab;/* Function table */
  459. static MTX *mtx_first, *mtx_last; /* Matrix list */
  460. static VAR *var_first, *var_last; /* Variable list */
  461. /*
  462. * Loops
  463. */
  464. typedef struct loop_t LOOP;
  465. struct loop_t {
  466. OBJ(LOOP);
  467. JUMP_MTX *lp_break;
  468. JUMP_MTX *lp_cont;
  469. };
  470. static OBUCKET loop_bkt = { sizeof(LOOP), NULL };
  471. static LOOP *loop_first, *loop_last;
  472. void loop_push(MTX *mtx);
  473. void loop_pop();
  474. void loop_fixup(JUMP_MTX *list, MTX *target);
  475. void loop_init();
  476. void loop_free_all();
  477. void loop_unwind_all();
  478. /*
  479. * Lexical analyzer stuff
  480. */
  481. static FILE *infile; /* Input file */
  482. static grad_locus_t locus; /* Input location */
  483. static char *inbuf; /* Input string */
  484. static char *curp; /* Current pointer */
  485. static int yyeof; /* rised when EOF is encountered */
  486. static struct obstack input_stk; /* Symbol stack */
  487. static grad_data_type_t return_type = Undefined;
  488. /* Data type of the topmost expression. */
  489. static int regcomp_flags = 0; /* Flags to be used with regcomps */
  490. #define regex_init() regcomp_flags = 0
  491. /* Runtime */
  492. static size_t rewrite_stack_size = 4096; /* Size of stack+heap */
  493. static RWSTYPE *runtime_stack;
  494. static RWMACH mach;
  495. /* Default domain for gettext functions. It is initialized to PACKAGE
  496. by default */
  497. static char *default_gettext_domain;
  498. /* ***************************************************************
  499. * Function declarations
  500. */
  501. /*
  502. * Lexical analyzer
  503. */
  504. static int yylex();
  505. static void yysync();
  506. static int yyerror(char *s);
  507. /*
  508. * Frames
  509. */
  510. static void frame_init();
  511. static void frame_push();
  512. static void frame_pop();
  513. static void frame_unwind_all();
  514. static void frame_free_all();
  515. /*
  516. * Variables
  517. */
  518. static void var_init();
  519. static VAR * var_alloc(grad_data_type_t type, char *name, int grow);
  520. static void var_unwind_level();
  521. static void var_unwind_all();
  522. static void var_type(grad_data_type_t type, VAR *var);
  523. static void var_free_all();
  524. static VAR *var_lookup(char *name);
  525. /*
  526. * Matrices
  527. */
  528. static void mtx_init();
  529. static void mtx_free_all();
  530. static void mtx_unwind_all();
  531. static MTX * mtx_cur();
  532. static MTX * mtx_nop();
  533. static MTX * mtx_jump();
  534. static MTX * mtx_frame(Mtxtype type, stkoff_t stksize);
  535. static MTX * mtx_stop();
  536. static MTX * mtx_pop();
  537. static MTX * mtx_return();
  538. static MTX * mtx_alloc(Mtxtype type);
  539. static MTX * mtx_const(grad_value_t *val);
  540. static MTX * mtx_ref(int num);
  541. static MTX * mtx_var(VAR *var);
  542. static MTX * mtx_asgn(VAR *var, MTX *arg);
  543. static MTX * mtx_bin(Bopcode opcode, MTX *arg1, MTX *arg2);
  544. static MTX * mtx_un(Uopcode opcode, MTX *arg);
  545. static MTX * mtx_match(int negated, MTX *mtx, COMP_REGEX *);
  546. static MTX * mtx_cond(MTX *cond, MTX *if_true, MTX *if_false);
  547. static MTX * mtx_coerce(grad_data_type_t type, MTX *arg);
  548. static MTX * mtx_call(FUNCTION *fun, MTX *args);
  549. static MTX * mtx_builtin(builtin_t *bin, MTX *args);
  550. static MTX * mtx_attr(grad_dict_attr_t *attr, MTX *index);
  551. static MTX * mtx_attr_asgn(grad_dict_attr_t *attr, MTX *index, MTX *rval);
  552. static MTX * mtx_attr_check(grad_dict_attr_t *attr, MTX *index);
  553. static MTX * mtx_attr_delete(grad_dict_attr_t *attr, MTX *index);
  554. static MTX * coerce(MTX *arg, grad_data_type_t type);
  555. /*
  556. * Regular expressions
  557. */
  558. static COMP_REGEX * rx_alloc(regex_t *regex, int nmatch);
  559. static void rx_free(COMP_REGEX *rx);
  560. static COMP_REGEX * compile_regexp(char *str);
  561. /*
  562. * Functions
  563. */
  564. static FUNCTION * function_install(FUNCTION *fun);
  565. static int function_free(FUNCTION *fun);
  566. static void function_delete();
  567. static void function_cleanup();
  568. /*
  569. * Built-in functions
  570. */
  571. static builtin_t * builtin_lookup(char *name);
  572. /*
  573. * Code optimizer and generator
  574. */
  575. static int optimize();
  576. static pctr_t codegen();
  577. static void code_init();
  578. static void code_check();
  579. /*
  580. * Auxiliary and debugging functions
  581. */
  582. static void debug_dump_code();
  583. static const char * datatype_str_nom(grad_data_type_t type);
  584. static const char * datatype_str_acc(grad_data_type_t type);
  585. static const char * datatype_str_abl(grad_data_type_t type);
  586. static grad_data_type_t attr_datatype(grad_dict_attr_t *);
  587. /*
  588. * Run-Time
  589. */
  590. static void gc();
  591. static void run(pctr_t pc);
  592. static int run_init(pctr_t pc, grad_request_t *req);
  593. static int rw_error(const char *msg);
  594. static int rw_error_free(char *msg);
  595. /* These used to lock/unlock access to rw_code array. Now this is
  596. not needed. However, I left the placeholders for a while... */
  597. #define rw_code_lock()
  598. #define rw_code_unlock()
  599. #define AVPLIST(m) ((m)->req ? (m)->req->avlist : NULL)
  600. static FUNCTION fmain;
  601. %}
  602. %union {
  603. int number;
  604. int type;
  605. VAR *var;
  606. MTX *mtx;
  607. FUNCTION *fun;
  608. builtin_t *btin;
  609. grad_dict_attr_t *attr;
  610. struct {
  611. MTX *arg_first;
  612. MTX *arg_last;
  613. } arg;
  614. struct {
  615. int nmatch;
  616. regex_t regex;
  617. } rx;
  618. char *string;
  619. };
  620. %token <type> TYPE
  621. %token IF ELSE RETURN WHILE FOR DO BREAK CONTINUE DELETE
  622. %token <string> STRING IDENT
  623. %token <number> NUMBER REFERENCE
  624. %token <var> VARIABLE
  625. %token <fun> FUN
  626. %token <btin> BUILTIN
  627. %token <attr> ATTR
  628. %token BOGUS
  629. %type <arg> arglist
  630. %type <mtx> stmt expr list cond else while do arg args
  631. %type <var> varlist parmlist parm dclparm
  632. %right '='
  633. %left OR
  634. %left AND
  635. %nonassoc MT NM
  636. %left '|'
  637. %left '^'
  638. %left '&'
  639. %left EQ NE
  640. %left LT LE GT GE
  641. %left SHL SHR
  642. %left '+' '-'
  643. %left '*' '/' '%'
  644. %left UMINUS NOT TYPECAST
  645. %%
  646. program : input
  647. {
  648. var_free_all();
  649. loop_free_all();
  650. frame_free_all();
  651. mtx_free_all();
  652. }
  653. ;
  654. input : dcllist
  655. {
  656. return_type = Undefined;
  657. }
  658. | expr
  659. {
  660. if (errcnt) {
  661. YYERROR;
  662. }
  663. mtx_return($1);
  664. memset(&fmain, 0, sizeof(fmain));
  665. fmain.name = "main";
  666. fmain.rettype = return_type = $1->gen.datatype;
  667. function = &fmain;
  668. if (optimize() == 0) {
  669. codegen();
  670. if (errcnt) {
  671. YYERROR;
  672. }
  673. }
  674. }
  675. ;
  676. dcllist : decl
  677. | dcllist decl
  678. | dcllist error
  679. {
  680. /* Roll back all changes done so far */
  681. var_unwind_all();
  682. loop_unwind_all();
  683. frame_unwind_all();
  684. mtx_unwind_all();
  685. function_delete();
  686. /* Synchronize input after error */
  687. yysync();
  688. /* Clear input and error condition */
  689. yyclearin;
  690. yyerrok;
  691. errcnt = 0;
  692. }
  693. ;
  694. decl : fundecl begin list end
  695. {
  696. if (errcnt) {
  697. function_delete();
  698. YYERROR;
  699. }
  700. if (optimize() == 0) {
  701. codegen();
  702. if (errcnt) {
  703. function_delete();
  704. YYERROR;
  705. }
  706. } else {
  707. function_delete();
  708. }
  709. /* clean up things */
  710. var_unwind_all();
  711. loop_unwind_all();
  712. frame_unwind_all();
  713. mtx_unwind_all();
  714. function_cleanup();
  715. }
  716. ;
  717. fundecl : TYPE IDENT dclparm
  718. {
  719. VAR *var;
  720. PARAMETER *last, *parm;
  721. FUNCTION f;
  722. if (errcnt)
  723. YYERROR;
  724. memset(&f, 0, sizeof(f));
  725. f.name = $2;
  726. f.rettype = $1;
  727. f.entry = 0;
  728. f.loc = locus;
  729. f.nparm = 0;
  730. f.parm = NULL;
  731. /* Count number of parameters */
  732. for (var = $3; var; var = var->next)
  733. f.nparm++;
  734. f.parm = last = NULL;
  735. for (var = $3; var; var = var->next) {
  736. parm = grad_emalloc(sizeof(*parm));
  737. parm->datatype = var->datatype;
  738. var->offset = -(STACK_BASE+
  739. f.nparm - var->offset);
  740. parm->offset = var->offset;
  741. parm->prev = last;
  742. parm->next = NULL;
  743. if (f.parm == NULL)
  744. f.parm = parm;
  745. else
  746. last->next = parm;
  747. last = parm;
  748. }
  749. function = function_install(&f);
  750. }
  751. | TYPE FUN dclparm
  752. {
  753. grad_log_loc(GRAD_LOG_ERR, &locus,
  754. _("redefinition of function `%s'"), $2->name);
  755. grad_log_loc(GRAD_LOG_ERR, &$2->loc,
  756. _("previously defined here"));
  757. errcnt++;
  758. YYERROR;
  759. }
  760. ;
  761. begin : obrace
  762. | obrace autodcl
  763. ;
  764. end : cbrace
  765. ;
  766. obrace : '{'
  767. {
  768. frame_push();
  769. }
  770. ;
  771. cbrace : '}'
  772. {
  773. var_unwind_level();
  774. frame_pop();
  775. }
  776. ;
  777. /*
  778. * Automatic variables
  779. */
  780. autodcl : autovar
  781. | autodcl autovar
  782. ;
  783. autovar : TYPE varlist ';'
  784. {
  785. var_type($1, $2);
  786. }
  787. ;
  788. varlist : IDENT
  789. {
  790. $$ = var_alloc(Undefined, $1, +1);
  791. $$->dcllink = NULL;
  792. }
  793. | varlist ',' IDENT
  794. {
  795. VAR *var = var_alloc(Undefined, $3, +1);
  796. var->dcllink = $1;
  797. $$ = var;
  798. }
  799. ;
  800. /*
  801. * Function Parameters
  802. */
  803. dclparm : '(' ')'
  804. {
  805. $$ = NULL;
  806. }
  807. | '(' parmlist ')'
  808. {
  809. $$ = $2;
  810. }
  811. ;
  812. parmlist: parm
  813. {
  814. /*FIXME*/
  815. /*$$->dcllink = NULL;*/
  816. }
  817. | parmlist ',' parm
  818. {
  819. /*$1->dcllink = $3;*/
  820. $$ = $1;
  821. }
  822. ;
  823. parm : TYPE IDENT
  824. {
  825. $$ = var_alloc($1, $2, +1);
  826. }
  827. ;
  828. /* Argument lists
  829. */
  830. args : /* empty */
  831. {
  832. $$ = NULL;
  833. }
  834. | arglist
  835. {
  836. $$ = $1.arg_first;
  837. }
  838. ;
  839. arglist : arg
  840. {
  841. $1->gen.arglink = NULL;
  842. $$.arg_first = $$.arg_last = $1;
  843. }
  844. | arglist ',' arg
  845. {
  846. $1.arg_last->gen.arglink = $3;
  847. $1.arg_last = $3;
  848. $$ = $1;
  849. }
  850. ;
  851. arg : expr
  852. ;
  853. /*
  854. * Statement list and individual statements
  855. */
  856. list : stmt
  857. | list stmt
  858. ;
  859. stmt : begin list end
  860. {
  861. $$ = $2;
  862. }
  863. | expr ';'
  864. {
  865. mtx_stop();
  866. mtx_pop();
  867. }
  868. | IF cond stmt
  869. {
  870. $2->cond.if_false = mtx_nop();
  871. $$ = mtx_cur();
  872. }
  873. | IF cond stmt else stmt
  874. {
  875. mtx_stop();
  876. $2->cond.if_false = $4;
  877. $4->nop.prev->jump.dest = mtx_nop();
  878. $$ = mtx_cur();
  879. }
  880. | RETURN expr ';'
  881. {
  882. /*mtx_stop();*/
  883. $$ = mtx_return($2);
  884. }
  885. | while cond stmt
  886. {
  887. MTX *mtx;
  888. mtx_stop();
  889. mtx = mtx_jump();
  890. mtx->jump.dest = $1;
  891. $2->cond.if_false = mtx_nop();
  892. $$ = mtx_cur();
  893. /* Fixup possible breaks */
  894. loop_fixup(loop_last->lp_break, $$);
  895. /* Fixup possible continues */
  896. loop_fixup(loop_last->lp_cont, $1);
  897. loop_pop();
  898. }
  899. | do stmt { $<mtx>$ = mtx_nop(); } WHILE cond ';'
  900. {
  901. /* Default cond rule sets if_true to the next NOP matrix
  902. * Invert this behaviour.
  903. */
  904. $5->cond.if_false = $5->cond.if_true;
  905. $5->cond.if_true = $1;
  906. $$ = mtx_cur();
  907. /* Fixup possible breaks */
  908. loop_fixup(loop_last->lp_break, $$);
  909. /* Fixup possible continues */
  910. loop_fixup(loop_last->lp_cont, $<mtx>3);
  911. loop_pop();
  912. }
  913. /* ***********************
  914. For future use:
  915. | FOR '(' for_expr for_expr for_expr ')' stmt
  916. *********************** */
  917. | BREAK ';'
  918. {
  919. if (!loop_last) {
  920. grad_log_loc(GRAD_LOG_ERR, &locus,
  921. "%s",
  922. _("nothing to break from"));
  923. errcnt++;
  924. YYERROR;
  925. }
  926. $$ = mtx_jump();
  927. $$->jump.link = (MTX*)loop_last->lp_break;
  928. loop_last->lp_break = (JUMP_MTX*)$$;
  929. }
  930. | CONTINUE ';'
  931. {
  932. if (!loop_last) {
  933. grad_log_loc(GRAD_LOG_ERR, &locus,
  934. "%s",
  935. _("nothing to continue"));
  936. errcnt++;
  937. YYERROR;
  938. }
  939. $$ = mtx_jump();
  940. $$->jump.link = (MTX*)loop_last->lp_cont;
  941. loop_last->lp_cont = (JUMP_MTX*)$$;
  942. }
  943. | DELETE ATTR ';'
  944. {
  945. $$ = mtx_attr_delete($2, NULL);
  946. }
  947. | DELETE ATTR '(' expr ')' ';'
  948. {
  949. $$ = mtx_attr_delete($2, $4);
  950. }
  951. ;
  952. while : WHILE
  953. {
  954. $$ = mtx_nop();
  955. loop_push($$);
  956. }
  957. ;
  958. do : DO
  959. {
  960. $$ = mtx_nop();
  961. loop_push($$);
  962. }
  963. ;
  964. else : ELSE
  965. {
  966. mtx_stop();
  967. mtx_jump();
  968. $$ = mtx_nop();
  969. }
  970. ;
  971. cond : '(' expr ')'
  972. {
  973. mtx_stop();
  974. $$ = mtx_cond($2, NULL, NULL);
  975. $$->cond.if_true = mtx_nop();
  976. }
  977. ;
  978. /*
  979. * Expressions
  980. */
  981. expr : NUMBER
  982. {
  983. grad_value_t val;
  984. val.type = Integer;
  985. val.datum.ival = $1;
  986. $$ = mtx_const(&val);
  987. }
  988. | STRING
  989. {
  990. grad_value_t val;
  991. val.type = String;
  992. val.datum.sval.size = strlen($1);
  993. val.datum.sval.data = $1;
  994. $$ = mtx_const(&val);
  995. }
  996. | REFERENCE
  997. {
  998. $$ = mtx_ref($1);
  999. }
  1000. | VARIABLE
  1001. {
  1002. $$ = mtx_var($1);
  1003. }
  1004. | IDENT
  1005. {
  1006. grad_log_loc(GRAD_LOG_ERR, &locus, _("undefined variable: %s"), $1);
  1007. errcnt++;
  1008. YYERROR;
  1009. }
  1010. | VARIABLE '=' expr
  1011. {
  1012. $$ = mtx_asgn($1, $3);
  1013. }
  1014. | ATTR
  1015. {
  1016. $$ = mtx_attr($1, NULL);
  1017. }
  1018. | ATTR '(' expr ')'
  1019. {
  1020. $$ = mtx_attr($1, $3);
  1021. }
  1022. | '*' ATTR
  1023. {
  1024. $$ = mtx_attr_check($2, NULL);
  1025. }
  1026. | '*' ATTR '(' expr ')'
  1027. {
  1028. $$ = mtx_attr_check($2, $4);
  1029. }
  1030. | ATTR '=' expr
  1031. {
  1032. $$ = mtx_attr_asgn($1, NULL, $3);
  1033. }
  1034. | ATTR '(' expr ')' '=' expr
  1035. {
  1036. $$ = mtx_attr_asgn($1, $3, $6);
  1037. }
  1038. | FUN '(' args ')'
  1039. {
  1040. $$ = mtx_call($1, $3);
  1041. }
  1042. | BUILTIN '(' args ')'
  1043. {
  1044. $$ = mtx_builtin($1, $3);
  1045. }
  1046. | expr '+' expr
  1047. {
  1048. $$ = mtx_bin(Add, $1, $3);
  1049. }
  1050. | expr '-' expr
  1051. {
  1052. $$ = mtx_bin(Sub, $1, $3);
  1053. }
  1054. | expr '*' expr
  1055. {
  1056. $$ = mtx_bin(Mul, $1, $3);
  1057. }
  1058. | expr '/' expr
  1059. {
  1060. $$ = mtx_bin(Div, $1, $3);
  1061. }
  1062. | expr '%' expr
  1063. {
  1064. $$ = mtx_bin(Rem, $1, $3);
  1065. }
  1066. | expr '|' expr
  1067. {
  1068. $$ = mtx_bin(BOr, $1, $3);
  1069. }
  1070. | expr '&' expr
  1071. {
  1072. $$ = mtx_bin(BAnd, $1, $3);
  1073. }
  1074. | expr '^' expr
  1075. {
  1076. $$ = mtx_bin(BXor, $1, $3);
  1077. }
  1078. | expr SHL expr
  1079. {
  1080. $$ = mtx_bin(Shl, $1, $3);
  1081. }
  1082. | expr SHR expr
  1083. {
  1084. $$ = mtx_bin(Shr, $1, $3);
  1085. }
  1086. | expr AND expr
  1087. {
  1088. $$ = mtx_bin(And, $1, $3);
  1089. }
  1090. | expr OR expr
  1091. {
  1092. $$ = mtx_bin(Or, $1, $3);
  1093. }
  1094. | '-' expr %prec UMINUS
  1095. {
  1096. $$ = mtx_un(Neg, $2);
  1097. }
  1098. | '+' expr %prec UMINUS
  1099. {
  1100. $$ = $2;
  1101. }
  1102. | NOT expr
  1103. {
  1104. $$ = mtx_un(Not, $2);
  1105. }
  1106. | '(' expr ')'
  1107. {
  1108. $$ = $2;
  1109. }
  1110. | '(' TYPE ')' expr %prec TYPECAST
  1111. {
  1112. $$ = mtx_coerce($2, $4);
  1113. }
  1114. | expr EQ expr
  1115. {
  1116. $$ = mtx_bin(Eq, $1, $3);
  1117. }
  1118. | expr NE expr
  1119. {
  1120. $$ = mtx_bin(Ne, $1, $3);
  1121. }
  1122. | expr LT expr
  1123. {
  1124. $$ = mtx_bin(Lt, $1, $3);
  1125. }
  1126. | expr LE expr
  1127. {
  1128. $$ = mtx_bin(Le, $1, $3);
  1129. }
  1130. | expr GT expr
  1131. {
  1132. $$ = mtx_bin(Gt, $1, $3);
  1133. }
  1134. | expr GE expr
  1135. {
  1136. $$ = mtx_bin(Ge, $1, $3);
  1137. }
  1138. | expr MT STRING
  1139. {
  1140. COMP_REGEX *rx;
  1141. if ((rx = compile_regexp($3)) == NULL) {
  1142. errcnt++;
  1143. YYERROR;
  1144. }
  1145. $$ = mtx_match(0, $1, rx);
  1146. }
  1147. | expr NM STRING
  1148. {
  1149. COMP_REGEX *rx;
  1150. if ((rx = compile_regexp($3)) == NULL) {
  1151. errcnt++;
  1152. YYERROR;
  1153. }
  1154. $$ = mtx_match(1, $1, rx);
  1155. }
  1156. ;
  1157. %%
  1158. int
  1159. yyerror(char *s)
  1160. {
  1161. grad_log_loc(GRAD_LOG_ERR, &locus, "%s", s);
  1162. errcnt++;
  1163. return 0;
  1164. }
  1165. /* **************************************************************************
  1166. * Interface functions
  1167. */
  1168. int
  1169. parse_rewrite(char *path)
  1170. {
  1171. locus.file = path;
  1172. infile = fopen(locus.file, "r");
  1173. if (!infile) {
  1174. if (errno != ENOENT) {
  1175. grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
  1176. _("can't open file `%s'"),
  1177. locus.file);
  1178. return -1;
  1179. }
  1180. return -2;
  1181. }
  1182. GRAD_DEBUG1(1, "Loading file %s", locus.file);
  1183. rw_code_lock();
  1184. yyeof = 0;
  1185. locus.line = 1;
  1186. errcnt = 0;
  1187. regex_init();
  1188. obstack_init(&input_stk);
  1189. mtx_init();
  1190. var_init();
  1191. loop_init();
  1192. frame_init();
  1193. frame_push();
  1194. yyparse();
  1195. var_free_all();
  1196. frame_free_all();
  1197. mtx_free_all();
  1198. fclose(infile);
  1199. obstack_free(&input_stk, NULL);
  1200. rw_code_unlock();
  1201. return errcnt;
  1202. }
  1203. static int
  1204. parse_rewrite_string(char *str)
  1205. {
  1206. rw_code_lock();
  1207. code_check();
  1208. yyeof = 0;
  1209. locus.file = "<string>";
  1210. locus.line = 1;
  1211. errcnt = 0;
  1212. regex_init();
  1213. obstack_init(&input_stk);
  1214. mtx_init();
  1215. var_init();
  1216. loop_init();
  1217. frame_init();
  1218. frame_push();
  1219. if (GRAD_DEBUG_LEVEL(50))
  1220. yydebug++;
  1221. infile = 0;
  1222. inbuf = curp = str;
  1223. yyparse();
  1224. #if defined(MAINTAINER_MODE)
  1225. if (GRAD_DEBUG_LEVEL(100))
  1226. debug_dump_code();
  1227. #endif
  1228. var_free_all();
  1229. frame_free_all();
  1230. mtx_free_all();
  1231. obstack_free(&input_stk, NULL);
  1232. rw_code_unlock();
  1233. return errcnt;
  1234. }
  1235. /* **************************************************************************
  1236. * Lexical analyzer stuff: too simple to be written in lex.
  1237. */
  1238. static int
  1239. unput(int c)
  1240. {
  1241. if (!c)
  1242. return 0;
  1243. if (infile)
  1244. ungetc(c, infile);
  1245. else if (curp > inbuf)
  1246. *--curp = c;
  1247. return c;
  1248. }
  1249. static int
  1250. input()
  1251. {
  1252. if (yyeof)
  1253. yychar = 0;
  1254. else if (infile) {
  1255. if ((yychar = getc(infile)) <= 0) {
  1256. yyeof++;
  1257. yychar = 0;
  1258. }
  1259. } else if (curp) {
  1260. yychar = *curp++;
  1261. if (!yychar)
  1262. yyeof++;
  1263. }
  1264. return yychar;
  1265. }
  1266. static int rw_backslash();
  1267. static int c2d(int c);
  1268. static int read_number();
  1269. static int read_num(int n, int base);
  1270. static char *read_string();
  1271. static char *read_ident(int c);
  1272. static char *read_to_delim(int c);
  1273. static int skip_to_nl();
  1274. static int c_comment();
  1275. /*
  1276. * Convert a character to digit. Only octal, decimal and hex digits are
  1277. * allowed. If any other character is input, c2d() returns 100, which is
  1278. * greater than any number base allowed.
  1279. */
  1280. int
  1281. c2d(int c)
  1282. {
  1283. switch (c) {
  1284. case '0':
  1285. case '1':
  1286. case '2':
  1287. case '3':
  1288. case '4':
  1289. case '5':
  1290. case '6':
  1291. case '7':
  1292. case '8':
  1293. case '9':
  1294. return c - '0';
  1295. case 'A':
  1296. case 'B':
  1297. case 'C':
  1298. case 'D':
  1299. case 'E':
  1300. case 'F':
  1301. return c - 'A' + 16;
  1302. case 'a':
  1303. case 'b':
  1304. case 'c':
  1305. case 'd':
  1306. case 'e':
  1307. case 'f':
  1308. return c - 'a' + 10;
  1309. }
  1310. return 100;
  1311. }
  1312. /*
  1313. * Read a number. Usual C conventions apply.
  1314. */
  1315. int
  1316. read_number()
  1317. {
  1318. int c;
  1319. int base;
  1320. int res;
  1321. c = yychar;
  1322. if (c == '0') {
  1323. if (input() == 'x' || yychar == 'X') {
  1324. base = 16;
  1325. } else {
  1326. base = 8;
  1327. unput(yychar);
  1328. }
  1329. } else
  1330. base = 10;
  1331. res = read_num(c2d(c), base);
  1332. if (base == 10 && yychar == '.') {
  1333. int n;
  1334. for (n = 0; n < 3 && yychar == '.'; n++) {
  1335. int val;
  1336. input();
  1337. val = read_num(0, base);
  1338. res = (res << 8) + val;
  1339. }
  1340. if (n != 3)
  1341. res <<= 8 * (3-n);
  1342. }
  1343. return res;
  1344. }
  1345. int
  1346. read_num(int n, int base)
  1347. {
  1348. int d;
  1349. while (input() && (d = c2d(yychar)) < 16)
  1350. n = n*base + d;
  1351. unput(yychar);
  1352. return n;
  1353. }
  1354. int
  1355. rw_backslash()
  1356. {
  1357. switch (input()) {
  1358. case '\\':
  1359. return '\\';
  1360. case 'a':
  1361. return '\a';
  1362. case 'b':
  1363. return '\b';
  1364. case 'f':
  1365. return '\f';
  1366. case 'n':
  1367. return '\n';
  1368. case 'r':
  1369. return '\r';
  1370. case 't':
  1371. return '\t';
  1372. case 'e':
  1373. return '\033';
  1374. case '0':
  1375. return read_number();
  1376. case 'x':
  1377. case 'X':
  1378. return read_num(0, 16);
  1379. case '(':
  1380. case ')':
  1381. /* Preserve regular expressions */
  1382. unput(yychar);
  1383. yychar = '\\';
  1384. }
  1385. return yychar;
  1386. }
  1387. /*
  1388. * Read a string up to the closing doublequote
  1389. */
  1390. char *
  1391. read_string()
  1392. {
  1393. while (input() && yychar != '"') {
  1394. if (yychar == '\\')
  1395. yychar = rw_backslash();
  1396. obstack_1grow(&input_stk, yychar);
  1397. }
  1398. obstack_1grow(&input_stk, 0);
  1399. return obstack_finish(&input_stk);
  1400. }
  1401. /*
  1402. * Read everything up to the given delimiter
  1403. */
  1404. char *
  1405. read_to_delim(int c)
  1406. {
  1407. while (input() && yychar != c)
  1408. obstack_1grow(&input_stk, yychar);
  1409. obstack_1grow(&input_stk, 0);
  1410. return obstack_finish(&input_stk);
  1411. }
  1412. /*
  1413. * Is `c' a part of the word?
  1414. */
  1415. #define isword(c) (isalnum(c) || c == '_' || c == '$')
  1416. /*
  1417. * Is `c' a whitespace character?
  1418. */
  1419. #define isws(c) ((c) == ' ' || (c) == '\t')
  1420. /*
  1421. * Read identifier
  1422. */
  1423. char *
  1424. read_ident(int c)
  1425. {
  1426. obstack_1grow(&input_stk, c);
  1427. while (input() && isword(yychar))
  1428. obstack_1grow(&input_stk, yychar);
  1429. obstack_1grow(&input_stk, 0);
  1430. unput(yychar);
  1431. return obstack_finish(&input_stk);
  1432. }
  1433. /*
  1434. * Skip input up to the next newline
  1435. */
  1436. int
  1437. skip_to_nl()
  1438. {
  1439. while (input() && yychar != '\n')
  1440. ;
  1441. return unput(yychar);
  1442. }
  1443. /*
  1444. * Skip a C-style comment
  1445. */
  1446. int
  1447. c_comment()
  1448. {
  1449. if (yychar != '/')
  1450. return 0;
  1451. if (input() == '*') {
  1452. size_t keep_line = locus.line;
  1453. do {
  1454. while (input() != '*') {
  1455. if (yychar == 0) {
  1456. grad_log_loc(GRAD_LOG_ERR, &locus,
  1457. _("unexpected EOF in comment started at line %lu"),
  1458. (unsigned long) keep_line);
  1459. return 0;
  1460. } else if (yychar == '\n')
  1461. locus.line++;
  1462. }
  1463. } while (input() != '/');
  1464. return 1;
  1465. }
  1466. unput(yychar);
  1467. yychar = '/';
  1468. return 0;
  1469. }
  1470. /* Pragmatic comments */
  1471. enum pragma_handler_phase {
  1472. pragma_begin,
  1473. pragma_cont,
  1474. pragma_error,
  1475. pragma_end
  1476. };
  1477. typedef int (*pragma_handler_fp) (enum pragma_handler_phase);
  1478. static int
  1479. regex_pragma (enum pragma_handler_phase phase)
  1480. {
  1481. int disable = 0;
  1482. int bit;
  1483. char *s;
  1484. static int regexp_accum;
  1485. switch (phase) {
  1486. case pragma_begin:
  1487. regexp_accum = 0;
  1488. return 0;
  1489. case pragma_end:
  1490. regcomp_flags = regexp_accum;
  1491. return 0;
  1492. case pragma_error:
  1493. return 0;
  1494. case pragma_cont:
  1495. break;
  1496. }
  1497. switch (yychar) {
  1498. case '+':
  1499. disable = 0;
  1500. input();
  1501. break;
  1502. case '-':
  1503. disable = 1;
  1504. input();
  1505. break;
  1506. }
  1507. if (!isword(yychar)) {
  1508. grad_log_loc(GRAD_LOG_ERR, &locus, _("Malformed pragma"));
  1509. return 1;
  1510. }
  1511. s = read_ident(yychar);
  1512. if (strcmp (s, "extended") == 0)
  1513. bit = REG_EXTENDED;
  1514. else if (strcmp (s, "icase") == 0)
  1515. bit = REG_ICASE;
  1516. else if (strcmp (s, "newline") == 0)
  1517. bit = REG_NEWLINE;
  1518. else {
  1519. grad_log_loc(GRAD_LOG_ERR, &locus,
  1520. _("Unknown regexp flag: %s"), s);
  1521. return 1;
  1522. }
  1523. if (disable)
  1524. regexp_accum &= ~bit;
  1525. else
  1526. regexp_accum |= bit;
  1527. return 0;
  1528. }
  1529. static pragma_handler_fp
  1530. find_pragma_handler(char *s)
  1531. {
  1532. if (strcmp(s, "regex") == 0)
  1533. return regex_pragma;
  1534. return NULL;
  1535. }
  1536. static void
  1537. handle_pragma()
  1538. {
  1539. int rc;
  1540. pragma_handler_fp pragma_handler;
  1541. while (input() && isws(yychar))
  1542. ;
  1543. if (yychar == 0)
  1544. return;
  1545. pragma_handler = find_pragma_handler (read_ident(yychar));
  1546. if (pragma_handler) {
  1547. pragma_handler(pragma_begin);
  1548. do {
  1549. while (input() && isws(yychar))
  1550. ;
  1551. if (yychar == 0 || yychar == '\n')
  1552. break;
  1553. rc = pragma_handler(pragma_cont);
  1554. } while (rc == 0 && yychar != '\n' && yychar != 0);
  1555. pragma_handler(rc ? pragma_error : pragma_end);
  1556. }
  1557. }
  1558. /* Parse a 'sharp' (single-line) comment */
  1559. void
  1560. sharp_comment()
  1561. {
  1562. while (input() && isws(yychar))
  1563. ;
  1564. if (yychar == 0)
  1565. return;
  1566. else if (yychar == '\n') {
  1567. locus.line++;
  1568. return;
  1569. } else if (isword(yychar)) {
  1570. if (strcmp(read_ident(yychar), "pragma") == 0)
  1571. handle_pragma();
  1572. }
  1573. skip_to_nl();
  1574. }
  1575. #if defined(MAINTAINER_MODE)
  1576. # define DEBUG_LEX1(s) if (GRAD_DEBUG_LEVEL(60)) printf("yylex: " s "\n")
  1577. # define DEBUG_LEX2(s,v) if (GRAD_DEBUG_LEVEL(60)) printf("yylex: " s "\n", v)
  1578. #else
  1579. # define DEBUG_LEX1(s)
  1580. # define DEBUG_LEX2(s,v)
  1581. #endif
  1582. static grad_keyword_t rw_kw[] = {
  1583. { "if", IF },
  1584. { "else", ELSE },
  1585. { "return", RETURN },
  1586. { "for", FOR },
  1587. { "do", DO },
  1588. { "while", WHILE },
  1589. { "break", BREAK },
  1590. { "continue", CONTINUE },
  1591. { "delete", DELETE },
  1592. { NULL }
  1593. };
  1594. int
  1595. yylex()
  1596. {
  1597. int nl;
  1598. int c;
  1599. VAR *var;
  1600. FUNCTION *fun;
  1601. builtin_t *btin;
  1602. /* Skip whitespace and comment lines */
  1603. do {
  1604. nl = 0;
  1605. while (input() && isspace(yychar))
  1606. if (yychar == '\n')
  1607. locus.line++;
  1608. if (!yychar)
  1609. return 0;
  1610. if (yychar == '#') {
  1611. sharp_comment();
  1612. nl = 1;
  1613. }
  1614. } while (nl || c_comment());
  1615. /*
  1616. * A regexp reference
  1617. */
  1618. if (yychar == '\\') {
  1619. input();
  1620. yylval.number = read_number();
  1621. DEBUG_LEX2("REFERENCE %d", yylval.number);
  1622. return REFERENCE;
  1623. }
  1624. /*
  1625. * A character
  1626. */
  1627. if (yychar == '\'') {
  1628. if (input() == '\\')
  1629. c = rw_backslash();
  1630. else
  1631. c = yychar;
  1632. if (input() != '\'') {
  1633. grad_log_loc(GRAD_LOG_ERR, &locus,
  1634. "%s",
  1635. _("unterminated character constant"));
  1636. errcnt++;
  1637. }
  1638. yylval.number = c;
  1639. DEBUG_LEX2("CHAR %d", c);
  1640. return NUMBER;
  1641. }
  1642. /*
  1643. * A number
  1644. */
  1645. if (isdigit(yychar)) {
  1646. yylval.number = read_number();
  1647. DEBUG_LEX2("NUMBER %d", yylval.number);
  1648. return NUMBER;
  1649. }
  1650. /*
  1651. * Quoted string
  1652. */
  1653. if (yychar == '"') {
  1654. yylval.string = read_string();
  1655. DEBUG_LEX2("STRING %s", yylval.string);
  1656. return STRING;
  1657. }
  1658. /* A/V pair reference.
  1659. We do not allow %<number> sequences, since it would result
  1660. in conflict with binary '%' operator.
  1661. Thanks to Clement Gerouville for noticing. */
  1662. if (yychar == '%') {
  1663. grad_dict_attr_t *attr = 0;
  1664. char *attr_name;
  1665. input();
  1666. if (yychar == '[' || yychar == '{') {
  1667. attr_name = read_to_delim(yychar == '[' ? ']' : '}');
  1668. attr = grad_attr_name_to_dict(attr_name);
  1669. } else {
  1670. unput(yychar);
  1671. return '%';
  1672. }
  1673. if (!attr) {
  1674. grad_log_loc(GRAD_LOG_ERR, &locus,
  1675. _("unknown attribute `%s'"),
  1676. attr_name);
  1677. errcnt++;
  1678. return BOGUS;
  1679. }
  1680. yylval.attr = attr;
  1681. DEBUG_LEX2("ATTR: %s", attr->name);
  1682. return ATTR;
  1683. }
  1684. /*
  1685. * Data type or identifier
  1686. */
  1687. if (isword(yychar)) {
  1688. yylval.string = read_ident(yychar);
  1689. if (strcmp(yylval.string, "integer") == 0) {
  1690. DEBUG_LEX1("TYPE(Integer)");
  1691. yylval.type = Integer;
  1692. return TYPE;
  1693. } else if (strcmp(yylval.string, "string") == 0) {
  1694. DEBUG_LEX1("TYPE(String)");
  1695. yylval.type = String;
  1696. return TYPE;
  1697. }
  1698. if ((c = grad_xlat_keyword(rw_kw, yylval.string, 0)) != 0) {
  1699. DEBUG_LEX2("KW: %s", yylval.string);
  1700. return c;
  1701. }
  1702. if (var = var_lookup(yylval.string)) {
  1703. DEBUG_LEX2("VARIABLE: %s", yylval.string);
  1704. yylval.var = var;
  1705. return VARIABLE;
  1706. }
  1707. if (fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, yylval.string)) {
  1708. DEBUG_LEX2("FUN %s", yylval.string);
  1709. yylval.fun = fun;
  1710. return FUN;
  1711. }
  1712. if (btin = builtin_lookup(yylval.string)) {
  1713. DEBUG_LEX2("BUILTIN %s", yylval.string);
  1714. yylval.btin = btin;
  1715. return BUILTIN;
  1716. }
  1717. DEBUG_LEX2("IDENT: %s", yylval.string);
  1718. return IDENT;
  1719. }
  1720. /*
  1721. * Boolean expressions
  1722. */
  1723. if (yychar == '&' || yychar == '|') {
  1724. int c = yychar;
  1725. if (input() == c) {
  1726. DEBUG_LEX2("%s", yychar == '&' ? "AND" : "OR");
  1727. return yychar == '&' ? AND : OR;
  1728. }
  1729. unput(yychar);
  1730. DEBUG_LEX2("%c", c);
  1731. return c;
  1732. }
  1733. /*
  1734. * Comparison operator
  1735. */
  1736. if (strchr("<>=!", yychar)) {
  1737. int c = yychar;
  1738. if (input() == '=') {
  1739. switch (c) {
  1740. case '<':
  1741. DEBUG_LEX1("LE");
  1742. return LE;
  1743. case '>':
  1744. DEBUG_LEX1("GE");
  1745. return GE;
  1746. case '=':
  1747. DEBUG_LEX1("EQ");
  1748. return EQ;
  1749. case '!':
  1750. DEBUG_LEX1("NE");
  1751. return NE;
  1752. }
  1753. } else if (c == yychar) {
  1754. if (c == '<') {
  1755. DEBUG_LEX1("SHL");
  1756. return SHL;
  1757. }
  1758. if (c == '>') {
  1759. DEBUG_LEX1("SHR");
  1760. return SHR;
  1761. }
  1762. unput(yychar);
  1763. DEBUG_LEX2("%c", yychar);
  1764. return yychar;
  1765. } else if (yychar == '~') {
  1766. if (c == '=') {
  1767. DEBUG_LEX1("MT");
  1768. return MT;
  1769. }
  1770. if (c == '!') {
  1771. DEBUG_LEX1("NM");
  1772. return NM;
  1773. }
  1774. }
  1775. unput(yychar);
  1776. switch (c) {
  1777. case '<':
  1778. DEBUG_LEX1("LT");
  1779. return LT;
  1780. case '>':
  1781. DEBUG_LEX1("GT");
  1782. return GT;
  1783. case '!':
  1784. DEBUG_LEX1("NOT");
  1785. return NOT;
  1786. default:
  1787. return c;
  1788. }
  1789. }
  1790. DEBUG_LEX2("%c", yychar);
  1791. return yychar;
  1792. }
  1793. void
  1794. yysync()
  1795. {
  1796. while (skip_to_nl() == '\n' && !isalpha(input()))
  1797. locus.line++;
  1798. unput(yychar);
  1799. }
  1800. /* ****************************************************************************
  1801. * Generalized list functions
  1802. */
  1803. static RWLIST *_list_insert(RWLIST **first, RWLIST **last, RWLIST *prev,
  1804. RWLIST *obj, int before);
  1805. static RWLIST *_list_remove(RWLIST **first, RWLIST **last, RWLIST *obj);
  1806. static RWLIST *_list_append(RWLIST **first, RWLIST **last, RWLIST *obj);
  1807. #define rw_list_insert(first, last, prev, obj, before) \
  1808. _list_insert((RWLIST**)first,(RWLIST**)last,(RWLIST*)prev,(RWLIST*)obj, before)
  1809. #define rw_list_remove(first, last, obj) \
  1810. _list_remove((RWLIST**)first,(RWLIST**)last,(RWLIST *)obj)
  1811. #define rw_list_append(first, last, obj) \
  1812. _list_append((RWLIST**)first, (RWLIST**)last, (RWLIST*)obj)
  1813. RWLIST *
  1814. _list_append(RWLIST **first, RWLIST **last, RWLIST *obj)
  1815. {
  1816. return rw_list_insert(first, last, *last, obj, 0);
  1817. }
  1818. RWLIST *
  1819. _list_insert(RWLIST **first, RWLIST **last, RWLIST *prev, RWLIST *obj,
  1820. int before)
  1821. {
  1822. RWLIST *next;
  1823. /*
  1824. * No first element: initialize whole list
  1825. */
  1826. if (!*first) {
  1827. *first = obj;
  1828. if (last)
  1829. *last = obj;
  1830. obj->prev = obj->next = NULL;
  1831. return obj;
  1832. }
  1833. /*
  1834. * Insert before `prev'
  1835. */
  1836. if (before) {
  1837. _list_insert(first, last, prev, obj, 0);
  1838. _list_remove(first, last, prev);
  1839. _list_insert(first, last, obj, prev, 0);
  1840. return obj;
  1841. }
  1842. /*
  1843. * Default: insert after prev
  1844. */
  1845. obj->prev = prev;
  1846. obj->next = prev->next;
  1847. if (next = prev->next)
  1848. next->prev = obj;
  1849. prev->next = obj;
  1850. if (last && prev == *last)
  1851. *last = obj;
  1852. return obj;
  1853. }
  1854. RWLIST *
  1855. _list_remove(RWLIST **first, RWLIST **last, RWLIST *obj)
  1856. {
  1857. RWLIST *temp;
  1858. if (temp = obj->prev)
  1859. temp->next = obj->next;
  1860. else
  1861. *first = obj->next;
  1862. if (temp = obj->next)
  1863. temp->prev = obj->prev;
  1864. else if (last)
  1865. *last = obj->prev;
  1866. obj->prev = obj->next = NULL;
  1867. return obj;
  1868. }
  1869. /* ****************************************************************************
  1870. * Generalized object handling
  1871. */
  1872. void *obj_alloc(OBUCKET *bucket);
  1873. void obj_free_all(OBUCKET *bucket);
  1874. void *
  1875. obj_alloc(OBUCKET *bucket)
  1876. {
  1877. OBJECT *optr;
  1878. optr = grad_emalloc(bucket->size);
  1879. optr->alloc = bucket->alloc_list;
  1880. bucket->alloc_list = optr;
  1881. return optr;
  1882. }
  1883. void
  1884. obj_free_all(OBUCKET *bucket)
  1885. {
  1886. OBJECT *obj, *next;
  1887. obj = bucket->alloc_list;
  1888. while (obj) {
  1889. next = obj->alloc;
  1890. if (bucket->free)
  1891. bucket->free(obj);
  1892. grad_free(obj);
  1893. obj = next;
  1894. }
  1895. bucket->alloc_list = NULL;
  1896. }
  1897. /* **************************************************************************
  1898. * Frames
  1899. */
  1900. void
  1901. frame_init()
  1902. {
  1903. frame_bkt.alloc_list = NULL;
  1904. frame_first = frame_last = NULL;
  1905. }
  1906. void
  1907. frame_push()
  1908. {
  1909. FRAME *this_frame = obj_alloc(&frame_bkt);
  1910. if (!frame_last) {
  1911. this_frame->level = 0;
  1912. this_frame->stack_offset = 0;
  1913. } else {
  1914. if (frame_last->level == 0)
  1915. this_frame->stack_offset = 1;
  1916. else
  1917. this_frame->stack_offset = frame_last->stack_offset;
  1918. this_frame->level = frame_last->level + 1;
  1919. }
  1920. rw_list_append(&frame_first, &frame_last, this_frame);
  1921. }
  1922. void
  1923. frame_pop()
  1924. {
  1925. rw_list_remove(&frame_first, &frame_last, frame_last);
  1926. }
  1927. void
  1928. frame_update_alloc()
  1929. {
  1930. FRAME *this_frame = frame_last;
  1931. if (this_frame->stack_offset > function->stack_alloc)
  1932. function->stack_alloc = this_frame->stack_offset;
  1933. }
  1934. void
  1935. frame_free_all()
  1936. {
  1937. obj_free_all(&frame_bkt);
  1938. frame_first = frame_last = NULL;
  1939. }
  1940. void
  1941. frame_unwind_all()
  1942. {
  1943. while (frame_last)
  1944. rw_list_remove(&frame_first, &frame_last, frame_last);
  1945. frame_push();
  1946. }
  1947. /* **************************************************************************
  1948. * Loops
  1949. */
  1950. void
  1951. loop_init()
  1952. {
  1953. loop_bkt.alloc_list = NULL;
  1954. loop_first = loop_last = NULL;
  1955. }
  1956. void
  1957. loop_free_all()
  1958. {
  1959. obj_free_all(&loop_bkt);
  1960. loop_first = loop_last = NULL;
  1961. }
  1962. void
  1963. loop_unwind_all()
  1964. {
  1965. loop_first = loop_last = NULL;
  1966. }
  1967. /*ARGSUSED*/
  1968. void
  1969. loop_push(MTX *mtx)
  1970. {
  1971. LOOP *this_loop = obj_alloc(&loop_bkt);
  1972. rw_list_append(&loop_first, &loop_last, this_loop);
  1973. }
  1974. void
  1975. loop_pop()
  1976. {
  1977. rw_list_remove(&loop_first, &loop_last, loop_last);
  1978. }
  1979. void
  1980. loop_fixup(JUMP_MTX *list, MTX *target)
  1981. {
  1982. JUMP_MTX *jp;
  1983. for (jp = list; jp; jp = (JUMP_MTX*)jp->link)
  1984. jp->dest = target;
  1985. }
  1986. /* **************************************************************************
  1987. * Variables
  1988. */
  1989. OBUCKET var_bucket = { sizeof(VAR), NULL };
  1990. void
  1991. var_init()
  1992. {
  1993. var_bucket.alloc_list = NULL;
  1994. var_first = var_last = NULL;
  1995. }
  1996. VAR *
  1997. var_alloc(grad_data_type_t type, char *name, int grow)
  1998. {
  1999. VAR *var;
  2000. var = (VAR*) obj_alloc(&var_bucket);
  2001. rw_list_append(&var_first, &var_last, var);
  2002. /* Initialize fields */
  2003. var->name = name;
  2004. var->datatype = type;
  2005. var->level = curframe->level;
  2006. var->offset = curframe->stack_offset;
  2007. curframe->stack_offset += grow;
  2008. return var;
  2009. }
  2010. void
  2011. var_unwind_level()
  2012. {
  2013. int cnt = 0;
  2014. while (var_last && var_last->level == curframe->level) {
  2015. rw_list_remove(&var_first, &var_last, var_last);
  2016. cnt++;
  2017. }
  2018. if (cnt)
  2019. frame_update_alloc();
  2020. }
  2021. void
  2022. var_unwind_all()
  2023. {
  2024. while (var_last)
  2025. rw_list_remove(&var_first, &var_last, var_last);
  2026. }
  2027. void
  2028. var_type(grad_data_type_t type, VAR *var)
  2029. {
  2030. for (; var; var = var->dcllink)
  2031. var->datatype = type;
  2032. }
  2033. void
  2034. var_free_all()
  2035. {
  2036. obj_free_all(&var_bucket);
  2037. var_first = var_last = NULL;
  2038. }
  2039. VAR *
  2040. var_lookup(char *name)
  2041. {
  2042. VAR *var;
  2043. var = var_last;
  2044. while (var && strcmp(var->name, name))
  2045. var = var->prev;
  2046. return var;
  2047. }
  2048. /* **************************************************************************
  2049. * Matrix generation
  2050. */
  2051. OBUCKET mtx_bucket = { sizeof(MTX), NULL };
  2052. #if defined(MAINTAINER_MODE)
  2053. int mtx_current_id ;
  2054. #endif
  2055. /*
  2056. * Insert a matrix into list
  2057. */
  2058. #define mtx_remove(mtx) rw_list_remove(&mtx_first, &mtx_last, mtx)
  2059. #define mtx_append(mtx) rw_list_append(&mtx_first, &mtx_last, mtx)
  2060. void
  2061. mtx_insert(MTX *prev, MTX *mtx)
  2062. {
  2063. MTX *up;
  2064. rw_list_insert(&mtx_first, &mtx_last, prev, mtx, 0);
  2065. if (up = prev->gen.uplink) {
  2066. switch (up->gen.type) {
  2067. case Unary:
  2068. up->un.arg = mtx;
  2069. break;
  2070. case Binary:
  2071. if (up->bin.arg[0] == prev)
  2072. up->bin.arg[0] = mtx;
  2073. else
  2074. up->bin.arg[1] = mtx;
  2075. break;
  2076. case Return:
  2077. up->ret.expr = mtx;
  2078. break;
  2079. default:
  2080. /*should not happen*/
  2081. break;
  2082. }
  2083. }
  2084. }
  2085. void
  2086. mtx_init()
  2087. {
  2088. mtx_bucket.alloc_list = NULL;
  2089. mtx_first = mtx_last = NULL;
  2090. }
  2091. void
  2092. mtx_unwind_all()
  2093. {
  2094. while (mtx_last)
  2095. rw_list_remove(&mtx_first, &mtx_last, mtx_last);
  2096. }
  2097. void
  2098. mtx_free_all()
  2099. {
  2100. obj_free_all(&mtx_bucket);
  2101. mtx_first = mtx_last = NULL;
  2102. }
  2103. MTX *
  2104. mtx_cur()
  2105. {
  2106. return mtx_last;
  2107. }
  2108. MTX *
  2109. mtx_frame(Mtxtype type, stkoff_t stksize)
  2110. {
  2111. FRAME_MTX *mtx = (FRAME_MTX *)mtx_alloc(type);
  2112. mtx_append(mtx);
  2113. mtx->stacksize = stksize;
  2114. return (MTX*)mtx;
  2115. }
  2116. MTX *
  2117. mtx_nop()
  2118. {
  2119. MTX *mtx = mtx_alloc(Nop);
  2120. mtx_append(mtx);
  2121. return mtx;
  2122. }
  2123. MTX *
  2124. mtx_jump()
  2125. {
  2126. MTX *mtx = mtx_alloc(Jump);
  2127. mtx_append(mtx);
  2128. return mtx;
  2129. }
  2130. MTX *
  2131. mtx_stop()
  2132. {
  2133. MTX *mtx = mtx_alloc(Stop);
  2134. mtx_append(mtx);
  2135. return mtx;
  2136. }
  2137. MTX *
  2138. mtx_pop()
  2139. {
  2140. MTX *mtx = mtx_alloc(Pop);
  2141. mtx_append(mtx);
  2142. return mtx;
  2143. }
  2144. MTX *
  2145. mtx_return(MTX *arg)
  2146. {
  2147. MTX *mtx = mtx_alloc(Return);
  2148. mtx_append(mtx);
  2149. mtx->ret.expr = arg;
  2150. arg->gen.uplink = (MTX*)mtx;
  2151. return (MTX*)mtx;
  2152. }
  2153. /*
  2154. * Allocate a matrix of given type and append it to the list
  2155. */
  2156. MTX *
  2157. mtx_alloc(Mtxtype type)
  2158. {
  2159. MTX *mtx = obj_alloc(&mtx_bucket);
  2160. mtx->gen.type = type;
  2161. mtx->gen.loc = locus;
  2162. #if defined(MAINTAINER_MODE)
  2163. mtx->gen.id = mtx_current_id++;
  2164. #endif
  2165. return mtx;
  2166. }
  2167. /*
  2168. * Create a Constant matrix
  2169. */
  2170. MTX *
  2171. mtx_const(grad_value_t *val)
  2172. {
  2173. CONST_MTX *mtx = (CONST_MTX *)mtx_alloc(Constant);
  2174. mtx_append(mtx);
  2175. mtx->datatype = val->type;
  2176. mtx->datum = val->datum;
  2177. return (MTX*)mtx;
  2178. }
  2179. /*
  2180. * Create a Reference matrix
  2181. */
  2182. MTX *
  2183. mtx_ref(int num)
  2184. {
  2185. MATCHREF_MTX *mtx = (MATCHREF_MTX*)mtx_alloc(Matchref);
  2186. mtx_append(mtx);
  2187. mtx->datatype = String;
  2188. mtx->num = num;
  2189. return (MTX*)mtx;
  2190. }
  2191. MTX *
  2192. mtx_var(VAR *var)
  2193. {
  2194. VAR_MTX *mtx = (VAR_MTX*)mtx_alloc(Variable);
  2195. mtx_append(mtx);
  2196. mtx->datatype = var->datatype;
  2197. mtx->var = var;
  2198. return (MTX*)mtx;
  2199. }
  2200. MTX *
  2201. mtx_asgn(VAR *var, MTX *arg)
  2202. {
  2203. ASGN_MTX *mtx = (ASGN_MTX*)mtx_alloc(Asgn);
  2204. mtx_append(mtx);
  2205. if (var->datatype != arg->gen.datatype)
  2206. coerce(arg, var->datatype);
  2207. mtx->datatype = var->datatype;
  2208. mtx->lval = var;
  2209. mtx->arg = arg;
  2210. return (MTX*)mtx;
  2211. }
  2212. grad_data_type_t
  2213. attr_datatype(grad_dict_attr_t *attr)
  2214. {
  2215. switch (attr->type) {
  2216. case GRAD_TYPE_STRING:
  2217. /* FIXME: It could be a nice move to do
  2218. (attr->prop & GRAD_AP_BINARY_STRING) ? Binstr : String;
  2219. instead... */
  2220. return String;
  2221. case GRAD_TYPE_DATE:
  2222. return String;
  2223. case GRAD_TYPE_INTEGER:
  2224. case GRAD_TYPE_IPADDR:
  2225. return Integer;
  2226. default:
  2227. grad_insist_fail("unknown attribute type");
  2228. }
  2229. /*NOTREACHED*/
  2230. }
  2231. MTX *
  2232. mtx_attr(grad_dict_attr_t *attr, MTX *index)
  2233. {
  2234. ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr);
  2235. mtx_append(mtx);
  2236. mtx->attrno = attr->value;
  2237. mtx->datatype = attr_datatype(attr);
  2238. mtx->index = index;
  2239. return (MTX*)mtx;
  2240. }
  2241. MTX *
  2242. mtx_attr_check(grad_dict_attr_t *attr, MTX *index)
  2243. {
  2244. ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_check);
  2245. mtx_append(mtx);
  2246. mtx->attrno = attr->value;
  2247. mtx->datatype = Integer;
  2248. mtx->index = index;
  2249. return (MTX*)mtx;
  2250. }
  2251. void
  2252. rw_coercion_warning(grad_data_type_t from, grad_data_type_t to, char *pref)
  2253. {
  2254. grad_log_loc(GRAD_LOG_WARN, &locus,
  2255. _("%s implicit coercion %s %s"),
  2256. pref ? pref : "",
  2257. datatype_str_abl(from),
  2258. datatype_str_acc(to));
  2259. }
  2260. MTX *
  2261. mtx_attr_asgn(grad_dict_attr_t *attr, MTX *index, MTX *rval)
  2262. {
  2263. ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_asgn);
  2264. mtx_append(mtx);
  2265. mtx->attrno = attr->value;
  2266. mtx->datatype = attr_datatype(attr);
  2267. if (rval->gen.datatype != mtx->datatype) {
  2268. rw_coercion_warning(rval->gen.datatype, mtx->datatype, NULL);
  2269. rval = coerce(rval, mtx->datatype);
  2270. }
  2271. mtx->index = index;
  2272. mtx->rval = rval;
  2273. return (MTX*)mtx;
  2274. }
  2275. MTX *
  2276. mtx_attr_delete(grad_dict_attr_t *attr, MTX *index)
  2277. {
  2278. ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_delete);
  2279. mtx_append(mtx);
  2280. mtx->attrno = attr->value;
  2281. mtx->datatype = attr_datatype(attr);
  2282. mtx->index = index;
  2283. return (MTX*)mtx;
  2284. }
  2285. MTX *
  2286. mtx_bin(Bopcode opcode, MTX *arg1, MTX *arg2)
  2287. {
  2288. BIN_MTX *mtx = (BIN_MTX*)mtx_alloc(Binary);
  2289. mtx_append(mtx);
  2290. if (arg1->gen.datatype != arg2->gen.datatype) {
  2291. rw_coercion_warning(String, Integer, NULL);
  2292. if (arg1->gen.datatype == String)
  2293. arg1 = coerce(arg1, Integer);
  2294. else
  2295. arg2 = coerce(arg2, Integer);
  2296. }
  2297. switch (arg1->gen.datatype) {
  2298. case String:
  2299. switch (opcode) {
  2300. case Add:
  2301. mtx->datatype = String;
  2302. break;
  2303. case Eq:
  2304. case Ne:
  2305. case Lt:
  2306. case Le:
  2307. case Gt:
  2308. case Ge:
  2309. mtx->datatype = Integer;
  2310. break;
  2311. default:
  2312. grad_log_loc(GRAD_LOG_ERR, &locus,
  2313. "%s",
  2314. _("operation not applicable to strings"));
  2315. errcnt++;
  2316. return (MTX*)mtx;
  2317. }
  2318. break;
  2319. case Integer:
  2320. mtx->datatype = Integer;
  2321. break;
  2322. default:
  2323. grad_insist_fail("unknown data type");
  2324. }
  2325. mtx->opcode = opcode;
  2326. mtx->arg[0] = arg1;
  2327. mtx->arg[1] = arg2;
  2328. arg1->gen.uplink = arg2->gen.uplink = (MTX*)mtx;
  2329. return (MTX*)mtx;
  2330. }
  2331. MTX *
  2332. mtx_un(Uopcode opcode, MTX *arg)
  2333. {
  2334. UN_MTX *mtx = (UN_MTX*)mtx_alloc(Unary);
  2335. mtx_append(mtx);
  2336. if (arg->gen.datatype != Integer) {
  2337. rw_coercion_warning(String, Integer, NULL);
  2338. coerce(arg, Integer);
  2339. }
  2340. mtx->datatype = Integer;
  2341. mtx->opcode = opcode;
  2342. mtx->arg = arg;
  2343. arg->gen.uplink = (MTX*)mtx;
  2344. return (MTX*)mtx;
  2345. }
  2346. MTX *
  2347. mtx_match(int negated, MTX *arg, COMP_REGEX *rx)
  2348. {
  2349. MATCH_MTX *mtx = (MATCH_MTX*)mtx_alloc(Match);
  2350. mtx_append(mtx);
  2351. if (arg->gen.datatype != String) {
  2352. rw_coercion_warning(Integer, String, NULL);
  2353. coerce(arg, String);
  2354. }
  2355. mtx->datatype = Integer;
  2356. mtx->negated = negated;
  2357. mtx->arg = arg;
  2358. mtx->rx = rx;
  2359. return (MTX*)mtx;
  2360. }
  2361. MTX *
  2362. mtx_cond(MTX *cond, MTX *if_true, MTX *if_false)
  2363. {
  2364. COND_MTX *mtx = (COND_MTX*)mtx_alloc(Cond);
  2365. mtx_append(mtx);
  2366. mtx->expr = cond;
  2367. mtx->if_true = if_true;
  2368. mtx->if_false = if_false;
  2369. return (MTX*)mtx;
  2370. }
  2371. MTX *
  2372. mtx_coerce(grad_data_type_t type, MTX *arg)
  2373. {
  2374. if (type == arg->gen.datatype)
  2375. return mtx_cur();
  2376. return coerce(arg, type);
  2377. }
  2378. MTX *
  2379. coerce(MTX *arg, grad_data_type_t type)
  2380. {
  2381. COERCE_MTX *mtx = (COERCE_MTX*)mtx_alloc(Coercion);
  2382. mtx_insert(arg, (MTX*) mtx);
  2383. mtx->datatype = type;
  2384. mtx->arg = arg;
  2385. return (MTX*)mtx;
  2386. }
  2387. MTX *
  2388. mtx_call(FUNCTION *fun, MTX *args)
  2389. {
  2390. MTX *argp;
  2391. CALL_MTX *call;
  2392. PARAMETER *parmp;
  2393. int argn;
  2394. /*
  2395. * Test the number and types of arguments. Insert reasonable
  2396. * typecasts.
  2397. */
  2398. argn = 0;
  2399. argp = args;
  2400. parmp = fun->parm;
  2401. while (argp && parmp) {
  2402. if (argp->gen.datatype != parmp->datatype) {
  2403. char buf[24];
  2404. snprintf(buf, sizeof buf, _("(argument %d)"), argn);
  2405. rw_coercion_warning(argp->gen.datatype,
  2406. parmp->datatype, buf);
  2407. coerce(argp, parmp->datatype);
  2408. }
  2409. argn++;
  2410. argp = argp->gen.arglink;
  2411. parmp = parmp->next;
  2412. }
  2413. /*
  2414. * Note that the argument count mismatch is not an error!
  2415. */
  2416. if (argp) {
  2417. grad_log_loc(GRAD_LOG_ERR, &locus,
  2418. _("too many arguments in call to %s"),
  2419. fun->name);
  2420. errcnt++;
  2421. } else if (parmp) {
  2422. grad_log_loc(GRAD_LOG_ERR, &locus,
  2423. _("too few arguments in call to %s"),
  2424. fun->name);
  2425. errcnt++;
  2426. }
  2427. call = (CALL_MTX*) mtx_alloc(Call);
  2428. mtx_append((MTX*)call);
  2429. call->datatype = fun->rettype;
  2430. call->fun = fun;
  2431. call->args = args;
  2432. call->nargs = argn;
  2433. return (MTX*) call;
  2434. }
  2435. MTX *
  2436. mtx_builtin(builtin_t *bin, MTX *args)
  2437. {
  2438. MTX *argp;
  2439. BTIN_MTX *call;
  2440. int argn;
  2441. char *parmp;
  2442. grad_data_type_t type;
  2443. /*
  2444. * Test the number and types of arguments. Insert reasonable
  2445. * typecasts.
  2446. */
  2447. argn = 0;
  2448. argp = args;
  2449. parmp = bin->parms;
  2450. while (argp && parmp) {
  2451. switch (parmp[0]) {
  2452. case 'i':
  2453. type = Integer;
  2454. break;
  2455. case 's':
  2456. type = String;
  2457. break;
  2458. default:
  2459. grad_insist_fail("malformed builtin");
  2460. }
  2461. if (argp->gen.datatype != type) {
  2462. char buf[24];
  2463. snprintf(buf, sizeof buf, _("(argument %d)"), argn);
  2464. rw_coercion_warning(argp->gen.datatype, type, buf);
  2465. coerce(argp, type);
  2466. }
  2467. argn++;
  2468. argp = argp->gen.arglink;
  2469. parmp++;
  2470. }
  2471. if (argp) {
  2472. grad_log_loc(GRAD_LOG_ERR, &locus,
  2473. _("too many arguments in call to %s"),
  2474. bin->name);
  2475. errcnt++;
  2476. } else if (*parmp) {
  2477. grad_log_loc(GRAD_LOG_ERR, &locus,
  2478. _("too few arguments in call to %s"),
  2479. bin->name);
  2480. errcnt++;
  2481. }
  2482. call = (BTIN_MTX*) mtx_alloc(Builtin);
  2483. mtx_append((MTX*)call);
  2484. call->datatype = bin->rettype;
  2485. call->fun = bin->handler;
  2486. call->args = args;
  2487. call->nargs = argn;
  2488. return (MTX*) call;
  2489. }
  2490. /* ****************************************************************************
  2491. * Code optimizer (rudimentary)
  2492. */
  2493. const char *
  2494. datatype_str_nom(grad_data_type_t type)
  2495. {
  2496. switch (type) {
  2497. case Undefined:
  2498. return _("Undefined");
  2499. case Integer:
  2500. return _("integer");
  2501. case String:
  2502. return _("string");
  2503. default:
  2504. return _("UNKNOWN");
  2505. }
  2506. }
  2507. const char *
  2508. datatype_str_abl(grad_data_type_t type)
  2509. {
  2510. switch (type) {
  2511. case Undefined:
  2512. return _("from Undefined");
  2513. case Integer:
  2514. return _("from integer");
  2515. case String:
  2516. return _("from string");
  2517. default:
  2518. return _("from UNKNOWN");
  2519. }
  2520. }
  2521. const char *
  2522. datatype_str_acc(grad_data_type_t type)
  2523. {
  2524. switch (type) {
  2525. case Undefined:
  2526. return _("to Undefined");
  2527. case Integer:
  2528. return _("to integer");
  2529. case String:
  2530. return _("to string");
  2531. default:
  2532. return _("to UNKNOWN");
  2533. }
  2534. }
  2535. FILE *
  2536. debug_open_file()
  2537. {
  2538. FILE *fp;
  2539. char *path;
  2540. path = grad_mkfilename(grad_log_dir, "radius.mtx");
  2541. if ((fp = fopen(path, "a")) == NULL) {
  2542. grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
  2543. _("can't open file `%s'"),
  2544. path);
  2545. }
  2546. grad_free(path);
  2547. return fp;
  2548. }
  2549. #if defined(MAINTAINER_MODE)
  2550. static void debug_print_datum(FILE *fp, grad_data_type_t type, grad_datum_t *datum);
  2551. static void debug_print_var(FILE *fp, VAR *var);
  2552. static void debug_print_unary(FILE *fp, UN_MTX *mtx);
  2553. static void debug_print_binary(FILE *fp, BIN_MTX *mtx);
  2554. static void debug_print_mtxlist();
  2555. static char *b_opstr[] = {
  2556. "Eq",
  2557. "Ne",
  2558. "Lt",
  2559. "Le",
  2560. "Gt",
  2561. "Ge",
  2562. "&",
  2563. "^",
  2564. "|",
  2565. "And",
  2566. "Or",
  2567. "Shl",
  2568. "Shr",
  2569. "Add",
  2570. "Sub",
  2571. "Mul",
  2572. "Div",
  2573. "Rem",
  2574. };
  2575. static char *u_opstr[] = {
  2576. "Neg",
  2577. "Not"
  2578. };
  2579. #define LINK(m) (m ? m->gen.id : 0)
  2580. void
  2581. debug_print_datum(FILE *fp, grad_data_type_t type, grad_datum_t *datum)
  2582. {
  2583. fprintf(fp, "%3.3s ", datatype_str_nom(type));
  2584. switch (type) {
  2585. case Integer:
  2586. fprintf(fp, "%d", datum->ival);
  2587. break;
  2588. case String:
  2589. fprintf(fp, "%s", datum->sval);
  2590. break;
  2591. default:
  2592. grad_insist_fail("unknown data type");
  2593. }
  2594. }
  2595. void
  2596. debug_print_var(FILE *fp, VAR *var)
  2597. {
  2598. fprintf(fp, "%3.3s %s L:%d S:%d",
  2599. datatype_str_nom(var->datatype),
  2600. var->name,
  2601. var->level,
  2602. var->offset);
  2603. if (var->constant) {
  2604. fprintf(fp, "CONST ");
  2605. debug_print_datum(fp, var->datatype, &var->datum);
  2606. }
  2607. }
  2608. void
  2609. debug_print_unary(FILE *fp, UN_MTX *mtx)
  2610. {
  2611. fprintf(fp, "OP:%s M:%d",
  2612. u_opstr[mtx->opcode], LINK(mtx->arg));
  2613. }
  2614. void
  2615. debug_print_binary(FILE *fp, BIN_MTX *mtx)
  2616. {
  2617. fprintf(fp, "OP:%s M1:%d M2:%d",
  2618. b_opstr[mtx->opcode],
  2619. LINK(mtx->arg[0]),
  2620. LINK(mtx->arg[1]));
  2621. }
  2622. void
  2623. debug_print_mtxlist(char *s)
  2624. {
  2625. FILE *fp;
  2626. MTX *mtx, *tmp;
  2627. if ((fp = debug_open_file()) == NULL)
  2628. return;
  2629. #define CASE(c) case c: fprintf(fp, "%-10.10s", #c);
  2630. fprintf(fp, "%s\n", s);
  2631. for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
  2632. fprintf(fp, "%4d: %4d %4d ",
  2633. mtx->gen.id,
  2634. LINK(mtx->gen.prev),
  2635. LINK(mtx->gen.next));
  2636. switch (mtx->gen.type) {
  2637. CASE (Generic)
  2638. break;
  2639. CASE (Nop)
  2640. break;
  2641. CASE (Enter)
  2642. fprintf(fp, "%3.3s %d",
  2643. "",
  2644. mtx->frame.stacksize);
  2645. break;
  2646. CASE (Leave)
  2647. fprintf(fp, "%3.3s %d",
  2648. "",
  2649. mtx->frame.stacksize);
  2650. break;
  2651. CASE (Stop)
  2652. break;
  2653. CASE (Constant)
  2654. debug_print_datum(fp, mtx->cnst.datatype,
  2655. &mtx->cnst.datum);
  2656. break;
  2657. CASE (Matchref)
  2658. fprintf(fp, "%3.3s %d",
  2659. datatype_str_nom(String),
  2660. mtx->ref.num);
  2661. break;
  2662. CASE (Variable)
  2663. debug_print_var(fp, mtx->var.var);
  2664. break;
  2665. CASE (Unary)
  2666. fprintf(fp, "%3.3s ", datatype_str_nom(mtx->gen.datatype));
  2667. debug_print_unary(fp, &mtx->un);
  2668. break;
  2669. CASE (Binary)
  2670. fprintf(fp, "%3.3s ", datatype_str_nom(mtx->gen.datatype));
  2671. debug_print_binary(fp, &mtx->bin);
  2672. break;
  2673. CASE (Cond)
  2674. fprintf(fp, "%3.3s ", "");
  2675. fprintf(fp, "C:%4d T:%4d F:%4d",
  2676. LINK(mtx->cond.expr),
  2677. LINK(mtx->cond.if_true),
  2678. LINK(mtx->cond.if_false));
  2679. break;
  2680. CASE (Asgn)
  2681. fprintf(fp, "%3.3s ",
  2682. datatype_str_nom(mtx->gen.datatype));
  2683. fprintf(fp, "V:%s,%d,%d M:%4d",
  2684. mtx->asgn.lval->name,
  2685. mtx->asgn.lval->level,
  2686. mtx->asgn.lval->offset,
  2687. LINK(mtx->asgn.arg));
  2688. break;
  2689. CASE (Match)
  2690. fprintf(fp, " N:%1d M:%4d RX:%p",
  2691. mtx->match.negated,
  2692. LINK(mtx->match.arg),
  2693. mtx->match.rx);
  2694. break;
  2695. CASE (Coercion)
  2696. fprintf(fp, "%3.3s M:%4d",
  2697. datatype_str_nom(mtx->coerce.datatype),
  2698. LINK(mtx->coerce.arg));
  2699. break;
  2700. CASE (Return)
  2701. fprintf(fp, "%3.3s M:%4d",
  2702. datatype_str_nom(mtx->ret.expr->gen.datatype),
  2703. LINK(mtx->ret.expr));
  2704. break;
  2705. CASE (Jump)
  2706. fprintf(fp, "%3.3s M:%4d",
  2707. "",
  2708. LINK(mtx->jump.dest));
  2709. break;
  2710. CASE (Branch)
  2711. fprintf(fp, "%3.3s M:%4d",
  2712. mtx->branch.cond ? "NE" : "EQ",
  2713. LINK(mtx->branch.dest));
  2714. break;
  2715. CASE (Call)
  2716. fprintf(fp, "%3.3s F:%s, A:%d:",
  2717. datatype_str_nom(mtx->call.datatype),
  2718. mtx->call.fun->name,
  2719. mtx->call.fun->nparm);
  2720. for (tmp = mtx->call.args; tmp; tmp = tmp->gen.arglink)
  2721. fprintf(fp, "%d,", tmp->gen.id);
  2722. break;
  2723. CASE(Builtin)
  2724. fprintf(fp, "%3.3s F:%p, A:%d:",
  2725. datatype_str_nom(mtx->btin.datatype),
  2726. mtx->btin.fun,
  2727. mtx->btin.nargs);
  2728. for (tmp = mtx->btin.args; tmp; tmp = tmp->gen.arglink)
  2729. fprintf(fp, "%d,", tmp->gen.id);
  2730. break;
  2731. CASE (Pop)
  2732. break;
  2733. CASE (Pusha)
  2734. break;
  2735. CASE (Popa)
  2736. break;
  2737. CASE (Attr)
  2738. fprintf(fp, "%3.3s A:%d I:%d",
  2739. datatype_str_nom(mtx->gen.datatype),
  2740. mtx->attr.attrno,
  2741. mtx->attr.index ? mtx->attr.index->gen.id : 0);
  2742. break;
  2743. CASE (Attr_check)
  2744. fprintf(fp, "%3.3s A:%d I:%d",
  2745. datatype_str_nom(mtx->gen.datatype),
  2746. mtx->attr.attrno,
  2747. mtx->attr.index ? mtx->attr.index->gen.id : 0);
  2748. break;
  2749. CASE (Attr_asgn)
  2750. fprintf(fp, "%3.3s A:%d I:%d M:%d",
  2751. datatype_str_nom(mtx->gen.datatype),
  2752. mtx->attr.attrno,
  2753. mtx->attr.index ? mtx->attr.index->gen.id : 0,
  2754. LINK(mtx->attr.rval));
  2755. break;
  2756. CASE (Attr_delete)
  2757. fprintf(fp, "%3.3s A:%d I:%d",
  2758. datatype_str_nom(mtx->gen.datatype),
  2759. mtx->attr.attrno,
  2760. mtx->attr.index ? mtx->attr.index->gen.id : 0);
  2761. break;
  2762. default:
  2763. fprintf(fp, "UNKNOWN: %d", mtx->gen.type);
  2764. }
  2765. fprintf(fp, "\n");
  2766. }
  2767. fclose(fp);
  2768. }
  2769. void
  2770. debug_print_function()
  2771. {
  2772. FILE *fp;
  2773. PARAMETER *parm;
  2774. int n;
  2775. if ((fp = debug_open_file()) == NULL)
  2776. return;
  2777. fprintf(fp, "FUNCTION: %s\n", function->name);
  2778. fprintf(fp, "RETURNS : %s\n", datatype_str_nom(function->rettype));
  2779. fprintf(fp, "NPARMS : %d\n", function->nparm);
  2780. fprintf(fp, "PARMS :\n");
  2781. for (parm = function->parm, n = 0; parm; parm = parm->next, n++)
  2782. fprintf(fp, " %4d: %s at %4d\n",
  2783. n, datatype_str_nom(parm->datatype),
  2784. parm->offset);
  2785. fclose(fp);
  2786. }
  2787. #endif /* MAINTAINER_MODE */
  2788. #if defined(MAINTAINER_MODE)
  2789. # define DEBUG_MTX(c) if (GRAD_DEBUG_LEVEL(30)) debug_print_mtxlist(c);
  2790. # define DEBUG_FUN() if (GRAD_DEBUG_LEVEL(25)) debug_print_function();
  2791. #else
  2792. # define DEBUG_MTX(c)
  2793. # define DEBUG_FUN()
  2794. #endif
  2795. static void pass1();
  2796. static int pass2_unary(MTX *mtx);
  2797. static int pass2_binary(MTX *mtx);
  2798. void
  2799. pass1()
  2800. {
  2801. MTX *mtx;
  2802. MTX *end;
  2803. /*
  2804. * Create an entry matrix
  2805. */
  2806. mtx = mtx_alloc(Enter);
  2807. rw_list_insert(&mtx_first, &mtx_last, mtx_first, mtx, 1);
  2808. mtx->frame.stacksize = function->stack_alloc;
  2809. /*
  2810. * Provide a default return statement if necessary
  2811. */
  2812. if (mtx_last->gen.type != Return) {
  2813. grad_value_t val;
  2814. grad_log_loc(GRAD_LOG_WARN, &mtx_last->gen.loc,
  2815. _("missing return statement"));
  2816. val.type = function->rettype;
  2817. switch (function->rettype) {
  2818. case Integer:
  2819. val.datum.ival = 0;
  2820. break;
  2821. case String:
  2822. val.datum.sval.data = "";
  2823. val.datum.sval.size = 0;
  2824. break;
  2825. default:
  2826. grad_insist_fail("Unknown data type");
  2827. }
  2828. mtx_const(&val);
  2829. mtx_frame(Leave, function->stack_alloc);
  2830. } else {
  2831. mtx_last->gen.type = Leave;
  2832. mtx_last->frame.stacksize = function->stack_alloc;
  2833. }
  2834. /*
  2835. * Insert a no-op matrix before the `leave' one
  2836. */
  2837. end = mtx_alloc(Nop);
  2838. rw_list_insert(&mtx_first, &mtx_last, mtx_last, end, 1);
  2839. for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
  2840. if (mtx->gen.type == Return) {
  2841. if (mtx->ret.expr->gen.datatype != function->rettype) {
  2842. rw_coercion_warning(
  2843. mtx->ret.expr->gen.datatype,
  2844. function->rettype, NULL);
  2845. coerce(mtx->ret.expr, function->rettype);
  2846. }
  2847. mtx->gen.type = Jump;
  2848. mtx->jump.dest = end;
  2849. }
  2850. }
  2851. }
  2852. /*
  2853. * Second pass: elimination of constant sub-expressions
  2854. */
  2855. /*
  2856. * Perform immediate unary calculations
  2857. */
  2858. int
  2859. pass2_unary(MTX *mtx)
  2860. {
  2861. MTX *arg = mtx->un.arg;
  2862. switch (mtx->un.opcode) {
  2863. case Not:
  2864. arg->cnst.datum.ival = !arg->cnst.datum.ival;
  2865. break;
  2866. case Neg:
  2867. arg->cnst.datum.ival = -arg->cnst.datum.ival;
  2868. break;
  2869. default:
  2870. grad_insist_fail("Unexpected opcode");
  2871. }
  2872. mtx->gen.type = Constant;
  2873. mtx->cnst.datum = arg->cnst.datum;
  2874. mtx_remove(arg);
  2875. return 0;
  2876. }
  2877. /*
  2878. * Perform immediate binary computations
  2879. */
  2880. int
  2881. pass2_binary(MTX *mtx)
  2882. {
  2883. MTX *arg0 = mtx->bin.arg[0];
  2884. MTX *arg1 = mtx->bin.arg[1];
  2885. grad_datum_t dat;
  2886. switch (mtx->bin.opcode) {
  2887. case Eq:
  2888. dat.ival = arg0->cnst.datum.ival == arg1->cnst.datum.ival;
  2889. break;
  2890. case Ne:
  2891. dat.ival = arg0->cnst.datum.ival != arg1->cnst.datum.ival;
  2892. break;
  2893. case Lt:
  2894. dat.ival = arg0->cnst.datum.ival < arg1->cnst.datum.ival;
  2895. break;
  2896. case Le:
  2897. dat.ival = arg0->cnst.datum.ival <= arg1->cnst.datum.ival;
  2898. break;
  2899. case Gt:
  2900. dat.ival = arg0->cnst.datum.ival > arg1->cnst.datum.ival;
  2901. break;
  2902. case Ge:
  2903. dat.ival = arg0->cnst.datum.ival >= arg1->cnst.datum.ival;
  2904. break;
  2905. case BAnd:
  2906. dat.ival = arg0->cnst.datum.ival & arg1->cnst.datum.ival;
  2907. break;
  2908. case BOr:
  2909. dat.ival = arg0->cnst.datum.ival | arg1->cnst.datum.ival;
  2910. break;
  2911. case BXor:
  2912. dat.ival = arg0->cnst.datum.ival ^ arg1->cnst.datum.ival;
  2913. break;
  2914. case And:
  2915. dat.ival = arg0->cnst.datum.ival && arg1->cnst.datum.ival;
  2916. break;
  2917. case Or:
  2918. dat.ival = arg0->cnst.datum.ival || arg1->cnst.datum.ival;
  2919. break;
  2920. case Shl:
  2921. dat.ival = arg0->cnst.datum.ival << arg1->cnst.datum.ival;
  2922. break;
  2923. case Shr:
  2924. dat.ival = arg0->cnst.datum.ival >> arg1->cnst.datum.ival;
  2925. break;
  2926. case Add:
  2927. dat.ival = arg0->cnst.datum.ival + arg1->cnst.datum.ival;
  2928. break;
  2929. case Sub:
  2930. dat.ival = arg0->cnst.datum.ival - arg1->cnst.datum.ival;
  2931. break;
  2932. case Mul:
  2933. dat.ival = arg0->cnst.datum.ival * arg1->cnst.datum.ival;
  2934. break;
  2935. case Div:
  2936. if (arg1->cnst.datum.ival == 0) {
  2937. grad_log_loc(GRAD_LOG_ERR, &arg1->cnst.loc,
  2938. _("divide by zero"));
  2939. errcnt++;
  2940. } else
  2941. dat.ival =
  2942. arg0->cnst.datum.ival / arg1->cnst.datum.ival;
  2943. break;
  2944. case Rem:
  2945. if (arg1->cnst.datum.ival == 0) {
  2946. grad_log_loc(GRAD_LOG_ERR, &arg1->cnst.loc,
  2947. _("divide by zero"));
  2948. errcnt++;
  2949. } else
  2950. dat.ival =
  2951. arg0->cnst.datum.ival % arg1->cnst.datum.ival;
  2952. break;
  2953. default:
  2954. grad_insist_fail("Unexpected opcode");
  2955. }
  2956. mtx->gen.type = Constant;
  2957. mtx->cnst.datum = dat;
  2958. mtx_remove(arg0);
  2959. mtx_remove(arg1);
  2960. return 0;
  2961. }
  2962. MTX *
  2963. mtx_branch(int cond, MTX *target)
  2964. {
  2965. MTX *nop = mtx_alloc(Nop);
  2966. MTX *mtx = mtx_alloc(Branch);
  2967. mtx_insert(target, nop);
  2968. mtx->branch.cond = cond;
  2969. mtx->branch.dest = nop;
  2970. return mtx;
  2971. }
  2972. void
  2973. mtx_bool(MTX *mtx)
  2974. {
  2975. MTX *j_mtx, *p, *p1;
  2976. /* Insert after first operand:
  2977. popa
  2978. pusha
  2979. pusha ;; Duplicate tos value
  2980. j?e L10
  2981. popa ;; Pop up the unneded value */
  2982. p = mtx_alloc(Popa);
  2983. mtx_insert(mtx->bin.arg[0], p);
  2984. p1 = mtx_alloc(Pusha);
  2985. mtx_insert(p, p1);
  2986. p = mtx_alloc(Pusha);
  2987. mtx_insert(p1, p);
  2988. j_mtx = mtx_branch(mtx->bin.opcode == Or, mtx);
  2989. mtx_insert(p, j_mtx);
  2990. p1 = mtx_alloc(Popa);
  2991. mtx_insert(j_mtx, p1);
  2992. /* Remove the op matrix
  2993. Note that the mtx->cond.expr is not correct after this
  2994. operation, but this does not affect the functionality */
  2995. mtx_remove(mtx);
  2996. }
  2997. /*
  2998. * Second optimization pass: immediate computations
  2999. */
  3000. int
  3001. pass2()
  3002. {
  3003. MTX *mtx, *next;
  3004. int optcnt;
  3005. int errcnt = 0;
  3006. do {
  3007. optcnt = 0;
  3008. mtx = mtx_first;
  3009. while (mtx) {
  3010. next = mtx->gen.next;
  3011. switch (mtx->gen.type) {
  3012. case Unary:
  3013. if (mtx->un.arg->gen.type != Constant)
  3014. break;
  3015. if (pass2_unary(mtx))
  3016. errcnt++;
  3017. else
  3018. optcnt++;
  3019. break;
  3020. case Binary:
  3021. if (mtx->bin.arg[0]->gen.type == Constant
  3022. && mtx->bin.arg[1]->gen.type == Constant) {
  3023. switch (mtx->bin.datatype) {
  3024. case Integer:
  3025. if (pass2_binary(mtx))
  3026. errcnt++;
  3027. else
  3028. optcnt++;
  3029. break;
  3030. case String:
  3031. /*NO STRING OPS SO FAR */;
  3032. break;
  3033. default:
  3034. grad_insist_fail("Unknown data type");
  3035. }
  3036. } else if (mtx->bin.opcode == And
  3037. || mtx->bin.opcode == Or) {
  3038. mtx_bool(mtx);
  3039. }
  3040. break;
  3041. /*FIXME: ADD `if (1)'/`if 0' evaluation */
  3042. case Jump:
  3043. if (mtx->jump.dest == mtx->jump.next)
  3044. mtx_remove(mtx);
  3045. break;
  3046. case Attr:
  3047. case Attr_asgn:
  3048. case Attr_check:
  3049. case Attr_delete:
  3050. /*FIXME: the rw_attr.0 functions should
  3051. expect an immediate value after the
  3052. attribute number */
  3053. break;
  3054. default:
  3055. break;
  3056. }
  3057. mtx = next;
  3058. }
  3059. } while (errcnt == 0 && optcnt > 0);
  3060. return errcnt;
  3061. }
  3062. int
  3063. optimize()
  3064. {
  3065. DEBUG_FUN();
  3066. DEBUG_MTX("on entry to optimize");
  3067. pass1();
  3068. DEBUG_MTX("after first pass");
  3069. if (pass2())
  3070. return -1;
  3071. DEBUG_MTX("after second pass (immediate computations)");
  3072. return 0;
  3073. }
  3074. /* ****************************************************************************
  3075. * Code generator
  3076. */
  3077. static INSTR *rw_code; /* Code segment */
  3078. static pctr_t rw_pc; /* PC when compiling the code */
  3079. static size_t rw_codesize; /* Length of code segment */
  3080. void
  3081. code_check()
  3082. {
  3083. if (rw_code == NULL) {
  3084. rw_codesize = 4096;
  3085. rw_code = grad_emalloc(rw_codesize * sizeof(rw_code[0]));
  3086. }
  3087. }
  3088. void
  3089. code_init()
  3090. {
  3091. code_check();
  3092. /* code cell #0 is the default return address */
  3093. rw_code[0] = 0;
  3094. rw_pc = 1;
  3095. }
  3096. #if defined(MAINTAINER_MODE)
  3097. void
  3098. debug_dump_code()
  3099. {
  3100. FILE *fp;
  3101. pctr_t pc;
  3102. int i;
  3103. if ((fp = debug_open_file()) == NULL)
  3104. return;
  3105. fprintf(fp, "Code size: %d\n", rw_codesize);
  3106. fprintf(fp, "Code dump:\n");
  3107. pc = 0;
  3108. do {
  3109. fprintf(fp, "%4d:", pc);
  3110. for (i = 0; i < 8 && pc < rw_codesize; i++, pc++)
  3111. fprintf(fp, " %8x", (u_int) rw_code[pc]);
  3112. fprintf(fp, "\n");
  3113. } while (pc < rw_codesize);
  3114. fclose(fp);
  3115. }
  3116. #endif
  3117. /*
  3118. * Runtime function prototypes
  3119. */
  3120. static int pushn(RWSTYPE n);
  3121. static int cpopn(RWSTYPE *np);
  3122. static RWSTYPE popn();
  3123. static void checkpop(int cnt);
  3124. static void pushref(char *str, int from, int to);
  3125. static RWSTYPE *heap_reserve(int size);
  3126. static void pushs(RWSTYPE *sptr, size_t size, int len);
  3127. static void pushstr(const char *str, int len);
  3128. static void rw_pushn();
  3129. static void rw_pushs();
  3130. static void rw_pushref();
  3131. static void rw_pushv();
  3132. static void rw_i2s();
  3133. static void rw_s2i();
  3134. static void rw_eq();
  3135. static void rw_ne();
  3136. static void rw_lt();
  3137. static void rw_le();
  3138. static void rw_gt();
  3139. static void rw_ge();
  3140. static void rw_eqs();
  3141. static void rw_nes();
  3142. static void rw_lts();
  3143. static void rw_les();
  3144. static void rw_gts();
  3145. static void rw_ges();
  3146. static void rw_b_xor();
  3147. static void rw_b_and();
  3148. static void rw_b_or();
  3149. static void rw_shl();
  3150. static void rw_shr();
  3151. static void rw_add();
  3152. static void rw_sub();
  3153. static void rw_mul();
  3154. static void rw_div();
  3155. static void rw_rem();
  3156. static void rw_not();
  3157. static void rw_neg();
  3158. static void rw_asgn();
  3159. static void rw_enter();
  3160. static void rw_leave();
  3161. static void rw_match();
  3162. static void rw_jmp();
  3163. static void rw_jne();
  3164. static void rw_je();
  3165. static void rw_adds();
  3166. static void rw_adjstk();
  3167. static void rw_popn();
  3168. static void rw_pusha();
  3169. static void rw_popa();
  3170. static void rw_call();
  3171. static void rw_builtin();
  3172. static void rw_attrs();
  3173. static void rw_attrs0();
  3174. static void rw_attrn();
  3175. static void rw_attrn0();
  3176. static void rw_attrcheck();
  3177. static void rw_attrcheck0();
  3178. static void rw_attrasgn();
  3179. static void rw_attrasgn0();
  3180. static void rw_attr_delete();
  3181. static void rw_attr_delete0();
  3182. INSTR bin_codetab[] = {
  3183. rw_eq,
  3184. rw_ne,
  3185. rw_lt,
  3186. rw_le,
  3187. rw_gt,
  3188. rw_ge,
  3189. rw_b_and,
  3190. rw_b_xor,
  3191. rw_b_or,
  3192. NULL,
  3193. NULL,
  3194. rw_shl,
  3195. rw_shr,
  3196. rw_add,
  3197. rw_sub,
  3198. rw_mul,
  3199. rw_div,
  3200. rw_rem,
  3201. };
  3202. INSTR bin_string_codetab[] = {
  3203. rw_eqs,
  3204. rw_nes,
  3205. rw_lts,
  3206. rw_les,
  3207. rw_gts,
  3208. rw_ges,
  3209. NULL,
  3210. NULL,
  3211. NULL,
  3212. NULL,
  3213. NULL,
  3214. NULL,
  3215. NULL,
  3216. rw_adds,
  3217. NULL,
  3218. NULL,
  3219. NULL,
  3220. NULL
  3221. };
  3222. INSTR coerce_tab[Max_datatype][Max_datatype] = {
  3223. /* Undefined Integer String */
  3224. /* Undefined */ { NULL, NULL, NULL },
  3225. /* Integer */ { NULL, NULL, rw_i2s },
  3226. /* String */ { NULL, rw_s2i, NULL },
  3227. };
  3228. static void check_codesize(int delta);
  3229. static int code(INSTR instr);
  3230. static int data(int val);
  3231. static int data_str(char *ptr);
  3232. static void add_target(NOP_MTX *mtx, pctr_t pc);
  3233. void
  3234. add_target(NOP_MTX *mtx, pctr_t pc)
  3235. {
  3236. TGT_MTX *tgt = (TGT_MTX *)mtx_alloc(Target);
  3237. tgt->next = (MTX*)mtx->tgt;
  3238. mtx->tgt = tgt;
  3239. tgt->pc = pc;
  3240. }
  3241. void
  3242. fixup_target(NOP_MTX *mtx, pctr_t pc)
  3243. {
  3244. TGT_MTX *tgt;
  3245. for (tgt = (TGT_MTX*)mtx->tgt; tgt; tgt = (TGT_MTX*)tgt->next)
  3246. rw_code[tgt->pc] = (INSTR)pc;
  3247. mtx->tgt = NULL;
  3248. }
  3249. pctr_t
  3250. codegen()
  3251. {
  3252. MTX *mtx;
  3253. function->entry = rw_pc;
  3254. for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
  3255. switch (mtx->gen.type) {
  3256. case Generic:
  3257. case Return:
  3258. default:
  3259. grad_log(GRAD_LOG_CRIT,
  3260. "INTERNAL ERROR: codegen stumbled accross generic matrix!");
  3261. errcnt++;
  3262. return 0;
  3263. case Nop:
  3264. /* Fix-up the references */
  3265. fixup_target(&mtx->nop, rw_pc);
  3266. mtx->nop.pc = rw_pc;
  3267. break;
  3268. case Stop:
  3269. break;
  3270. case Enter:
  3271. code(rw_enter);
  3272. data(mtx->frame.stacksize);
  3273. break;
  3274. case Leave:
  3275. code(rw_leave);
  3276. break;
  3277. case Constant:
  3278. switch (mtx->cnst.datatype) {
  3279. case Integer:
  3280. code(rw_pushn);
  3281. data(mtx->cnst.datum.ival);
  3282. break;
  3283. case String:
  3284. code(rw_pushs);
  3285. data_str(mtx->cnst.datum.sval.data);
  3286. break;
  3287. default:
  3288. grad_insist_fail("Unknown data type");
  3289. }
  3290. break;
  3291. case Matchref:
  3292. code(rw_pushref);
  3293. data(mtx->ref.num);
  3294. break;
  3295. case Variable:
  3296. /* Variable dereference.
  3297. */
  3298. code(rw_pushv);
  3299. data(mtx->var.var->offset);
  3300. break;
  3301. case Unary:
  3302. switch (mtx->un.opcode) {
  3303. case Not:
  3304. code(rw_not);
  3305. break;
  3306. case Neg:
  3307. code(rw_neg);
  3308. break;
  3309. default:
  3310. grad_insist_fail("Unexpected opcode");
  3311. }
  3312. break;
  3313. case Binary:
  3314. if (mtx->bin.arg[0]->gen.datatype == String)
  3315. code(bin_string_codetab[mtx->bin.opcode]);
  3316. else
  3317. code(bin_codetab[mtx->bin.opcode]);
  3318. break;
  3319. case Cond:
  3320. /*FIXME: this needs optimization */
  3321. code(rw_jne);
  3322. add_target(&mtx->cond.if_true->nop, rw_pc);
  3323. code(NULL);
  3324. if (mtx->cond.if_false) {
  3325. code(rw_jmp);
  3326. add_target(&mtx->cond.if_false->nop, rw_pc);
  3327. code(NULL);
  3328. }
  3329. break;
  3330. case Asgn:
  3331. code(rw_asgn);
  3332. data(mtx->asgn.lval->offset);
  3333. break;
  3334. case Match:
  3335. code(rw_match);
  3336. code((INSTR)mtx->match.rx);
  3337. if (mtx->match.negated)
  3338. code(rw_not);
  3339. break;
  3340. case Coercion:
  3341. code(coerce_tab[mtx->coerce.arg->gen.datatype][mtx->coerce.datatype]);
  3342. break;
  3343. case Jump:
  3344. code(rw_jmp);
  3345. add_target(&mtx->jump.dest->nop, rw_pc);
  3346. code(NULL);
  3347. break;
  3348. case Branch:
  3349. code(mtx->branch.cond ? rw_jne : rw_je);
  3350. add_target(&mtx->branch.dest->nop, rw_pc);
  3351. code(NULL);
  3352. break;
  3353. case Call:
  3354. code(rw_call);
  3355. code((INSTR) mtx->call.fun->entry);
  3356. code(rw_adjstk);
  3357. data(mtx->call.nargs);
  3358. break;
  3359. case Builtin:
  3360. code(rw_builtin);
  3361. code(mtx->btin.fun);
  3362. code(rw_adjstk);
  3363. data(mtx->btin.nargs);
  3364. break;
  3365. case Pop:
  3366. code(rw_popn);
  3367. break;
  3368. case Popa:
  3369. code(rw_popa);
  3370. break;
  3371. case Pusha:
  3372. code(rw_pusha);
  3373. break;
  3374. case Attr:
  3375. switch (mtx->attr.datatype) {
  3376. case Integer:
  3377. if (mtx->attr.index)
  3378. code(rw_attrn);
  3379. else
  3380. code(rw_attrn0);
  3381. break;
  3382. case String:
  3383. if (mtx->attr.index)
  3384. code(rw_attrs);
  3385. else
  3386. code(rw_attrs0);
  3387. break;
  3388. default:
  3389. grad_insist_fail("Unknown data type");
  3390. }
  3391. data(mtx->attr.attrno);
  3392. break;
  3393. case Attr_check:
  3394. if (mtx->attr.index)
  3395. code(rw_attrcheck);
  3396. else
  3397. code(rw_attrcheck0);
  3398. data(mtx->attr.attrno);
  3399. break;
  3400. case Attr_asgn:
  3401. if (mtx->attr.index)
  3402. code(rw_attrasgn);
  3403. else
  3404. code(rw_attrasgn0);
  3405. data(mtx->attr.attrno);
  3406. break;
  3407. case Attr_delete:
  3408. if (mtx->attr.index)
  3409. code(rw_attr_delete);
  3410. else
  3411. code(rw_attr_delete0);
  3412. data(mtx->attr.attrno);
  3413. break;
  3414. }
  3415. }
  3416. /*
  3417. * Second pass: fixup backward references
  3418. */
  3419. for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
  3420. if (mtx->gen.type == Nop)
  3421. fixup_target(&mtx->nop, mtx->nop.pc);
  3422. }
  3423. #if defined(MAINTAINER_MODE)
  3424. if (GRAD_DEBUG_LEVEL(25)) {
  3425. FILE *fp = debug_open_file();
  3426. fprintf(fp, "entry: %d, size %d\n",
  3427. function->entry, rw_pc - function->entry);
  3428. fclose(fp);
  3429. }
  3430. #endif
  3431. return function->entry;
  3432. }
  3433. void
  3434. check_codesize(int delta)
  3435. {
  3436. if (rw_pc + delta >= rw_codesize) {
  3437. INSTR *p = grad_emalloc((rw_codesize + 4096) * sizeof(rw_code[0]));
  3438. memcpy(p, rw_code, rw_codesize * sizeof(rw_code[0]));
  3439. grad_free(rw_code);
  3440. rw_code = p;
  3441. rw_codesize += 4096;
  3442. }
  3443. }
  3444. int
  3445. code(INSTR instr)
  3446. {
  3447. check_codesize(1);
  3448. rw_code[rw_pc] = instr;
  3449. return rw_pc++;
  3450. }
  3451. int
  3452. data(int val)
  3453. {
  3454. return code((INSTR)(RWSTYPE)val);
  3455. }
  3456. int
  3457. data_str(char *ptr)
  3458. {
  3459. int len = strlen(ptr) + 1;
  3460. RWSTYPE delta = (len + sizeof(rw_code[0])) / sizeof(rw_code[0]);
  3461. check_codesize(delta+1);
  3462. rw_code[rw_pc++] = (INSTR)delta;
  3463. memcpy(rw_code + rw_pc, ptr, len);
  3464. rw_pc += delta;
  3465. return rw_pc;
  3466. }
  3467. /* ****************************************************************************
  3468. * Regular expressions
  3469. */
  3470. COMP_REGEX *
  3471. rx_alloc(regex_t *regex, int nmatch)
  3472. {
  3473. COMP_REGEX *rx;
  3474. rx = grad_emalloc(sizeof(*rx));
  3475. rx->regex = *regex;
  3476. rx->nmatch = nmatch;
  3477. rw_list_insert(&function->rx_list, NULL, function->rx_list, rx, 1);
  3478. return rx;
  3479. }
  3480. void
  3481. rx_free(COMP_REGEX *rx)
  3482. {
  3483. COMP_REGEX *next;
  3484. while (rx) {
  3485. next = rx->next;
  3486. regfree(&rx->regex);
  3487. grad_free(rx);
  3488. rx = next;
  3489. }
  3490. }
  3491. COMP_REGEX *
  3492. compile_regexp(char *str)
  3493. {
  3494. char *p;
  3495. regex_t regex;
  3496. int nmatch;
  3497. int rc = regcomp(&regex, str, regcomp_flags);
  3498. if (rc) {
  3499. char errbuf[512];
  3500. regerror(rc, &regex, errbuf, sizeof(errbuf));
  3501. grad_log_loc(GRAD_LOG_ERR, &locus,
  3502. _("regexp error: %s"),
  3503. errbuf);
  3504. return NULL;
  3505. }
  3506. /* count the number of matches */
  3507. nmatch = 0;
  3508. for (p = str; *p; ) {
  3509. if (*p == '\\')
  3510. if (p[1] == '(') {
  3511. nmatch++;
  3512. p += 2;
  3513. continue;
  3514. }
  3515. p++;
  3516. }
  3517. return rx_alloc(&regex, nmatch);
  3518. }
  3519. void
  3520. function_delete()
  3521. {
  3522. if (function) {
  3523. grad_symtab_delete(rewrite_tab, (grad_symbol_t*)function);
  3524. function_cleanup();
  3525. }
  3526. }
  3527. void
  3528. function_cleanup()
  3529. {
  3530. function = NULL;
  3531. }
  3532. /* ****************************************************************************
  3533. * Runtime functions
  3534. */
  3535. /*
  3536. * Push a number on stack
  3537. */
  3538. int
  3539. pushn(RWSTYPE n)
  3540. {
  3541. if (mach.st >= mach.ht) {
  3542. /*FIXME: gc();*/
  3543. GRAD_DEBUG2(1, "st=%d, ht=%d", mach.st, mach.ht);
  3544. rw_error(_("out of pushdown space"));
  3545. }
  3546. mach.stack[mach.st++] = n;
  3547. return 0;
  3548. }
  3549. /*
  3550. * Push a string on stack
  3551. */
  3552. void
  3553. pushs(RWSTYPE *sptr, size_t size, int len)
  3554. {
  3555. if (mach.ht - len - 1 <= mach.st) {
  3556. /* Heap overrun: */
  3557. /*gc(); */
  3558. rw_error(_("heap overrun"));
  3559. }
  3560. while (len)
  3561. mach.stack[mach.ht--] = sptr[--len];
  3562. mach.stack[mach.ht--] = size;
  3563. pushn((RWSTYPE) (mach.stack + mach.ht + 1));
  3564. }
  3565. void
  3566. pushstr(const char *str, int len)
  3567. {
  3568. RWSTYPE *p = heap_reserve(sizeof(RWSTYPE) + len + 1);
  3569. char *s = (char*)(p + 1);
  3570. memcpy(s, str, len);
  3571. s[len] = 0;
  3572. p[0] = len;
  3573. pushn((RWSTYPE)p);
  3574. }
  3575. #define B2RW(s) (s + sizeof(mach.stack[0]) - 1) / sizeof(mach.stack[0])
  3576. RWSTYPE *
  3577. heap_reserve(int size)
  3578. {
  3579. size_t words = B2RW(size);
  3580. if (mach.ht - words <= mach.st) {
  3581. /* Heap overrun: */
  3582. gc();
  3583. if (mach.ht - words <= mach.st)
  3584. rw_error(_("heap overrun"));
  3585. }
  3586. mach.ht -= words;
  3587. return mach.stack + mach.ht--;
  3588. }
  3589. /* Temporary space functions */
  3590. char *
  3591. temp_space_create()
  3592. {
  3593. return (char*)(mach.stack + mach.st);
  3594. }
  3595. size_t
  3596. temp_space_size()
  3597. {
  3598. return (mach.ht - mach.st)*sizeof(mach.stack[0]);
  3599. }
  3600. void
  3601. temp_space_copy(char **baseptr, char *text, size_t size)
  3602. {
  3603. size_t len = (size + sizeof(mach.stack[0])) / sizeof(mach.stack[0]);
  3604. if (*baseptr + len >= (char*)(mach.stack + mach.ht))
  3605. rw_error(_("out of heap space"));
  3606. memcpy(*baseptr, text, size);
  3607. *baseptr += size;
  3608. }
  3609. RWSTYPE *
  3610. temp_space_fix(char *end)
  3611. {
  3612. size_t len, size;
  3613. char *base = (char*)(mach.stack + mach.st);
  3614. temp_space_copy(&end, "", 0);
  3615. size = end - base;
  3616. len = B2RW(size);
  3617. mach.ht -= len;
  3618. memmove(mach.stack + mach.ht, base, size);
  3619. mach.stack[--mach.ht] = strlen(base);
  3620. return mach.stack + mach.ht--;
  3621. }
  3622. /*
  3623. * Pop number from stack and store into NP.
  3624. */
  3625. int
  3626. cpopn(RWSTYPE *np)
  3627. {
  3628. if (mach.st <= 0) {
  3629. rw_error(_("out of popup"));
  3630. }
  3631. *np = mach.stack[--mach.st];
  3632. return 0;
  3633. }
  3634. /*
  3635. * Pop the number from stack without error checking. checkpop() function
  3636. * should be called before calling this one.
  3637. */
  3638. RWSTYPE
  3639. popn()
  3640. {
  3641. return mach.stack[--mach.st];
  3642. }
  3643. void
  3644. mem2string(grad_string_t *p, RWSTYPE *loc)
  3645. {
  3646. p->size = loc[0];
  3647. p->data = (unsigned char*) (loc + 1);
  3648. }
  3649. void
  3650. poparr(grad_string_t *p)
  3651. {
  3652. mem2string(p, (RWSTYPE*) popn());
  3653. }
  3654. RWSTYPE
  3655. tos()
  3656. {
  3657. return mach.stack[mach.st-1];
  3658. }
  3659. /*
  3660. * Check if the stack contains at list CNT elements.
  3661. */
  3662. void
  3663. checkpop(int cnt)
  3664. {
  3665. if (mach.st < cnt)
  3666. rw_error(_("out of popup"));
  3667. }
  3668. /*
  3669. * Push a backreference value on stack.
  3670. * Arguments: str -- input string
  3671. * from -- start of reference in string
  3672. * to -- end of reference in string
  3673. */
  3674. void
  3675. pushref(char *str, int from, int to)
  3676. {
  3677. pushstr(str + from, to - from);
  3678. }
  3679. /*
  3680. * Create a stack frame and enter the function
  3681. */
  3682. void
  3683. enter(int n)
  3684. {
  3685. pushn(mach.sb);
  3686. mach.sb = mach.st;
  3687. mach.st += n;
  3688. }
  3689. /*
  3690. * Destroy the stack frame and leave the function
  3691. */
  3692. void
  3693. leave()
  3694. {
  3695. /* Save return value */
  3696. mach.rA = popn();
  3697. /* Restore stack frame */
  3698. mach.st = mach.sb;
  3699. mach.sb = popn();
  3700. mach.pc = (pctr_t) popn();
  3701. }
  3702. RWSTYPE
  3703. getarg(int num)
  3704. {
  3705. return mach.stack[mach.sb - (STACK_BASE + num)];
  3706. }
  3707. /* ****************************************************************************
  3708. * Instructions
  3709. */
  3710. static int
  3711. rw_error(const char *msg)
  3712. {
  3713. grad_log(GRAD_LOG_ERR,
  3714. "%s: %s",
  3715. _("rewrite runtime error"), msg);
  3716. longjmp(mach.jmp, 1);
  3717. /*NOTREACHED*/
  3718. }
  3719. static int
  3720. rw_error_free(char *msg)
  3721. {
  3722. grad_log(GRAD_LOG_ERR,
  3723. "%s: %s",
  3724. _("rewrite runtime error"), msg);
  3725. free(msg);
  3726. longjmp(mach.jmp, 1);
  3727. /*NOTREACHED*/
  3728. }
  3729. void
  3730. rw_call()
  3731. {
  3732. pctr_t pc = (pctr_t) rw_code[mach.pc++];
  3733. pushn(mach.pc); /* save return address */
  3734. mach.pc = pc;
  3735. }
  3736. void
  3737. rw_adjstk()
  3738. {
  3739. int delta = (int) rw_code[mach.pc++];
  3740. mach.st -= delta;
  3741. pushn(mach.rA); /* Push the return back on stack */
  3742. }
  3743. void
  3744. rw_enter()
  3745. {
  3746. /*FIXME: runtime checking */
  3747. int n = (int) rw_code[mach.pc++];
  3748. enter(n);
  3749. }
  3750. void
  3751. rw_leave()
  3752. {
  3753. leave();
  3754. }
  3755. /*
  3756. * Push a number on stack
  3757. */
  3758. void
  3759. rw_pushn()
  3760. {
  3761. RWSTYPE n = (RWSTYPE) rw_code[mach.pc++];
  3762. pushn(n);
  3763. }
  3764. /*
  3765. * Push a reference value on stack
  3766. */
  3767. void
  3768. rw_pushref()
  3769. {
  3770. int i = (int) rw_code[mach.pc++];
  3771. pushref(mach.sA, mach.pmatch[i].rm_so, mach.pmatch[i].rm_eo);
  3772. }
  3773. /*
  3774. * Push a variable on stack
  3775. */
  3776. void
  3777. rw_pushv()
  3778. {
  3779. stkoff_t n = (stkoff_t) rw_code[mach.pc++];
  3780. pushn(mach.stack[mach.sb + n]);
  3781. }
  3782. void
  3783. rw_pushs()
  3784. {
  3785. int len = (int) rw_code[mach.pc++];
  3786. RWSTYPE *sptr = (RWSTYPE*) (rw_code + mach.pc);
  3787. mach.pc += len;
  3788. pushs(sptr, strlen((char*)sptr), len);
  3789. }
  3790. /*
  3791. * Assign a value to a variable
  3792. */
  3793. void
  3794. rw_asgn()
  3795. {
  3796. stkoff_t off = (stkoff_t) rw_code[mach.pc++];
  3797. RWSTYPE n;
  3798. cpopn(&n);
  3799. mach.stack[mach.sb + off] = n;
  3800. pushn(n);
  3801. }
  3802. void
  3803. assert_request_presence()
  3804. {
  3805. if (!mach.req)
  3806. rw_error(_("no request supplied"));
  3807. }
  3808. /* Check if the A/V pair is supplied in the request
  3809. */
  3810. void
  3811. rw_attrcheck0()
  3812. {
  3813. int attr = (int) rw_code[mach.pc++];
  3814. pushn(grad_avl_find(AVPLIST(&mach), attr) != NULL);
  3815. }
  3816. void
  3817. rw_attrcheck()
  3818. {
  3819. int attr = (int) rw_code[mach.pc++];
  3820. RWSTYPE index;
  3821. cpopn(&index);
  3822. pushn(grad_avl_find_n(AVPLIST(&mach), attr, index) != NULL);
  3823. }
  3824. /*
  3825. * Assign a value to an A/V pair
  3826. */
  3827. void
  3828. attrasgn_internal(int attr, grad_avp_t *pair, RWSTYPE val)
  3829. {
  3830. grad_string_t str;
  3831. assert_request_presence();
  3832. if (!pair) {
  3833. pair = grad_avp_create(attr);
  3834. if (!pair)
  3835. rw_error(_("can't create A/V pair"));
  3836. grad_avl_add_pair(&mach.req->avlist, pair);
  3837. }
  3838. switch (pair->type) {
  3839. case GRAD_TYPE_STRING:
  3840. case GRAD_TYPE_DATE:
  3841. mem2string(&str, (RWSTYPE*)val);
  3842. grad_free(pair->avp_strvalue);
  3843. pair->avp_strvalue = grad_malloc(str.size+1);
  3844. memcpy(pair->avp_strvalue, str.data, str.size);
  3845. pair->avp_strvalue[str.size] = 0;
  3846. pair->avp_strlength = str.size;
  3847. break;
  3848. case GRAD_TYPE_INTEGER:
  3849. case GRAD_TYPE_IPADDR:
  3850. pair->avp_lvalue = val;
  3851. break;
  3852. }
  3853. pushn(val);
  3854. }
  3855. void
  3856. rw_attrasgn0()
  3857. {
  3858. int attr = (int) rw_code[mach.pc++];
  3859. RWSTYPE val;
  3860. cpopn(&val);
  3861. attrasgn_internal(attr, grad_avl_find(AVPLIST(&mach), attr), val);
  3862. }
  3863. void
  3864. rw_attrasgn()
  3865. {
  3866. int attr = (int) rw_code[mach.pc++];
  3867. RWSTYPE val;
  3868. RWSTYPE index;
  3869. cpopn(&val);
  3870. cpopn(&index);
  3871. attrasgn_internal(attr, grad_avl_find_n(AVPLIST(&mach), attr, index),
  3872. val);
  3873. }
  3874. void
  3875. rw_attrs0()
  3876. {
  3877. int attr = (int) rw_code[mach.pc++];
  3878. grad_avp_t *pair;
  3879. if ((pair = grad_avl_find(AVPLIST(&mach), attr)) == NULL)
  3880. pushstr("", 0);
  3881. else if (pair->prop & GRAD_AP_ENCRYPT) {
  3882. char string[GRAD_STRING_LENGTH+1];
  3883. int len;
  3884. req_decrypt_password(string, mach.req, pair);
  3885. len = strlen(string);
  3886. pushstr(string, len);
  3887. } else
  3888. pushstr(pair->avp_strvalue, pair->avp_strlength);
  3889. }
  3890. void
  3891. rw_attrn0()
  3892. {
  3893. int attr = (int) rw_code[mach.pc++];
  3894. grad_avp_t *pair;
  3895. if ((pair = grad_avl_find(AVPLIST(&mach), attr)) == NULL)
  3896. pushn(0);
  3897. else
  3898. pushn(pair->avp_lvalue);
  3899. }
  3900. void
  3901. rw_attrs()
  3902. {
  3903. int attr = (int) rw_code[mach.pc++];
  3904. grad_avp_t *pair;
  3905. RWSTYPE index;
  3906. cpopn(&index);
  3907. if ((pair = grad_avl_find_n(AVPLIST(&mach), attr, index)) == NULL)
  3908. pushstr("", 0);
  3909. else
  3910. pushstr(pair->avp_strvalue, pair->avp_strlength);
  3911. }
  3912. void
  3913. rw_attrn()
  3914. {
  3915. int attr = (int) rw_code[mach.pc++];
  3916. grad_avp_t *pair;
  3917. RWSTYPE index;
  3918. cpopn(&index);
  3919. if ((pair = grad_avl_find_n(AVPLIST(&mach), attr, index)) == NULL)
  3920. pushn(0);
  3921. else
  3922. pushn(pair->avp_lvalue);
  3923. }
  3924. void
  3925. rw_attr_delete0()
  3926. {
  3927. int attr = (int) rw_code[mach.pc++];
  3928. grad_avl_delete(&mach.req->avlist, attr);
  3929. }
  3930. void
  3931. rw_attr_delete()
  3932. {
  3933. int attr = (int) rw_code[mach.pc++];
  3934. RWSTYPE index;
  3935. assert_request_presence();
  3936. cpopn(&index);
  3937. grad_avl_delete_n(&mach.req->avlist, attr, index);
  3938. }
  3939. /*
  3940. * Pop (and discard) a value from stack
  3941. */
  3942. void
  3943. rw_popn()
  3944. {
  3945. RWSTYPE n;
  3946. cpopn(&n);
  3947. }
  3948. /*
  3949. * Pop a value from stack into the accumulator
  3950. */
  3951. void
  3952. rw_popa()
  3953. {
  3954. cpopn(&mach.rA);
  3955. }
  3956. /*
  3957. * Push accumulator on stack
  3958. */
  3959. void
  3960. rw_pusha()
  3961. {
  3962. pushn(mach.rA);
  3963. }
  3964. /*
  3965. * String concatenation
  3966. */
  3967. void
  3968. rw_adds()
  3969. {
  3970. grad_string_t s1, s2;
  3971. RWSTYPE *p;
  3972. char *s;
  3973. checkpop(2);
  3974. poparr(&s2);
  3975. poparr(&s1);
  3976. p = heap_reserve(sizeof(RWSTYPE) + s1.size + s2.size + 1);
  3977. s = (char*)(p + 1);
  3978. memcpy(s, s1.data, s1.size);
  3979. s += s1.size;
  3980. memcpy(s, s2.data, s2.size);
  3981. s += s2.size;
  3982. *s = 0;
  3983. p[0] = s1.size + s2.size;
  3984. pushn((RWSTYPE)p);
  3985. }
  3986. /*
  3987. * Unary negation
  3988. */
  3989. void
  3990. rw_neg()
  3991. {
  3992. checkpop(1);
  3993. pushn(-popn());
  3994. }
  3995. /*
  3996. * Bitwise operations
  3997. */
  3998. void
  3999. rw_b_and()
  4000. {
  4001. int n1, n2;
  4002. checkpop(2);
  4003. n2 = popn();
  4004. n1 = popn();
  4005. pushn(n1 & n2);
  4006. }
  4007. void
  4008. rw_b_or()
  4009. {
  4010. int n1, n2;
  4011. checkpop(2);
  4012. n2 = popn();
  4013. n1 = popn();
  4014. pushn(n1 | n2);
  4015. }
  4016. void
  4017. rw_b_xor()
  4018. {
  4019. int n1, n2;
  4020. checkpop(2);
  4021. n2 = popn();
  4022. n1 = popn();
  4023. pushn(n1 ^ n2);
  4024. }
  4025. void
  4026. rw_shl()
  4027. {
  4028. int n1, n2;
  4029. checkpop(2);
  4030. n2 = popn();
  4031. n1 = popn();
  4032. pushn(n1 << n2);
  4033. }
  4034. void
  4035. rw_shr()
  4036. {
  4037. int n1, n2;
  4038. checkpop(2);
  4039. n2 = popn();
  4040. n1 = popn();
  4041. pushn(n1 >> n2);
  4042. }
  4043. /*
  4044. * Addition
  4045. */
  4046. void
  4047. rw_add()
  4048. {
  4049. int n1, n2;
  4050. checkpop(2);
  4051. n2 = popn();
  4052. n1 = popn();
  4053. pushn(n1+n2);
  4054. }
  4055. /*
  4056. * Subtraction
  4057. */
  4058. void
  4059. rw_sub()
  4060. {
  4061. int n1, n2;
  4062. checkpop(2);
  4063. n2 = popn();
  4064. n1 = popn();
  4065. pushn(n1-n2);
  4066. }
  4067. /*
  4068. * Multiplication
  4069. */
  4070. void
  4071. rw_mul()
  4072. {
  4073. int n1, n2;
  4074. checkpop(2);
  4075. n2 = popn();
  4076. n1 = popn();
  4077. pushn(n1*n2);
  4078. }
  4079. /*
  4080. * Division
  4081. */
  4082. void
  4083. rw_div()
  4084. {
  4085. int n1, n2;
  4086. checkpop(2);
  4087. n2 = popn();
  4088. n1 = popn();
  4089. if (n2 == 0)
  4090. rw_error(_("division by zero!"));
  4091. pushn(n1/n2);
  4092. }
  4093. /*
  4094. * Remainder
  4095. */
  4096. void
  4097. rw_rem()
  4098. {
  4099. int n1, n2;
  4100. checkpop(2);
  4101. n2 = popn();
  4102. n1 = popn();
  4103. if (n2 == 0)
  4104. rw_error(_("division by zero!"));
  4105. pushn(n1%n2);
  4106. }
  4107. /* Type conversion */
  4108. void
  4109. rw_i2s()
  4110. {
  4111. int n = popn();
  4112. char buf[64];
  4113. snprintf(buf, sizeof(buf), "%d", n);
  4114. pushstr(buf, strlen(buf));
  4115. }
  4116. void
  4117. rw_s2i()
  4118. {
  4119. grad_string_t s;
  4120. mem2string(&s, (RWSTYPE *)popn());
  4121. pushn(strtol(s.data, NULL, 0));
  4122. }
  4123. void
  4124. rw_eq()
  4125. {
  4126. int n1, n2;
  4127. checkpop(2);
  4128. n2 = popn();
  4129. n1 = popn();
  4130. pushn(n1 == n2);
  4131. }
  4132. void
  4133. rw_ne()
  4134. {
  4135. int n1, n2;
  4136. checkpop(2);
  4137. n2 = popn();
  4138. n1 = popn();
  4139. pushn(n1 != n2);
  4140. }
  4141. void
  4142. rw_lt()
  4143. {
  4144. int n1, n2;
  4145. checkpop(2);
  4146. n2 = popn();
  4147. n1 = popn();
  4148. pushn(n1 < n2);
  4149. }
  4150. void
  4151. rw_le()
  4152. {
  4153. int n1, n2;
  4154. checkpop(2);
  4155. n2 = popn();
  4156. n1 = popn();
  4157. pushn(n1 <= n2);
  4158. }
  4159. void
  4160. rw_gt()
  4161. {
  4162. int n1, n2;
  4163. checkpop(2);
  4164. n2 = popn();
  4165. n1 = popn();
  4166. pushn(n1 > n2);
  4167. }
  4168. void
  4169. rw_ge()
  4170. {
  4171. int n1, n2;
  4172. checkpop(2);
  4173. n2 = popn();
  4174. n1 = popn();
  4175. pushn(n1 >= n2);
  4176. }
  4177. void
  4178. rw_eqs()
  4179. {
  4180. grad_string_t s1, s2;
  4181. checkpop(2);
  4182. poparr(&s2);
  4183. poparr(&s1);
  4184. pushn(s1.size == s2.size && memcmp(s1.data, s2.data, s1.size) == 0);
  4185. }
  4186. void
  4187. rw_nes()
  4188. {
  4189. grad_string_t s1, s2;
  4190. checkpop(2);
  4191. poparr(&s2);
  4192. poparr(&s1);
  4193. pushn(!(s1.size == s2.size && memcmp(s1.data, s2.data, s1.size) == 0));
  4194. }
  4195. void
  4196. rw_lts()
  4197. {
  4198. grad_string_t s1, s2;
  4199. size_t size;
  4200. checkpop(2);
  4201. poparr(&s2);
  4202. poparr(&s1);
  4203. size = RW_MIN(s1.size, s2.size);
  4204. pushn(memcmp(s1.data, s2.data, size < 0) || s1.size < s2.size);
  4205. }
  4206. void
  4207. rw_les()
  4208. {
  4209. grad_string_t s1, s2;
  4210. size_t size;
  4211. checkpop(2);
  4212. poparr(&s2);
  4213. poparr(&s1);
  4214. size = RW_MIN(s1.size, s2.size);
  4215. pushn(memcmp(s1.data, s2.data, size <= 0) || s1.size <= s2.size);
  4216. }
  4217. void
  4218. rw_gts()
  4219. {
  4220. grad_string_t s1, s2;
  4221. size_t size;
  4222. checkpop(2);
  4223. poparr(&s2);
  4224. poparr(&s1);
  4225. size = RW_MIN(s1.size, s2.size);
  4226. pushn(memcmp(s1.data, s2.data, size > 0) || s1.size > s2.size);
  4227. }
  4228. void
  4229. rw_ges()
  4230. {
  4231. grad_string_t s1, s2;
  4232. size_t size;
  4233. checkpop(2);
  4234. poparr(&s2);
  4235. poparr(&s1);
  4236. size = RW_MIN(s1.size, s2.size);
  4237. pushn(memcmp(s1.data, s2.data, size >= 0) || s1.size >= s2.size);
  4238. }
  4239. void
  4240. rw_not()
  4241. {
  4242. int n;
  4243. checkpop(1);
  4244. n = popn();
  4245. pushn(!n);
  4246. }
  4247. static void
  4248. need_pmatch(size_t n)
  4249. {
  4250. n++;
  4251. if (mach.nmatch < n) {
  4252. grad_free(mach.pmatch);
  4253. mach.nmatch = n;
  4254. mach.pmatch = grad_emalloc(n * sizeof(mach.pmatch[0]));
  4255. }
  4256. }
  4257. void
  4258. rw_match()
  4259. {
  4260. COMP_REGEX *rx = (COMP_REGEX *)rw_code[mach.pc++];
  4261. grad_string_t s;
  4262. int rc;
  4263. poparr(&s);
  4264. need_pmatch(rx->nmatch);
  4265. mach.sA = s.data;
  4266. rc = regexec(&rx->regex, mach.sA,
  4267. rx->nmatch + 1, mach.pmatch, 0);
  4268. if (rc && GRAD_DEBUG_LEVEL(1)) {
  4269. char errbuf[512];
  4270. regerror(rc, &rx->regex,
  4271. errbuf, sizeof(errbuf));
  4272. grad_log(GRAD_LOG_DEBUG,
  4273. _("rewrite regex failure: %s. Input: %s"),
  4274. errbuf, (char*)mach.rA);
  4275. }
  4276. pushn(rc == 0);
  4277. }
  4278. void
  4279. rw_jmp()
  4280. {
  4281. pctr_t pc = (pctr_t) rw_code[mach.pc++];
  4282. mach.pc = pc;
  4283. }
  4284. void
  4285. rw_jne()
  4286. {
  4287. int n;
  4288. pctr_t pc = (pctr_t) rw_code[mach.pc++];
  4289. n = popn();
  4290. if (n != 0)
  4291. mach.pc = pc;
  4292. }
  4293. void
  4294. rw_je()
  4295. {
  4296. int n;
  4297. pctr_t pc = (pctr_t) rw_code[mach.pc++];
  4298. n = popn();
  4299. if (n == 0)
  4300. mach.pc = pc;
  4301. }
  4302. void
  4303. rw_builtin()
  4304. {
  4305. INSTR fun = (INSTR) rw_code[mach.pc++];
  4306. pushn(mach.pc);
  4307. enter(0);
  4308. fun();
  4309. leave();
  4310. }
  4311. void
  4312. run(pctr_t pc)
  4313. {
  4314. mach.pc = pc;
  4315. while (rw_code[mach.pc]) {
  4316. if (mach.pc >= rw_codesize)
  4317. rw_error(_("pc out of range"));
  4318. (*(rw_code[mach.pc++]))();
  4319. }
  4320. }
  4321. /* ****************************************************************************
  4322. * A placeholder for the garbage collector
  4323. */
  4324. void
  4325. gc()
  4326. {
  4327. }
  4328. /* ****************************************************************************
  4329. * Built-in functions
  4330. */
  4331. /*
  4332. * integer length(string s)
  4333. */
  4334. static void
  4335. bi_length()
  4336. {
  4337. grad_string_t s;
  4338. mem2string(&s, (RWSTYPE*)getarg(1));
  4339. pushn(s.size);
  4340. }
  4341. /*
  4342. * integer index(string s, integer a)
  4343. */
  4344. static void
  4345. bi_index()
  4346. {
  4347. grad_string_t s;
  4348. char *p;
  4349. int c;
  4350. mem2string(&s, (RWSTYPE*) getarg(2));
  4351. c = (int) getarg(1);
  4352. p = memchr(s.data, c, s.size);
  4353. pushn(p ? p - s.data : -1);
  4354. }
  4355. /*
  4356. * integer rindex(string s, integer a)
  4357. */
  4358. static void
  4359. bi_rindex()
  4360. {
  4361. grad_string_t s;
  4362. int i;
  4363. int c;
  4364. mem2string(&s, (RWSTYPE*) getarg(2));
  4365. for (i = s.size - 1; i >= 0; i--)
  4366. if (s.data[i] == c)
  4367. break;
  4368. pushn(i);
  4369. }
  4370. /*
  4371. * string substr(string s, int start, int length)
  4372. */
  4373. static void
  4374. bi_substr()
  4375. {
  4376. grad_string_t src;
  4377. RWSTYPE *p;
  4378. char *dest;
  4379. int start, length;
  4380. mem2string(&src, (RWSTYPE*)getarg(3));
  4381. start = getarg(2);
  4382. length = getarg(1);
  4383. if (length < 0)
  4384. length = src.size - start;
  4385. p = heap_reserve(sizeof(RWSTYPE) + length + 1);
  4386. dest = (char *)(p + 1);
  4387. if (length > 0)
  4388. memcpy(dest, src.data + start, length);
  4389. dest[length] = 0;
  4390. p[0] = length;
  4391. pushn((RWSTYPE)p);
  4392. }
  4393. static void
  4394. bi_field()
  4395. {
  4396. grad_string_t str;
  4397. char *p, *endp;
  4398. int fn = getarg(1);
  4399. char *s = "";
  4400. int len = 1;
  4401. mem2string(&str, (RWSTYPE*) getarg(2));
  4402. endp = str.data + str.size;
  4403. for (p = str.data; p < endp && fn--; ) {
  4404. /* skip initial whitespace */
  4405. while (p < endp && isspace(*p))
  4406. p++;
  4407. s = p;
  4408. len = 0;
  4409. while (p < endp && !isspace(*p)) {
  4410. p++;
  4411. len++;
  4412. }
  4413. }
  4414. if (p == endp && fn)
  4415. pushstr("", 0);
  4416. else
  4417. pushstr(s, len);
  4418. }
  4419. static void
  4420. bi_logit()
  4421. {
  4422. grad_string_t msg;
  4423. mem2string(&msg, (RWSTYPE*) getarg(1));
  4424. grad_log(GRAD_LOG_INFO, "%s", msg.data);
  4425. pushn(0);
  4426. }
  4427. static void
  4428. bi_htonl()
  4429. {
  4430. pushn(htonl(getarg(1)));
  4431. }
  4432. static void
  4433. bi_ntohl()
  4434. {
  4435. pushn(ntohl(getarg(1)));
  4436. }
  4437. static void
  4438. bi_htons()
  4439. {
  4440. pushn(htons(getarg(1) & 0xffff));
  4441. }
  4442. static void
  4443. bi_ntohs()
  4444. {
  4445. pushn(ntohs(getarg(1) & 0xffff));
  4446. }
  4447. static void
  4448. bi_inet_ntoa()
  4449. {
  4450. char buffer[GRAD_IPV4_STRING_LENGTH];
  4451. char *s = grad_ip_iptostr(getarg(1), buffer);
  4452. pushstr(s, strlen(s));
  4453. }
  4454. static void
  4455. bi_inet_aton()
  4456. {
  4457. grad_string_t s;
  4458. mem2string(&s, (RWSTYPE*)getarg(1));
  4459. /* Note: inet_aton is not always present. See lib/iputils.c */
  4460. pushn(grad_ip_strtoip(s.data));
  4461. }
  4462. static void
  4463. bi_tolower()
  4464. {
  4465. grad_string_t src;
  4466. grad_string_t dest;
  4467. int i;
  4468. mem2string(&src, (RWSTYPE*) getarg(1));
  4469. pushstr(src.data, src.size);
  4470. mem2string(&dest, (RWSTYPE*) tos());
  4471. for (i = 0; i < dest.size; i++)
  4472. dest.data[i] = tolower(dest.data[i]);
  4473. }
  4474. static void
  4475. bi_toupper()
  4476. {
  4477. grad_string_t src;
  4478. grad_string_t dest;
  4479. int i;
  4480. mem2string(&src, (RWSTYPE*) getarg(1));
  4481. pushstr(src.data, src.size);
  4482. mem2string(&dest, (RWSTYPE*) tos());
  4483. for (i = 0; i < dest.size; i++)
  4484. dest.data[i] = toupper(dest.data[i]);
  4485. }
  4486. static void
  4487. bi_request_code_string()
  4488. {
  4489. int code = (int) getarg(1);
  4490. const char *s = grad_request_code_to_name(code);
  4491. pushstr(s, strlen(s));
  4492. }
  4493. static void
  4494. bi_request_source_ip()
  4495. {
  4496. assert_request_presence();
  4497. pushn((RWSTYPE) mach.req->ipaddr);
  4498. }
  4499. static void
  4500. bi_request_source_port()
  4501. {
  4502. assert_request_presence();
  4503. pushn((RWSTYPE) mach.req->udp_port);
  4504. }
  4505. static void
  4506. bi_request_id()
  4507. {
  4508. assert_request_presence();
  4509. pushn((RWSTYPE) mach.req->id);
  4510. }
  4511. static void
  4512. bi_request_code()
  4513. {
  4514. assert_request_presence();
  4515. pushn((RWSTYPE) mach.req->code);
  4516. }
  4517. static void
  4518. bi_nas_name()
  4519. {
  4520. grad_nas_t *nas;
  4521. grad_uint32_t ip = (grad_uint32_t) getarg(1);
  4522. if ((nas = grad_nas_lookup_ip(ip)) != NULL) {
  4523. char *s = nas->shortname[0] ? nas->shortname : nas->longname;
  4524. pushstr(s, strlen(s));
  4525. } else {
  4526. char nasname[GRAD_MAX_LONGNAME];
  4527. grad_ip_gethostname(ip, nasname, sizeof(nasname));
  4528. pushstr(nasname, strlen(nasname));
  4529. }
  4530. }
  4531. static void
  4532. bi_nas_short_name()
  4533. {
  4534. grad_nas_t *nas;
  4535. grad_uint32_t ip = (grad_uint32_t) getarg(1);
  4536. if ((nas = grad_nas_lookup_ip(ip)) && nas->shortname[0]) {
  4537. pushstr(nas->shortname, strlen(nas->shortname));
  4538. } else {
  4539. char nasname[GRAD_MAX_LONGNAME];
  4540. grad_ip_gethostname(ip, nasname, sizeof(nasname));
  4541. pushstr(nasname, strlen(nasname));
  4542. }
  4543. }
  4544. static void
  4545. bi_nas_full_name()
  4546. {
  4547. grad_nas_t *nas;
  4548. grad_uint32_t ip = (grad_uint32_t) getarg(1);
  4549. if ((nas = grad_nas_lookup_ip(ip)) != NULL) {
  4550. pushstr(nas->longname, strlen(nas->longname));
  4551. } else {
  4552. char nasname[GRAD_MAX_LONGNAME];
  4553. grad_ip_gethostname(ip, nasname, sizeof(nasname));
  4554. pushstr(nasname, strlen(nasname));
  4555. }
  4556. }
  4557. static void
  4558. bi_gethostbyaddr()
  4559. {
  4560. grad_uint32_t ip = (grad_uint32_t) getarg(1);
  4561. char nasname[GRAD_MAX_LONGNAME];
  4562. grad_ip_gethostname(ip, nasname, sizeof(nasname));
  4563. pushstr(nasname, strlen(nasname));
  4564. }
  4565. static void
  4566. bi_gethostbyname()
  4567. {
  4568. grad_string_t s;
  4569. mem2string(&s, (RWSTYPE*)getarg(1));
  4570. pushn((RWSTYPE) grad_ip_gethostaddr(s.data));
  4571. }
  4572. static void
  4573. bi_time()
  4574. {
  4575. pushn((RWSTYPE) time(NULL));
  4576. }
  4577. static void
  4578. bi_strftime()
  4579. {
  4580. struct tm *tm;
  4581. char *base;
  4582. time_t t = (time_t) getarg(1);
  4583. grad_string_t fmt;
  4584. size_t n;
  4585. mem2string(&fmt, (RWSTYPE*) getarg(2));
  4586. tm = localtime(&t);
  4587. base = temp_space_create();
  4588. n = strftime(base, temp_space_size(), fmt.data, tm);
  4589. pushstr(base, n);
  4590. }
  4591. static void
  4592. rw_regerror(const char *prefix, regex_t *rx, int rc)
  4593. {
  4594. size_t sz = regerror(rc, rx, NULL, 0);
  4595. char *errbuf = malloc(sz + strlen (prefix) + 1);
  4596. if (!errbuf)
  4597. rw_error(prefix);
  4598. else {
  4599. strcpy (errbuf, prefix);
  4600. regerror(rc, rx, errbuf + strlen(prefix), sz);
  4601. rw_error_free(errbuf);
  4602. }
  4603. }
  4604. enum subst_segment_type {
  4605. subst_text, /* pure text */
  4606. subst_ref, /* back reference (\NN) */
  4607. subst_match /* substitute whole match (&) */
  4608. };
  4609. struct subst_segment {
  4610. enum subst_segment_type type;
  4611. union {
  4612. struct {
  4613. char *ptr;
  4614. size_t len;
  4615. } text; /* type == subst_text */
  4616. size_t ref; /* type == subst_ref */
  4617. } v;
  4618. };
  4619. static void
  4620. add_text_segment(grad_list_t *lst, char *ptr, char *end)
  4621. {
  4622. struct subst_segment *seg;
  4623. if (ptr >= end)
  4624. return;
  4625. seg = grad_emalloc(sizeof(*seg));
  4626. seg->type = subst_text;
  4627. seg->v.text.ptr = ptr;
  4628. seg->v.text.len = end - ptr;
  4629. grad_list_append(lst, seg);
  4630. }
  4631. static void
  4632. add_match_segment(grad_list_t *lst)
  4633. {
  4634. struct subst_segment *seg = grad_emalloc(sizeof(*seg));
  4635. seg->type = subst_match;
  4636. grad_list_append(lst, seg);
  4637. }
  4638. static void
  4639. add_ref_segment(grad_list_t *lst, size_t ref)
  4640. {
  4641. struct subst_segment *seg = grad_emalloc(sizeof(*seg));
  4642. seg->type = subst_ref;
  4643. seg->v.ref = ref;
  4644. grad_list_append(lst, seg);
  4645. }
  4646. grad_list_t *
  4647. subst_create(char *text)
  4648. {
  4649. char *p;
  4650. grad_list_t *lst = grad_list_create();
  4651. if (!lst)
  4652. return lst;
  4653. p = text;
  4654. while (*p) {
  4655. if (*p == '\\' && p[1]) {
  4656. if (p[1] == '&') {
  4657. add_text_segment(lst, text, p);
  4658. text = ++p;
  4659. p++;
  4660. } else if (p[1] == '\\') {
  4661. add_text_segment(lst, text, p+1);
  4662. p += 2;
  4663. text = p;
  4664. } else if (isdigit(p[1])) {
  4665. size_t ref;
  4666. char *q;
  4667. add_text_segment(lst, text, p);
  4668. ref = strtoul(p+1, &q, 10);
  4669. add_ref_segment(lst, ref);
  4670. text = p = q;
  4671. } else {
  4672. add_text_segment(lst, text, p);
  4673. text = ++p;
  4674. }
  4675. } else if (*p == '&') {
  4676. add_text_segment(lst, text, p);
  4677. add_match_segment(lst);
  4678. text = ++p;
  4679. } else
  4680. p++;
  4681. }
  4682. add_text_segment(lst, text, p);
  4683. return lst;
  4684. }
  4685. int
  4686. seg_free(void *item, void *data ARG_UNUSED)
  4687. {
  4688. grad_free(item);
  4689. return 0;
  4690. }
  4691. void
  4692. subst_destroy(grad_list_t *lst)
  4693. {
  4694. grad_list_destroy(&lst, seg_free, NULL);
  4695. }
  4696. void
  4697. subst_run(grad_list_t *subst, size_t nsub,
  4698. char **baseptr, char *arg)
  4699. {
  4700. grad_iterator_t *itr = grad_iterator_create(subst);
  4701. struct subst_segment *seg;
  4702. for (seg = grad_iterator_first(itr); seg; seg = grad_iterator_next(itr)) {
  4703. switch (seg->type) {
  4704. case subst_text:
  4705. temp_space_copy(baseptr,
  4706. seg->v.text.ptr, seg->v.text.len);
  4707. break;
  4708. case subst_ref:
  4709. if (seg->v.ref >= nsub)
  4710. rw_error(_("Invalid backreference"));
  4711. temp_space_copy(baseptr,
  4712. arg + mach.pmatch[seg->v.ref].rm_so,
  4713. mach.pmatch[seg->v.ref].rm_eo -
  4714. mach.pmatch[seg->v.ref].rm_so);
  4715. break;
  4716. case subst_match:
  4717. temp_space_copy(baseptr,
  4718. arg + mach.pmatch[0].rm_so,
  4719. mach.pmatch[0].rm_eo -
  4720. mach.pmatch[0].rm_so);
  4721. }
  4722. }
  4723. grad_iterator_destroy(&itr);
  4724. }
  4725. static void
  4726. bi_gsub()
  4727. {
  4728. grad_string_t re_str;
  4729. grad_string_t repl;
  4730. grad_string_t arg;
  4731. char *p;
  4732. char *base;
  4733. regex_t rx;
  4734. grad_list_t *subst;
  4735. int rc;
  4736. mem2string(&re_str, (RWSTYPE*) getarg(3));
  4737. mem2string(&repl, (RWSTYPE*) getarg(2));
  4738. mem2string(&arg, (RWSTYPE*) getarg(1));
  4739. p = arg.data;
  4740. rc = regcomp(&rx, re_str.data, regcomp_flags);
  4741. if (rc)
  4742. rw_regerror(_("regexp compile error: "), &rx, rc);
  4743. need_pmatch(rx.re_nsub);
  4744. subst = subst_create(repl.data);
  4745. if (!subst)
  4746. rw_error(_("gsub: not enough memory"));
  4747. base = temp_space_create();
  4748. while (*p
  4749. && regexec(&rx, p, rx.re_nsub + 1, mach.pmatch, 0) == 0) {
  4750. temp_space_copy(&base, p, mach.pmatch[0].rm_so);
  4751. subst_run(subst, rx.re_nsub + 1, &base, p);
  4752. p += mach.pmatch[0].rm_eo;
  4753. if (mach.pmatch[0].rm_eo == 0)
  4754. p++;
  4755. }
  4756. temp_space_copy(&base, p, strlen(p) + 1);
  4757. subst_destroy(subst);
  4758. regfree(&rx);
  4759. pushn((RWSTYPE)temp_space_fix(base));
  4760. }
  4761. static void
  4762. bi_sub()
  4763. {
  4764. grad_string_t re_str;
  4765. grad_string_t repl;
  4766. grad_string_t arg;
  4767. char *p;
  4768. char *base;
  4769. regex_t rx;
  4770. grad_list_t *subst;
  4771. int rc;
  4772. mem2string(&re_str, (RWSTYPE*) getarg(3));
  4773. mem2string(&repl, (RWSTYPE*) getarg(2));
  4774. mem2string(&arg, (RWSTYPE*) getarg(1));
  4775. rc = regcomp(&rx, re_str.data, regcomp_flags);
  4776. if (rc)
  4777. rw_regerror(_("regexp compile error: "), &rx, rc);
  4778. need_pmatch(rx.re_nsub);
  4779. subst = subst_create(repl.data);
  4780. if (!subst)
  4781. rw_error(_("sub: not enough memory"));
  4782. base = temp_space_create();
  4783. p = arg.data;
  4784. if (regexec(&rx, p, rx.re_nsub + 1, mach.pmatch, 0) == 0) {
  4785. temp_space_copy(&base, p, mach.pmatch[0].rm_so);
  4786. subst_run(subst, rx.re_nsub + 1, &base, p);
  4787. p += mach.pmatch[0].rm_eo;
  4788. }
  4789. temp_space_copy(&base, p, strlen(p) + 1);
  4790. subst_destroy(subst);
  4791. regfree(&rx);
  4792. pushn((RWSTYPE)temp_space_fix(base));
  4793. }
  4794. #define ISPRINT(c) (((unsigned char)c) < 128 && (isalnum(c) || c == '-'))
  4795. static void
  4796. bi_qprn()
  4797. {
  4798. grad_string_t arg;
  4799. char *p, *s, *end;
  4800. size_t count;
  4801. RWSTYPE *sp;
  4802. mem2string(&arg, (RWSTYPE*)getarg(1));
  4803. end = arg.data + arg.size;
  4804. for (count = 0, p = arg.data; p < end; p++)
  4805. if (!ISPRINT(*p))
  4806. count++;
  4807. /* Each encoded character takes 3 bytes. */
  4808. sp = heap_reserve(sizeof(RWSTYPE) + arg.size + 2*count + 1);
  4809. sp[0] = arg.size + 2*count;
  4810. pushn((RWSTYPE) sp);
  4811. for (p = (char*)(sp + 1), s = arg.data; s < end; s++) {
  4812. if (ISPRINT(*s))
  4813. *p++ = *s;
  4814. else {
  4815. char buf[3];
  4816. snprintf(buf, sizeof buf, "%02X", *(unsigned char*)s);
  4817. *p++ = '%';
  4818. *p++ = buf[0];
  4819. *p++ = buf[1];
  4820. }
  4821. }
  4822. *p = 0;
  4823. }
  4824. static void
  4825. bi_quote_string()
  4826. {
  4827. int quote;
  4828. grad_string_t arg;
  4829. RWSTYPE *sp;
  4830. char *p;
  4831. size_t size;
  4832. mem2string(&arg, (RWSTYPE*)getarg(1));
  4833. size = grad_argcv_quoted_length_n(arg.data, arg.size, &quote);
  4834. sp = heap_reserve(sizeof(RWSTYPE) + size + 1);
  4835. sp[0] = size;
  4836. pushn((RWSTYPE)sp);
  4837. p = (char*)(sp + 1);
  4838. grad_argcv_quote_copy_n(p, arg.data, arg.size);
  4839. }
  4840. static void
  4841. bi_unquote_string()
  4842. {
  4843. int quote;
  4844. grad_string_t arg;
  4845. RWSTYPE *sp;
  4846. char *p;
  4847. size_t size;
  4848. mem2string(&arg, (RWSTYPE*)getarg(1));
  4849. sp = heap_reserve(sizeof(RWSTYPE) + arg.size + 1);
  4850. p = (char*)(sp + 1);
  4851. grad_argcv_unquote_copy(p, arg.data, arg.size);
  4852. sp[0] = strlen(p);
  4853. pushn((RWSTYPE)sp);
  4854. }
  4855. static void
  4856. bi_textdomain()
  4857. {
  4858. grad_string_t s;
  4859. mem2string(&s, (RWSTYPE*)getarg(1));
  4860. pushstr(default_gettext_domain, strlen (default_gettext_domain));
  4861. grad_string_replace(&default_gettext_domain, s.data);
  4862. }
  4863. static void
  4864. bi_gettext()
  4865. {
  4866. grad_string_t s;
  4867. const char *p;
  4868. mem2string(&s, (RWSTYPE*)getarg(1));
  4869. p = dgettext(default_gettext_domain, s.data);
  4870. pushstr(p, strlen(p));
  4871. }
  4872. static void
  4873. bi_dgettext()
  4874. {
  4875. grad_string_t domain;
  4876. grad_string_t text;
  4877. const char *p;
  4878. mem2string(&domain, (RWSTYPE*)getarg(2));
  4879. mem2string(&text, (RWSTYPE*)getarg(1));
  4880. p = dgettext(domain.data, text.data);
  4881. pushstr(p, strlen(p));
  4882. }
  4883. static void
  4884. bi_ngettext()
  4885. {
  4886. grad_string_t s;
  4887. grad_string_t pl;
  4888. unsigned long n;
  4889. const char *p;
  4890. mem2string(&s, (RWSTYPE*)getarg(3));
  4891. mem2string(&pl, (RWSTYPE*)getarg(2));
  4892. n = (unsigned long) getarg(1);
  4893. p = dngettext(default_gettext_domain,
  4894. s.data,
  4895. pl.data,
  4896. n);
  4897. pushstr(p, strlen(p));
  4898. }
  4899. static void
  4900. bi_dngettext()
  4901. {
  4902. grad_string_t domain;
  4903. grad_string_t s;
  4904. grad_string_t pl;
  4905. unsigned long n;
  4906. const char *p;
  4907. mem2string(&domain, (RWSTYPE*)getarg(4));
  4908. mem2string(&s, (RWSTYPE*)getarg(3));
  4909. mem2string(&pl, (RWSTYPE*)getarg(2));
  4910. n = (unsigned long) getarg(1);
  4911. p = dngettext(domain.data, s.data, pl.data, n);
  4912. pushstr(p, strlen(p));
  4913. }
  4914. static builtin_t builtin[] = {
  4915. { bi_length, "length", Integer, "s" },
  4916. { bi_index, "index", Integer, "si" },
  4917. { bi_rindex, "rindex", Integer, "si" },
  4918. { bi_substr, "substr", String, "sii" },
  4919. { bi_logit, "logit", Integer, "s" },
  4920. { bi_field, "field", String, "si" },
  4921. { bi_ntohl, "ntohl", Integer, "i" },
  4922. { bi_htonl, "htonl", Integer, "i" },
  4923. { bi_ntohs, "ntohs", Integer, "i" },
  4924. { bi_htons, "htons", Integer, "i" },
  4925. { bi_inet_ntoa, "inet_ntoa", String, "i" },
  4926. { bi_inet_aton, "inet_aton", Integer, "s" },
  4927. { bi_sub, "sub", String, "sss" },
  4928. { bi_gsub, "gsub", String, "sss" },
  4929. { bi_qprn, "qprn", String, "s" },
  4930. { bi_tolower, "tolower", String, "s" },
  4931. { bi_toupper, "toupper", String, "s" },
  4932. { bi_unquote_string, "unquote_string", String, "s" },
  4933. { bi_quote_string, "quote_string", String, "s" },
  4934. { bi_request_code_string, "request_code_string", String, "i" },
  4935. /* i18n support */
  4936. { bi_gettext, "gettext", String, "s" },
  4937. { bi_gettext, "_", String, "s" },
  4938. { bi_dgettext, "dgettext", String, "ss" },
  4939. { bi_ngettext, "ngettext", String, "ssi" },
  4940. { bi_dngettext, "dngettext", String, "sssi" },
  4941. { bi_textdomain, "textdomain", String, "s" },
  4942. /* Request internals */
  4943. { bi_request_source_ip, "request_source_ip", Integer, "" },
  4944. { bi_request_source_port, "request_source_port", Integer, "" },
  4945. { bi_request_id, "request_id", Integer, "" },
  4946. { bi_request_code, "request_code", Integer, "" },
  4947. /* Radius database */
  4948. { bi_nas_name, "nas_name", String, "i" },
  4949. { bi_nas_short_name, "nas_short_name", String, "i" },
  4950. { bi_nas_full_name, "nas_full_name", String, "i" },
  4951. /* DNS lookups */
  4952. { bi_gethostbyaddr, "gethostbyaddr", Integer, "s" },
  4953. { bi_gethostbyname, "gethostbyname", String, "i" },
  4954. /* Time functions */
  4955. { bi_time, "time", Integer, "" },
  4956. { bi_strftime, "strftime", String, "si" },
  4957. { NULL }
  4958. };
  4959. builtin_t *
  4960. builtin_lookup(char *name)
  4961. {
  4962. int i;
  4963. for (i = 0; builtin[i].handler; i++)
  4964. if (strcmp(name, builtin[i].name) == 0)
  4965. return &builtin[i];
  4966. return NULL;
  4967. }
  4968. /* ****************************************************************************
  4969. * Function registering/unregistering
  4970. */
  4971. int
  4972. function_free(FUNCTION *f)
  4973. {
  4974. PARAMETER *parm, *next;
  4975. rx_free(f->rx_list);
  4976. parm = f->parm;
  4977. while (parm) {
  4978. next = parm->next;
  4979. grad_free(parm);
  4980. parm = next;
  4981. }
  4982. return 0;
  4983. }
  4984. FUNCTION *
  4985. function_install(FUNCTION *fun)
  4986. {
  4987. FUNCTION *fp;
  4988. if (fp = (FUNCTION *)grad_sym_lookup(rewrite_tab, fun->name)) {
  4989. grad_log_loc(GRAD_LOG_ERR, &fun->loc,
  4990. _("redefinition of function %s"));
  4991. grad_log_loc(GRAD_LOG_ERR, &fp->loc,
  4992. _("previously defined here"));
  4993. errcnt++;
  4994. return fp;
  4995. }
  4996. fp = (FUNCTION*)grad_sym_install(rewrite_tab, fun->name);
  4997. fp->rettype = fun->rettype;
  4998. fp->entry = fun->entry;
  4999. fp->rx_list = fun->rx_list;
  5000. fp->nparm = fun->nparm;
  5001. fp->parm = fun->parm;
  5002. fp->stack_alloc = fun->stack_alloc;
  5003. fp->loc = fun->loc;
  5004. return fp;
  5005. }
  5006. /* ****************************************************************************
  5007. * Runtime functions
  5008. */
  5009. static char pair_print_prefix[] = " ";
  5010. static void
  5011. rw_mach_init()
  5012. {
  5013. memset(&mach, 0, sizeof(mach));
  5014. if (!runtime_stack)
  5015. runtime_stack = grad_emalloc(rewrite_stack_size *
  5016. sizeof(runtime_stack[0]));
  5017. mach.stack = runtime_stack;
  5018. mach.st = 0; /* Stack top */
  5019. mach.ht = rewrite_stack_size - 1; /* Heap top */
  5020. grad_string_replace(&default_gettext_domain, PACKAGE);
  5021. }
  5022. static void
  5023. rw_mach_destroy()
  5024. {
  5025. grad_free(mach.pmatch);
  5026. mach.pmatch = NULL;
  5027. }
  5028. FUNCTION *
  5029. rewrite_check_function(const char *name, grad_data_type_t rettype, char *typestr)
  5030. {
  5031. int i;
  5032. PARAMETER *p;
  5033. FUNCTION *fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, name);
  5034. if (!fun) {
  5035. grad_log(GRAD_LOG_ERR, _("function %s not defined"), name);
  5036. return NULL;
  5037. }
  5038. if (fun->rettype != rettype) {
  5039. grad_log(GRAD_LOG_ERR, _("function %s returns wrong data type"), name);
  5040. return NULL;
  5041. }
  5042. for (i = 0, p = fun->parm; i < fun->nparm; i++, p = p->next) {
  5043. switch (typestr[i]) {
  5044. case 0:
  5045. grad_log(GRAD_LOG_ERR,
  5046. _("function %s takes too many arguments"),
  5047. name);
  5048. return NULL;
  5049. case 'i':
  5050. if (p->datatype != Integer) {
  5051. grad_log(GRAD_LOG_ERR,
  5052. _("function %s: argument %d must be integer"),
  5053. name, i+1);
  5054. return NULL;
  5055. }
  5056. break;
  5057. case 's':
  5058. if (p->datatype != String) {
  5059. grad_log(GRAD_LOG_ERR,
  5060. _("function %s: argument %d must be string"),
  5061. name, i+1);
  5062. return NULL;
  5063. }
  5064. break;
  5065. default:
  5066. grad_insist_fail("bad datatype");
  5067. }
  5068. }
  5069. if (typestr[i]) {
  5070. grad_log(GRAD_LOG_ERR,
  5071. _("function %s takes too few arguments"),
  5072. name);
  5073. return NULL;
  5074. }
  5075. return fun;
  5076. }
  5077. int
  5078. run_init(pctr_t pc, grad_request_t *request)
  5079. {
  5080. FILE *fp;
  5081. rw_mach_init();
  5082. if (setjmp(mach.jmp)) {
  5083. rw_mach_destroy();
  5084. return -1;
  5085. }
  5086. mach.req = request;
  5087. if (GRAD_DEBUG_LEVEL(2)) {
  5088. fp = debug_open_file();
  5089. fprintf(fp, "Before rewriting:\n");
  5090. grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
  5091. fclose(fp);
  5092. }
  5093. /* Imitate a function call */
  5094. pushn(0); /* Return address */
  5095. run(pc); /* call function */
  5096. if (GRAD_DEBUG_LEVEL(2)) {
  5097. fp = debug_open_file();
  5098. fprintf(fp, "After rewriting\n");
  5099. grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
  5100. fclose(fp);
  5101. }
  5102. rw_mach_destroy();
  5103. return 0;
  5104. }
  5105. static void
  5106. return_value(grad_value_t *val)
  5107. {
  5108. u_char *p;
  5109. switch (val->type) {
  5110. case Integer:
  5111. val->datum.ival = mach.rA;
  5112. break;
  5113. case String:
  5114. mem2string(&val->datum.sval, (RWSTYPE*) mach.rA);
  5115. p = grad_emalloc (val->datum.sval.size + 1);
  5116. memcpy (p, val->datum.sval.data, val->datum.sval.size);
  5117. p[val->datum.sval.size] = 0;
  5118. val->datum.sval.data = p;
  5119. break;
  5120. default:
  5121. abort();
  5122. }
  5123. }
  5124. static int
  5125. evaluate(pctr_t pc, grad_request_t *req, grad_value_t *val)
  5126. {
  5127. if (run_init(pc, req))
  5128. return -1;
  5129. if (val)
  5130. return_value(val);
  5131. return 0;
  5132. }
  5133. int
  5134. rewrite_invoke(grad_data_type_t rettype, grad_value_t *val,
  5135. const char *name,
  5136. grad_request_t *request, char *typestr, ...)
  5137. {
  5138. FILE *fp;
  5139. va_list ap;
  5140. FUNCTION *fun;
  5141. int nargs;
  5142. char *s;
  5143. fun = rewrite_check_function(name, rettype, typestr);
  5144. if (!fun)
  5145. return -1;
  5146. rw_mach_init();
  5147. if (setjmp(mach.jmp)) {
  5148. rw_mach_destroy();
  5149. return -1;
  5150. }
  5151. mach.req = request;
  5152. if (GRAD_DEBUG_LEVEL(2)) {
  5153. fp = debug_open_file();
  5154. fprintf(fp, "Before rewriting:\n");
  5155. grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
  5156. fclose(fp);
  5157. }
  5158. /* Pass arguments */
  5159. nargs = 0;
  5160. va_start(ap, typestr);
  5161. while (*typestr) {
  5162. nargs++;
  5163. switch (*typestr++) {
  5164. case 'i':
  5165. pushn(va_arg(ap, int));
  5166. break;
  5167. case 's':
  5168. s = va_arg(ap, char*);
  5169. pushstr(s, strlen(s));
  5170. break;
  5171. default:
  5172. grad_insist_fail("bad datatype");
  5173. }
  5174. }
  5175. va_end(ap);
  5176. /* Imitate a function call */
  5177. pushn(0); /* Return address */
  5178. run(fun->entry); /* call function */
  5179. if (GRAD_DEBUG_LEVEL(2)) {
  5180. fp = debug_open_file();
  5181. fprintf(fp, "After rewriting\n");
  5182. grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
  5183. fclose(fp);
  5184. }
  5185. val->type = fun->rettype;
  5186. return_value(val);
  5187. rw_mach_destroy();
  5188. return 0;
  5189. }
  5190. char *
  5191. rewrite_compile(char *expr)
  5192. {
  5193. int rc;
  5194. FUNCTION *fun;
  5195. char *name = grad_emalloc(strlen(expr) + 3);
  5196. sprintf(name, "$%s$", expr);
  5197. fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, name);
  5198. if (!fun) {
  5199. rc = parse_rewrite_string(expr);
  5200. if (rc) {
  5201. grad_free(name);
  5202. return NULL;
  5203. }
  5204. function->name = name;
  5205. function_install(function);
  5206. }
  5207. return name;
  5208. }
  5209. int
  5210. rewrite_interpret(char *expr, grad_request_t *req, grad_value_t *val)
  5211. {
  5212. pctr_t save_pc = rw_pc;
  5213. int rc;
  5214. rc = parse_rewrite_string(expr);
  5215. rw_pc = save_pc;
  5216. if (rc)
  5217. return rc;
  5218. val->type = return_type;
  5219. if (return_type == Undefined)
  5220. return -1;
  5221. return evaluate(rw_pc, req, val);
  5222. }
  5223. int
  5224. rewrite_eval(char *symname, grad_request_t *req, grad_value_t *val)
  5225. {
  5226. FUNCTION *fun;
  5227. fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, symname);
  5228. if (!fun)
  5229. return -1;
  5230. if (fun->nparm) {
  5231. grad_log(GRAD_LOG_ERR,
  5232. ngettext("function %s() requires %d parameter",
  5233. "function %s() requires %d parameters",
  5234. fun->nparm),
  5235. fun->name, fun->nparm);
  5236. return -1;
  5237. }
  5238. if (val)
  5239. val->type = fun->rettype;
  5240. return evaluate(fun->entry, req, val);
  5241. }
  5242. /* ****************************************************************************
  5243. * Configuration
  5244. */
  5245. static grad_list_t *source_list; /* List of loaded source files */
  5246. static grad_list_t *rewrite_load_path; /* Load path list */
  5247. /* Add a path to load path */
  5248. static void
  5249. rewrite_add_load_path(const char *str)
  5250. {
  5251. if (!rewrite_load_path)
  5252. rewrite_load_path = grad_list_create();
  5253. grad_list_append(rewrite_load_path, grad_estrdup(str));
  5254. }
  5255. void
  5256. register_source_name(char *path)
  5257. {
  5258. if (!source_list)
  5259. source_list = grad_list_create();
  5260. grad_list_append(source_list, path);
  5261. }
  5262. struct load_data {
  5263. int rc;
  5264. char *name;
  5265. };
  5266. /* Try to load a source file.
  5267. ITEM is a directory name, DATA is struct load_data.
  5268. Return 1 if the file was found (no matter was it loaded or not) */
  5269. static int
  5270. try_load(void *item, void *data)
  5271. {
  5272. int rc = 0;
  5273. struct load_data *lp = data;
  5274. char *path = grad_mkfilename((char*)item, lp->name);
  5275. lp->rc = parse_rewrite(path);
  5276. if (lp->rc >= 0) {
  5277. register_source_name(path);
  5278. rc = 1;
  5279. } else
  5280. grad_free(path);
  5281. return rc;
  5282. }
  5283. /* Load the given rewrite module. */
  5284. int
  5285. rewrite_load_module(char *name)
  5286. {
  5287. int rc;
  5288. if (name[0] == '/') {
  5289. register_source_name(grad_estrdup(name));
  5290. rc = parse_rewrite(name);
  5291. } else {
  5292. struct load_data ld;
  5293. ld.rc = 1;
  5294. ld.name = name;
  5295. grad_list_iterate(rewrite_load_path, try_load, &ld);
  5296. rc = ld.rc;
  5297. }
  5298. return rc;
  5299. }
  5300. static int
  5301. free_path(void *item, void *data ARG_UNUSED)
  5302. {
  5303. grad_free(item);
  5304. return 0;
  5305. }
  5306. static grad_list_t *source_candidate_list; /* List of modules that are to
  5307. be loaded */
  5308. int
  5309. rewrite_stmt_term(int finish, void *block_data, void *handler_data)
  5310. {
  5311. if (!finish) {
  5312. grad_symtab_clear(rewrite_tab);
  5313. yydebug = GRAD_DEBUG_LEVEL(50);
  5314. grad_list_destroy(&source_list, free_path, NULL);
  5315. grad_list_destroy(&rewrite_load_path, free_path, NULL);
  5316. rewrite_add_load_path(grad_config_dir);
  5317. rewrite_add_load_path(RADIUS_DATADIR "/rewrite");
  5318. grad_free(runtime_stack);
  5319. runtime_stack = NULL;
  5320. }
  5321. return 0;
  5322. }
  5323. static int
  5324. rewrite_cfg_add_load_path(int argc, cfg_value_t *argv,
  5325. void *block_data, void *handler_data)
  5326. {
  5327. if (argc > 2) {
  5328. cfg_argc_error(0);
  5329. return 0;
  5330. }
  5331. if (argv[1].type != CFG_STRING) {
  5332. cfg_type_error(CFG_STRING);
  5333. return 0;
  5334. }
  5335. rewrite_add_load_path(argv[1].v.string);
  5336. return 0;
  5337. }
  5338. static int
  5339. rewrite_cfg_load(int argc, cfg_value_t *argv,
  5340. void *block_data, void *handler_data)
  5341. {
  5342. if (argc > 2) {
  5343. cfg_argc_error(0);
  5344. return 0;
  5345. }
  5346. if (argv[1].type != CFG_STRING) {
  5347. cfg_type_error(CFG_STRING);
  5348. return 0;
  5349. }
  5350. grad_list_append(source_candidate_list, grad_estrdup(argv[1].v.string));
  5351. return 0;
  5352. }
  5353. /* Configuration hooks and initialization */
  5354. static void
  5355. rewrite_before_config_hook(void *a ARG_UNUSED, void *b ARG_UNUSED)
  5356. {
  5357. grad_list_destroy(&source_candidate_list, free_path, NULL);
  5358. source_candidate_list = grad_list_create();
  5359. code_init();
  5360. }
  5361. static int
  5362. _load_module(void *item, void *data ARG_UNUSED)
  5363. {
  5364. if (rewrite_load_module(item) == -2)
  5365. grad_log(GRAD_LOG_ERR, _("file not found: %s"), item);
  5366. return 0;
  5367. }
  5368. void
  5369. rewrite_load_all(void *a ARG_UNUSED, void *b ARG_UNUSED)
  5370. {
  5371. if (!source_candidate_list)
  5372. return;
  5373. /* For compatibility with previous versions load the
  5374. file $grad_config_dir/rewrite, if no explicit "load" statements
  5375. were given */
  5376. if (grad_list_count(source_candidate_list) == 0)
  5377. rewrite_load_module("rewrite");
  5378. grad_list_iterate(source_candidate_list, _load_module, NULL);
  5379. #if defined(MAINTAINER_MODE)
  5380. if (GRAD_DEBUG_LEVEL(100))
  5381. debug_dump_code();
  5382. #endif
  5383. }
  5384. void
  5385. rewrite_init()
  5386. {
  5387. rewrite_tab = grad_symtab_create(sizeof(FUNCTION), function_free);
  5388. radiusd_set_preconfig_hook(rewrite_before_config_hook, NULL, 0);
  5389. }
  5390. struct cfg_stmt rewrite_stmt[] = {
  5391. { "stack-size", CS_STMT, NULL, cfg_get_number, &rewrite_stack_size,
  5392. NULL, NULL },
  5393. { "load-path", CS_STMT, NULL, rewrite_cfg_add_load_path, NULL, NULL, NULL },
  5394. { "load", CS_STMT, NULL, rewrite_cfg_load, NULL, NULL, NULL },
  5395. { NULL, }
  5396. };
  5397. size_t
  5398. rewrite_get_stack_size()
  5399. {
  5400. return rewrite_stack_size;
  5401. }
  5402. void
  5403. rewrite_set_stack_size(size_t s)
  5404. {
  5405. if (s == rewrite_stack_size)
  5406. return;
  5407. rewrite_stack_size = s;
  5408. grad_free(runtime_stack);
  5409. runtime_stack = NULL;
  5410. }
  5411. void
  5412. grad_value_free(grad_value_t *val)
  5413. {
  5414. if (val->type == String)
  5415. grad_free(val->datum.sval.data);
  5416. }
  5417. /* ****************************************************************************
  5418. * Guile interface
  5419. */
  5420. #ifdef USE_SERVER_GUILE
  5421. SCM
  5422. radscm_datum_to_scm(grad_value_t *val)
  5423. {
  5424. switch (val->type) {
  5425. case Integer:
  5426. return scm_from_long(val->datum.ival);
  5427. case String:
  5428. /* FIXME! */
  5429. return scm_from_locale_string(val->datum.sval.data);
  5430. default:
  5431. grad_insist_fail("Unknown data type");
  5432. }
  5433. return SCM_UNSPECIFIED;
  5434. }
  5435. int
  5436. radscm_scm_to_ival(SCM cell, int *val)
  5437. {
  5438. if (scm_is_number(cell))
  5439. *val = scm_to_int(cell);
  5440. else if (SCM_CHARP(cell))
  5441. *val = SCM_CHAR(cell);
  5442. else if (scm_is_bool(cell))
  5443. *val = scm_to_bool(cell);
  5444. else if (scm_is_null(cell))
  5445. *val = 0;
  5446. else if (scm_is_string(cell)) {
  5447. char *p, *str = scm_to_locale_string(cell);
  5448. int x = strtol(str, &p, 0);
  5449. int rc = *p ? -1 : 0;
  5450. free(str);
  5451. if (rc)
  5452. return rc;
  5453. } else
  5454. return -1;
  5455. return 0;
  5456. }
  5457. SCM
  5458. radscm_rewrite_execute(const char *func_name, SCM ARGS)
  5459. {
  5460. char *name;
  5461. FUNCTION *fun;
  5462. PARAMETER *parm;
  5463. int nargs;
  5464. int n, rc;
  5465. grad_value_t value;
  5466. SCM cell;
  5467. SCM FNAME;
  5468. SCM retval;
  5469. FNAME = SCM_CAR(ARGS);
  5470. ARGS = SCM_CDR(ARGS);
  5471. SCM_ASSERT(scm_is_string(FNAME), FNAME, SCM_ARG1, func_name);
  5472. name = scm_to_locale_string(FNAME);
  5473. fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, name);
  5474. free(name);
  5475. if (!fun)
  5476. scm_misc_error(func_name,
  5477. _("function ~S not defined"),
  5478. scm_list_1(FNAME));
  5479. rw_mach_init();
  5480. /* Pass arguments */
  5481. nargs = 0;
  5482. parm = fun->parm;
  5483. for (cell = ARGS; !scm_is_null(cell);
  5484. cell = SCM_CDR(cell), parm = parm->next) {
  5485. SCM car = SCM_CAR(cell);
  5486. if (++nargs > fun->nparm) {
  5487. rw_code_unlock();
  5488. scm_misc_error(func_name,
  5489. _("too many arguments for ~S"),
  5490. scm_list_1(FNAME));
  5491. }
  5492. switch (parm->datatype) {
  5493. case Integer:
  5494. rc = radscm_scm_to_ival(car, &n);
  5495. if (!rc)
  5496. pushn(n);
  5497. break;
  5498. case String:
  5499. if (scm_is_string(car)) {
  5500. char *p = scm_to_locale_string(car);
  5501. pushstr(p, strlen(p));
  5502. free(p);
  5503. rc = 0;
  5504. } else
  5505. rc = 1;
  5506. break;
  5507. default:
  5508. grad_insist_fail("Unknown data type");
  5509. }
  5510. if (rc) {
  5511. rw_mach_destroy();
  5512. scm_misc_error(func_name,
  5513. _("type mismatch in argument ~S(~S) in call to ~S"),
  5514. scm_list_3(scm_from_int(nargs),
  5515. car,
  5516. FNAME));
  5517. }
  5518. }
  5519. if (fun->nparm != nargs) {
  5520. rw_mach_destroy();
  5521. scm_misc_error(func_name,
  5522. _("too few arguments for ~S"),
  5523. scm_list_1(FNAME));
  5524. }
  5525. /* Imitate a function call */
  5526. if (setjmp(mach.jmp)) {
  5527. rw_mach_destroy();
  5528. return SCM_BOOL_F;
  5529. }
  5530. pushn(0); /* Return address */
  5531. run(fun->entry); /* call function */
  5532. value.type = fun->rettype;
  5533. return_value(&value);
  5534. retval = radscm_datum_to_scm(&value);
  5535. grad_value_free(&value);
  5536. rw_mach_destroy();
  5537. return retval;
  5538. }
  5539. #endif
  5540. /*HONY SOIT QUI MAL Y PENSE*/