/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
- %{
- /* This file is part of GNU Radius.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2010, 2013 Free Software Foundation, Inc.
- Written by Sergey Poznyakoff
-
- GNU Radius is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- GNU Radius is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU Radius. If not, see <http://www.gnu.org/licenses/>. */
- #if defined(HAVE_CONFIG_H)
- # include <config.h>
- #endif
- #include <sys/types.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <errno.h>
- #include <radiusd.h>
- #include <setjmp.h>
- #include <rewrite.h>
- #ifdef USE_SERVER_GUILE
- # include <libguile.h>
- # include <radius/radscm.h>
- #endif
-
- typedef long RWSTYPE;
- #define RW_MIN(a,b) ((a)<(b)) ? (a) : (b)
-
- /*
- * Generalized list structure
- */
- typedef struct rw_list RWLIST;
- #define RWLIST(type) \
- type *next;\
- type *prev
- struct rw_list {
- RWLIST(RWLIST);
- };
- /*
- * Generalized object
- */
- typedef struct object_t OBJECT ;
- #define OBJ(type) \
- RWLIST(type);\
- type *alloc
- struct object_t {
- OBJ(OBJECT);
- };
- typedef struct {
- size_t size; /* Size of an element */
- void (*free)(); /* deallocator */
- OBJECT *alloc_list; /* list of allocated elements */
- } OBUCKET;
-
- /* ************************************************************
- * Basic data types
- */
- typedef int stkoff_t; /* Offset on stack */
- typedef unsigned int pctr_t; /* Program counter */
- #define RW_REG ('z'-'a'+1)
- typedef struct {
- RWSTYPE reg[RW_REG]; /* Registers */
- #define rA reg[0]
- char *sA; /* String accumulator */
- pctr_t pc; /* Program counter */
-
- RWSTYPE *stack; /* Stack+heap space */
- int stacksize; /* Size of stack */
- int st; /* Top of stack */
- int sb; /* Stack base */
- int ht; /* Top of heap */
-
- int nmatch;
- regmatch_t *pmatch;
- grad_request_t *req;
-
- jmp_buf jmp;
- } RWMACH;
- typedef void (*INSTR)(); /* program instruction */
-
- /* Compiled regular expression
- */
- typedef struct comp_regex COMP_REGEX;
- struct comp_regex {
- OBJ(COMP_REGEX);
- regex_t regex; /* compiled regex itself */
- int nmatch; /* number of \( ... \) groups */
- };
- /*
- * Binary Operations
- */
- typedef enum {
- Eq,
- Ne,
- Lt,
- Le,
- Gt,
- Ge,
- BAnd,
- BXor,
- BOr,
- And,
- Or,
- Shl,
- Shr,
- Add,
- Sub,
- Mul,
- Div,
- Rem,
- Max_opcode
- } Bopcode;
- /*
- * Unary operations
- */
- typedef enum {
- Neg,
- Not,
- Max_unary
- } Uopcode;
- /*
- * Matrix types
- */
- typedef enum {
- Generic,
- Nop,
- Enter,
- Leave,
- Stop,
- Constant,
- Matchref,
- Variable,
- Unary,
- Binary,
- Cond,
- Asgn,
- Match,
- Coercion,
- Expression,
- Return,
- Jump,
- Branch,
- Target,
- Call,
- Builtin,
- Pop,
- Pusha,
- Popa,
- Attr,
- Attr_asgn,
- Attr_check,
- Attr_delete,
- Max_mtxtype
- } Mtxtype;
- /*
- * Function parameter
- */
- typedef struct parm_t PARAMETER;
- struct parm_t {
- PARAMETER *prev; /* Previous parameter */
- PARAMETER *next; /* Next parameter */
- grad_data_type_t datatype; /* type */
- stkoff_t offset; /* Offset on stack */
- };
- /*
- * Local variable
- */
- typedef struct variable VAR;
- struct variable {
- OBJ(VAR);
- VAR *dcllink; /* Link to the next variable vithin the
- * same declaration
- */
- char *name; /* name of the variable */
- int level; /* nesting level */
- int offset; /* offset on stack */
- grad_data_type_t datatype; /* type */
- int constant; /* true if assigned a constant value */
- grad_datum_t datum; /* constant value itself */
- };
- /*
- * Function definition
- */
- typedef struct function_def {
- struct function_def *next;
- char *name; /* Function name */
- grad_data_type_t rettype; /* Return type */
- pctr_t entry; /* Code entry */
- COMP_REGEX *rx_list; /* List of compiled regexps */
- int nparm; /* Number of parameters */
- PARAMETER *parm; /* List of parameters */
- stkoff_t stack_alloc; /* required stack allocation */
- grad_locus_t loc; /* source location where the function
- * was declared
- */
- } FUNCTION;
- #define STACK_BASE 2
- /*
- * Built-in function
- */
- typedef struct {
- INSTR handler; /* Function itself */
- char *name; /* Function name */
- grad_data_type_t rettype; /* Return type */
- char *parms; /* coded parameter types */
- } builtin_t;
- /*
- * Operation matrices
- */
- typedef union mtx MTX;
- /*
- * All matrices contain the following common fields:
- * alloc- link to the previously allocated matrix.
- * It is used at the end of code generation
- * pass to free all allocated matrices.
- * next - link to the next matrix in the subexpression
- * prev - link to the previous matrix in the subexpression
- * Additionally, all expression matrices contain the field
- * `datatype' which contains the data type for this matrix.
- */
- #if defined(MAINTAINER_MODE)
- # define COMMON_MTX \
- OBJ(MTX);\
- int id;\
- grad_locus_t loc;\
- Mtxtype type;
- #else
- # define COMMON_MTX \
- OBJ(MTX);\
- grad_locus_t loc;\
- Mtxtype type;
- #endif
-
- #define COMMON_EXPR_MTX \
- COMMON_MTX\
- grad_data_type_t datatype;\
- MTX *uplink;\
- MTX *arglink;
- /*
- * Generic matrix: nothing special
- * Type: Generic
- */
- typedef struct {
- COMMON_EXPR_MTX
- } GEN_MTX;
- /*
- * Constant matrix
- * Type: Constant
- */
- typedef struct {
- COMMON_EXPR_MTX
- grad_datum_t datum; /* Constant value */
- } CONST_MTX;
- /*
- * Reference to a previous regexp: corresponds to a \N construct
- * Type: Matchref
- */
- typedef struct {
- COMMON_EXPR_MTX
- int num; /* Number of \( ... \) to be referenced */
- } MATCHREF_MTX;
- /*
- * Reference to a variable
- * Type: Variable
- */
- typedef struct {
- COMMON_EXPR_MTX
- VAR *var; /* Variable being referenced */
- } VAR_MTX;
- /*
- * Unary operation matrix
- * Type: Unary
- */
- typedef struct {
- COMMON_EXPR_MTX
- Uopcode opcode; /* Operation code */
- MTX *arg; /* Argument */
- } UN_MTX;
- /*
- * Binary operation matrix
- * Type: Binary
- */
- typedef struct {
- COMMON_EXPR_MTX
- Bopcode opcode; /* Operation code */
- MTX *arg[2]; /* Arguments */
- } BIN_MTX;
- /*
- * Assignment matrix
- * Type: Asgn
- */
- typedef struct {
- COMMON_EXPR_MTX
- VAR *lval; /* Lvalue */
- MTX *arg; /* Rvalue */
- } ASGN_MTX;
- /*
- * Conditional expression matrix
- * Type: Cond
- */
- typedef struct {
- COMMON_MTX
- MTX *expr; /* Conditional expression */
- MTX *if_true; /* Branch if true */
- MTX *if_false; /* Branch if false */
- } COND_MTX;
- /*
- * Regexp match
- * Type: Match
- */
- typedef struct {
- COMMON_EXPR_MTX
- int negated; /* Is the match negated ? */
- MTX *arg; /* Argument (lhs) */
- COMP_REGEX *rx; /* Regexp (rhs) */
- } MATCH_MTX;
- /*
- * Type coercion
- * Type: Coerce
- */
- typedef struct {
- COMMON_EXPR_MTX
- MTX *arg; /* Argument of the coercion */
- } COERCE_MTX;
- /*
- * Expression
- * Type: Expression
- */
- typedef struct {
- COMMON_EXPR_MTX
- MTX *expr;
- } EXPR_MTX;
- /*
- * Return from function
- * Type: Return
- */
- typedef struct {
- COMMON_EXPR_MTX
- MTX *expr; /* Return value */
- } RET_MTX;
- /*
- * Unconditional branch (jump)
- * Type: Jump
- */
- typedef struct {
- COMMON_MTX
- MTX *link; /* Link to the next jump matrix
- * (for break and continue matrices)
- */
- MTX *dest; /* Jump destination (usually a NOP matrix) */
- } JUMP_MTX;
- /*
- * Conditional branch
- * Type: Branch
- */
- typedef struct {
- COMMON_MTX
- int cond; /* Condition: 1 - equal, 0 - not equal */
- MTX *dest; /* Jump destination (usually a NOP matrix) */
- } BRANCH_MTX;
- /*
- * Stack frame matrix
- * Type: Enter, Leave
- */
- typedef struct {
- COMMON_MTX
- stkoff_t stacksize;/* Required stack size */
- } FRAME_MTX;
- /*
- * Jump target
- * Type: Target
- */
- typedef struct {
- COMMON_MTX
- pctr_t pc; /* Target's program counter */
- } TGT_MTX;
- /*
- * No-op matrix. It is always inserted at the branch destination
- * points. Its purpose is to keep a singly-linked list of jump
- * locations for fixing up jump statements.
- * Type: Nop
- */
- typedef struct {
- COMMON_MTX
- TGT_MTX *tgt; /* Target list */
- pctr_t pc; /* Program counter for backward
- references */
- } NOP_MTX;
- /*
- * Function call
- * Type: Call
- */
- typedef struct {
- COMMON_EXPR_MTX
- FUNCTION *fun; /* Called function */
- int nargs; /* Number of arguments */
- MTX *args; /* Arguments */
- } CALL_MTX;
- /*
- * Builtin function call
- * Type: Builtin
- */
- typedef struct {
- COMMON_EXPR_MTX
- INSTR fun; /* Handler function */
- int nargs; /* Number of arguments */
- MTX *args; /* Arguments */
- } BTIN_MTX;
- /*
- * Attribute matrix
- * Type: Attr, Attr_asgn, Attr_check
- */
- typedef struct {
- COMMON_EXPR_MTX
- int attrno; /* Attribute number */
- MTX *index; /* Index expression */
- MTX *rval; /* Rvalue */
- } ATTR_MTX;
- union mtx {
- GEN_MTX gen;
- NOP_MTX nop;
- FRAME_MTX frame;
- CONST_MTX cnst;
- MATCHREF_MTX ref;
- VAR_MTX var;
- UN_MTX un;
- BIN_MTX bin;
- COND_MTX cond;
- ASGN_MTX asgn;
- MATCH_MTX match;
- COERCE_MTX coerce;
- RET_MTX ret;
- JUMP_MTX jump;
- BRANCH_MTX branch;
- TGT_MTX tgt;
- CALL_MTX call;
- BTIN_MTX btin;
- ATTR_MTX attr;
- };
- /*
- * Stack frame
- */
- typedef struct frame_t FRAME;
- struct frame_t {
- OBJ(FRAME);
- int level; /* nesting level */
- stkoff_t stack_offset; /* offset in the stack */
- };
- /* *****************************************************************
- * Static data
- */
- /*
- * Stack Frame list
- */
- static OBUCKET frame_bkt = { sizeof(FRAME), NULL };
- static FRAME *frame_first, *frame_last;
- #define curframe frame_last
- static int errcnt; /* Number of errors detected */
- static FUNCTION *function; /* Function being compiled */
- static grad_symtab_t *rewrite_tab;/* Function table */
- static MTX *mtx_first, *mtx_last; /* Matrix list */
- static VAR *var_first, *var_last; /* Variable list */
- /*
- * Loops
- */
- typedef struct loop_t LOOP;
- struct loop_t {
- OBJ(LOOP);
- JUMP_MTX *lp_break;
- JUMP_MTX *lp_cont;
- };
- static OBUCKET loop_bkt = { sizeof(LOOP), NULL };
- static LOOP *loop_first, *loop_last;
- void loop_push(MTX *mtx);
- void loop_pop();
- void loop_fixup(JUMP_MTX *list, MTX *target);
- void loop_init();
- void loop_free_all();
- void loop_unwind_all();
- /*
- * Lexical analyzer stuff
- */
- static FILE *infile; /* Input file */
- static grad_locus_t locus; /* Input location */
- static char *inbuf; /* Input string */
- static char *curp; /* Current pointer */
-
- static int yyeof; /* rised when EOF is encountered */
- static struct obstack input_stk; /* Symbol stack */
- static grad_data_type_t return_type = Undefined;
- /* Data type of the topmost expression. */
- static int regcomp_flags = 0; /* Flags to be used with regcomps */
- #define regex_init() regcomp_flags = 0
-
- /* Runtime */
- static size_t rewrite_stack_size = 4096; /* Size of stack+heap */
- static RWSTYPE *runtime_stack;
- static RWMACH mach;
- /* Default domain for gettext functions. It is initialized to PACKAGE
- by default */
- static char *default_gettext_domain;
-
- /* ***************************************************************
- * Function declarations
- */
- /*
- * Lexical analyzer
- */
- static int yylex();
- static void yysync();
- static int yyerror(char *s);
-
- /*
- * Frames
- */
- static void frame_init();
- static void frame_push();
- static void frame_pop();
- static void frame_unwind_all();
- static void frame_free_all();
- /*
- * Variables
- */
- static void var_init();
- static VAR * var_alloc(grad_data_type_t type, char *name, int grow);
- static void var_unwind_level();
- static void var_unwind_all();
- static void var_type(grad_data_type_t type, VAR *var);
- static void var_free_all();
- static VAR *var_lookup(char *name);
- /*
- * Matrices
- */
- static void mtx_init();
- static void mtx_free_all();
- static void mtx_unwind_all();
- static MTX * mtx_cur();
- static MTX * mtx_nop();
- static MTX * mtx_jump();
- static MTX * mtx_frame(Mtxtype type, stkoff_t stksize);
- static MTX * mtx_stop();
- static MTX * mtx_pop();
- static MTX * mtx_return();
- static MTX * mtx_alloc(Mtxtype type);
- static MTX * mtx_const(grad_value_t *val);
- static MTX * mtx_ref(int num);
- static MTX * mtx_var(VAR *var);
- static MTX * mtx_asgn(VAR *var, MTX *arg);
- static MTX * mtx_bin(Bopcode opcode, MTX *arg1, MTX *arg2);
- static MTX * mtx_un(Uopcode opcode, MTX *arg);
- static MTX * mtx_match(int negated, MTX *mtx, COMP_REGEX *);
- static MTX * mtx_cond(MTX *cond, MTX *if_true, MTX *if_false);
- static MTX * mtx_coerce(grad_data_type_t type, MTX *arg);
- static MTX * mtx_call(FUNCTION *fun, MTX *args);
- static MTX * mtx_builtin(builtin_t *bin, MTX *args);
- static MTX * mtx_attr(grad_dict_attr_t *attr, MTX *index);
- static MTX * mtx_attr_asgn(grad_dict_attr_t *attr, MTX *index, MTX *rval);
- static MTX * mtx_attr_check(grad_dict_attr_t *attr, MTX *index);
- static MTX * mtx_attr_delete(grad_dict_attr_t *attr, MTX *index);
- static MTX * coerce(MTX *arg, grad_data_type_t type);
- /*
- * Regular expressions
- */
- static COMP_REGEX * rx_alloc(regex_t *regex, int nmatch);
- static void rx_free(COMP_REGEX *rx);
- static COMP_REGEX * compile_regexp(char *str);
- /*
- * Functions
- */
- static FUNCTION * function_install(FUNCTION *fun);
- static int function_free(FUNCTION *fun);
- static void function_delete();
- static void function_cleanup();
- /*
- * Built-in functions
- */
- static builtin_t * builtin_lookup(char *name);
- /*
- * Code optimizer and generator
- */
- static int optimize();
- static pctr_t codegen();
- static void code_init();
- static void code_check();
- /*
- * Auxiliary and debugging functions
- */
- static void debug_dump_code();
- static const char * datatype_str_nom(grad_data_type_t type);
- static const char * datatype_str_acc(grad_data_type_t type);
- static const char * datatype_str_abl(grad_data_type_t type);
- static grad_data_type_t attr_datatype(grad_dict_attr_t *);
- /*
- * Run-Time
- */
- static void gc();
- static void run(pctr_t pc);
- static int run_init(pctr_t pc, grad_request_t *req);
- static int rw_error(const char *msg);
- static int rw_error_free(char *msg);
-
- /* These used to lock/unlock access to rw_code array. Now this is
- not needed. However, I left the placeholders for a while... */
- #define rw_code_lock()
- #define rw_code_unlock()
- #define AVPLIST(m) ((m)->req ? (m)->req->avlist : NULL)
- static FUNCTION fmain;
- %}
- %union {
- int number;
- int type;
- VAR *var;
- MTX *mtx;
- FUNCTION *fun;
- builtin_t *btin;
- grad_dict_attr_t *attr;
- struct {
- MTX *arg_first;
- MTX *arg_last;
- } arg;
- struct {
- int nmatch;
- regex_t regex;
- } rx;
- char *string;
- };
- %token <type> TYPE
- %token IF ELSE RETURN WHILE FOR DO BREAK CONTINUE DELETE
- %token <string> STRING IDENT
- %token <number> NUMBER REFERENCE
- %token <var> VARIABLE
- %token <fun> FUN
- %token <btin> BUILTIN
- %token <attr> ATTR
- %token BOGUS
- %type <arg> arglist
- %type <mtx> stmt expr list cond else while do arg args
- %type <var> varlist parmlist parm dclparm
- %right '='
- %left OR
- %left AND
- %nonassoc MT NM
- %left '|'
- %left '^'
- %left '&'
- %left EQ NE
- %left LT LE GT GE
- %left SHL SHR
- %left '+' '-'
- %left '*' '/' '%'
- %left UMINUS NOT TYPECAST
- %%
- program : input
- {
- var_free_all();
- loop_free_all();
- frame_free_all();
- mtx_free_all();
- }
- ;
- input : dcllist
- {
- return_type = Undefined;
- }
- | expr
- {
- if (errcnt) {
- YYERROR;
- }
-
- mtx_return($1);
-
- memset(&fmain, 0, sizeof(fmain));
- fmain.name = "main";
- fmain.rettype = return_type = $1->gen.datatype;
- function = &fmain;
- if (optimize() == 0) {
- codegen();
- if (errcnt) {
- YYERROR;
- }
- }
- }
- ;
- dcllist : decl
- | dcllist decl
- | dcllist error
- {
- /* Roll back all changes done so far */
- var_unwind_all();
- loop_unwind_all();
- frame_unwind_all();
- mtx_unwind_all();
- function_delete();
- /* Synchronize input after error */
- yysync();
- /* Clear input and error condition */
- yyclearin;
- yyerrok;
- errcnt = 0;
- }
- ;
- decl : fundecl begin list end
- {
- if (errcnt) {
- function_delete();
- YYERROR;
- }
-
- if (optimize() == 0) {
- codegen();
- if (errcnt) {
- function_delete();
- YYERROR;
- }
- } else {
- function_delete();
- }
-
- /* clean up things */
- var_unwind_all();
- loop_unwind_all();
- frame_unwind_all();
- mtx_unwind_all();
- function_cleanup();
- }
- ;
- fundecl : TYPE IDENT dclparm
- {
- VAR *var;
- PARAMETER *last, *parm;
- FUNCTION f;
-
- if (errcnt)
- YYERROR;
-
- memset(&f, 0, sizeof(f));
- f.name = $2;
- f.rettype = $1;
- f.entry = 0;
- f.loc = locus;
-
- f.nparm = 0;
- f.parm = NULL;
- /* Count number of parameters */
- for (var = $3; var; var = var->next)
- f.nparm++;
- f.parm = last = NULL;
- for (var = $3; var; var = var->next) {
- parm = grad_emalloc(sizeof(*parm));
- parm->datatype = var->datatype;
- var->offset = -(STACK_BASE+
- f.nparm - var->offset);
- parm->offset = var->offset;
- parm->prev = last;
- parm->next = NULL;
- if (f.parm == NULL)
- f.parm = parm;
- else
- last->next = parm;
- last = parm;
- }
- function = function_install(&f);
- }
- | TYPE FUN dclparm
- {
- grad_log_loc(GRAD_LOG_ERR, &locus,
- _("redefinition of function `%s'"), $2->name);
- grad_log_loc(GRAD_LOG_ERR, &$2->loc,
- _("previously defined here"));
- errcnt++;
- YYERROR;
- }
- ;
- begin : obrace
- | obrace autodcl
- ;
- end : cbrace
- ;
-
- obrace : '{'
- {
- frame_push();
- }
- ;
- cbrace : '}'
- {
- var_unwind_level();
- frame_pop();
- }
- ;
- /*
- * Automatic variables
- */
- autodcl : autovar
- | autodcl autovar
- ;
- autovar : TYPE varlist ';'
- {
- var_type($1, $2);
- }
- ;
- varlist : IDENT
- {
- $$ = var_alloc(Undefined, $1, +1);
- $$->dcllink = NULL;
- }
- | varlist ',' IDENT
- {
- VAR *var = var_alloc(Undefined, $3, +1);
- var->dcllink = $1;
- $$ = var;
- }
- ;
- /*
- * Function Parameters
- */
- dclparm : '(' ')'
- {
- $$ = NULL;
- }
- | '(' parmlist ')'
- {
- $$ = $2;
- }
- ;
- parmlist: parm
- {
- /*FIXME*/
- /*$$->dcllink = NULL;*/
- }
- | parmlist ',' parm
- {
- /*$1->dcllink = $3;*/
- $$ = $1;
- }
- ;
- parm : TYPE IDENT
- {
- $$ = var_alloc($1, $2, +1);
- }
- ;
- /* Argument lists
- */
- args : /* empty */
- {
- $$ = NULL;
- }
- | arglist
- {
- $$ = $1.arg_first;
- }
- ;
- arglist : arg
- {
- $1->gen.arglink = NULL;
- $$.arg_first = $$.arg_last = $1;
- }
- | arglist ',' arg
- {
- $1.arg_last->gen.arglink = $3;
- $1.arg_last = $3;
- $$ = $1;
- }
- ;
- arg : expr
- ;
- /*
- * Statement list and individual statements
- */
- list : stmt
- | list stmt
- ;
- stmt : begin list end
- {
- $$ = $2;
- }
- | expr ';'
- {
- mtx_stop();
- mtx_pop();
- }
- | IF cond stmt
- {
- $2->cond.if_false = mtx_nop();
- $$ = mtx_cur();
- }
- | IF cond stmt else stmt
- {
- mtx_stop();
- $2->cond.if_false = $4;
- $4->nop.prev->jump.dest = mtx_nop();
- $$ = mtx_cur();
- }
- | RETURN expr ';'
- {
- /*mtx_stop();*/
- $$ = mtx_return($2);
- }
- | while cond stmt
- {
- MTX *mtx;
-
- mtx_stop();
- mtx = mtx_jump();
- mtx->jump.dest = $1;
- $2->cond.if_false = mtx_nop();
- $$ = mtx_cur();
-
- /* Fixup possible breaks */
- loop_fixup(loop_last->lp_break, $$);
- /* Fixup possible continues */
- loop_fixup(loop_last->lp_cont, $1);
- loop_pop();
- }
- | do stmt { $<mtx>$ = mtx_nop(); } WHILE cond ';'
- {
- /* Default cond rule sets if_true to the next NOP matrix
- * Invert this behaviour.
- */
- $5->cond.if_false = $5->cond.if_true;
- $5->cond.if_true = $1;
- $$ = mtx_cur();
- /* Fixup possible breaks */
- loop_fixup(loop_last->lp_break, $$);
- /* Fixup possible continues */
- loop_fixup(loop_last->lp_cont, $<mtx>3);
- loop_pop();
- }
- /* ***********************
- For future use:
- | FOR '(' for_expr for_expr for_expr ')' stmt
- *********************** */
- | BREAK ';'
- {
- if (!loop_last) {
- grad_log_loc(GRAD_LOG_ERR, &locus,
- "%s",
- _("nothing to break from"));
- errcnt++;
- YYERROR;
- }
- $$ = mtx_jump();
- $$->jump.link = (MTX*)loop_last->lp_break;
- loop_last->lp_break = (JUMP_MTX*)$$;
- }
- | CONTINUE ';'
- {
- if (!loop_last) {
- grad_log_loc(GRAD_LOG_ERR, &locus,
- "%s",
- _("nothing to continue"));
- errcnt++;
- YYERROR;
- }
- $$ = mtx_jump();
- $$->jump.link = (MTX*)loop_last->lp_cont;
- loop_last->lp_cont = (JUMP_MTX*)$$;
- }
- | DELETE ATTR ';'
- {
- $$ = mtx_attr_delete($2, NULL);
- }
- | DELETE ATTR '(' expr ')' ';'
- {
- $$ = mtx_attr_delete($2, $4);
- }
- ;
- while : WHILE
- {
- $$ = mtx_nop();
- loop_push($$);
- }
- ;
- do : DO
- {
- $$ = mtx_nop();
- loop_push($$);
- }
- ;
- else : ELSE
- {
- mtx_stop();
- mtx_jump();
- $$ = mtx_nop();
- }
- ;
- cond : '(' expr ')'
- {
- mtx_stop();
- $$ = mtx_cond($2, NULL, NULL);
- $$->cond.if_true = mtx_nop();
- }
- ;
- /*
- * Expressions
- */
- expr : NUMBER
- {
- grad_value_t val;
- val.type = Integer;
- val.datum.ival = $1;
- $$ = mtx_const(&val);
- }
- | STRING
- {
- grad_value_t val;
- val.type = String;
- val.datum.sval.size = strlen($1);
- val.datum.sval.data = $1;
- $$ = mtx_const(&val);
- }
- | REFERENCE
- {
- $$ = mtx_ref($1);
- }
- | VARIABLE
- {
- $$ = mtx_var($1);
- }
- | IDENT
- {
- grad_log_loc(GRAD_LOG_ERR, &locus, _("undefined variable: %s"), $1);
- errcnt++;
- YYERROR;
- }
- | VARIABLE '=' expr
- {
- $$ = mtx_asgn($1, $3);
- }
- | ATTR
- {
- $$ = mtx_attr($1, NULL);
- }
- | ATTR '(' expr ')'
- {
- $$ = mtx_attr($1, $3);
- }
- | '*' ATTR
- {
- $$ = mtx_attr_check($2, NULL);
- }
- | '*' ATTR '(' expr ')'
- {
- $$ = mtx_attr_check($2, $4);
- }
- | ATTR '=' expr
- {
- $$ = mtx_attr_asgn($1, NULL, $3);
- }
- | ATTR '(' expr ')' '=' expr
- {
- $$ = mtx_attr_asgn($1, $3, $6);
- }
- | FUN '(' args ')'
- {
- $$ = mtx_call($1, $3);
- }
- | BUILTIN '(' args ')'
- {
- $$ = mtx_builtin($1, $3);
- }
- | expr '+' expr
- {
- $$ = mtx_bin(Add, $1, $3);
- }
- | expr '-' expr
- {
- $$ = mtx_bin(Sub, $1, $3);
- }
- | expr '*' expr
- {
- $$ = mtx_bin(Mul, $1, $3);
- }
- | expr '/' expr
- {
- $$ = mtx_bin(Div, $1, $3);
- }
- | expr '%' expr
- {
- $$ = mtx_bin(Rem, $1, $3);
- }
- | expr '|' expr
- {
- $$ = mtx_bin(BOr, $1, $3);
- }
- | expr '&' expr
- {
- $$ = mtx_bin(BAnd, $1, $3);
- }
- | expr '^' expr
- {
- $$ = mtx_bin(BXor, $1, $3);
- }
- | expr SHL expr
- {
- $$ = mtx_bin(Shl, $1, $3);
- }
- | expr SHR expr
- {
- $$ = mtx_bin(Shr, $1, $3);
- }
- | expr AND expr
- {
- $$ = mtx_bin(And, $1, $3);
- }
- | expr OR expr
- {
- $$ = mtx_bin(Or, $1, $3);
- }
- | '-' expr %prec UMINUS
- {
- $$ = mtx_un(Neg, $2);
- }
- | '+' expr %prec UMINUS
- {
- $$ = $2;
- }
- | NOT expr
- {
- $$ = mtx_un(Not, $2);
- }
- | '(' expr ')'
- {
- $$ = $2;
- }
- | '(' TYPE ')' expr %prec TYPECAST
- {
- $$ = mtx_coerce($2, $4);
- }
- | expr EQ expr
- {
- $$ = mtx_bin(Eq, $1, $3);
- }
- | expr NE expr
- {
- $$ = mtx_bin(Ne, $1, $3);
- }
- | expr LT expr
- {
- $$ = mtx_bin(Lt, $1, $3);
- }
- | expr LE expr
- {
- $$ = mtx_bin(Le, $1, $3);
- }
- | expr GT expr
- {
- $$ = mtx_bin(Gt, $1, $3);
- }
- | expr GE expr
- {
- $$ = mtx_bin(Ge, $1, $3);
- }
- | expr MT STRING
- {
- COMP_REGEX *rx;
- if ((rx = compile_regexp($3)) == NULL) {
- errcnt++;
- YYERROR;
- }
- $$ = mtx_match(0, $1, rx);
- }
- | expr NM STRING
- {
- COMP_REGEX *rx;
- if ((rx = compile_regexp($3)) == NULL) {
- errcnt++;
- YYERROR;
- }
- $$ = mtx_match(1, $1, rx);
- }
- ;
- %%
- int
- yyerror(char *s)
- {
- grad_log_loc(GRAD_LOG_ERR, &locus, "%s", s);
- errcnt++;
- return 0;
- }
- /* **************************************************************************
- * Interface functions
- */
- int
- parse_rewrite(char *path)
- {
- locus.file = path;
- infile = fopen(locus.file, "r");
- if (!infile) {
- if (errno != ENOENT) {
- grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
- _("can't open file `%s'"),
- locus.file);
- return -1;
- }
- return -2;
- }
- GRAD_DEBUG1(1, "Loading file %s", locus.file);
- rw_code_lock();
- yyeof = 0;
- locus.line = 1;
- errcnt = 0;
- regex_init();
- obstack_init(&input_stk);
- mtx_init();
- var_init();
- loop_init();
- frame_init();
-
- frame_push();
-
- yyparse();
- var_free_all();
- frame_free_all();
- mtx_free_all();
-
- fclose(infile);
- obstack_free(&input_stk, NULL);
- rw_code_unlock();
- return errcnt;
- }
- static int
- parse_rewrite_string(char *str)
- {
- rw_code_lock();
- code_check();
- yyeof = 0;
- locus.file = "<string>";
- locus.line = 1;
- errcnt = 0;
- regex_init();
- obstack_init(&input_stk);
- mtx_init();
- var_init();
- loop_init();
- frame_init();
-
- frame_push();
-
- if (GRAD_DEBUG_LEVEL(50))
- yydebug++;
- infile = 0;
- inbuf = curp = str;
-
- yyparse();
- #if defined(MAINTAINER_MODE)
- if (GRAD_DEBUG_LEVEL(100))
- debug_dump_code();
- #endif
-
- var_free_all();
- frame_free_all();
- mtx_free_all();
-
- obstack_free(&input_stk, NULL);
- rw_code_unlock();
- return errcnt;
- }
- /* **************************************************************************
- * Lexical analyzer stuff: too simple to be written in lex.
- */
- static int
- unput(int c)
- {
- if (!c)
- return 0;
- if (infile)
- ungetc(c, infile);
- else if (curp > inbuf)
- *--curp = c;
- return c;
- }
- static int
- input()
- {
- if (yyeof)
- yychar = 0;
- else if (infile) {
- if ((yychar = getc(infile)) <= 0) {
- yyeof++;
- yychar = 0;
- }
- } else if (curp) {
- yychar = *curp++;
- if (!yychar)
- yyeof++;
- }
- return yychar;
- }
- static int rw_backslash();
- static int c2d(int c);
- static int read_number();
- static int read_num(int n, int base);
- static char *read_string();
- static char *read_ident(int c);
- static char *read_to_delim(int c);
- static int skip_to_nl();
- static int c_comment();
- /*
- * Convert a character to digit. Only octal, decimal and hex digits are
- * allowed. If any other character is input, c2d() returns 100, which is
- * greater than any number base allowed.
- */
- int
- c2d(int c)
- {
- switch (c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return c - '0';
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- return c - 'A' + 16;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- return c - 'a' + 10;
- }
- return 100;
- }
- /*
- * Read a number. Usual C conventions apply.
- */
- int
- read_number()
- {
- int c;
- int base;
- int res;
-
- c = yychar;
- if (c == '0') {
- if (input() == 'x' || yychar == 'X') {
- base = 16;
- } else {
- base = 8;
- unput(yychar);
- }
- } else
- base = 10;
- res = read_num(c2d(c), base);
- if (base == 10 && yychar == '.') {
- int n;
- for (n = 0; n < 3 && yychar == '.'; n++) {
- int val;
-
- input();
- val = read_num(0, base);
- res = (res << 8) + val;
- }
- if (n != 3)
- res <<= 8 * (3-n);
- }
- return res;
- }
- int
- read_num(int n, int base)
- {
- int d;
- while (input() && (d = c2d(yychar)) < 16)
- n = n*base + d;
- unput(yychar);
- return n;
- }
- int
- rw_backslash()
- {
- switch (input()) {
- case '\\':
- return '\\';
- case 'a':
- return '\a';
- case 'b':
- return '\b';
- case 'f':
- return '\f';
- case 'n':
- return '\n';
- case 'r':
- return '\r';
- case 't':
- return '\t';
- case 'e':
- return '\033';
- case '0':
- return read_number();
- case 'x':
- case 'X':
- return read_num(0, 16);
- case '(':
- case ')':
- /* Preserve regular expressions */
- unput(yychar);
- yychar = '\\';
- }
- return yychar;
- }
- /*
- * Read a string up to the closing doublequote
- */
- char *
- read_string()
- {
- while (input() && yychar != '"') {
- if (yychar == '\\')
- yychar = rw_backslash();
- obstack_1grow(&input_stk, yychar);
- }
- obstack_1grow(&input_stk, 0);
- return obstack_finish(&input_stk);
- }
- /*
- * Read everything up to the given delimiter
- */
- char *
- read_to_delim(int c)
- {
- while (input() && yychar != c)
- obstack_1grow(&input_stk, yychar);
- obstack_1grow(&input_stk, 0);
- return obstack_finish(&input_stk);
- }
- /*
- * Is `c' a part of the word?
- */
- #define isword(c) (isalnum(c) || c == '_' || c == '$')
- /*
- * Is `c' a whitespace character?
- */
- #define isws(c) ((c) == ' ' || (c) == '\t')
- /*
- * Read identifier
- */
- char *
- read_ident(int c)
- {
- obstack_1grow(&input_stk, c);
- while (input() && isword(yychar))
- obstack_1grow(&input_stk, yychar);
- obstack_1grow(&input_stk, 0);
- unput(yychar);
- return obstack_finish(&input_stk);
- }
- /*
- * Skip input up to the next newline
- */
- int
- skip_to_nl()
- {
- while (input() && yychar != '\n')
- ;
- return unput(yychar);
- }
- /*
- * Skip a C-style comment
- */
- int
- c_comment()
- {
- if (yychar != '/')
- return 0;
- if (input() == '*') {
- size_t keep_line = locus.line;
- do {
- while (input() != '*') {
- if (yychar == 0) {
- grad_log_loc(GRAD_LOG_ERR, &locus,
- _("unexpected EOF in comment started at line %lu"),
- (unsigned long) keep_line);
- return 0;
- } else if (yychar == '\n')
- locus.line++;
- }
- } while (input() != '/');
- return 1;
- }
- unput(yychar);
- yychar = '/';
- return 0;
- }
- /* Pragmatic comments */
- enum pragma_handler_phase {
- pragma_begin,
- pragma_cont,
- pragma_error,
- pragma_end
- };
- typedef int (*pragma_handler_fp) (enum pragma_handler_phase);
- static int
- regex_pragma (enum pragma_handler_phase phase)
- {
- int disable = 0;
- int bit;
- char *s;
- static int regexp_accum;
-
- switch (phase) {
- case pragma_begin:
- regexp_accum = 0;
- return 0;
-
- case pragma_end:
- regcomp_flags = regexp_accum;
- return 0;
- case pragma_error:
- return 0;
-
- case pragma_cont:
- break;
- }
- switch (yychar) {
- case '+':
- disable = 0;
- input();
- break;
- case '-':
- disable = 1;
- input();
- break;
- }
- if (!isword(yychar)) {
- grad_log_loc(GRAD_LOG_ERR, &locus, _("Malformed pragma"));
- return 1;
- }
-
- s = read_ident(yychar);
- if (strcmp (s, "extended") == 0)
- bit = REG_EXTENDED;
- else if (strcmp (s, "icase") == 0)
- bit = REG_ICASE;
- else if (strcmp (s, "newline") == 0)
- bit = REG_NEWLINE;
- else {
- grad_log_loc(GRAD_LOG_ERR, &locus,
- _("Unknown regexp flag: %s"), s);
- return 1;
- }
- if (disable)
- regexp_accum &= ~bit;
- else
- regexp_accum |= bit;
- return 0;
- }
- static pragma_handler_fp
- find_pragma_handler(char *s)
- {
- if (strcmp(s, "regex") == 0)
- return regex_pragma;
- return NULL;
- }
- static void
- handle_pragma()
- {
- int rc;
- pragma_handler_fp pragma_handler;
-
- while (input() && isws(yychar))
- ;
- if (yychar == 0)
- return;
-
- pragma_handler = find_pragma_handler (read_ident(yychar));
-
- if (pragma_handler) {
- pragma_handler(pragma_begin);
- do {
- while (input() && isws(yychar))
- ;
- if (yychar == 0 || yychar == '\n')
- break;
- rc = pragma_handler(pragma_cont);
- } while (rc == 0 && yychar != '\n' && yychar != 0);
-
- pragma_handler(rc ? pragma_error : pragma_end);
- }
- }
- /* Parse a 'sharp' (single-line) comment */
- void
- sharp_comment()
- {
- while (input() && isws(yychar))
- ;
- if (yychar == 0)
- return;
- else if (yychar == '\n') {
- locus.line++;
- return;
- } else if (isword(yychar)) {
- if (strcmp(read_ident(yychar), "pragma") == 0)
- handle_pragma();
- }
-
- skip_to_nl();
- }
- #if defined(MAINTAINER_MODE)
- # define DEBUG_LEX1(s) if (GRAD_DEBUG_LEVEL(60)) printf("yylex: " s "\n")
- # define DEBUG_LEX2(s,v) if (GRAD_DEBUG_LEVEL(60)) printf("yylex: " s "\n", v)
- #else
- # define DEBUG_LEX1(s)
- # define DEBUG_LEX2(s,v)
- #endif
- static grad_keyword_t rw_kw[] = {
- { "if", IF },
- { "else", ELSE },
- { "return", RETURN },
- { "for", FOR },
- { "do", DO },
- { "while", WHILE },
- { "break", BREAK },
- { "continue", CONTINUE },
- { "delete", DELETE },
- { NULL }
- };
- int
- yylex()
- {
- int nl;
- int c;
- VAR *var;
- FUNCTION *fun;
- builtin_t *btin;
-
- /* Skip whitespace and comment lines */
- do {
- nl = 0;
- while (input() && isspace(yychar))
- if (yychar == '\n')
- locus.line++;
-
- if (!yychar)
- return 0;
- if (yychar == '#') {
- sharp_comment();
- nl = 1;
- }
- } while (nl || c_comment());
- /*
- * A regexp reference
- */
- if (yychar == '\\') {
- input();
- yylval.number = read_number();
- DEBUG_LEX2("REFERENCE %d", yylval.number);
- return REFERENCE;
- }
- /*
- * A character
- */
- if (yychar == '\'') {
- if (input() == '\\')
- c = rw_backslash();
- else
- c = yychar;
- if (input() != '\'') {
- grad_log_loc(GRAD_LOG_ERR, &locus,
- "%s",
- _("unterminated character constant"));
- errcnt++;
- }
- yylval.number = c;
- DEBUG_LEX2("CHAR %d", c);
- return NUMBER;
- }
-
- /*
- * A number
- */
- if (isdigit(yychar)) {
- yylval.number = read_number();
- DEBUG_LEX2("NUMBER %d", yylval.number);
- return NUMBER;
- }
- /*
- * Quoted string
- */
- if (yychar == '"') {
- yylval.string = read_string();
- DEBUG_LEX2("STRING %s", yylval.string);
- return STRING;
- }
- /* A/V pair reference.
- We do not allow %<number> sequences, since it would result
- in conflict with binary '%' operator.
- Thanks to Clement Gerouville for noticing. */
- if (yychar == '%') {
- grad_dict_attr_t *attr = 0;
- char *attr_name;
-
- input();
- if (yychar == '[' || yychar == '{') {
- attr_name = read_to_delim(yychar == '[' ? ']' : '}');
- attr = grad_attr_name_to_dict(attr_name);
- } else {
- unput(yychar);
- return '%';
- }
- if (!attr) {
- grad_log_loc(GRAD_LOG_ERR, &locus,
- _("unknown attribute `%s'"),
- attr_name);
- errcnt++;
- return BOGUS;
- }
- yylval.attr = attr;
- DEBUG_LEX2("ATTR: %s", attr->name);
- return ATTR;
- }
-
-
- /*
- * Data type or identifier
- */
- if (isword(yychar)) {
- yylval.string = read_ident(yychar);
- if (strcmp(yylval.string, "integer") == 0) {
- DEBUG_LEX1("TYPE(Integer)");
- yylval.type = Integer;
- return TYPE;
- } else if (strcmp(yylval.string, "string") == 0) {
- DEBUG_LEX1("TYPE(String)");
- yylval.type = String;
- return TYPE;
- }
-
- if ((c = grad_xlat_keyword(rw_kw, yylval.string, 0)) != 0) {
- DEBUG_LEX2("KW: %s", yylval.string);
- return c;
- }
- if (var = var_lookup(yylval.string)) {
- DEBUG_LEX2("VARIABLE: %s", yylval.string);
- yylval.var = var;
- return VARIABLE;
- }
-
- if (fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, yylval.string)) {
- DEBUG_LEX2("FUN %s", yylval.string);
- yylval.fun = fun;
- return FUN;
- }
- if (btin = builtin_lookup(yylval.string)) {
- DEBUG_LEX2("BUILTIN %s", yylval.string);
- yylval.btin = btin;
- return BUILTIN;
- }
- DEBUG_LEX2("IDENT: %s", yylval.string);
- return IDENT;
- }
- /*
- * Boolean expressions
- */
- if (yychar == '&' || yychar == '|') {
- int c = yychar;
- if (input() == c) {
- DEBUG_LEX2("%s", yychar == '&' ? "AND" : "OR");
- return yychar == '&' ? AND : OR;
- }
- unput(yychar);
-
- DEBUG_LEX2("%c", c);
- return c;
- }
-
- /*
- * Comparison operator
- */
- if (strchr("<>=!", yychar)) {
- int c = yychar;
- if (input() == '=') {
- switch (c) {
- case '<':
- DEBUG_LEX1("LE");
- return LE;
- case '>':
- DEBUG_LEX1("GE");
- return GE;
- case '=':
- DEBUG_LEX1("EQ");
- return EQ;
- case '!':
- DEBUG_LEX1("NE");
- return NE;
- }
- } else if (c == yychar) {
- if (c == '<') {
- DEBUG_LEX1("SHL");
- return SHL;
- }
- if (c == '>') {
- DEBUG_LEX1("SHR");
- return SHR;
- }
- unput(yychar);
- DEBUG_LEX2("%c", yychar);
- return yychar;
- } else if (yychar == '~') {
- if (c == '=') {
- DEBUG_LEX1("MT");
- return MT;
- }
- if (c == '!') {
- DEBUG_LEX1("NM");
- return NM;
- }
- }
- unput(yychar);
- switch (c) {
- case '<':
- DEBUG_LEX1("LT");
- return LT;
- case '>':
- DEBUG_LEX1("GT");
- return GT;
- case '!':
- DEBUG_LEX1("NOT");
- return NOT;
- default:
- return c;
- }
- }
- DEBUG_LEX2("%c", yychar);
- return yychar;
- }
- void
- yysync()
- {
- while (skip_to_nl() == '\n' && !isalpha(input()))
- locus.line++;
- unput(yychar);
- }
- /* ****************************************************************************
- * Generalized list functions
- */
- static RWLIST *_list_insert(RWLIST **first, RWLIST **last, RWLIST *prev,
- RWLIST *obj, int before);
- static RWLIST *_list_remove(RWLIST **first, RWLIST **last, RWLIST *obj);
- static RWLIST *_list_append(RWLIST **first, RWLIST **last, RWLIST *obj);
- #define rw_list_insert(first, last, prev, obj, before) \
- _list_insert((RWLIST**)first,(RWLIST**)last,(RWLIST*)prev,(RWLIST*)obj, before)
- #define rw_list_remove(first, last, obj) \
- _list_remove((RWLIST**)first,(RWLIST**)last,(RWLIST *)obj)
- #define rw_list_append(first, last, obj) \
- _list_append((RWLIST**)first, (RWLIST**)last, (RWLIST*)obj)
-
- RWLIST *
- _list_append(RWLIST **first, RWLIST **last, RWLIST *obj)
- {
- return rw_list_insert(first, last, *last, obj, 0);
- }
- RWLIST *
- _list_insert(RWLIST **first, RWLIST **last, RWLIST *prev, RWLIST *obj,
- int before)
- {
- RWLIST *next;
- /*
- * No first element: initialize whole list
- */
- if (!*first) {
- *first = obj;
- if (last)
- *last = obj;
- obj->prev = obj->next = NULL;
- return obj;
- }
- /*
- * Insert before `prev'
- */
- if (before) {
- _list_insert(first, last, prev, obj, 0);
- _list_remove(first, last, prev);
- _list_insert(first, last, obj, prev, 0);
- return obj;
- }
- /*
- * Default: insert after prev
- */
- obj->prev = prev;
- obj->next = prev->next;
-
- if (next = prev->next)
- next->prev = obj;
- prev->next = obj;
- if (last && prev == *last)
- *last = obj;
-
- return obj;
- }
- RWLIST *
- _list_remove(RWLIST **first, RWLIST **last, RWLIST *obj)
- {
- RWLIST *temp;
- if (temp = obj->prev)
- temp->next = obj->next;
- else
- *first = obj->next;
- if (temp = obj->next)
- temp->prev = ob…
Large files files are truncated, but you can click here to view the full file