PageRenderTime 110ms CodeModel.GetById 20ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full file

  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 = ob

Large files files are truncated, but you can click here to view the full file