1 /* A Bison parser, made by GNU Bison 2.3.  */
2 
3 /* Skeleton implementation for Bison's Yacc-like parsers in C
4 
5    Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
6    Free Software Foundation, Inc.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2, or (at your option)
11    any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301, USA.  */
22 
23 /* As a special exception, you may create a larger work that contains
24    part or all of the Bison parser skeleton and distribute that work
25    under terms of your choice, so long as that work isn't itself a
26    parser generator using the skeleton or a modified version thereof
27    as a parser skeleton.  Alternatively, if you modify or redistribute
28    the parser skeleton itself, you may (at your option) remove this
29    special exception, which will cause the skeleton and the resulting
30    Bison output files to be licensed under the GNU General Public
31    License without this special exception.
32 
33    This special exception was added by the Free Software Foundation in
34    version 2.2 of Bison.  */
35 
36 /* C LALR(1) parser skeleton written by Richard Stallman, by
37    simplifying the original so-called "semantic" parser.  */
38 
39 /* All symbols defined below should begin with rw_yy or YY, to avoid
40    infringing on user name space.  This should be done even for local
41    variables, as they might otherwise be expanded by user macros.
42    There are some unavoidable exceptions within include files to
43    define necessary library symbols; they are noted "INFRINGES ON
44    USER NAME SPACE" below.  */
45 
46 /* Identify Bison output.  */
47 #define YYBISON 1
48 
49 /* Bison version.  */
50 #define YYBISON_VERSION "2.3"
51 
52 /* Skeleton name.  */
53 #define YYSKELETON_NAME "yacc.c"
54 
55 /* Pure parsers.  */
56 #define YYPURE 0
57 
58 /* Using locations.  */
59 #define YYLSP_NEEDED 0
60 
61 
62 
63 /* Tokens.  */
64 #ifndef YYTOKENTYPE
65 # define YYTOKENTYPE
66    /* Put the tokens into the symbol table, so that GDB and other debuggers
67       know about them.  */
68    enum rw_yytokentype {
69      TYPE = 258,
70      IF = 259,
71      ELSE = 260,
72      RETURN = 261,
73      WHILE = 262,
74      FOR = 263,
75      DO = 264,
76      BREAK = 265,
77      CONTINUE = 266,
78      DELETE = 267,
79      STRING = 268,
80      IDENT = 269,
81      NUMBER = 270,
82      REFERENCE = 271,
83      VARIABLE = 272,
84      FUN = 273,
85      BUILTIN = 274,
86      ATTR = 275,
87      BOGUS = 276,
88      OR = 277,
89      AND = 278,
90      NM = 279,
91      MT = 280,
92      NE = 281,
93      EQ = 282,
94      GE = 283,
95      GT = 284,
96      LE = 285,
97      LT = 286,
98      SHR = 287,
99      SHL = 288,
100      TYPECAST = 289,
101      NOT = 290,
102      UMINUS = 291
103    };
104 #endif
105 /* Tokens.  */
106 #define TYPE 258
107 #define IF 259
108 #define ELSE 260
109 #define RETURN 261
110 #define WHILE 262
111 #define FOR 263
112 #define DO 264
113 #define BREAK 265
114 #define CONTINUE 266
115 #define DELETE 267
116 #define STRING 268
117 #define IDENT 269
118 #define NUMBER 270
119 #define REFERENCE 271
120 #define VARIABLE 272
121 #define FUN 273
122 #define BUILTIN 274
123 #define ATTR 275
124 #define BOGUS 276
125 #define OR 277
126 #define AND 278
127 #define NM 279
128 #define MT 280
129 #define NE 281
130 #define EQ 282
131 #define GE 283
132 #define GT 284
133 #define LE 285
134 #define LT 286
135 #define SHR 287
136 #define SHL 288
137 #define TYPECAST 289
138 #define NOT 290
139 #define UMINUS 291
140 
141 
142 
143 
144 /* Copy the first part of user declarations.  */
145 #line 1 "rewrite.y"
146 
147 /* This file is part of GNU Radius.
148    Copyright (C) 2000,2001,2002,2003,2004,2005,
149    2006,2007,2008 Free Software Foundation, Inc.
150 
151    Written by Sergey Poznyakoff
152 
153    GNU Radius is free software; you can redistribute it and/or modify
154    it under the terms of the GNU General Public License as published by
155    the Free Software Foundation; either version 3 of the License, or
156    (at your option) any later version.
157 
158    GNU Radius is distributed in the hope that it will be useful,
159    but WITHOUT ANY WARRANTY; without even the implied warranty of
160    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161    GNU General Public License for more details.
162 
163    You should have received a copy of the GNU General Public License
164    along with GNU Radius; if not, write to the Free Software Foundation,
165    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
166 
167 #if defined(HAVE_CONFIG_H)
168 # include <config.h>
169 #endif
170 #include <sys/types.h>
171 #include <stdio.h>
172 #include <string.h>
173 #include <ctype.h>
174 #include <errno.h>
175 
176 #include <radiusd.h>
177 #include <setjmp.h>
178 #include <rewrite.h>
179 #ifdef USE_SERVER_GUILE
180 # include <libguile.h>
181 # include <radius/radscm.h>
182 #endif
183 
184 typedef long RWSTYPE;
185 #define RW_MIN(a,b) ((a)<(b)) ? (a) : (b)
186 
187 /*
188  * Generalized list structure
189  */
190 typedef struct rw_list RWLIST;
191 #define RWLIST(type) \
192         type     *next;\
193         type     *prev
194 
195 struct rw_list {
196         RWLIST(RWLIST);
197 };
198 
199 /*
200  * Generalized object
201  */
202 typedef struct object_t OBJECT ;
203 
204 #define OBJ(type) \
205         RWLIST(type);\
206         type    *alloc
207 
208 struct object_t {
209         OBJ(OBJECT);
210 };
211 
212 typedef struct {
213         size_t   size;        /* Size of an element */
214         void     (*free)();   /* deallocator */
215         OBJECT   *alloc_list; /* list of allocated elements */
216 } OBUCKET;
217 
218 
219 
220 /* ************************************************************
221  * Basic data types
222  */
223 
224 typedef int stkoff_t;             /* Offset on stack */
225 typedef unsigned int pctr_t;      /* Program counter */
226 
227 #define RW_REG ('z'-'a'+1)
228 
229 typedef struct {
230         RWSTYPE    reg[RW_REG];       /* Registers */
231         #define rA reg[0]
232         char       *sA;               /* String accumulator */
233         pctr_t     pc;                /* Program counter */
234 
235         RWSTYPE    *stack;            /* Stack+heap space */
236         int        stacksize;         /* Size of stack */
237         int        st;                /* Top of stack */
238         int        sb;                /* Stack base */
239         int        ht;                /* Top of heap */
240 
241         int        nmatch;
242         regmatch_t *pmatch;
243 
244         grad_request_t *req;
245 
246         jmp_buf    jmp;
247 } RWMACH;
248 
249 typedef void (*INSTR)();       /* program instruction */
250 
251 /* Compiled regular expression
252  */
253 typedef struct comp_regex COMP_REGEX;
254 struct comp_regex {
255         OBJ(COMP_REGEX);
256         regex_t      regex;    /* compiled regex itself */
257         int          nmatch;   /* number of \( ... \) groups */
258 };
259 
260 /*
261  * Binary Operations
262  */
263 typedef enum {
264         Eq,
265         Ne,
266         Lt,
267         Le,
268         Gt,
269         Ge,
270         BAnd,
271         BXor,
272         BOr,
273         And,
274         Or,
275         Shl,
276         Shr,
277         Add,
278         Sub,
279         Mul,
280         Div,
281         Rem,
282         Max_opcode
283 } Bopcode;
284 
285 /*
286  * Unary operations
287  */
288 typedef enum {
289         Neg,
290         Not,
291         Max_unary
292 } Uopcode;
293 
294 /*
295  * Matrix types
296  */
297 typedef enum {
298         Generic,
299         Nop,
300         Enter,
301         Leave,
302         Stop,
303         Constant,
304         Matchref,
305         Variable,
306         Unary,
307         Binary,
308         Cond,
309         Asgn,
310         Match,
311         Coercion,
312         Expression,
313         Return,
314         Jump,
315         Branch,
316         Target,
317         Call,
318         Builtin,
319         Pop,
320         Pusha,
321         Popa,
322         Attr,
323         Attr_asgn,
324         Attr_check,
325 	Attr_delete,
326         Max_mtxtype
327 } Mtxtype;
328 
329 /*
330  * Function parameter
331  */
332 typedef struct parm_t PARAMETER;
333 struct parm_t {
334         PARAMETER   *prev;     /* Previous parameter */
335         PARAMETER   *next;     /* Next parameter */
336         grad_data_type_t    datatype;  /* type */
337         stkoff_t    offset;    /* Offset on stack */
338 };
339 
340 /*
341  * Local variable
342  */
343 typedef struct variable VAR;
344 struct variable {
345         OBJ(VAR);
346         VAR       *dcllink;  /* Link to the next variable vithin the
347                               * same declaration
348                               */
349         char      *name;     /* name of the variable */
350         int       level;     /* nesting level */
351         int       offset;    /* offset on stack */
352         grad_data_type_t  datatype;  /* type */
353         int       constant;  /* true if assigned a constant value */
354         grad_datum_t     datum;     /* constant value itself */
355 };
356 
357 /*
358  * Function definition
359  */
360 typedef struct function_def {
361         struct function_def *next;
362         char       *name;        /* Function name */
363         grad_data_type_t   rettype;      /* Return type */
364         pctr_t     entry;        /* Code entry */
365         COMP_REGEX *rx_list;     /* List of compiled regexps */
366         int        nparm;        /* Number of parameters */
367         PARAMETER  *parm;        /* List of parameters */
368         stkoff_t   stack_alloc;  /* required stack allocation */
369         grad_locus_t      loc;   /* source location where the function
370                                   * was declared
371                                   */
372 } FUNCTION;
373 
374 #define STACK_BASE 2
375 
376 /*
377  * Built-in function
378  */
379 typedef struct  {
380         INSTR    handler;        /* Function itself */
381         char     *name;          /* Function name */
382         grad_data_type_t rettype;        /* Return type */
383         char     *parms;         /* coded parameter types */
384 } builtin_t;
385 
386 /*
387  * Operation matrices
388  */
389 typedef union mtx MTX;
390 /*
391  * All matrices contain the following common fields:
392  *    alloc- link to the previously allocated matrix.
393  *           It is used at the end of code generation
394  *           pass to free all allocated matrices.
395  *    next - link to the next matrix in the subexpression
396  *    prev - link to the previous matrix in the subexpression
397  * Additionally, all expression matrices contain the field
398  * `datatype' which contains the data type for this matrix.
399  */
400 #if defined(MAINTAINER_MODE)
401 # define COMMON_MTX \
402         OBJ(MTX);\
403         int      id;\
404         grad_locus_t    loc;\
405         Mtxtype  type;
406 #else
407 # define COMMON_MTX \
408         OBJ(MTX);\
409         grad_locus_t    loc;\
410         Mtxtype  type;
411 #endif
412 
413 #define COMMON_EXPR_MTX \
414         COMMON_MTX\
415         grad_data_type_t datatype;\
416         MTX      *uplink;\
417         MTX      *arglink;
418 
419 /*
420  * Generic matrix: nothing special
421  * Type: Generic
422  */
423 typedef struct {
424         COMMON_EXPR_MTX
425 } GEN_MTX;
426 /*
427  * Constant matrix
428  * Type: Constant
429  */
430 typedef struct {
431         COMMON_EXPR_MTX
432         grad_datum_t    datum;     /* Constant value */
433 } CONST_MTX;
434 /*
435  * Reference to a previous regexp: corresponds to a \N construct
436  * Type: Matchref
437  */
438 typedef struct {
439         COMMON_EXPR_MTX
440         int      num;       /* Number of \( ... \) to be referenced */
441 } MATCHREF_MTX;
442 /*
443  * Reference to a variable
444  * Type: Variable
445  */
446 typedef struct {
447         COMMON_EXPR_MTX
448         VAR      *var;      /* Variable being referenced */
449 } VAR_MTX;
450 /*
451  * Unary operation matrix
452  * Type: Unary
453  */
454 typedef struct {
455         COMMON_EXPR_MTX
456         Uopcode  opcode;    /* Operation code */
457         MTX      *arg;      /* Argument */
458 } UN_MTX;
459 /*
460  * Binary operation matrix
461  * Type: Binary
462  */
463 typedef struct {
464         COMMON_EXPR_MTX
465         Bopcode   opcode;   /* Operation code */
466         MTX      *arg[2];   /* Arguments */
467 } BIN_MTX;
468 /*
469  * Assignment matrix
470  * Type: Asgn
471  */
472 typedef struct {
473         COMMON_EXPR_MTX
474         VAR      *lval;     /* Lvalue */
475         MTX      *arg;      /* Rvalue */
476 } ASGN_MTX;
477 /*
478  * Conditional expression matrix
479  * Type: Cond
480  */
481 typedef struct {
482         COMMON_MTX
483         MTX      *expr;     /* Conditional expression */
484         MTX      *if_true;  /* Branch if true */
485         MTX      *if_false; /* Branch if false */
486 } COND_MTX;
487 /*
488  * Regexp match
489  * Type: Match
490  */
491 typedef struct {
492         COMMON_EXPR_MTX
493         int        negated; /* Is the match negated ? */
494         MTX        *arg;    /* Argument (lhs) */
495         COMP_REGEX *rx;     /* Regexp (rhs) */
496 } MATCH_MTX;
497 /*
498  * Type coercion
499  * Type: Coerce
500  */
501 typedef struct {
502         COMMON_EXPR_MTX
503         MTX      *arg;      /* Argument of the coercion */
504 } COERCE_MTX;
505 /*
506  * Expression
507  * Type: Expression
508  */
509 typedef struct {
510         COMMON_EXPR_MTX
511         MTX      *expr;
512 } EXPR_MTX;
513 /*
514  * Return from function
515  * Type: Return
516  */
517 typedef struct {
518         COMMON_EXPR_MTX
519         MTX      *expr;     /* Return value */
520 } RET_MTX;
521 /*
522  * Unconditional branch (jump)
523  * Type: Jump
524  */
525 typedef struct {
526         COMMON_MTX
527         MTX *link;          /* Link to the next jump matrix
528                              * (for break and continue matrices)
529                              */
530         MTX      *dest;     /* Jump destination (usually a NOP matrix) */
531 } JUMP_MTX;
532 /*
533  * Conditional branch
534  * Type: Branch
535  */
536 typedef struct {
537         COMMON_MTX
538         int      cond;      /* Condition: 1 - equal, 0 - not equal */
539         MTX      *dest;     /* Jump destination (usually a NOP matrix) */
540 } BRANCH_MTX;
541 /*
542  * Stack frame matrix
543  * Type: Enter, Leave
544  */
545 typedef struct {
546         COMMON_MTX
547         stkoff_t  stacksize;/* Required stack size */
548 } FRAME_MTX;
549 /*
550  * Jump target
551  * Type: Target
552  */
553 typedef struct {
554         COMMON_MTX
555         pctr_t  pc;         /* Target's program counter */
556 } TGT_MTX;
557 /*
558  * No-op matrix. It is always inserted at the branch destination
559  * points. Its purpose is to keep a singly-linked list of jump
560  * locations for fixing up jump statements.
561  * Type: Nop
562  */
563 typedef struct {
564         COMMON_MTX
565         TGT_MTX   *tgt;     /* Target list */
566         pctr_t     pc;      /* Program counter for backward
567                                references */
568 } NOP_MTX;
569 /*
570  * Function call
571  * Type: Call
572  */
573 typedef struct {
574         COMMON_EXPR_MTX
575         FUNCTION  *fun;     /* Called function */
576         int       nargs;    /* Number of arguments */
577         MTX       *args;    /* Arguments */
578 } CALL_MTX;
579 /*
580  * Builtin function call
581  * Type: Builtin
582  */
583 typedef struct {
584         COMMON_EXPR_MTX
585         INSTR     fun;      /* Handler function */
586         int       nargs;    /* Number of arguments */
587         MTX       *args;    /* Arguments */
588 } BTIN_MTX;
589 /*
590  * Attribute matrix
591  * Type: Attr, Attr_asgn, Attr_check
592  */
593 typedef struct {
594         COMMON_EXPR_MTX
595         int       attrno;   /* Attribute number */
596 	MTX       *index;   /* Index expression */
597         MTX       *rval;    /* Rvalue */
598 } ATTR_MTX;
599 
600 union mtx {
601         GEN_MTX    gen;
602         NOP_MTX    nop;
603         FRAME_MTX  frame;
604         CONST_MTX  cnst;
605         MATCHREF_MTX    ref;
606         VAR_MTX    var;
607         UN_MTX     un;
608         BIN_MTX    bin;
609         COND_MTX   cond;
610         ASGN_MTX   asgn;
611         MATCH_MTX  match;
612         COERCE_MTX coerce;
613         RET_MTX    ret;
614         JUMP_MTX   jump;
615         BRANCH_MTX branch;
616         TGT_MTX    tgt;
617         CALL_MTX   call;
618         BTIN_MTX   btin;
619         ATTR_MTX   attr;
620 };
621 
622 /*
623  * Stack frame
624  */
625 typedef struct frame_t FRAME;
626 
627 struct frame_t {
628         OBJ(FRAME);
629         int       level;        /* nesting level */
630         stkoff_t  stack_offset; /* offset in the stack */
631 };
632 
633 
634 /* *****************************************************************
635  * Static data
636  */
637 /*
638  * Stack Frame list
639  */
640 static OBUCKET frame_bkt = { sizeof(FRAME), NULL };
641 static FRAME *frame_first, *frame_last;
642 #define curframe frame_last
643 
644 static int errcnt;         /* Number of errors detected */
645 static FUNCTION *function; /* Function being compiled */
646 static grad_symtab_t *rewrite_tab;/* Function table */
647 
648 static MTX *mtx_first, *mtx_last;  /* Matrix list */
649 static VAR *var_first, *var_last;  /* Variable list */
650 
651 /*
652  * Loops
653  */
654 typedef struct loop_t LOOP;
655 struct loop_t {
656         OBJ(LOOP);
657         JUMP_MTX *lp_break;
658         JUMP_MTX *lp_cont;
659 };
660 static OBUCKET loop_bkt = { sizeof(LOOP), NULL };
661 static LOOP *loop_first, *loop_last;
662 
663 void loop_push(MTX *mtx);
664 void loop_pop();
665 void loop_fixup(JUMP_MTX *list, MTX *target);
666 void loop_init();
667 void loop_free_all();
668 void loop_unwind_all();
669 
670 /*
671  * Lexical analyzer stuff
672  */
673 static FILE *infile;               /* Input file */
674 static grad_locus_t locus;         /* Input location */
675 
676 static char *inbuf;                /* Input string */
677 static char *curp;                 /* Current pointer */
678 
679 static int   rw_yyeof;                /* rised when EOF is encountered */
680 static struct obstack input_stk;   /* Symbol stack */
681 
682 static grad_data_type_t return_type = Undefined;
683                                    /* Data type of the topmost expression. */
684 
685 static int regcomp_flags = 0;      /* Flags to be used with regcomps */
686 
687 #define regex_init() regcomp_flags = 0
688 
689 /* Runtime */
690 static size_t rewrite_stack_size = 4096;  /* Size of stack+heap */
691 static RWSTYPE *runtime_stack;
692 static RWMACH mach;
693 
694 /* Default domain for gettext functions. It is initialized to PACKAGE
695    by default */
696 static char *default_gettext_domain;
697 
698 
699 /* ***************************************************************
700  * Function declarations
701  */
702 
703 /*
704  * Lexical analyzer
705  */
706 static int rw_yylex();
707 static void rw_yysync();
708 static int rw_yyerror(char *s);
709 
710 /*
711  * Frames
712  */
713 static void frame_init();
714 static void frame_push();
715 static void frame_pop();
716 static void frame_unwind_all();
717 static void frame_free_all();
718 /*
719  * Variables
720  */
721 static void var_init();
722 static VAR * var_alloc(grad_data_type_t type, char *name, int grow);
723 static void var_unwind_level();
724 static void var_unwind_all();
725 static void var_type(grad_data_type_t type, VAR *var);
726 static void var_free_all();
727 static VAR *var_lookup(char *name);
728 /*
729  * Matrices
730  */
731 static void mtx_init();
732 static void mtx_free_all();
733 static void mtx_unwind_all();
734 static MTX * mtx_cur();
735 static MTX * mtx_nop();
736 static MTX * mtx_jump();
737 static MTX * mtx_frame(Mtxtype type, stkoff_t stksize);
738 static MTX * mtx_stop();
739 static MTX * mtx_pop();
740 static MTX * mtx_return();
741 static MTX * mtx_alloc(Mtxtype type);
742 static MTX * mtx_const(grad_value_t *val);
743 static MTX * mtx_ref(int num);
744 static MTX * mtx_var(VAR *var);
745 static MTX * mtx_asgn(VAR *var, MTX *arg);
746 static MTX * mtx_bin(Bopcode opcode, MTX *arg1, MTX *arg2);
747 static MTX * mtx_un(Uopcode opcode, MTX *arg);
748 static MTX * mtx_match(int negated, MTX *mtx, COMP_REGEX *);
749 static MTX * mtx_cond(MTX *cond, MTX *if_true, MTX *if_false);
750 static MTX * mtx_coerce(grad_data_type_t type, MTX *arg);
751 static MTX * mtx_call(FUNCTION *fun, MTX *args);
752 static MTX * mtx_builtin(builtin_t *bin, MTX *args);
753 static MTX * mtx_attr(grad_dict_attr_t *attr, MTX *index);
754 static MTX * mtx_attr_asgn(grad_dict_attr_t *attr, MTX *index, MTX *rval);
755 static MTX * mtx_attr_check(grad_dict_attr_t *attr, MTX *index);
756 static MTX * mtx_attr_delete(grad_dict_attr_t *attr, MTX *index);
757 
758 static MTX * coerce(MTX  *arg, grad_data_type_t type);
759 /*
760  * Regular expressions
761  */
762 static COMP_REGEX * rx_alloc(regex_t  *regex, int nmatch);
763 static void rx_free(COMP_REGEX *rx);
764 static COMP_REGEX * compile_regexp(char *str);
765 /*
766  * Functions
767  */
768 static FUNCTION * function_install(FUNCTION *fun);
769 static int  function_free(FUNCTION *fun);
770 static void function_delete();
771 static void function_cleanup();
772 /*
773  * Built-in functions
774  */
775 static builtin_t * builtin_lookup(char *name);
776 
777 /*
778  * Code optimizer and generator
779  */
780 static int optimize();
781 static pctr_t codegen();
782 static void code_init();
783 static void code_check();
784 
785 /*
786  * Auxiliary and debugging functions
787  */
788 static void debug_dump_code();
789 static const char * datatype_str_nom(grad_data_type_t type);
790 static const char * datatype_str_acc(grad_data_type_t type);
791 static const char * datatype_str_abl(grad_data_type_t type);
792 static grad_data_type_t attr_datatype(grad_dict_attr_t *);
793 
794 /*
795  * Run-Time
796  */
797 static void gc();
798 static void run(pctr_t pc);
799 static int run_init(pctr_t pc, grad_request_t *req);
800 static int rw_error(const char *msg);
801 static int rw_error_free(char *msg);
802 
803 /* These used to lock/unlock access to rw_code array. Now this is
804    not needed. However, I left the placeholders for a while... */
805 #define rw_code_lock()
806 #define rw_code_unlock()
807 
808 #define AVPLIST(m) ((m)->req ? (m)->req->avlist : NULL)
809 
810 static FUNCTION fmain;
811 
812 
813 /* Enabling traces.  */
814 #ifndef YYDEBUG
815 # define YYDEBUG 1
816 #endif
817 
818 /* Enabling verbose error messages.  */
819 #ifdef YYERROR_VERBOSE
820 # undef YYERROR_VERBOSE
821 # define YYERROR_VERBOSE 1
822 #else
823 # define YYERROR_VERBOSE 0
824 #endif
825 
826 /* Enabling the token table.  */
827 #ifndef YYTOKEN_TABLE
828 # define YYTOKEN_TABLE 0
829 #endif
830 
831 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
832 typedef union YYSTYPE
833 #line 669 "rewrite.y"
834 {
835         int   number;
836         int   type;
837         VAR   *var;
838         MTX   *mtx;
839         FUNCTION  *fun;
840         builtin_t *btin;
841         grad_dict_attr_t *attr;
842         struct {
843                 MTX *arg_first;
844                 MTX *arg_last;
845         } arg;
846         struct {
847                 int nmatch;
848                 regex_t regex;
849         } rx;
850         char  *string;
851 }
852 /* Line 187 of yacc.c.  */
853 #line 854 "rewrite.c"
854 	YYSTYPE;
855 # define rw_yystype YYSTYPE /* obsolescent; will be withdrawn */
856 # define YYSTYPE_IS_DECLARED 1
857 # define YYSTYPE_IS_TRIVIAL 1
858 #endif
859 
860 
861 
862 /* Copy the second part of user declarations.  */
863 
864 
865 /* Line 216 of yacc.c.  */
866 #line 867 "rewrite.c"
867 
868 #ifdef short
869 # undef short
870 #endif
871 
872 #ifdef YYTYPE_UINT8
873 typedef YYTYPE_UINT8 rw_yytype_uint8;
874 #else
875 typedef unsigned char rw_yytype_uint8;
876 #endif
877 
878 #ifdef YYTYPE_INT8
879 typedef YYTYPE_INT8 rw_yytype_int8;
880 #elif (defined __STDC__ || defined __C99__FUNC__ \
881      || defined __cplusplus || defined _MSC_VER)
882 typedef signed char rw_yytype_int8;
883 #else
884 typedef short int rw_yytype_int8;
885 #endif
886 
887 #ifdef YYTYPE_UINT16
888 typedef YYTYPE_UINT16 rw_yytype_uint16;
889 #else
890 typedef unsigned short int rw_yytype_uint16;
891 #endif
892 
893 #ifdef YYTYPE_INT16
894 typedef YYTYPE_INT16 rw_yytype_int16;
895 #else
896 typedef short int rw_yytype_int16;
897 #endif
898 
899 #ifndef YYSIZE_T
900 # ifdef __SIZE_TYPE__
901 #  define YYSIZE_T __SIZE_TYPE__
902 # elif defined size_t
903 #  define YYSIZE_T size_t
904 # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
905      || defined __cplusplus || defined _MSC_VER)
906 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
907 #  define YYSIZE_T size_t
908 # else
909 #  define YYSIZE_T unsigned int
910 # endif
911 #endif
912 
913 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
914 
915 #ifndef YY_
916 # if YYENABLE_NLS
917 #  if ENABLE_NLS
918 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
919 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
920 #  endif
921 # endif
922 # ifndef YY_
923 #  define YY_(msgid) msgid
924 # endif
925 #endif
926 
927 /* Suppress unused-variable warnings by "using" E.  */
928 #if ! defined lint || defined __GNUC__
929 # define YYUSE(e) ((void) (e))
930 #else
931 # define YYUSE(e) /* empty */
932 #endif
933 
934 /* Identity function, used to suppress warnings about constant conditions.  */
935 #ifndef lint
936 # define YYID(n) (n)
937 #else
938 #if (defined __STDC__ || defined __C99__FUNC__ \
939      || defined __cplusplus || defined _MSC_VER)
940 static int
YYID(int i)941 YYID (int i)
942 #else
943 static int
944 YYID (i)
945     int i;
946 #endif
947 {
948   return i;
949 }
950 #endif
951 
952 #if ! defined rw_yyoverflow || YYERROR_VERBOSE
953 
954 /* The parser invokes alloca or malloc; define the necessary symbols.  */
955 
956 # ifdef YYSTACK_USE_ALLOCA
957 #  if YYSTACK_USE_ALLOCA
958 #   ifdef __GNUC__
959 #    define YYSTACK_ALLOC __builtin_alloca
960 #   elif defined __BUILTIN_VA_ARG_INCR
961 #    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
962 #   elif defined _AIX
963 #    define YYSTACK_ALLOC __alloca
964 #   elif defined _MSC_VER
965 #    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
966 #    define alloca _alloca
967 #   else
968 #    define YYSTACK_ALLOC alloca
969 #    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
970      || defined __cplusplus || defined _MSC_VER)
971 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
972 #     ifndef _STDLIB_H
973 #      define _STDLIB_H 1
974 #     endif
975 #    endif
976 #   endif
977 #  endif
978 # endif
979 
980 # ifdef YYSTACK_ALLOC
981    /* Pacify GCC's `empty if-body' warning.  */
982 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
983 #  ifndef YYSTACK_ALLOC_MAXIMUM
984     /* The OS might guarantee only one guard page at the bottom of the stack,
985        and a page size can be as small as 4096 bytes.  So we cannot safely
986        invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
987        to allow for a few compiler-allocated temporary stack slots.  */
988 #   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
989 #  endif
990 # else
991 #  define YYSTACK_ALLOC YYMALLOC
992 #  define YYSTACK_FREE YYFREE
993 #  ifndef YYSTACK_ALLOC_MAXIMUM
994 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
995 #  endif
996 #  if (defined __cplusplus && ! defined _STDLIB_H \
997        && ! ((defined YYMALLOC || defined malloc) \
998 	     && (defined YYFREE || defined free)))
999 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
1000 #   ifndef _STDLIB_H
1001 #    define _STDLIB_H 1
1002 #   endif
1003 #  endif
1004 #  ifndef YYMALLOC
1005 #   define YYMALLOC malloc
1006 #   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
1007      || defined __cplusplus || defined _MSC_VER)
1008 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
1009 #   endif
1010 #  endif
1011 #  ifndef YYFREE
1012 #   define YYFREE free
1013 #   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
1014      || defined __cplusplus || defined _MSC_VER)
1015 void free (void *); /* INFRINGES ON USER NAME SPACE */
1016 #   endif
1017 #  endif
1018 # endif
1019 #endif /* ! defined rw_yyoverflow || YYERROR_VERBOSE */
1020 
1021 
1022 #if (! defined rw_yyoverflow \
1023      && (! defined __cplusplus \
1024 	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
1025 
1026 /* A type that is properly aligned for any stack member.  */
1027 union rw_yyalloc
1028 {
1029   rw_yytype_int16 rw_yyss;
1030   YYSTYPE rw_yyvs;
1031   };
1032 
1033 /* The size of the maximum gap between one aligned stack and the next.  */
1034 # define YYSTACK_GAP_MAXIMUM (sizeof (union rw_yyalloc) - 1)
1035 
1036 /* The size of an array large to enough to hold all stacks, each with
1037    N elements.  */
1038 # define YYSTACK_BYTES(N) \
1039      ((N) * (sizeof (rw_yytype_int16) + sizeof (YYSTYPE)) \
1040       + YYSTACK_GAP_MAXIMUM)
1041 
1042 /* Copy COUNT objects from FROM to TO.  The source and destination do
1043    not overlap.  */
1044 # ifndef YYCOPY
1045 #  if defined __GNUC__ && 1 < __GNUC__
1046 #   define YYCOPY(To, From, Count) \
1047       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
1048 #  else
1049 #   define YYCOPY(To, From, Count)		\
1050       do					\
1051 	{					\
1052 	  YYSIZE_T rw_yyi;				\
1053 	  for (rw_yyi = 0; rw_yyi < (Count); rw_yyi++)	\
1054 	    (To)[rw_yyi] = (From)[rw_yyi];		\
1055 	}					\
1056       while (YYID (0))
1057 #  endif
1058 # endif
1059 
1060 /* Relocate STACK from its old location to the new one.  The
1061    local variables YYSIZE and YYSTACKSIZE give the old and new number of
1062    elements in the stack, and YYPTR gives the new location of the
1063    stack.  Advance YYPTR to a properly aligned location for the next
1064    stack.  */
1065 # define YYSTACK_RELOCATE(Stack)					\
1066     do									\
1067       {									\
1068 	YYSIZE_T rw_yynewbytes;						\
1069 	YYCOPY (&rw_yyptr->Stack, Stack, rw_yysize);				\
1070 	Stack = &rw_yyptr->Stack;						\
1071 	rw_yynewbytes = rw_yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
1072 	rw_yyptr += rw_yynewbytes / sizeof (*rw_yyptr);				\
1073       }									\
1074     while (YYID (0))
1075 
1076 #endif
1077 
1078 /* YYFINAL -- State number of the termination state.  */
1079 #define YYFINAL  34
1080 /* YYLAST -- Last index in YYTABLE.  */
1081 #define YYLAST   535
1082 
1083 /* YYNTOKENS -- Number of terminals.  */
1084 #define YYNTOKENS  52
1085 /* YYNNTS -- Number of nonterminals.  */
1086 #define YYNNTS  27
1087 /* YYNRULES -- Number of rules.  */
1088 #define YYNRULES  87
1089 /* YYNRULES -- Number of states.  */
1090 #define YYNSTATES  166
1091 
1092 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
1093 #define YYUNDEFTOK  2
1094 #define YYMAXUTOK   291
1095 
1096 #define YYTRANSLATE(YYX)						\
1097   ((unsigned int) (YYX) <= YYMAXUTOK ? rw_yytranslate[YYX] : YYUNDEFTOK)
1098 
1099 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
1100 static const rw_yytype_uint8 rw_yytranslate[] =
1101 {
1102        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1103        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1104        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1105        2,     2,     2,     2,     2,     2,     2,    42,    29,     2,
1106       50,    51,    40,    38,    49,    39,     2,    41,     2,     2,
1107        2,     2,     2,     2,     2,     2,     2,     2,     2,    48,
1108        2,    22,     2,     2,     2,     2,     2,     2,     2,     2,
1109        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1110        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1111        2,     2,     2,     2,    28,     2,     2,     2,     2,     2,
1112        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1113        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1114        2,     2,     2,    46,    27,    47,     2,     2,     2,     2,
1115        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1116        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1117        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1118        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1119        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1120        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1121        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1122        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1123        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1124        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1125        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1126        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
1127        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
1128        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
1129       15,    16,    17,    18,    19,    20,    21,    23,    24,    25,
1130       26,    30,    31,    32,    33,    34,    35,    36,    37,    43,
1131       44,    45
1132 };
1133 
1134 #if YYDEBUG
1135 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
1136    YYRHS.  */
1137 static const rw_yytype_uint16 rw_yyprhs[] =
1138 {
1139        0,     0,     3,     5,     7,     9,    11,    14,    17,    22,
1140       26,    30,    32,    35,    37,    39,    41,    43,    46,    50,
1141       52,    56,    59,    63,    65,    69,    72,    73,    75,    77,
1142       81,    83,    85,    88,    92,    95,    99,   105,   109,   113,
1143      114,   121,   124,   127,   131,   138,   140,   142,   144,   148,
1144      150,   152,   154,   156,   158,   162,   164,   169,   172,   178,
1145      182,   189,   194,   199,   203,   207,   211,   215,   219,   223,
1146      227,   231,   235,   239,   243,   247,   250,   253,   256,   260,
1147      265,   269,   273,   277,   281,   285,   289,   293
1148 };
1149 
1150 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
1151 static const rw_yytype_int8 rw_yyrhs[] =
1152 {
1153       53,     0,    -1,    54,    -1,    55,    -1,    78,    -1,    56,
1154       -1,    55,    56,    -1,    55,     1,    -1,    57,    58,    71,
1155       59,    -1,     3,    14,    65,    -1,     3,    18,    65,    -1,
1156       60,    -1,    60,    62,    -1,    61,    -1,    46,    -1,    47,
1157       -1,    63,    -1,    62,    63,    -1,     3,    64,    48,    -1,
1158       14,    -1,    64,    49,    14,    -1,    50,    51,    -1,    50,
1159       66,    51,    -1,    67,    -1,    66,    49,    67,    -1,     3,
1160       14,    -1,    -1,    69,    -1,    70,    -1,    69,    49,    70,
1161       -1,    78,    -1,    72,    -1,    71,    72,    -1,    58,    71,
1162       59,    -1,    78,    48,    -1,     4,    77,    72,    -1,     4,
1163       77,    72,    76,    72,    -1,     6,    78,    48,    -1,    74,
1164       77,    72,    -1,    -1,    75,    72,    73,     7,    77,    48,
1165       -1,    10,    48,    -1,    11,    48,    -1,    12,    20,    48,
1166       -1,    12,    20,    50,    78,    51,    48,    -1,     7,    -1,
1167        9,    -1,     5,    -1,    50,    78,    51,    -1,    15,    -1,
1168       13,    -1,    16,    -1,    17,    -1,    14,    -1,    17,    22,
1169       78,    -1,    20,    -1,    20,    50,    78,    51,    -1,    40,
1170       20,    -1,    40,    20,    50,    78,    51,    -1,    20,    22,
1171       78,    -1,    20,    50,    78,    51,    22,    78,    -1,    18,
1172       50,    68,    51,    -1,    19,    50,    68,    51,    -1,    78,
1173       38,    78,    -1,    78,    39,    78,    -1,    78,    40,    78,
1174       -1,    78,    41,    78,    -1,    78,    42,    78,    -1,    78,
1175       27,    78,    -1,    78,    29,    78,    -1,    78,    28,    78,
1176       -1,    78,    37,    78,    -1,    78,    36,    78,    -1,    78,
1177       24,    78,    -1,    78,    23,    78,    -1,    39,    78,    -1,
1178       38,    78,    -1,    44,    78,    -1,    50,    78,    51,    -1,
1179       50,     3,    51,    78,    -1,    78,    31,    78,    -1,    78,
1180       30,    78,    -1,    78,    35,    78,    -1,    78,    34,    78,
1181       -1,    78,    33,    78,    -1,    78,    32,    78,    -1,    78,
1182       26,    13,    -1,    78,    25,    13,    -1
1183 };
1184 
1185 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
1186 static const rw_yytype_uint16 rw_yyrline[] =
1187 {
1188        0,   719,   719,   728,   732,   754,   755,   756,   773,   799,
1189      838,   849,   850,   853,   856,   862,   873,   874,   877,   883,
1190      888,   899,   903,   909,   914,   921,   931,   934,   940,   945,
1191      953,   959,   960,   963,   967,   972,   977,   984,   989,  1005,
1192     1005,  1024,  1038,  1051,  1055,  1061,  1068,  1075,  1083,  1094,
1193     1101,  1109,  1113,  1117,  1123,  1127,  1131,  1135,  1139,  1143,
1194     1147,  1151,  1155,  1159,  1163,  1167,  1171,  1175,  1179,  1183,
1195     1187,  1191,  1195,  1199,  1203,  1207,  1211,  1215,  1219,  1223,
1196     1227,  1231,  1235,  1239,  1243,  1247,  1251,  1260
1197 };
1198 #endif
1199 
1200 #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
1201 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
1202    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
1203 static const char *const rw_yytname[] =
1204 {
1205   "$end", "error", "$undefined", "TYPE", "IF", "ELSE", "RETURN", "WHILE",
1206   "FOR", "DO", "BREAK", "CONTINUE", "DELETE", "STRING", "IDENT", "NUMBER",
1207   "REFERENCE", "VARIABLE", "FUN", "BUILTIN", "ATTR", "BOGUS", "'='", "OR",
1208   "AND", "NM", "MT", "'|'", "'^'", "'&'", "NE", "EQ", "GE", "GT", "LE",
1209   "LT", "SHR", "SHL", "'+'", "'-'", "'*'", "'/'", "'%'", "TYPECAST", "NOT",
1210   "UMINUS", "'{'", "'}'", "';'", "','", "'('", "')'", "$accept", "program",
1211   "input", "dcllist", "decl", "fundecl", "begin", "end", "obrace",
1212   "cbrace", "autodcl", "autovar", "varlist", "dclparm", "parmlist", "parm",
1213   "args", "arglist", "arg", "list", "stmt", "@1", "while", "do", "else",
1214   "cond", "expr", 0
1215 };
1216 #endif
1217 
1218 # ifdef YYPRINT
1219 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
1220    token YYLEX-NUM.  */
1221 static const rw_yytype_uint16 rw_yytoknum[] =
1222 {
1223        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
1224      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
1225      275,   276,    61,   277,   278,   279,   280,   124,    94,    38,
1226      281,   282,   283,   284,   285,   286,   287,   288,    43,    45,
1227       42,    47,    37,   289,   290,   291,   123,   125,    59,    44,
1228       40,    41
1229 };
1230 # endif
1231 
1232 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
1233 static const rw_yytype_uint8 rw_yyr1[] =
1234 {
1235        0,    52,    53,    54,    54,    55,    55,    55,    56,    57,
1236       57,    58,    58,    59,    60,    61,    62,    62,    63,    64,
1237       64,    65,    65,    66,    66,    67,    68,    68,    69,    69,
1238       70,    71,    71,    72,    72,    72,    72,    72,    72,    73,
1239       72,    72,    72,    72,    72,    74,    75,    76,    77,    78,
1240       78,    78,    78,    78,    78,    78,    78,    78,    78,    78,
1241       78,    78,    78,    78,    78,    78,    78,    78,    78,    78,
1242       78,    78,    78,    78,    78,    78,    78,    78,    78,    78,
1243       78,    78,    78,    78,    78,    78,    78,    78
1244 };
1245 
1246 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
1247 static const rw_yytype_uint8 rw_yyr2[] =
1248 {
1249        0,     2,     1,     1,     1,     1,     2,     2,     4,     3,
1250        3,     1,     2,     1,     1,     1,     1,     2,     3,     1,
1251        3,     2,     3,     1,     3,     2,     0,     1,     1,     3,
1252        1,     1,     2,     3,     2,     3,     5,     3,     3,     0,
1253        6,     2,     2,     3,     6,     1,     1,     1,     3,     1,
1254        1,     1,     1,     1,     3,     1,     4,     2,     5,     3,
1255        6,     4,     4,     3,     3,     3,     3,     3,     3,     3,
1256        3,     3,     3,     3,     3,     2,     2,     2,     3,     4,
1257        3,     3,     3,     3,     3,     3,     3,     3
1258 };
1259 
1260 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
1261    STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
1262    means the default is an error.  */
1263 static const rw_yytype_uint8 rw_yydefact[] =
1264 {
1265        0,     0,    50,    53,    49,    51,    52,     0,     0,    55,
1266        0,     0,     0,     0,     0,     0,     2,     0,     5,     0,
1267        4,     0,     0,     0,    26,    26,     0,     0,    76,    75,
1268       57,    77,     0,     0,     1,     7,     6,    14,     0,    11,
1269        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
1270        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
1271        0,     9,    10,    54,     0,    27,    28,    30,     0,    59,
1272        0,     0,     0,    78,     0,     0,    45,    46,     0,     0,
1273        0,     0,     0,    31,     0,     0,     0,     0,    12,    16,
1274       74,    73,    87,    86,    68,    70,    69,    81,    80,    85,
1275       84,    83,    82,    72,    71,    63,    64,    65,    66,    67,
1276        0,    21,     0,    23,    61,     0,    62,    56,     0,    79,
1277        0,     0,     0,    41,    42,     0,     0,    15,     8,    13,
1278       32,     0,    39,    34,    19,     0,    17,    25,     0,    22,
1279       29,     0,    58,     0,    35,    37,    43,     0,    33,    38,
1280        0,    18,     0,    24,    60,    48,    47,     0,     0,     0,
1281       20,    36,     0,     0,    44,    40
1282 };
1283 
1284 /* YYDEFGOTO[NTERM-NUM].  */
1285 static const rw_yytype_int16 rw_yydefgoto[] =
1286 {
1287       -1,    15,    16,    17,    18,    19,    81,   128,    39,   129,
1288       88,    89,   135,    61,   112,   113,    64,    65,    66,    82,
1289       83,   150,    84,    85,   157,   121,    86
1290 };
1291 
1292 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
1293    STATE-NUM.  */
1294 #define YYPACT_NINF -84
1295 static const rw_yytype_int16 rw_yypact[] =
1296 {
1297       67,    17,   -84,   -84,   -84,   -84,    -1,   -22,    12,   -20,
1298      207,   207,    44,   207,   110,    65,   -84,    33,   -84,    20,
1299      432,    19,    19,   207,   207,   207,   207,   207,   -84,   -84,
1300       24,   -84,    16,   235,   -84,   -84,   -84,   -84,   169,    74,
1301      207,   207,    66,    90,   207,   207,   207,   207,   207,   207,
1302      207,   207,   207,   207,   207,   207,   207,   207,   207,   207,
1303        9,   -84,   -84,   432,    57,    61,   -84,   432,    58,   432,
1304      264,   207,   207,   -84,    62,   207,   -84,   -84,    68,    70,
1305       94,   169,   152,   -84,    62,   169,   380,   105,    74,   -84,
1306      451,   469,   -84,   -84,    60,   199,   482,   493,   493,   -33,
1307      -33,   -33,   -33,   -23,   -23,    -3,    -3,   -84,   -84,   -84,
1308      107,   -84,   -29,   -84,   -84,   207,   -84,   100,   293,   -84,
1309      207,   169,   406,   -84,   -84,    13,   152,   -84,   -84,   -84,
1310      -84,   169,   -84,   -84,   -84,    -6,   -84,   -84,   128,   -84,
1311      -84,   207,   -84,   322,   127,   -84,   -84,   207,   -84,   -84,
1312      126,   -84,   120,   -84,   432,   -84,   -84,   169,   351,    62,
1313      -84,   -84,    87,    88,   -84,   -84
1314 };
1315 
1316 /* YYPGOTO[NTERM-NUM].  */
1317 static const rw_yytype_int16 rw_yypgoto[] =
1318 {
1319      -84,   -84,   -84,   -84,   121,   -84,   118,    14,   -84,   -84,
1320      -84,    51,   -84,   122,   -84,     4,   130,   -84,    28,    64,
1321      -53,   -84,   -84,   -84,   -84,   -83,     0
1322 };
1323 
1324 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
1325    positive, shift that token.  If negative, reduce the rule which
1326    number is the opposite.  If zero, do what YYDEFACT says.
1327    If YYTABLE_NINF, syntax error.  */
1328 #define YYTABLE_NINF -4
1329 static const rw_yytype_int16 rw_yytable[] =
1330 {
1331       20,   131,    26,    53,    54,    55,    56,    57,    58,    59,
1332       28,    29,   110,    31,    33,    55,    56,    57,    58,    59,
1333      138,    23,   139,    63,    67,    67,    69,    70,    24,   130,
1334       27,    21,   132,    -3,    35,    22,     1,    57,    58,    59,
1335       90,    91,   151,   152,    94,    95,    96,    97,    98,    99,
1336      100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
1337      111,   146,    25,   147,    30,    34,    37,    72,   144,    60,
1338        1,   118,   119,   130,    71,   122,   163,    87,   149,    92,
1339        2,     3,     4,     5,     6,     7,     8,     9,    45,    46,
1340       47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
1341       57,    58,    59,    93,   161,    10,    11,    12,   114,   116,
1342      115,    13,   120,    32,   125,    67,   123,    14,   124,   134,
1343      143,   137,   141,     2,     3,     4,     5,     6,     7,     8,
1344        9,   110,   156,   159,   160,   164,   165,    38,    36,   136,
1345      148,   154,   153,   140,    62,   126,     0,   158,    10,    11,
1346       12,     0,     0,     0,    13,    68,    74,     0,    75,    76,
1347       14,    77,    78,    79,    80,     2,     3,     4,     5,     6,
1348        7,     8,     9,    74,     0,    75,    76,     0,    77,    78,
1349       79,    80,     2,     3,     4,     5,     6,     7,     8,     9,
1350       10,    11,    12,     0,     0,     0,    13,     0,    37,   127,
1351        0,     0,    14,     0,     0,     0,     0,    10,    11,    12,
1352        0,     0,     0,    13,     0,    37,     0,     0,     0,    14,
1353        2,     3,     4,     5,     6,     7,     8,     9,    46,    47,
1354       48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
1355       58,    59,     0,     0,     0,    10,    11,    12,     0,     0,
1356        0,    13,     0,     0,     0,     0,     0,    14,    40,    41,
1357       42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
1358       52,    53,    54,    55,    56,    57,    58,    59,     0,     0,
1359        0,     0,     0,     0,     0,     0,    73,    40,    41,    42,
1360       43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
1361       53,    54,    55,    56,    57,    58,    59,     0,     0,     0,
1362        0,     0,     0,     0,     0,   117,    40,    41,    42,    43,
1363       44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
1364       54,    55,    56,    57,    58,    59,     0,     0,     0,     0,
1365        0,     0,     0,     0,   142,    40,    41,    42,    43,    44,
1366       45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
1367       55,    56,    57,    58,    59,     0,     0,     0,     0,     0,
1368        0,     0,     0,   155,    40,    41,    42,    43,    44,    45,
1369       46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
1370       56,    57,    58,    59,     0,     0,     0,     0,     0,     0,
1371        0,     0,   162,    40,    41,    42,    43,    44,    45,    46,
1372       47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
1373       57,    58,    59,     0,     0,     0,     0,     0,   133,    40,
1374       41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
1375       51,    52,    53,    54,    55,    56,    57,    58,    59,     0,
1376        0,     0,     0,     0,   145,    40,    41,    42,    43,    44,
1377       45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
1378       55,    56,    57,    58,    59,    41,    42,    43,    44,    45,
1379       46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
1380       56,    57,    58,    59,    42,    43,    44,    45,    46,    47,
1381       48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
1382       58,    59,    47,    48,    49,    50,    51,    52,    53,    54,
1383       55,    56,    57,    58,    59,    49,    50,    51,    52,    53,
1384       54,    55,    56,    57,    58,    59
1385 };
1386 
1387 static const rw_yytype_int16 rw_yycheck[] =
1388 {
1389        0,    84,    22,    36,    37,    38,    39,    40,    41,    42,
1390       10,    11,     3,    13,    14,    38,    39,    40,    41,    42,
1391       49,    22,    51,    23,    24,    25,    26,    27,    50,    82,
1392       50,    14,    85,     0,     1,    18,     3,    40,    41,    42,
1393       40,    41,    48,    49,    44,    45,    46,    47,    48,    49,
1394       50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
1395       51,    48,    50,    50,    20,     0,    46,    51,   121,    50,
1396        3,    71,    72,   126,    50,    75,   159,     3,   131,    13,
1397       13,    14,    15,    16,    17,    18,    19,    20,    28,    29,
1398       30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
1399       40,    41,    42,    13,   157,    38,    39,    40,    51,    51,
1400       49,    44,    50,     3,    20,   115,    48,    50,    48,    14,
1401      120,    14,    22,    13,    14,    15,    16,    17,    18,    19,
1402       20,     3,     5,     7,    14,    48,    48,    19,    17,    88,
1403      126,   141,   138,   115,    22,    81,    -1,   147,    38,    39,
1404       40,    -1,    -1,    -1,    44,    25,     4,    -1,     6,     7,
1405       50,     9,    10,    11,    12,    13,    14,    15,    16,    17,
1406       18,    19,    20,     4,    -1,     6,     7,    -1,     9,    10,
1407       11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
1408       38,    39,    40,    -1,    -1,    -1,    44,    -1,    46,    47,
1409       -1,    -1,    50,    -1,    -1,    -1,    -1,    38,    39,    40,
1410       -1,    -1,    -1,    44,    -1,    46,    -1,    -1,    -1,    50,
1411       13,    14,    15,    16,    17,    18,    19,    20,    29,    30,
1412       31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
1413       41,    42,    -1,    -1,    -1,    38,    39,    40,    -1,    -1,
1414       -1,    44,    -1,    -1,    -1,    -1,    -1,    50,    23,    24,
1415       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
1416       35,    36,    37,    38,    39,    40,    41,    42,    -1,    -1,
1417       -1,    -1,    -1,    -1,    -1,    -1,    51,    23,    24,    25,
1418       26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
1419       36,    37,    38,    39,    40,    41,    42,    -1,    -1,    -1,
1420       -1,    -1,    -1,    -1,    -1,    51,    23,    24,    25,    26,
1421       27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
1422       37,    38,    39,    40,    41,    42,    -1,    -1,    -1,    -1,
1423       -1,    -1,    -1,    -1,    51,    23,    24,    25,    26,    27,
1424       28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
1425       38,    39,    40,    41,    42,    -1,    -1,    -1,    -1,    -1,
1426       -1,    -1,    -1,    51,    23,    24,    25,    26,    27,    28,
1427       29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
1428       39,    40,    41,    42,    -1,    -1,    -1,    -1,    -1,    -1,
1429       -1,    -1,    51,    23,    24,    25,    26,    27,    28,    29,
1430       30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
1431       40,    41,    42,    -1,    -1,    -1,    -1,    -1,    48,    23,
1432       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
1433       34,    35,    36,    37,    38,    39,    40,    41,    42,    -1,
1434       -1,    -1,    -1,    -1,    48,    23,    24,    25,    26,    27,
1435       28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
1436       38,    39,    40,    41,    42,    24,    25,    26,    27,    28,
1437       29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
1438       39,    40,    41,    42,    25,    26,    27,    28,    29,    30,
1439       31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
1440       41,    42,    30,    31,    32,    33,    34,    35,    36,    37,
1441       38,    39,    40,    41,    42,    32,    33,    34,    35,    36,
1442       37,    38,    39,    40,    41,    42
1443 };
1444 
1445 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
1446    symbol of state STATE-NUM.  */
1447 static const rw_yytype_uint8 rw_yystos[] =
1448 {
1449        0,     3,    13,    14,    15,    16,    17,    18,    19,    20,
1450       38,    39,    40,    44,    50,    53,    54,    55,    56,    57,
1451       78,    14,    18,    22,    50,    50,    22,    50,    78,    78,
1452       20,    78,     3,    78,     0,     1,    56,    46,    58,    60,
1453       23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
1454       33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
1455       50,    65,    65,    78,    68,    69,    70,    78,    68,    78,
1456       78,    50,    51,    51,     4,     6,     7,     9,    10,    11,
1457       12,    58,    71,    72,    74,    75,    78,     3,    62,    63,
1458       78,    78,    13,    13,    78,    78,    78,    78,    78,    78,
1459       78,    78,    78,    78,    78,    78,    78,    78,    78,    78,
1460        3,    51,    66,    67,    51,    49,    51,    51,    78,    78,
1461       50,    77,    78,    48,    48,    20,    71,    47,    59,    61,
1462       72,    77,    72,    48,    14,    64,    63,    14,    49,    51,
1463       70,    22,    51,    78,    72,    48,    48,    50,    59,    72,
1464       73,    48,    49,    67,    78,    51,     5,    76,    78,     7,
1465       14,    72,    51,    77,    48,    48
1466 };
1467 
1468 #define rw_yyerrok		(rw_yyerrstatus = 0)
1469 #define rw_yyclearin	(rw_yychar = YYEMPTY)
1470 #define YYEMPTY		(-2)
1471 #define YYEOF		0
1472 
1473 #define YYACCEPT	goto rw_yyacceptlab
1474 #define YYABORT		goto rw_yyabortlab
1475 #define YYERROR		goto rw_yyerrorlab
1476 
1477 
1478 /* Like YYERROR except do call rw_yyerror.  This remains here temporarily
1479    to ease the transition to the new meaning of YYERROR, for GCC.
1480    Once GCC version 2 has supplanted version 1, this can go.  */
1481 
1482 #define YYFAIL		goto rw_yyerrlab
1483 
1484 #define YYRECOVERING()  (!!rw_yyerrstatus)
1485 
1486 #define YYBACKUP(Token, Value)					\
1487 do								\
1488   if (rw_yychar == YYEMPTY && rw_yylen == 1)				\
1489     {								\
1490       rw_yychar = (Token);						\
1491       rw_yylval = (Value);						\
1492       rw_yytoken = YYTRANSLATE (rw_yychar);				\
1493       YYPOPSTACK (1);						\
1494       goto rw_yybackup;						\
1495     }								\
1496   else								\
1497     {								\
1498       rw_yyerror (YY_("syntax error: cannot back up")); \
1499       YYERROR;							\
1500     }								\
1501 while (YYID (0))
1502 
1503 
1504 #define YYTERROR	1
1505 #define YYERRCODE	256
1506 
1507 
1508 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
1509    If N is 0, then set CURRENT to the empty location which ends
1510    the previous symbol: RHS[0] (always defined).  */
1511 
1512 #define YYRHSLOC(Rhs, K) ((Rhs)[K])
1513 #ifndef YYLLOC_DEFAULT
1514 # define YYLLOC_DEFAULT(Current, Rhs, N)				\
1515     do									\
1516       if (YYID (N))                                                    \
1517 	{								\
1518 	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
1519 	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
1520 	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
1521 	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
1522 	}								\
1523       else								\
1524 	{								\
1525 	  (Current).first_line   = (Current).last_line   =		\
1526 	    YYRHSLOC (Rhs, 0).last_line;				\
1527 	  (Current).first_column = (Current).last_column =		\
1528 	    YYRHSLOC (Rhs, 0).last_column;				\
1529 	}								\
1530     while (YYID (0))
1531 #endif
1532 
1533 
1534 /* YY_LOCATION_PRINT -- Print the location on the stream.
1535    This macro was not mandated originally: define only if we know
1536    we won't break user code: when these are the locations we know.  */
1537 
1538 #ifndef YY_LOCATION_PRINT
1539 # if YYLTYPE_IS_TRIVIAL
1540 #  define YY_LOCATION_PRINT(File, Loc)			\
1541      fprintf (File, "%d.%d-%d.%d",			\
1542 	      (Loc).first_line, (Loc).first_column,	\
1543 	      (Loc).last_line,  (Loc).last_column)
1544 # else
1545 #  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
1546 # endif
1547 #endif
1548 
1549 
1550 /* YYLEX -- calling `rw_yylex' with the right arguments.  */
1551 
1552 #ifdef YYLEX_PARAM
1553 # define YYLEX rw_yylex (YYLEX_PARAM)
1554 #else
1555 # define YYLEX rw_yylex ()
1556 #endif
1557 
1558 /* Enable debugging if requested.  */
1559 #if YYDEBUG
1560 
1561 # ifndef YYFPRINTF
1562 #  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
1563 #  define YYFPRINTF fprintf
1564 # endif
1565 
1566 # define YYDPRINTF(Args)			\
1567 do {						\
1568   if (rw_yydebug)					\
1569     YYFPRINTF Args;				\
1570 } while (YYID (0))
1571 
1572 # define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
1573 do {									  \
1574   if (rw_yydebug)								  \
1575     {									  \
1576       YYFPRINTF (stderr, "%s ", Title);					  \
1577       rw_yy_symbol_print (stderr,						  \
1578 		  Type, Value); \
1579       YYFPRINTF (stderr, "\n");						  \
1580     }									  \
1581 } while (YYID (0))
1582 
1583 
1584 /*--------------------------------.
1585 | Print this symbol on YYOUTPUT.  |
1586 `--------------------------------*/
1587 
1588 /*ARGSUSED*/
1589 #if (defined __STDC__ || defined __C99__FUNC__ \
1590      || defined __cplusplus || defined _MSC_VER)
1591 static void
rw_yy_symbol_value_print(FILE * rw_yyoutput,int rw_yytype,YYSTYPE const * const rw_yyvaluep)1592 rw_yy_symbol_value_print (FILE *rw_yyoutput, int rw_yytype, YYSTYPE const * const rw_yyvaluep)
1593 #else
1594 static void
1595 rw_yy_symbol_value_print (rw_yyoutput, rw_yytype, rw_yyvaluep)
1596     FILE *rw_yyoutput;
1597     int rw_yytype;
1598     YYSTYPE const * const rw_yyvaluep;
1599 #endif
1600 {
1601   if (!rw_yyvaluep)
1602     return;
1603 # ifdef YYPRINT
1604   if (rw_yytype < YYNTOKENS)
1605     YYPRINT (rw_yyoutput, rw_yytoknum[rw_yytype], *rw_yyvaluep);
1606 # else
1607   YYUSE (rw_yyoutput);
1608 # endif
1609   switch (rw_yytype)
1610     {
1611       default:
1612 	break;
1613     }
1614 }
1615 
1616 
1617 /*--------------------------------.
1618 | Print this symbol on YYOUTPUT.  |
1619 `--------------------------------*/
1620 
1621 #if (defined __STDC__ || defined __C99__FUNC__ \
1622      || defined __cplusplus || defined _MSC_VER)
1623 static void
rw_yy_symbol_print(FILE * rw_yyoutput,int rw_yytype,YYSTYPE const * const rw_yyvaluep)1624 rw_yy_symbol_print (FILE *rw_yyoutput, int rw_yytype, YYSTYPE const * const rw_yyvaluep)
1625 #else
1626 static void
1627 rw_yy_symbol_print (rw_yyoutput, rw_yytype, rw_yyvaluep)
1628     FILE *rw_yyoutput;
1629     int rw_yytype;
1630     YYSTYPE const * const rw_yyvaluep;
1631 #endif
1632 {
1633   if (rw_yytype < YYNTOKENS)
1634     YYFPRINTF (rw_yyoutput, "token %s (", rw_yytname[rw_yytype]);
1635   else
1636     YYFPRINTF (rw_yyoutput, "nterm %s (", rw_yytname[rw_yytype]);
1637 
1638   rw_yy_symbol_value_print (rw_yyoutput, rw_yytype, rw_yyvaluep);
1639   YYFPRINTF (rw_yyoutput, ")");
1640 }
1641 
1642 /*------------------------------------------------------------------.
1643 | rw_yy_stack_print -- Print the state stack from its BOTTOM up to its |
1644 | TOP (included).                                                   |
1645 `------------------------------------------------------------------*/
1646 
1647 #if (defined __STDC__ || defined __C99__FUNC__ \
1648      || defined __cplusplus || defined _MSC_VER)
1649 static void
rw_yy_stack_print(rw_yytype_int16 * bottom,rw_yytype_int16 * top)1650 rw_yy_stack_print (rw_yytype_int16 *bottom, rw_yytype_int16 *top)
1651 #else
1652 static void
1653 rw_yy_stack_print (bottom, top)
1654     rw_yytype_int16 *bottom;
1655     rw_yytype_int16 *top;
1656 #endif
1657 {
1658   YYFPRINTF (stderr, "Stack now");
1659   for (; bottom <= top; ++bottom)
1660     YYFPRINTF (stderr, " %d", *bottom);
1661   YYFPRINTF (stderr, "\n");
1662 }
1663 
1664 # define YY_STACK_PRINT(Bottom, Top)				\
1665 do {								\
1666   if (rw_yydebug)							\
1667     rw_yy_stack_print ((Bottom), (Top));				\
1668 } while (YYID (0))
1669 
1670 
1671 /*------------------------------------------------.
1672 | Report that the YYRULE is going to be reduced.  |
1673 `------------------------------------------------*/
1674 
1675 #if (defined __STDC__ || defined __C99__FUNC__ \
1676      || defined __cplusplus || defined _MSC_VER)
1677 static void
rw_yy_reduce_print(YYSTYPE * rw_yyvsp,int rw_yyrule)1678 rw_yy_reduce_print (YYSTYPE *rw_yyvsp, int rw_yyrule)
1679 #else
1680 static void
1681 rw_yy_reduce_print (rw_yyvsp, rw_yyrule)
1682     YYSTYPE *rw_yyvsp;
1683     int rw_yyrule;
1684 #endif
1685 {
1686   int rw_yynrhs = rw_yyr2[rw_yyrule];
1687   int rw_yyi;
1688   unsigned long int rw_yylno = rw_yyrline[rw_yyrule];
1689   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
1690 	     rw_yyrule - 1, rw_yylno);
1691   /* The symbols being reduced.  */
1692   for (rw_yyi = 0; rw_yyi < rw_yynrhs; rw_yyi++)
1693     {
1694       fprintf (stderr, "   $%d = ", rw_yyi + 1);
1695       rw_yy_symbol_print (stderr, rw_yyrhs[rw_yyprhs[rw_yyrule] + rw_yyi],
1696 		       &(rw_yyvsp[(rw_yyi + 1) - (rw_yynrhs)])
1697 		       		       );
1698       fprintf (stderr, "\n");
1699     }
1700 }
1701 
1702 # define YY_REDUCE_PRINT(Rule)		\
1703 do {					\
1704   if (rw_yydebug)				\
1705     rw_yy_reduce_print (rw_yyvsp, Rule); \
1706 } while (YYID (0))
1707 
1708 /* Nonzero means print parse trace.  It is left uninitialized so that
1709    multiple parsers can coexist.  */
1710 int rw_yydebug;
1711 #else /* !YYDEBUG */
1712 # define YYDPRINTF(Args)
1713 # define YY_SYMBOL_PRINT(Title, Type, Value, Location)
1714 # define YY_STACK_PRINT(Bottom, Top)
1715 # define YY_REDUCE_PRINT(Rule)
1716 #endif /* !YYDEBUG */
1717 
1718 
1719 /* YYINITDEPTH -- initial size of the parser's stacks.  */
1720 #ifndef	YYINITDEPTH
1721 # define YYINITDEPTH 200
1722 #endif
1723 
1724 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
1725    if the built-in stack extension method is used).
1726 
1727    Do not make this value too large; the results are undefined if
1728    YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
1729    evaluated with infinite-precision integer arithmetic.  */
1730 
1731 #ifndef YYMAXDEPTH
1732 # define YYMAXDEPTH 10000
1733 #endif
1734 
1735 
1736 
1737 #if YYERROR_VERBOSE
1738 
1739 # ifndef rw_yystrlen
1740 #  if defined __GLIBC__ && defined _STRING_H
1741 #   define rw_yystrlen strlen
1742 #  else
1743 /* Return the length of YYSTR.  */
1744 #if (defined __STDC__ || defined __C99__FUNC__ \
1745      || defined __cplusplus || defined _MSC_VER)
1746 static YYSIZE_T
rw_yystrlen(const char * rw_yystr)1747 rw_yystrlen (const char *rw_yystr)
1748 #else
1749 static YYSIZE_T
1750 rw_yystrlen (rw_yystr)
1751     const char *rw_yystr;
1752 #endif
1753 {
1754   YYSIZE_T rw_yylen;
1755   for (rw_yylen = 0; rw_yystr[rw_yylen]; rw_yylen++)
1756     continue;
1757   return rw_yylen;
1758 }
1759 #  endif
1760 # endif
1761 
1762 # ifndef rw_yystpcpy
1763 #  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
1764 #   define rw_yystpcpy stpcpy
1765 #  else
1766 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
1767    YYDEST.  */
1768 #if (defined __STDC__ || defined __C99__FUNC__ \
1769      || defined __cplusplus || defined _MSC_VER)
1770 static char *
rw_yystpcpy(char * rw_yydest,const char * rw_yysrc)1771 rw_yystpcpy (char *rw_yydest, const char *rw_yysrc)
1772 #else
1773 static char *
1774 rw_yystpcpy (rw_yydest, rw_yysrc)
1775     char *rw_yydest;
1776     const char *rw_yysrc;
1777 #endif
1778 {
1779   char *rw_yyd = rw_yydest;
1780   const char *rw_yys = rw_yysrc;
1781 
1782   while ((*rw_yyd++ = *rw_yys++) != '\0')
1783     continue;
1784 
1785   return rw_yyd - 1;
1786 }
1787 #  endif
1788 # endif
1789 
1790 # ifndef rw_yytnamerr
1791 /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
1792    quotes and backslashes, so that it's suitable for rw_yyerror.  The
1793    heuristic is that double-quoting is unnecessary unless the string
1794    contains an apostrophe, a comma, or backslash (other than
1795    backslash-backslash).  YYSTR is taken from rw_yytname.  If YYRES is
1796    null, do not copy; instead, return the length of what the result
1797    would have been.  */
1798 static YYSIZE_T
rw_yytnamerr(char * rw_yyres,const char * rw_yystr)1799 rw_yytnamerr (char *rw_yyres, const char *rw_yystr)
1800 {
1801   if (*rw_yystr == '"')
1802     {
1803       YYSIZE_T rw_yyn = 0;
1804       char const *rw_yyp = rw_yystr;
1805 
1806       for (;;)
1807 	switch (*++rw_yyp)
1808 	  {
1809 	  case '\'':
1810 	  case ',':
1811 	    goto do_not_strip_quotes;
1812 
1813 	  case '\\':
1814 	    if (*++rw_yyp != '\\')
1815 	      goto do_not_strip_quotes;
1816 	    /* Fall through.  */
1817 	  default:
1818 	    if (rw_yyres)
1819 	      rw_yyres[rw_yyn] = *rw_yyp;
1820 	    rw_yyn++;
1821 	    break;
1822 
1823 	  case '"':
1824 	    if (rw_yyres)
1825 	      rw_yyres[rw_yyn] = '\0';
1826 	    return rw_yyn;
1827 	  }
1828     do_not_strip_quotes: ;
1829     }
1830 
1831   if (! rw_yyres)
1832     return rw_yystrlen (rw_yystr);
1833 
1834   return rw_yystpcpy (rw_yyres, rw_yystr) - rw_yyres;
1835 }
1836 # endif
1837 
1838 /* Copy into YYRESULT an error message about the unexpected token
1839    YYCHAR while in state YYSTATE.  Return the number of bytes copied,
1840    including the terminating null byte.  If YYRESULT is null, do not
1841    copy anything; just return the number of bytes that would be
1842    copied.  As a special case, return 0 if an ordinary "syntax error"
1843    message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
1844    size calculation.  */
1845 static YYSIZE_T
rw_yysyntax_error(char * rw_yyresult,int rw_yystate,int rw_yychar)1846 rw_yysyntax_error (char *rw_yyresult, int rw_yystate, int rw_yychar)
1847 {
1848   int rw_yyn = rw_yypact[rw_yystate];
1849 
1850   if (! (YYPACT_NINF < rw_yyn && rw_yyn <= YYLAST))
1851     return 0;
1852   else
1853     {
1854       int rw_yytype = YYTRANSLATE (rw_yychar);
1855       YYSIZE_T rw_yysize0 = rw_yytnamerr (0, rw_yytname[rw_yytype]);
1856       YYSIZE_T rw_yysize = rw_yysize0;
1857       YYSIZE_T rw_yysize1;
1858       int rw_yysize_overflow = 0;
1859       enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
1860       char const *rw_yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
1861       int rw_yyx;
1862 
1863 # if 0
1864       /* This is so xgettext sees the translatable formats that are
1865 	 constructed on the fly.  */
1866       YY_("syntax error, unexpected %s");
1867       YY_("syntax error, unexpected %s, expecting %s");
1868       YY_("syntax error, unexpected %s, expecting %s or %s");
1869       YY_("syntax error, unexpected %s, expecting %s or %s or %s");
1870       YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
1871 # endif
1872       char *rw_yyfmt;
1873       char const *rw_yyf;
1874       static char const rw_yyunexpected[] = "syntax error, unexpected %s";
1875       static char const rw_yyexpecting[] = ", expecting %s";
1876       static char const rw_yyor[] = " or %s";
1877       char rw_yyformat[sizeof rw_yyunexpected
1878 		    + sizeof rw_yyexpecting - 1
1879 		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
1880 		       * (sizeof rw_yyor - 1))];
1881       char const *rw_yyprefix = rw_yyexpecting;
1882 
1883       /* Start YYX at -YYN if negative to avoid negative indexes in
1884 	 YYCHECK.  */
1885       int rw_yyxbegin = rw_yyn < 0 ? -rw_yyn : 0;
1886 
1887       /* Stay within bounds of both rw_yycheck and rw_yytname.  */
1888       int rw_yychecklim = YYLAST - rw_yyn + 1;
1889       int rw_yyxend = rw_yychecklim < YYNTOKENS ? rw_yychecklim : YYNTOKENS;
1890       int rw_yycount = 1;
1891 
1892       rw_yyarg[0] = rw_yytname[rw_yytype];
1893       rw_yyfmt = rw_yystpcpy (rw_yyformat, rw_yyunexpected);
1894 
1895       for (rw_yyx = rw_yyxbegin; rw_yyx < rw_yyxend; ++rw_yyx)
1896 	if (rw_yycheck[rw_yyx + rw_yyn] == rw_yyx && rw_yyx != YYTERROR)
1897 	  {
1898 	    if (rw_yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
1899 	      {
1900 		rw_yycount = 1;
1901 		rw_yysize = rw_yysize0;
1902 		rw_yyformat[sizeof rw_yyunexpected - 1] = '\0';
1903 		break;
1904 	      }
1905 	    rw_yyarg[rw_yycount++] = rw_yytname[rw_yyx];
1906 	    rw_yysize1 = rw_yysize + rw_yytnamerr (0, rw_yytname[rw_yyx]);
1907 	    rw_yysize_overflow |= (rw_yysize1 < rw_yysize);
1908 	    rw_yysize = rw_yysize1;
1909 	    rw_yyfmt = rw_yystpcpy (rw_yyfmt, rw_yyprefix);
1910 	    rw_yyprefix = rw_yyor;
1911 	  }
1912 
1913       rw_yyf = YY_(rw_yyformat);
1914       rw_yysize1 = rw_yysize + rw_yystrlen (rw_yyf);
1915       rw_yysize_overflow |= (rw_yysize1 < rw_yysize);
1916       rw_yysize = rw_yysize1;
1917 
1918       if (rw_yysize_overflow)
1919 	return YYSIZE_MAXIMUM;
1920 
1921       if (rw_yyresult)
1922 	{
1923 	  /* Avoid sprintf, as that infringes on the user's name space.
1924 	     Don't have undefined behavior even if the translation
1925 	     produced a string with the wrong number of "%s"s.  */
1926 	  char *rw_yyp = rw_yyresult;
1927 	  int rw_yyi = 0;
1928 	  while ((*rw_yyp = *rw_yyf) != '\0')
1929 	    {
1930 	      if (*rw_yyp == '%' && rw_yyf[1] == 's' && rw_yyi < rw_yycount)
1931 		{
1932 		  rw_yyp += rw_yytnamerr (rw_yyp, rw_yyarg[rw_yyi++]);
1933 		  rw_yyf += 2;
1934 		}
1935 	      else
1936 		{
1937 		  rw_yyp++;
1938 		  rw_yyf++;
1939 		}
1940 	    }
1941 	}
1942       return rw_yysize;
1943     }
1944 }
1945 #endif /* YYERROR_VERBOSE */
1946 
1947 
1948 /*-----------------------------------------------.
1949 | Release the memory associated to this symbol.  |
1950 `-----------------------------------------------*/
1951 
1952 /*ARGSUSED*/
1953 #if (defined __STDC__ || defined __C99__FUNC__ \
1954      || defined __cplusplus || defined _MSC_VER)
1955 static void
rw_yydestruct(const char * rw_yymsg,int rw_yytype,YYSTYPE * rw_yyvaluep)1956 rw_yydestruct (const char *rw_yymsg, int rw_yytype, YYSTYPE *rw_yyvaluep)
1957 #else
1958 static void
1959 rw_yydestruct (rw_yymsg, rw_yytype, rw_yyvaluep)
1960     const char *rw_yymsg;
1961     int rw_yytype;
1962     YYSTYPE *rw_yyvaluep;
1963 #endif
1964 {
1965   YYUSE (rw_yyvaluep);
1966 
1967   if (!rw_yymsg)
1968     rw_yymsg = "Deleting";
1969   YY_SYMBOL_PRINT (rw_yymsg, rw_yytype, rw_yyvaluep, rw_yylocationp);
1970 
1971   switch (rw_yytype)
1972     {
1973 
1974       default:
1975 	break;
1976     }
1977 }
1978 
1979 
1980 /* Prevent warnings from -Wmissing-prototypes.  */
1981 
1982 #ifdef YYPARSE_PARAM
1983 #if defined __STDC__ || defined __cplusplus
1984 int rw_yyparse (void *YYPARSE_PARAM);
1985 #else
1986 int rw_yyparse ();
1987 #endif
1988 #else /* ! YYPARSE_PARAM */
1989 #if defined __STDC__ || defined __cplusplus
1990 int rw_yyparse (void);
1991 #else
1992 int rw_yyparse ();
1993 #endif
1994 #endif /* ! YYPARSE_PARAM */
1995 
1996 
1997 
1998 /* The look-ahead symbol.  */
1999 int rw_yychar;
2000 
2001 /* The semantic value of the look-ahead symbol.  */
2002 YYSTYPE rw_yylval;
2003 
2004 /* Number of syntax errors so far.  */
2005 int rw_yynerrs;
2006 
2007 
2008 
2009 /*----------.
2010 | rw_yyparse.  |
2011 `----------*/
2012 
2013 #ifdef YYPARSE_PARAM
2014 #if (defined __STDC__ || defined __C99__FUNC__ \
2015      || defined __cplusplus || defined _MSC_VER)
2016 int
rw_yyparse(void * YYPARSE_PARAM)2017 rw_yyparse (void *YYPARSE_PARAM)
2018 #else
2019 int
2020 rw_yyparse (YYPARSE_PARAM)
2021     void *YYPARSE_PARAM;
2022 #endif
2023 #else /* ! YYPARSE_PARAM */
2024 #if (defined __STDC__ || defined __C99__FUNC__ \
2025      || defined __cplusplus || defined _MSC_VER)
2026 int
2027 rw_yyparse (void)
2028 #else
2029 int
2030 rw_yyparse ()
2031 
2032 #endif
2033 #endif
2034 {
2035 
2036   int rw_yystate;
2037   int rw_yyn;
2038   int rw_yyresult;
2039   /* Number of tokens to shift before error messages enabled.  */
2040   int rw_yyerrstatus;
2041   /* Look-ahead token as an internal (translated) token number.  */
2042   int rw_yytoken = 0;
2043 #if YYERROR_VERBOSE
2044   /* Buffer for error messages, and its allocated size.  */
2045   char rw_yymsgbuf[128];
2046   char *rw_yymsg = rw_yymsgbuf;
2047   YYSIZE_T rw_yymsg_alloc = sizeof rw_yymsgbuf;
2048 #endif
2049 
2050   /* Three stacks and their tools:
2051      `rw_yyss': related to states,
2052      `rw_yyvs': related to semantic values,
2053      `rw_yyls': related to locations.
2054 
2055      Refer to the stacks thru separate pointers, to allow rw_yyoverflow
2056      to reallocate them elsewhere.  */
2057 
2058   /* The state stack.  */
2059   rw_yytype_int16 rw_yyssa[YYINITDEPTH];
2060   rw_yytype_int16 *rw_yyss = rw_yyssa;
2061   rw_yytype_int16 *rw_yyssp;
2062 
2063   /* The semantic value stack.  */
2064   YYSTYPE rw_yyvsa[YYINITDEPTH];
2065   YYSTYPE *rw_yyvs = rw_yyvsa;
2066   YYSTYPE *rw_yyvsp;
2067 
2068 
2069 
2070 #define YYPOPSTACK(N)   (rw_yyvsp -= (N), rw_yyssp -= (N))
2071 
2072   YYSIZE_T rw_yystacksize = YYINITDEPTH;
2073 
2074   /* The variables used to return semantic value and location from the
2075      action routines.  */
2076   YYSTYPE rw_yyval;
2077 
2078 
2079   /* The number of symbols on the RHS of the reduced rule.
2080      Keep to zero when no symbol should be popped.  */
2081   int rw_yylen = 0;
2082 
2083   YYDPRINTF ((stderr, "Starting parse\n"));
2084 
2085   rw_yystate = 0;
2086   rw_yyerrstatus = 0;
2087   rw_yynerrs = 0;
2088   rw_yychar = YYEMPTY;		/* Cause a token to be read.  */
2089 
2090   /* Initialize stack pointers.
2091      Waste one element of value and location stack
2092      so that they stay on the same level as the state stack.
2093      The wasted elements are never initialized.  */
2094 
2095   rw_yyssp = rw_yyss;
2096   rw_yyvsp = rw_yyvs;
2097 
2098   goto rw_yysetstate;
2099 
2100 /*------------------------------------------------------------.
2101 | rw_yynewstate -- Push a new state, which is found in rw_yystate.  |
2102 `------------------------------------------------------------*/
2103  rw_yynewstate:
2104   /* In all cases, when you get here, the value and location stacks
2105      have just been pushed.  So pushing a state here evens the stacks.  */
2106   rw_yyssp++;
2107 
2108  rw_yysetstate:
2109   *rw_yyssp = rw_yystate;
2110 
2111   if (rw_yyss + rw_yystacksize - 1 <= rw_yyssp)
2112     {
2113       /* Get the current used size of the three stacks, in elements.  */
2114       YYSIZE_T rw_yysize = rw_yyssp - rw_yyss + 1;
2115 
2116 #ifdef rw_yyoverflow
2117       {
2118 	/* Give user a chance to reallocate the stack.  Use copies of
2119 	   these so that the &'s don't force the real ones into
2120 	   memory.  */
2121 	YYSTYPE *rw_yyvs1 = rw_yyvs;
2122 	rw_yytype_int16 *rw_yyss1 = rw_yyss;
2123 
2124 
2125 	/* Each stack pointer address is followed by the size of the
2126 	   data in use in that stack, in bytes.  This used to be a
2127 	   conditional around just the two extra args, but that might
2128 	   be undefined if rw_yyoverflow is a macro.  */
2129 	rw_yyoverflow (YY_("memory exhausted"),
2130 		    &rw_yyss1, rw_yysize * sizeof (*rw_yyssp),
2131 		    &rw_yyvs1, rw_yysize * sizeof (*rw_yyvsp),
2132 
2133 		    &rw_yystacksize);
2134 
2135 	rw_yyss = rw_yyss1;
2136 	rw_yyvs = rw_yyvs1;
2137       }
2138 #else /* no rw_yyoverflow */
2139 # ifndef YYSTACK_RELOCATE
2140       goto rw_yyexhaustedlab;
2141 # else
2142       /* Extend the stack our own way.  */
2143       if (YYMAXDEPTH <= rw_yystacksize)
2144 	goto rw_yyexhaustedlab;
2145       rw_yystacksize *= 2;
2146       if (YYMAXDEPTH < rw_yystacksize)
2147 	rw_yystacksize = YYMAXDEPTH;
2148 
2149       {
2150 	rw_yytype_int16 *rw_yyss1 = rw_yyss;
2151 	union rw_yyalloc *rw_yyptr =
2152 	  (union rw_yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (rw_yystacksize));
2153 	if (! rw_yyptr)
2154 	  goto rw_yyexhaustedlab;
2155 	YYSTACK_RELOCATE (rw_yyss);
2156 	YYSTACK_RELOCATE (rw_yyvs);
2157 
2158 #  undef YYSTACK_RELOCATE
2159 	if (rw_yyss1 != rw_yyssa)
2160 	  YYSTACK_FREE (rw_yyss1);
2161       }
2162 # endif
2163 #endif /* no rw_yyoverflow */
2164 
2165       rw_yyssp = rw_yyss + rw_yysize - 1;
2166       rw_yyvsp = rw_yyvs + rw_yysize - 1;
2167 
2168 
2169       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
2170 		  (unsigned long int) rw_yystacksize));
2171 
2172       if (rw_yyss + rw_yystacksize - 1 <= rw_yyssp)
2173 	YYABORT;
2174     }
2175 
2176   YYDPRINTF ((stderr, "Entering state %d\n", rw_yystate));
2177 
2178   goto rw_yybackup;
2179 
2180 /*-----------.
2181 | rw_yybackup.  |
2182 `-----------*/
2183 rw_yybackup:
2184 
2185   /* Do appropriate processing given the current state.  Read a
2186      look-ahead token if we need one and don't already have one.  */
2187 
2188   /* First try to decide what to do without reference to look-ahead token.  */
2189   rw_yyn = rw_yypact[rw_yystate];
2190   if (rw_yyn == YYPACT_NINF)
2191     goto rw_yydefault;
2192 
2193   /* Not known => get a look-ahead token if don't already have one.  */
2194 
2195   /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
2196   if (rw_yychar == YYEMPTY)
2197     {
2198       YYDPRINTF ((stderr, "Reading a token: "));
2199       rw_yychar = YYLEX;
2200     }
2201 
2202   if (rw_yychar <= YYEOF)
2203     {
2204       rw_yychar = rw_yytoken = YYEOF;
2205       YYDPRINTF ((stderr, "Now at end of input.\n"));
2206     }
2207   else
2208     {
2209       rw_yytoken = YYTRANSLATE (rw_yychar);
2210       YY_SYMBOL_PRINT ("Next token is", rw_yytoken, &rw_yylval, &rw_yylloc);
2211     }
2212 
2213   /* If the proper action on seeing token YYTOKEN is to reduce or to
2214      detect an error, take that action.  */
2215   rw_yyn += rw_yytoken;
2216   if (rw_yyn < 0 || YYLAST < rw_yyn || rw_yycheck[rw_yyn] != rw_yytoken)
2217     goto rw_yydefault;
2218   rw_yyn = rw_yytable[rw_yyn];
2219   if (rw_yyn <= 0)
2220     {
2221       if (rw_yyn == 0 || rw_yyn == YYTABLE_NINF)
2222 	goto rw_yyerrlab;
2223       rw_yyn = -rw_yyn;
2224       goto rw_yyreduce;
2225     }
2226 
2227   if (rw_yyn == YYFINAL)
2228     YYACCEPT;
2229 
2230   /* Count tokens shifted since error; after three, turn off error
2231      status.  */
2232   if (rw_yyerrstatus)
2233     rw_yyerrstatus--;
2234 
2235   /* Shift the look-ahead token.  */
2236   YY_SYMBOL_PRINT ("Shifting", rw_yytoken, &rw_yylval, &rw_yylloc);
2237 
2238   /* Discard the shifted token unless it is eof.  */
2239   if (rw_yychar != YYEOF)
2240     rw_yychar = YYEMPTY;
2241 
2242   rw_yystate = rw_yyn;
2243   *++rw_yyvsp = rw_yylval;
2244 
2245   goto rw_yynewstate;
2246 
2247 
2248 /*-----------------------------------------------------------.
2249 | rw_yydefault -- do the default action for the current state.  |
2250 `-----------------------------------------------------------*/
2251 rw_yydefault:
2252   rw_yyn = rw_yydefact[rw_yystate];
2253   if (rw_yyn == 0)
2254     goto rw_yyerrlab;
2255   goto rw_yyreduce;
2256 
2257 
2258 /*-----------------------------.
2259 | rw_yyreduce -- Do a reduction.  |
2260 `-----------------------------*/
2261 rw_yyreduce:
2262   /* rw_yyn is the number of a rule to reduce with.  */
2263   rw_yylen = rw_yyr2[rw_yyn];
2264 
2265   /* If YYLEN is nonzero, implement the default value of the action:
2266      `$$ = $1'.
2267 
2268      Otherwise, the following line sets YYVAL to garbage.
2269      This behavior is undocumented and Bison
2270      users should not rely upon it.  Assigning to YYVAL
2271      unconditionally makes the parser a bit smaller, and it avoids a
2272      GCC warning that YYVAL may be used uninitialized.  */
2273   rw_yyval = rw_yyvsp[1-rw_yylen];
2274 
2275 
2276   YY_REDUCE_PRINT (rw_yyn);
2277   switch (rw_yyn)
2278     {
2279         case 2:
2280 #line 720 "rewrite.y"
2281     {
2282                   var_free_all();
2283                   loop_free_all();
2284                   frame_free_all();
2285                   mtx_free_all();
2286           }
2287     break;
2288 
2289   case 3:
2290 #line 729 "rewrite.y"
2291     {
2292 		  return_type = Undefined;
2293 	  }
2294     break;
2295 
2296   case 4:
2297 #line 733 "rewrite.y"
2298     {
2299                   if (errcnt) {
2300                           YYERROR;
2301                   }
2302 
2303 		  mtx_return((rw_yyvsp[(1) - (1)].mtx));
2304 
2305 		  memset(&fmain, 0, sizeof(fmain));
2306 		  fmain.name = "main";
2307 		  fmain.rettype = return_type = (rw_yyvsp[(1) - (1)].mtx)->gen.datatype;
2308 		  function = &fmain;
2309 
2310                   if (optimize() == 0) {
2311                           codegen();
2312                           if (errcnt) {
2313                                   YYERROR;
2314                           }
2315                   }
2316           }
2317     break;
2318 
2319   case 7:
2320 #line 757 "rewrite.y"
2321     {
2322                   /* Roll back all changes done so far */
2323                   var_unwind_all();
2324                   loop_unwind_all();
2325                   frame_unwind_all();
2326                   mtx_unwind_all();
2327                   function_delete();
2328                   /* Synchronize input after error */
2329                   rw_yysync();
2330                   /* Clear input and error condition */
2331                   rw_yyclearin;
2332                   rw_yyerrok;
2333                   errcnt = 0;
2334           }
2335     break;
2336 
2337   case 8:
2338 #line 774 "rewrite.y"
2339     {
2340                   if (errcnt) {
2341                           function_delete();
2342                           YYERROR;
2343                   }
2344 
2345                   if (optimize() == 0) {
2346                           codegen();
2347                           if (errcnt) {
2348                                   function_delete();
2349                                   YYERROR;
2350                           }
2351                   } else {
2352                           function_delete();
2353                   }
2354 
2355                   /* clean up things */
2356                   var_unwind_all();
2357                   loop_unwind_all();
2358                   frame_unwind_all();
2359                   mtx_unwind_all();
2360                   function_cleanup();
2361           }
2362     break;
2363 
2364   case 9:
2365 #line 800 "rewrite.y"
2366     {
2367                   VAR *var;
2368                   PARAMETER *last, *parm;
2369                   FUNCTION f;
2370 
2371                   if (errcnt)
2372                           YYERROR;
2373 
2374                   memset(&f, 0, sizeof(f));
2375                   f.name    = (rw_yyvsp[(2) - (3)].string);
2376                   f.rettype = (rw_yyvsp[(1) - (3)].type);
2377                   f.entry   = 0;
2378                   f.loc     = locus;
2379 
2380                   f.nparm   = 0;
2381                   f.parm    = NULL;
2382 
2383                   /* Count number of parameters */
2384                   for (var = (rw_yyvsp[(3) - (3)].var); var; var = var->next)
2385                           f.nparm++;
2386 
2387                   f.parm = last = NULL;
2388                   for (var = (rw_yyvsp[(3) - (3)].var); var; var = var->next) {
2389                           parm = grad_emalloc(sizeof(*parm));
2390                           parm->datatype = var->datatype;
2391                           var->offset = -(STACK_BASE+
2392                                           f.nparm - var->offset);
2393                           parm->offset   = var->offset;
2394                           parm->prev     = last;
2395                           parm->next     = NULL;
2396                           if (f.parm == NULL)
2397                                   f.parm = parm;
2398                           else
2399                                   last->next = parm;
2400                           last = parm;
2401                   }
2402                   function = function_install(&f);
2403           }
2404     break;
2405 
2406   case 10:
2407 #line 839 "rewrite.y"
2408     {
2409 		  grad_log_loc(GRAD_LOG_ERR, &locus,
2410 			       _("redefinition of function `%s'"), (rw_yyvsp[(2) - (3)].fun)->name);
2411 		  grad_log_loc(GRAD_LOG_ERR, &(rw_yyvsp[(2) - (3)].fun)->loc,
2412 			       _("previously defined here"));
2413 		  errcnt++;
2414 		  YYERROR;
2415           }
2416     break;
2417 
2418   case 14:
2419 #line 857 "rewrite.y"
2420     {
2421                   frame_push();
2422           }
2423     break;
2424 
2425   case 15:
2426 #line 863 "rewrite.y"
2427     {
2428                   var_unwind_level();
2429                   frame_pop();
2430           }
2431     break;
2432 
2433   case 18:
2434 #line 878 "rewrite.y"
2435     {
2436                   var_type((rw_yyvsp[(1) - (3)].type), (rw_yyvsp[(2) - (3)].var));
2437           }
2438     break;
2439 
2440   case 19:
2441 #line 884 "rewrite.y"
2442     {
2443                   (rw_yyval.var) = var_alloc(Undefined, (rw_yyvsp[(1) - (1)].string), +1);
2444                   (rw_yyval.var)->dcllink = NULL;
2445           }
2446     break;
2447 
2448   case 20:
2449 #line 889 "rewrite.y"
2450     {
2451                   VAR *var = var_alloc(Undefined, (rw_yyvsp[(3) - (3)].string), +1);
2452                   var->dcllink = (rw_yyvsp[(1) - (3)].var);
2453                   (rw_yyval.var) = var;
2454           }
2455     break;
2456 
2457   case 21:
2458 #line 900 "rewrite.y"
2459     {
2460                   (rw_yyval.var) = NULL;
2461           }
2462     break;
2463 
2464   case 22:
2465 #line 904 "rewrite.y"
2466     {
2467                   (rw_yyval.var) = (rw_yyvsp[(2) - (3)].var);
2468           }
2469     break;
2470 
2471   case 23:
2472 #line 910 "rewrite.y"
2473     {
2474                   /*FIXME*/
2475                   /*$$->dcllink = NULL;*/
2476           }
2477     break;
2478 
2479   case 24:
2480 #line 915 "rewrite.y"
2481     {
2482                   /*$1->dcllink = $3;*/
2483                   (rw_yyval.var) = (rw_yyvsp[(1) - (3)].var);
2484           }
2485     break;
2486 
2487   case 25:
2488 #line 922 "rewrite.y"
2489     {
2490                   (rw_yyval.var) = var_alloc((rw_yyvsp[(1) - (2)].type), (rw_yyvsp[(2) - (2)].string), +1);
2491           }
2492     break;
2493 
2494   case 26:
2495 #line 931 "rewrite.y"
2496     {
2497                   (rw_yyval.mtx) = NULL;
2498           }
2499     break;
2500 
2501   case 27:
2502 #line 935 "rewrite.y"
2503     {
2504                   (rw_yyval.mtx) = (rw_yyvsp[(1) - (1)].arg).arg_first;
2505           }
2506     break;
2507 
2508   case 28:
2509 #line 941 "rewrite.y"
2510     {
2511                   (rw_yyvsp[(1) - (1)].mtx)->gen.arglink = NULL;
2512                   (rw_yyval.arg).arg_first = (rw_yyval.arg).arg_last = (rw_yyvsp[(1) - (1)].mtx);
2513           }
2514     break;
2515 
2516   case 29:
2517 #line 946 "rewrite.y"
2518     {
2519                   (rw_yyvsp[(1) - (3)].arg).arg_last->gen.arglink = (rw_yyvsp[(3) - (3)].mtx);
2520                   (rw_yyvsp[(1) - (3)].arg).arg_last = (rw_yyvsp[(3) - (3)].mtx);
2521                   (rw_yyval.arg) = (rw_yyvsp[(1) - (3)].arg);
2522           }
2523     break;
2524 
2525   case 33:
2526 #line 964 "rewrite.y"
2527     {
2528                   (rw_yyval.mtx) = (rw_yyvsp[(2) - (3)].mtx);
2529           }
2530     break;
2531 
2532   case 34:
2533 #line 968 "rewrite.y"
2534     {
2535                   mtx_stop();
2536                   mtx_pop();
2537           }
2538     break;
2539 
2540   case 35:
2541 #line 973 "rewrite.y"
2542     {
2543                   (rw_yyvsp[(2) - (3)].mtx)->cond.if_false = mtx_nop();
2544                   (rw_yyval.mtx) = mtx_cur();
2545           }
2546     break;
2547 
2548   case 36:
2549 #line 978 "rewrite.y"
2550     {
2551                   mtx_stop();
2552                   (rw_yyvsp[(2) - (5)].mtx)->cond.if_false = (rw_yyvsp[(4) - (5)].mtx);
2553                   (rw_yyvsp[(4) - (5)].mtx)->nop.prev->jump.dest = mtx_nop();
2554                   (rw_yyval.mtx) = mtx_cur();
2555           }
2556     break;
2557 
2558   case 37:
2559 #line 985 "rewrite.y"
2560     {
2561                   /*mtx_stop();*/
2562                   (rw_yyval.mtx) = mtx_return((rw_yyvsp[(2) - (3)].mtx));
2563           }
2564     break;
2565 
2566   case 38:
2567 #line 990 "rewrite.y"
2568     {
2569                   MTX *mtx;
2570 
2571                   mtx_stop();
2572                   mtx = mtx_jump();
2573                   mtx->jump.dest = (rw_yyvsp[(1) - (3)].mtx);
2574                   (rw_yyvsp[(2) - (3)].mtx)->cond.if_false = mtx_nop();
2575                   (rw_yyval.mtx) = mtx_cur();
2576 
2577                   /* Fixup possible breaks */
2578                   loop_fixup(loop_last->lp_break, (rw_yyval.mtx));
2579                   /* Fixup possible continues */
2580                   loop_fixup(loop_last->lp_cont, (rw_yyvsp[(1) - (3)].mtx));
2581                   loop_pop();
2582           }
2583     break;
2584 
2585   case 39:
2586 #line 1005 "rewrite.y"
2587     { (rw_yyval.mtx) = mtx_nop(); }
2588     break;
2589 
2590   case 40:
2591 #line 1006 "rewrite.y"
2592     {
2593                   /* Default cond rule sets if_true to the next NOP matrix
2594                    * Invert this behaviour.
2595                    */
2596                   (rw_yyvsp[(5) - (6)].mtx)->cond.if_false = (rw_yyvsp[(5) - (6)].mtx)->cond.if_true;
2597                   (rw_yyvsp[(5) - (6)].mtx)->cond.if_true = (rw_yyvsp[(1) - (6)].mtx);
2598                   (rw_yyval.mtx) = mtx_cur();
2599 
2600                   /* Fixup possible breaks */
2601                   loop_fixup(loop_last->lp_break, (rw_yyval.mtx));
2602                   /* Fixup possible continues */
2603                   loop_fixup(loop_last->lp_cont, (rw_yyvsp[(3) - (6)].mtx));
2604                   loop_pop();
2605           }
2606     break;
2607 
2608   case 41:
2609 #line 1025 "rewrite.y"
2610     {
2611                   if (!loop_last) {
2612                           grad_log_loc(GRAD_LOG_ERR, &locus,
2613 				       "%s",
2614 				       _("nothing to break from"));
2615                           errcnt++;
2616                           YYERROR;
2617                   }
2618 
2619                   (rw_yyval.mtx) = mtx_jump();
2620                   (rw_yyval.mtx)->jump.link = (MTX*)loop_last->lp_break;
2621                   loop_last->lp_break = (JUMP_MTX*)(rw_yyval.mtx);
2622           }
2623     break;
2624 
2625   case 42:
2626 #line 1039 "rewrite.y"
2627     {
2628                   if (!loop_last) {
2629                           grad_log_loc(GRAD_LOG_ERR, &locus,
2630 				       "%s",
2631 				       _("nothing to continue"));
2632                           errcnt++;
2633                           YYERROR;
2634                   }
2635                   (rw_yyval.mtx) = mtx_jump();
2636                   (rw_yyval.mtx)->jump.link = (MTX*)loop_last->lp_cont;
2637                   loop_last->lp_cont = (JUMP_MTX*)(rw_yyval.mtx);
2638           }
2639     break;
2640 
2641   case 43:
2642 #line 1052 "rewrite.y"
2643     {
2644 		  (rw_yyval.mtx) = mtx_attr_delete((rw_yyvsp[(2) - (3)].attr), NULL);
2645 	  }
2646     break;
2647 
2648   case 44:
2649 #line 1056 "rewrite.y"
2650     {
2651 		  (rw_yyval.mtx) = mtx_attr_delete((rw_yyvsp[(2) - (6)].attr), (rw_yyvsp[(4) - (6)].mtx));
2652 	  }
2653     break;
2654 
2655   case 45:
2656 #line 1062 "rewrite.y"
2657     {
2658                   (rw_yyval.mtx) = mtx_nop();
2659                   loop_push((rw_yyval.mtx));
2660           }
2661     break;
2662 
2663   case 46:
2664 #line 1069 "rewrite.y"
2665     {
2666                   (rw_yyval.mtx) = mtx_nop();
2667                   loop_push((rw_yyval.mtx));
2668           }
2669     break;
2670 
2671   case 47:
2672 #line 1076 "rewrite.y"
2673     {
2674                   mtx_stop();
2675                   mtx_jump();
2676                   (rw_yyval.mtx) = mtx_nop();
2677           }
2678     break;
2679 
2680   case 48:
2681 #line 1084 "rewrite.y"
2682     {
2683                   mtx_stop();
2684                   (rw_yyval.mtx) = mtx_cond((rw_yyvsp[(2) - (3)].mtx), NULL, NULL);
2685                   (rw_yyval.mtx)->cond.if_true = mtx_nop();
2686           }
2687     break;
2688 
2689   case 49:
2690 #line 1095 "rewrite.y"
2691     {
2692 		  grad_value_t val;
2693 		  val.type = Integer;
2694 		  val.datum.ival = (rw_yyvsp[(1) - (1)].number);
2695                   (rw_yyval.mtx) = mtx_const(&val);
2696           }
2697     break;
2698 
2699   case 50:
2700 #line 1102 "rewrite.y"
2701     {
2702 		  grad_value_t val;
2703 		  val.type = String;
2704 		  val.datum.sval.size = strlen((rw_yyvsp[(1) - (1)].string));
2705 		  val.datum.sval.data = (rw_yyvsp[(1) - (1)].string);
2706                   (rw_yyval.mtx) = mtx_const(&val);
2707           }
2708     break;
2709 
2710   case 51:
2711 #line 1110 "rewrite.y"
2712     {
2713                   (rw_yyval.mtx) = mtx_ref((rw_yyvsp[(1) - (1)].number));
2714           }
2715     break;
2716 
2717   case 52:
2718 #line 1114 "rewrite.y"
2719     {
2720                   (rw_yyval.mtx) = mtx_var((rw_yyvsp[(1) - (1)].var));
2721           }
2722     break;
2723 
2724   case 53:
2725 #line 1118 "rewrite.y"
2726     {
2727                   grad_log_loc(GRAD_LOG_ERR, &locus, _("undefined variable: %s"), (rw_yyvsp[(1) - (1)].string));
2728                   errcnt++;
2729                   YYERROR;
2730           }
2731     break;
2732 
2733   case 54:
2734 #line 1124 "rewrite.y"
2735     {
2736                   (rw_yyval.mtx) = mtx_asgn((rw_yyvsp[(1) - (3)].var), (rw_yyvsp[(3) - (3)].mtx));
2737           }
2738     break;
2739 
2740   case 55:
2741 #line 1128 "rewrite.y"
2742     {
2743                   (rw_yyval.mtx) = mtx_attr((rw_yyvsp[(1) - (1)].attr), NULL);
2744           }
2745     break;
2746 
2747   case 56:
2748 #line 1132 "rewrite.y"
2749     {
2750                   (rw_yyval.mtx) = mtx_attr((rw_yyvsp[(1) - (4)].attr), (rw_yyvsp[(3) - (4)].mtx));
2751           }
2752     break;
2753 
2754   case 57:
2755 #line 1136 "rewrite.y"
2756     {
2757                   (rw_yyval.mtx) = mtx_attr_check((rw_yyvsp[(2) - (2)].attr), NULL);
2758           }
2759     break;
2760 
2761   case 58:
2762 #line 1140 "rewrite.y"
2763     {
2764 		  (rw_yyval.mtx) = mtx_attr_check((rw_yyvsp[(2) - (5)].attr), (rw_yyvsp[(4) - (5)].mtx));
2765 	  }
2766     break;
2767 
2768   case 59:
2769 #line 1144 "rewrite.y"
2770     {
2771                   (rw_yyval.mtx) = mtx_attr_asgn((rw_yyvsp[(1) - (3)].attr), NULL, (rw_yyvsp[(3) - (3)].mtx));
2772           }
2773     break;
2774 
2775   case 60:
2776 #line 1148 "rewrite.y"
2777     {
2778                   (rw_yyval.mtx) = mtx_attr_asgn((rw_yyvsp[(1) - (6)].attr), (rw_yyvsp[(3) - (6)].mtx), (rw_yyvsp[(6) - (6)].mtx));
2779           }
2780     break;
2781 
2782   case 61:
2783 #line 1152 "rewrite.y"
2784     {
2785                   (rw_yyval.mtx) = mtx_call((rw_yyvsp[(1) - (4)].fun), (rw_yyvsp[(3) - (4)].mtx));
2786           }
2787     break;
2788 
2789   case 62:
2790 #line 1156 "rewrite.y"
2791     {
2792                   (rw_yyval.mtx) = mtx_builtin((rw_yyvsp[(1) - (4)].btin), (rw_yyvsp[(3) - (4)].mtx));
2793           }
2794     break;
2795 
2796   case 63:
2797 #line 1160 "rewrite.y"
2798     {
2799                   (rw_yyval.mtx) = mtx_bin(Add, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2800           }
2801     break;
2802 
2803   case 64:
2804 #line 1164 "rewrite.y"
2805     {
2806                   (rw_yyval.mtx) = mtx_bin(Sub, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2807           }
2808     break;
2809 
2810   case 65:
2811 #line 1168 "rewrite.y"
2812     {
2813                   (rw_yyval.mtx) = mtx_bin(Mul, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2814           }
2815     break;
2816 
2817   case 66:
2818 #line 1172 "rewrite.y"
2819     {
2820                   (rw_yyval.mtx) = mtx_bin(Div, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2821           }
2822     break;
2823 
2824   case 67:
2825 #line 1176 "rewrite.y"
2826     {
2827                   (rw_yyval.mtx) = mtx_bin(Rem, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2828           }
2829     break;
2830 
2831   case 68:
2832 #line 1180 "rewrite.y"
2833     {
2834                   (rw_yyval.mtx) = mtx_bin(BOr, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2835           }
2836     break;
2837 
2838   case 69:
2839 #line 1184 "rewrite.y"
2840     {
2841                   (rw_yyval.mtx) = mtx_bin(BAnd, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2842           }
2843     break;
2844 
2845   case 70:
2846 #line 1188 "rewrite.y"
2847     {
2848                   (rw_yyval.mtx) = mtx_bin(BXor, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2849           }
2850     break;
2851 
2852   case 71:
2853 #line 1192 "rewrite.y"
2854     {
2855                   (rw_yyval.mtx) = mtx_bin(Shl, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2856           }
2857     break;
2858 
2859   case 72:
2860 #line 1196 "rewrite.y"
2861     {
2862                   (rw_yyval.mtx) = mtx_bin(Shr, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2863           }
2864     break;
2865 
2866   case 73:
2867 #line 1200 "rewrite.y"
2868     {
2869                   (rw_yyval.mtx) = mtx_bin(And, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2870           }
2871     break;
2872 
2873   case 74:
2874 #line 1204 "rewrite.y"
2875     {
2876                   (rw_yyval.mtx) = mtx_bin(Or, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2877           }
2878     break;
2879 
2880   case 75:
2881 #line 1208 "rewrite.y"
2882     {
2883                   (rw_yyval.mtx) = mtx_un(Neg, (rw_yyvsp[(2) - (2)].mtx));
2884           }
2885     break;
2886 
2887   case 76:
2888 #line 1212 "rewrite.y"
2889     {
2890                   (rw_yyval.mtx) = (rw_yyvsp[(2) - (2)].mtx);
2891           }
2892     break;
2893 
2894   case 77:
2895 #line 1216 "rewrite.y"
2896     {
2897                   (rw_yyval.mtx) = mtx_un(Not, (rw_yyvsp[(2) - (2)].mtx));
2898           }
2899     break;
2900 
2901   case 78:
2902 #line 1220 "rewrite.y"
2903     {
2904                   (rw_yyval.mtx) = (rw_yyvsp[(2) - (3)].mtx);
2905           }
2906     break;
2907 
2908   case 79:
2909 #line 1224 "rewrite.y"
2910     {
2911                   (rw_yyval.mtx) = mtx_coerce((rw_yyvsp[(2) - (4)].type), (rw_yyvsp[(4) - (4)].mtx));
2912           }
2913     break;
2914 
2915   case 80:
2916 #line 1228 "rewrite.y"
2917     {
2918                   (rw_yyval.mtx) = mtx_bin(Eq, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2919           }
2920     break;
2921 
2922   case 81:
2923 #line 1232 "rewrite.y"
2924     {
2925                   (rw_yyval.mtx) = mtx_bin(Ne, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2926           }
2927     break;
2928 
2929   case 82:
2930 #line 1236 "rewrite.y"
2931     {
2932                   (rw_yyval.mtx) = mtx_bin(Lt, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2933           }
2934     break;
2935 
2936   case 83:
2937 #line 1240 "rewrite.y"
2938     {
2939                   (rw_yyval.mtx) = mtx_bin(Le, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2940           }
2941     break;
2942 
2943   case 84:
2944 #line 1244 "rewrite.y"
2945     {
2946                   (rw_yyval.mtx) = mtx_bin(Gt, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2947           }
2948     break;
2949 
2950   case 85:
2951 #line 1248 "rewrite.y"
2952     {
2953                   (rw_yyval.mtx) = mtx_bin(Ge, (rw_yyvsp[(1) - (3)].mtx), (rw_yyvsp[(3) - (3)].mtx));
2954           }
2955     break;
2956 
2957   case 86:
2958 #line 1252 "rewrite.y"
2959     {
2960                   COMP_REGEX *rx;
2961                   if ((rx = compile_regexp((rw_yyvsp[(3) - (3)].string))) == NULL) {
2962                           errcnt++;
2963                           YYERROR;
2964                   }
2965                   (rw_yyval.mtx) = mtx_match(0, (rw_yyvsp[(1) - (3)].mtx), rx);
2966           }
2967     break;
2968 
2969   case 87:
2970 #line 1261 "rewrite.y"
2971     {
2972                   COMP_REGEX *rx;
2973                   if ((rx = compile_regexp((rw_yyvsp[(3) - (3)].string))) == NULL) {
2974                           errcnt++;
2975                           YYERROR;
2976                   }
2977                   (rw_yyval.mtx) = mtx_match(1, (rw_yyvsp[(1) - (3)].mtx), rx);
2978           }
2979     break;
2980 
2981 
2982 /* Line 1267 of yacc.c.  */
2983 #line 2984 "rewrite.c"
2984       default: break;
2985     }
2986   YY_SYMBOL_PRINT ("-> $$ =", rw_yyr1[rw_yyn], &rw_yyval, &rw_yyloc);
2987 
2988   YYPOPSTACK (rw_yylen);
2989   rw_yylen = 0;
2990   YY_STACK_PRINT (rw_yyss, rw_yyssp);
2991 
2992   *++rw_yyvsp = rw_yyval;
2993 
2994 
2995   /* Now `shift' the result of the reduction.  Determine what state
2996      that goes to, based on the state we popped back to and the rule
2997      number reduced by.  */
2998 
2999   rw_yyn = rw_yyr1[rw_yyn];
3000 
3001   rw_yystate = rw_yypgoto[rw_yyn - YYNTOKENS] + *rw_yyssp;
3002   if (0 <= rw_yystate && rw_yystate <= YYLAST && rw_yycheck[rw_yystate] == *rw_yyssp)
3003     rw_yystate = rw_yytable[rw_yystate];
3004   else
3005     rw_yystate = rw_yydefgoto[rw_yyn - YYNTOKENS];
3006 
3007   goto rw_yynewstate;
3008 
3009 
3010 /*------------------------------------.
3011 | rw_yyerrlab -- here on detecting error |
3012 `------------------------------------*/
3013 rw_yyerrlab:
3014   /* If not already recovering from an error, report this error.  */
3015   if (!rw_yyerrstatus)
3016     {
3017       ++rw_yynerrs;
3018 #if ! YYERROR_VERBOSE
3019       rw_yyerror (YY_("syntax error"));
3020 #else
3021       {
3022 	YYSIZE_T rw_yysize = rw_yysyntax_error (0, rw_yystate, rw_yychar);
3023 	if (rw_yymsg_alloc < rw_yysize && rw_yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
3024 	  {
3025 	    YYSIZE_T rw_yyalloc = 2 * rw_yysize;
3026 	    if (! (rw_yysize <= rw_yyalloc && rw_yyalloc <= YYSTACK_ALLOC_MAXIMUM))
3027 	      rw_yyalloc = YYSTACK_ALLOC_MAXIMUM;
3028 	    if (rw_yymsg != rw_yymsgbuf)
3029 	      YYSTACK_FREE (rw_yymsg);
3030 	    rw_yymsg = (char *) YYSTACK_ALLOC (rw_yyalloc);
3031 	    if (rw_yymsg)
3032 	      rw_yymsg_alloc = rw_yyalloc;
3033 	    else
3034 	      {
3035 		rw_yymsg = rw_yymsgbuf;
3036 		rw_yymsg_alloc = sizeof rw_yymsgbuf;
3037 	      }
3038 	  }
3039 
3040 	if (0 < rw_yysize && rw_yysize <= rw_yymsg_alloc)
3041 	  {
3042 	    (void) rw_yysyntax_error (rw_yymsg, rw_yystate, rw_yychar);
3043 	    rw_yyerror (rw_yymsg);
3044 	  }
3045 	else
3046 	  {
3047 	    rw_yyerror (YY_("syntax error"));
3048 	    if (rw_yysize != 0)
3049 	      goto rw_yyexhaustedlab;
3050 	  }
3051       }
3052 #endif
3053     }
3054 
3055 
3056 
3057   if (rw_yyerrstatus == 3)
3058     {
3059       /* If just tried and failed to reuse look-ahead token after an
3060 	 error, discard it.  */
3061 
3062       if (rw_yychar <= YYEOF)
3063 	{
3064 	  /* Return failure if at end of input.  */
3065 	  if (rw_yychar == YYEOF)
3066 	    YYABORT;
3067 	}
3068       else
3069 	{
3070 	  rw_yydestruct ("Error: discarding",
3071 		      rw_yytoken, &rw_yylval);
3072 	  rw_yychar = YYEMPTY;
3073 	}
3074     }
3075 
3076   /* Else will try to reuse look-ahead token after shifting the error
3077      token.  */
3078   goto rw_yyerrlab1;
3079 
3080 
3081 /*---------------------------------------------------.
3082 | rw_yyerrorlab -- error raised explicitly by YYERROR.  |
3083 `---------------------------------------------------*/
3084 rw_yyerrorlab:
3085 
3086   /* Pacify compilers like GCC when the user code never invokes
3087      YYERROR and the label rw_yyerrorlab therefore never appears in user
3088      code.  */
3089   if (/*CONSTCOND*/ 0)
3090      goto rw_yyerrorlab;
3091 
3092   /* Do not reclaim the symbols of the rule which action triggered
3093      this YYERROR.  */
3094   YYPOPSTACK (rw_yylen);
3095   rw_yylen = 0;
3096   YY_STACK_PRINT (rw_yyss, rw_yyssp);
3097   rw_yystate = *rw_yyssp;
3098   goto rw_yyerrlab1;
3099 
3100 
3101 /*-------------------------------------------------------------.
3102 | rw_yyerrlab1 -- common code for both syntax error and YYERROR.  |
3103 `-------------------------------------------------------------*/
3104 rw_yyerrlab1:
3105   rw_yyerrstatus = 3;	/* Each real token shifted decrements this.  */
3106 
3107   for (;;)
3108     {
3109       rw_yyn = rw_yypact[rw_yystate];
3110       if (rw_yyn != YYPACT_NINF)
3111 	{
3112 	  rw_yyn += YYTERROR;
3113 	  if (0 <= rw_yyn && rw_yyn <= YYLAST && rw_yycheck[rw_yyn] == YYTERROR)
3114 	    {
3115 	      rw_yyn = rw_yytable[rw_yyn];
3116 	      if (0 < rw_yyn)
3117 		break;
3118 	    }
3119 	}
3120 
3121       /* Pop the current state because it cannot handle the error token.  */
3122       if (rw_yyssp == rw_yyss)
3123 	YYABORT;
3124 
3125 
3126       rw_yydestruct ("Error: popping",
3127 		  rw_yystos[rw_yystate], rw_yyvsp);
3128       YYPOPSTACK (1);
3129       rw_yystate = *rw_yyssp;
3130       YY_STACK_PRINT (rw_yyss, rw_yyssp);
3131     }
3132 
3133   if (rw_yyn == YYFINAL)
3134     YYACCEPT;
3135 
3136   *++rw_yyvsp = rw_yylval;
3137 
3138 
3139   /* Shift the error token.  */
3140   YY_SYMBOL_PRINT ("Shifting", rw_yystos[rw_yyn], rw_yyvsp, rw_yylsp);
3141 
3142   rw_yystate = rw_yyn;
3143   goto rw_yynewstate;
3144 
3145 
3146 /*-------------------------------------.
3147 | rw_yyacceptlab -- YYACCEPT comes here.  |
3148 `-------------------------------------*/
3149 rw_yyacceptlab:
3150   rw_yyresult = 0;
3151   goto rw_yyreturn;
3152 
3153 /*-----------------------------------.
3154 | rw_yyabortlab -- YYABORT comes here.  |
3155 `-----------------------------------*/
3156 rw_yyabortlab:
3157   rw_yyresult = 1;
3158   goto rw_yyreturn;
3159 
3160 #ifndef rw_yyoverflow
3161 /*-------------------------------------------------.
3162 | rw_yyexhaustedlab -- memory exhaustion comes here.  |
3163 `-------------------------------------------------*/
3164 rw_yyexhaustedlab:
3165   rw_yyerror (YY_("memory exhausted"));
3166   rw_yyresult = 2;
3167   /* Fall through.  */
3168 #endif
3169 
3170 rw_yyreturn:
3171   if (rw_yychar != YYEOF && rw_yychar != YYEMPTY)
3172      rw_yydestruct ("Cleanup: discarding lookahead",
3173 		 rw_yytoken, &rw_yylval);
3174   /* Do not reclaim the symbols of the rule which action triggered
3175      this YYABORT or YYACCEPT.  */
3176   YYPOPSTACK (rw_yylen);
3177   YY_STACK_PRINT (rw_yyss, rw_yyssp);
3178   while (rw_yyssp != rw_yyss)
3179     {
3180       rw_yydestruct ("Cleanup: popping",
3181 		  rw_yystos[*rw_yyssp], rw_yyvsp);
3182       YYPOPSTACK (1);
3183     }
3184 #ifndef rw_yyoverflow
3185   if (rw_yyss != rw_yyssa)
3186     YYSTACK_FREE (rw_yyss);
3187 #endif
3188 #if YYERROR_VERBOSE
3189   if (rw_yymsg != rw_yymsgbuf)
3190     YYSTACK_FREE (rw_yymsg);
3191 #endif
3192   /* Make sure YYID is used.  */
3193   return YYID (rw_yyresult);
3194 }
3195 
3196 
3197 #line 1271 "rewrite.y"
3198 
3199 
3200 int
rw_yyerror(char * s)3201 rw_yyerror(char *s)
3202 {
3203         grad_log_loc(GRAD_LOG_ERR, &locus, "%s", s);
3204         errcnt++;
3205 	return 0;
3206 }
3207 
3208 
3209 /* **************************************************************************
3210  * Interface functions
3211  */
3212 int
parse_rewrite(char * path)3213 parse_rewrite(char *path)
3214 {
3215         locus.file = path;
3216         infile = fopen(locus.file, "r");
3217         if (!infile) {
3218                 if (errno != ENOENT) {
3219                         grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
3220                                  _("can't open file `%s'"),
3221                                  locus.file);
3222 			return -1;
3223                 }
3224                 return -2;
3225         }
3226 
3227 	GRAD_DEBUG1(1, "Loading file %s", locus.file);
3228         rw_code_lock();
3229         rw_yyeof = 0;
3230         locus.line = 1;
3231 	errcnt = 0;
3232         regex_init();
3233         obstack_init(&input_stk);
3234 
3235         mtx_init();
3236         var_init();
3237         loop_init();
3238         frame_init();
3239 
3240         frame_push();
3241 
3242         rw_yyparse();
3243 
3244         var_free_all();
3245         frame_free_all();
3246         mtx_free_all();
3247 
3248         fclose(infile);
3249         obstack_free(&input_stk, NULL);
3250         rw_code_unlock();
3251         return errcnt;
3252 }
3253 
3254 static int
parse_rewrite_string(char * str)3255 parse_rewrite_string(char *str)
3256 {
3257         rw_code_lock();
3258 	code_check();
3259         rw_yyeof = 0;
3260 	locus.file = "<string>";
3261 	locus.line = 1;
3262 	errcnt = 0;
3263         regex_init();
3264         obstack_init(&input_stk);
3265 
3266         mtx_init();
3267         var_init();
3268         loop_init();
3269         frame_init();
3270 
3271         frame_push();
3272 
3273         if (GRAD_DEBUG_LEVEL(50))
3274                 rw_yydebug++;
3275 
3276 	infile = 0;
3277 	inbuf = curp = str;
3278 
3279         rw_yyparse();
3280 
3281 #if defined(MAINTAINER_MODE)
3282         if (GRAD_DEBUG_LEVEL(100))
3283                 debug_dump_code();
3284 #endif
3285 
3286         var_free_all();
3287         frame_free_all();
3288         mtx_free_all();
3289 
3290         obstack_free(&input_stk, NULL);
3291         rw_code_unlock();
3292         return errcnt;
3293 }
3294 
3295 
3296 /* **************************************************************************
3297  * Lexical analyzer stuff: too simple to be written in lex.
3298  */
3299 static int
unput(int c)3300 unput(int c)
3301 {
3302 	if (!c)
3303 		return 0;
3304 	if (infile)
3305 		ungetc(c, infile);
3306 	else if (curp > inbuf)
3307 		*--curp = c;
3308 	return c;
3309 }
3310 
3311 static int
input()3312 input()
3313 {
3314         if (rw_yyeof)
3315                 rw_yychar = 0;
3316 	else if (infile) {
3317 		if ((rw_yychar = getc(infile)) <= 0) {
3318 			rw_yyeof++;
3319 			rw_yychar = 0;
3320 		}
3321 	} else if (curp) {
3322 		rw_yychar = *curp++;
3323 		if (!rw_yychar)
3324 			rw_yyeof++;
3325 	}
3326         return rw_yychar;
3327 }
3328 
3329 static int  rw_backslash();
3330 static int  c2d(int c);
3331 static int  read_number();
3332 static int  read_num(int n, int base);
3333 static char *read_string();
3334 static char *read_ident(int c);
3335 static char *read_to_delim(int c);
3336 static int  skip_to_nl();
3337 static int c_comment();
3338 
3339 /*
3340  * Convert a character to digit. Only octal, decimal and hex digits are
3341  * allowed. If any other character is input, c2d() returns 100, which is
3342  * greater than any number base allowed.
3343  */
3344 int
c2d(int c)3345 c2d(int c)
3346 {
3347         switch (c) {
3348         case '0':
3349         case '1':
3350         case '2':
3351         case '3':
3352         case '4':
3353         case '5':
3354         case '6':
3355         case '7':
3356         case '8':
3357         case '9':
3358                 return c - '0';
3359         case 'A':
3360         case 'B':
3361         case 'C':
3362         case 'D':
3363         case 'E':
3364         case 'F':
3365                 return c - 'A' + 16;
3366         case 'a':
3367         case 'b':
3368         case 'c':
3369         case 'd':
3370         case 'e':
3371         case 'f':
3372                 return c - 'a' + 10;
3373         }
3374         return 100;
3375 }
3376 
3377 /*
3378  * Read a number. Usual C conventions apply.
3379  */
3380 int
read_number()3381 read_number()
3382 {
3383         int c;
3384         int base;
3385 	int res;
3386 
3387         c = rw_yychar;
3388         if (c == '0') {
3389                 if (input() == 'x' || rw_yychar == 'X') {
3390                         base = 16;
3391                 } else {
3392                         base = 8;
3393                         unput(rw_yychar);
3394                 }
3395         } else
3396                 base = 10;
3397 
3398 	res = read_num(c2d(c), base);
3399 	if (base == 10 && rw_yychar == '.') {
3400 		int n;
3401 
3402 		for (n = 0; n < 3 && rw_yychar == '.'; n++) {
3403 			int val;
3404 
3405 			input();
3406 			val = read_num(0, base);
3407 			res = (res << 8) + val;
3408 		}
3409 		if (n != 3)
3410 			res <<= 8 * (3-n);
3411 	}
3412 	return res;
3413 }
3414 
3415 int
read_num(int n,int base)3416 read_num(int n, int base)
3417 {
3418         int d;
3419 
3420         while (input() && (d = c2d(rw_yychar)) < 16)
3421                 n = n*base + d;
3422         unput(rw_yychar);
3423         return n;
3424 }
3425 
3426 int
rw_backslash()3427 rw_backslash()
3428 {
3429         switch (input()) {
3430         case '\\':
3431                 return '\\';
3432         case 'a':
3433                 return '\a';
3434         case 'b':
3435                 return '\b';
3436         case 'f':
3437                 return '\f';
3438         case 'n':
3439                 return '\n';
3440         case 'r':
3441                 return '\r';
3442         case 't':
3443                 return '\t';
3444         case 'e':
3445                 return '\033';
3446         case '0':
3447                 return read_number();
3448         case 'x':
3449         case 'X':
3450                 return read_num(0, 16);
3451         case '(':
3452         case ')':
3453                 /* Preserve regular expressions */
3454                 unput(rw_yychar);
3455                 rw_yychar = '\\';
3456         }
3457         return rw_yychar;
3458 }
3459 
3460 /*
3461  * Read a string up to the closing doublequote
3462  */
3463 char *
read_string()3464 read_string()
3465 {
3466         while (input() && rw_yychar != '"') {
3467                 if (rw_yychar == '\\')
3468                         rw_yychar = rw_backslash();
3469                 obstack_1grow(&input_stk, rw_yychar);
3470         }
3471         obstack_1grow(&input_stk, 0);
3472         return obstack_finish(&input_stk);
3473 }
3474 
3475 /*
3476  * Read everything up to the given delimiter
3477  */
3478 char *
read_to_delim(int c)3479 read_to_delim(int c)
3480 {
3481         while (input() && rw_yychar != c)
3482                 obstack_1grow(&input_stk, rw_yychar);
3483         obstack_1grow(&input_stk, 0);
3484         return obstack_finish(&input_stk);
3485 }
3486 
3487 /*
3488  * Is `c' a part of the word?
3489  */
3490 #define isword(c) (isalnum(c) || c == '_' || c == '$')
3491 
3492 /*
3493  * Is `c' a whitespace character?
3494  */
3495 #define isws(c) ((c) == ' ' || (c) == '\t')
3496 
3497 /*
3498  * Read identifier
3499  */
3500 char *
read_ident(int c)3501 read_ident(int c)
3502 {
3503         obstack_1grow(&input_stk, c);
3504         while (input() && isword(rw_yychar))
3505                 obstack_1grow(&input_stk, rw_yychar);
3506         obstack_1grow(&input_stk, 0);
3507         unput(rw_yychar);
3508         return obstack_finish(&input_stk);
3509 }
3510 
3511 /*
3512  * Skip input up to the next newline
3513  */
3514 int
skip_to_nl()3515 skip_to_nl()
3516 {
3517         while (input() && rw_yychar != '\n')
3518                 ;
3519         return unput(rw_yychar);
3520 }
3521 
3522 /*
3523  * Skip a C-style comment
3524  */
3525 int
c_comment()3526 c_comment()
3527 {
3528         if (rw_yychar != '/')
3529                 return 0;
3530         if (input() == '*') {
3531                 size_t keep_line = locus.line;
3532 
3533                 do {
3534                         while (input() != '*') {
3535                                 if (rw_yychar == 0) {
3536                                         grad_log_loc(GRAD_LOG_ERR, &locus,
3537 		       _("unexpected EOF in comment started at line %lu"),
3538 						     (unsigned long) keep_line);
3539                                         return 0;
3540                                 } else if (rw_yychar == '\n')
3541                                         locus.line++;
3542                         }
3543                 } while (input() != '/');
3544                 return 1;
3545         }
3546         unput(rw_yychar);
3547         rw_yychar = '/';
3548         return 0;
3549 }
3550 
3551 
3552 /* Pragmatic comments */
3553 enum pragma_handler_phase {
3554 	pragma_begin,
3555 	pragma_cont,
3556 	pragma_error,
3557 	pragma_end
3558 };
3559 
3560 typedef int (*pragma_handler_fp) (enum pragma_handler_phase);
3561 
3562 static int
regex_pragma(enum pragma_handler_phase phase)3563 regex_pragma (enum pragma_handler_phase phase)
3564 {
3565 	int disable = 0;
3566 	int bit;
3567 	char *s;
3568 	static int regexp_accum;
3569 
3570 	switch (phase) {
3571 	case pragma_begin:
3572 		regexp_accum = 0;
3573 		return 0;
3574 
3575 	case pragma_end:
3576 		regcomp_flags = regexp_accum;
3577 		return 0;
3578 
3579 	case pragma_error:
3580 		return 0;
3581 
3582 	case pragma_cont:
3583 		break;
3584 	}
3585 
3586 	switch (rw_yychar) {
3587 	case '+':
3588 		disable = 0;
3589 		input();
3590 		break;
3591 
3592 	case '-':
3593 		disable = 1;
3594 		input();
3595 		break;
3596 	}
3597 	if (!isword(rw_yychar)) {
3598 		grad_log_loc(GRAD_LOG_ERR, &locus, _("Malformed pragma"));
3599 		return 1;
3600 	}
3601 
3602 	s = read_ident(rw_yychar);
3603 
3604 	if (strcmp (s, "extended") == 0)
3605 		bit = REG_EXTENDED;
3606 	else if (strcmp (s, "icase") == 0)
3607 		bit = REG_ICASE;
3608 	else if (strcmp (s, "newline") == 0)
3609 		bit = REG_NEWLINE;
3610 	else {
3611 		grad_log_loc(GRAD_LOG_ERR, &locus,
3612 			     _("Unknown regexp flag: %s"), s);
3613 		return 1;
3614 	}
3615 
3616 	if (disable)
3617 		regexp_accum &= ~bit;
3618 	else
3619 		regexp_accum |= bit;
3620 	return 0;
3621 }
3622 
3623 static pragma_handler_fp
find_pragma_handler(char * s)3624 find_pragma_handler(char *s)
3625 {
3626 	if (strcmp(s, "regex") == 0)
3627 		return regex_pragma;
3628 	return NULL;
3629 }
3630 
3631 static void
handle_pragma()3632 handle_pragma()
3633 {
3634 	int rc;
3635 	pragma_handler_fp pragma_handler;
3636 
3637 	while (input() && isws(rw_yychar))
3638 		;
3639 	if (rw_yychar == 0)
3640 		return;
3641 
3642 	pragma_handler = find_pragma_handler (read_ident(rw_yychar));
3643 
3644 	if (pragma_handler) {
3645 		pragma_handler(pragma_begin);
3646 
3647 		do {
3648 			while (input() && isws(rw_yychar))
3649 				;
3650 			if (rw_yychar == 0 || rw_yychar == '\n')
3651 				break;
3652 			rc = pragma_handler(pragma_cont);
3653 		} while (rc == 0 && rw_yychar != '\n' && rw_yychar != 0);
3654 
3655 		pragma_handler(rc ? pragma_error : pragma_end);
3656 	}
3657 }
3658 
3659 
3660 
3661 
3662 /* Parse a 'sharp' (single-line) comment */
3663 void
sharp_comment()3664 sharp_comment()
3665 {
3666 	while (input() && isws(rw_yychar))
3667 		;
3668 	if (rw_yychar == 0)
3669 		return;
3670 	else if (rw_yychar == '\n') {
3671 		locus.line++;
3672 		return;
3673 	} else if (isword(rw_yychar)) {
3674 		if (strcmp(read_ident(rw_yychar), "pragma") == 0)
3675 			handle_pragma();
3676 	}
3677 
3678 	skip_to_nl();
3679 }
3680 
3681 
3682 #if defined(MAINTAINER_MODE)
3683 # define DEBUG_LEX1(s) if (GRAD_DEBUG_LEVEL(60)) printf("rw_yylex: " s "\n")
3684 # define DEBUG_LEX2(s,v) if (GRAD_DEBUG_LEVEL(60)) printf("rw_yylex: " s "\n", v)
3685 #else
3686 # define DEBUG_LEX1(s)
3687 # define DEBUG_LEX2(s,v)
3688 #endif
3689 
3690 static grad_keyword_t rw_kw[] = {
3691         { "if",       IF },
3692         { "else",     ELSE },
3693         { "return",   RETURN },
3694         { "for",      FOR },
3695         { "do",       DO },
3696         { "while",    WHILE },
3697         { "break",    BREAK },
3698         { "continue", CONTINUE },
3699 	{ "delete",   DELETE },
3700         { NULL }
3701 };
3702 
3703 int
rw_yylex()3704 rw_yylex()
3705 {
3706         int nl;
3707         int c;
3708         VAR *var;
3709         FUNCTION *fun;
3710         builtin_t *btin;
3711 
3712         /* Skip whitespace and comment lines */
3713         do {
3714                 nl = 0;
3715                 while (input() && isspace(rw_yychar))
3716                         if (rw_yychar == '\n')
3717                                 locus.line++;
3718 
3719                 if (!rw_yychar)
3720                         return 0;
3721 
3722                 if (rw_yychar == '#') {
3723                         sharp_comment();
3724                         nl = 1;
3725                 }
3726         } while (nl || c_comment());
3727 
3728         /*
3729          * A regexp reference
3730          */
3731         if (rw_yychar == '\\') {
3732                 input();
3733                 rw_yylval.number = read_number();
3734                 DEBUG_LEX2("REFERENCE %d", rw_yylval.number);
3735                 return REFERENCE;
3736         }
3737 
3738         /*
3739          * A character
3740          */
3741         if (rw_yychar == '\'') {
3742                 if (input() == '\\')
3743                         c = rw_backslash();
3744                 else
3745                         c = rw_yychar;
3746                 if (input() != '\'') {
3747                         grad_log_loc(GRAD_LOG_ERR, &locus,
3748 				     "%s",
3749 				     _("unterminated character constant"));
3750                         errcnt++;
3751                 }
3752                 rw_yylval.number = c;
3753                 DEBUG_LEX2("CHAR %d", c);
3754                 return NUMBER;
3755         }
3756 
3757         /*
3758          * A number
3759          */
3760         if (isdigit(rw_yychar)) {
3761                 rw_yylval.number = read_number();
3762                 DEBUG_LEX2("NUMBER %d", rw_yylval.number);
3763                 return NUMBER;
3764         }
3765 
3766         /*
3767          * Quoted string
3768          */
3769         if (rw_yychar == '"') {
3770                 rw_yylval.string = read_string();
3771                 DEBUG_LEX2("STRING %s", rw_yylval.string);
3772                 return STRING;
3773         }
3774 
3775         /* A/V  pair reference.
3776            We do not allow %<number> sequences, since it would result
3777            in conflict with binary '%' operator.
3778            Thanks to Clement Gerouville for noticing.  */
3779         if (rw_yychar == '%') {
3780                 grad_dict_attr_t *attr = 0;
3781                 char *attr_name;
3782 
3783                 input();
3784                 if (rw_yychar == '[' || rw_yychar == '{') {
3785                         attr_name = read_to_delim(rw_yychar == '[' ? ']' : '}');
3786                         attr = grad_attr_name_to_dict(attr_name);
3787                 } else {
3788                         unput(rw_yychar);
3789                         return '%';
3790                 }
3791                 if (!attr) {
3792                         grad_log_loc(GRAD_LOG_ERR, &locus,
3793 				     _("unknown attribute `%s'"),
3794 				     attr_name);
3795                         errcnt++;
3796                         return BOGUS;
3797                 }
3798                 rw_yylval.attr = attr;
3799                 DEBUG_LEX2("ATTR: %s", attr->name);
3800                 return ATTR;
3801         }
3802 
3803 
3804         /*
3805          * Data type or identifier
3806          */
3807         if (isword(rw_yychar)) {
3808                 rw_yylval.string = read_ident(rw_yychar);
3809 
3810                 if (strcmp(rw_yylval.string, "integer") == 0) {
3811                         DEBUG_LEX1("TYPE(Integer)");
3812                         rw_yylval.type = Integer;
3813                         return TYPE;
3814                 } else if (strcmp(rw_yylval.string, "string") == 0) {
3815                         DEBUG_LEX1("TYPE(String)");
3816                         rw_yylval.type = String;
3817                         return TYPE;
3818 		}
3819 
3820                 if ((c = grad_xlat_keyword(rw_kw, rw_yylval.string, 0)) != 0) {
3821                         DEBUG_LEX2("KW: %s", rw_yylval.string);
3822                         return c;
3823                 }
3824 
3825                 if (var = var_lookup(rw_yylval.string)) {
3826                         DEBUG_LEX2("VARIABLE: %s", rw_yylval.string);
3827                         rw_yylval.var = var;
3828                         return VARIABLE;
3829                 }
3830 
3831                 if (fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, rw_yylval.string)) {
3832                         DEBUG_LEX2("FUN %s", rw_yylval.string);
3833                         rw_yylval.fun = fun;
3834                         return FUN;
3835                 }
3836 
3837                 if (btin = builtin_lookup(rw_yylval.string)) {
3838                         DEBUG_LEX2("BUILTIN %s", rw_yylval.string);
3839                         rw_yylval.btin = btin;
3840                         return BUILTIN;
3841                 }
3842                 DEBUG_LEX2("IDENT: %s", rw_yylval.string);
3843                 return IDENT;
3844         }
3845 
3846         /*
3847          * Boolean expressions
3848          */
3849         if (rw_yychar == '&' || rw_yychar == '|') {
3850                 int c = rw_yychar;
3851 
3852                 if (input() == c) {
3853                         DEBUG_LEX2("%s", rw_yychar == '&' ? "AND" : "OR");
3854                         return rw_yychar == '&' ? AND : OR;
3855                 }
3856                 unput(rw_yychar);
3857 
3858                 DEBUG_LEX2("%c", c);
3859                 return c;
3860         }
3861 
3862         /*
3863          * Comparison operator
3864          */
3865         if (strchr("<>=!", rw_yychar)) {
3866                 int c = rw_yychar;
3867                 if (input() == '=') {
3868                         switch (c) {
3869                         case '<':
3870                                 DEBUG_LEX1("LE");
3871                                 return LE;
3872                         case '>':
3873                                 DEBUG_LEX1("GE");
3874                                 return GE;
3875                         case '=':
3876                                 DEBUG_LEX1("EQ");
3877                                 return EQ;
3878                         case '!':
3879                                 DEBUG_LEX1("NE");
3880                                 return NE;
3881                         }
3882                 } else if (c == rw_yychar) {
3883                         if (c == '<') {
3884                                 DEBUG_LEX1("SHL");
3885                                 return SHL;
3886                         }
3887                         if (c == '>') {
3888                                 DEBUG_LEX1("SHR");
3889                                 return SHR;
3890                         }
3891                         unput(rw_yychar);
3892                         DEBUG_LEX2("%c", rw_yychar);
3893                         return rw_yychar;
3894                 } else if (rw_yychar == '~') {
3895                         if (c == '=') {
3896                                 DEBUG_LEX1("MT");
3897                                 return MT;
3898                         }
3899                         if (c == '!') {
3900                                 DEBUG_LEX1("NM");
3901                                 return NM;
3902                         }
3903                 }
3904                 unput(rw_yychar);
3905                 switch (c) {
3906                 case '<':
3907                         DEBUG_LEX1("LT");
3908                         return LT;
3909                 case '>':
3910                         DEBUG_LEX1("GT");
3911                         return GT;
3912                 case '!':
3913                         DEBUG_LEX1("NOT");
3914                         return NOT;
3915                 default:
3916                         return c;
3917                 }
3918         }
3919 
3920         DEBUG_LEX2("%c", rw_yychar);
3921         return rw_yychar;
3922 }
3923 
3924 void
rw_yysync()3925 rw_yysync()
3926 {
3927         while (skip_to_nl() == '\n' && !isalpha(input()))
3928                 locus.line++;
3929         unput(rw_yychar);
3930 }
3931 
3932 
3933 /* ****************************************************************************
3934  * Generalized list functions
3935  */
3936 static RWLIST *_list_insert(RWLIST **first, RWLIST **last, RWLIST *prev,
3937 			    RWLIST *obj, int before);
3938 static RWLIST *_list_remove(RWLIST **first, RWLIST **last, RWLIST *obj);
3939 static RWLIST *_list_append(RWLIST **first, RWLIST **last, RWLIST *obj);
3940 
3941 #define rw_list_insert(first, last, prev, obj, before) \
3942  _list_insert((RWLIST**)first,(RWLIST**)last,(RWLIST*)prev,(RWLIST*)obj, before)
3943 #define rw_list_remove(first, last, obj) \
3944  _list_remove((RWLIST**)first,(RWLIST**)last,(RWLIST *)obj)
3945 #define rw_list_append(first, last, obj) \
3946  _list_append((RWLIST**)first, (RWLIST**)last, (RWLIST*)obj)
3947 
3948 RWLIST *
_list_append(RWLIST ** first,RWLIST ** last,RWLIST * obj)3949 _list_append(RWLIST **first, RWLIST **last, RWLIST *obj)
3950 {
3951         return rw_list_insert(first, last, *last, obj, 0);
3952 }
3953 
3954 RWLIST *
_list_insert(RWLIST ** first,RWLIST ** last,RWLIST * prev,RWLIST * obj,int before)3955 _list_insert(RWLIST **first, RWLIST **last, RWLIST *prev, RWLIST *obj,
3956 	     int before)
3957 {
3958         RWLIST   *next;
3959 
3960         /*
3961          * No first element: initialize whole list
3962          */
3963         if (!*first) {
3964                 *first = obj;
3965                 if (last)
3966                         *last = obj;
3967                 obj->prev = obj->next = NULL;
3968                 return obj;
3969         }
3970 
3971         /*
3972          * Insert before `prev'
3973          */
3974         if (before) {
3975                 _list_insert(first, last, prev, obj, 0);
3976                 _list_remove(first, last, prev);
3977                 _list_insert(first, last, obj, prev, 0);
3978                 return obj;
3979         }
3980 
3981         /*
3982          * Default: insert after prev
3983          */
3984         obj->prev = prev;
3985         obj->next = prev->next;
3986 
3987         if (next = prev->next)
3988                 next->prev = obj;
3989 
3990         prev->next = obj;
3991         if (last && prev == *last)
3992                 *last = obj;
3993 
3994 
3995         return obj;
3996 }
3997 
3998 RWLIST *
_list_remove(RWLIST ** first,RWLIST ** last,RWLIST * obj)3999 _list_remove(RWLIST **first, RWLIST **last, RWLIST *obj)
4000 {
4001         RWLIST *temp;
4002 
4003         if (temp = obj->prev)
4004                 temp->next = obj->next;
4005         else
4006                 *first = obj->next;
4007 
4008         if (temp = obj->next)
4009                 temp->prev = obj->prev;
4010         else if (last)
4011                 *last = obj->prev;
4012 
4013         obj->prev = obj->next = NULL;
4014 
4015         return obj;
4016 }
4017 
4018 
4019 /* ****************************************************************************
4020  * Generalized object handling
4021  */
4022 
4023 void *obj_alloc(OBUCKET *bucket);
4024 void obj_free_all(OBUCKET *bucket);
4025 
4026 
4027 void *
obj_alloc(OBUCKET * bucket)4028 obj_alloc(OBUCKET *bucket)
4029 {
4030         OBJECT *optr;
4031 
4032         optr = grad_emalloc(bucket->size);
4033 
4034         optr->alloc        = bucket->alloc_list;
4035         bucket->alloc_list = optr;
4036 
4037         return optr;
4038 }
4039 
4040 void
obj_free_all(OBUCKET * bucket)4041 obj_free_all(OBUCKET *bucket)
4042 {
4043         OBJECT *obj, *next;
4044 
4045         obj = bucket->alloc_list;
4046 
4047         while (obj) {
4048                 next = obj->alloc;
4049                 if (bucket->free)
4050                         bucket->free(obj);
4051                 grad_free(obj);
4052                 obj = next;
4053         }
4054         bucket->alloc_list = NULL;
4055 }
4056 
4057 
4058 /* **************************************************************************
4059  * Frames
4060  */
4061 
4062 void
frame_init()4063 frame_init()
4064 {
4065         frame_bkt.alloc_list = NULL;
4066         frame_first = frame_last = NULL;
4067 }
4068 
4069 void
frame_push()4070 frame_push()
4071 {
4072         FRAME *this_frame = obj_alloc(&frame_bkt);
4073 
4074         if (!frame_last) {
4075                 this_frame->level = 0;
4076                 this_frame->stack_offset = 0;
4077         } else {
4078                 if (frame_last->level == 0)
4079                         this_frame->stack_offset = 1;
4080                 else
4081                         this_frame->stack_offset = frame_last->stack_offset;
4082                 this_frame->level = frame_last->level + 1;
4083         }
4084         rw_list_append(&frame_first, &frame_last, this_frame);
4085 }
4086 
4087 void
frame_pop()4088 frame_pop()
4089 {
4090         rw_list_remove(&frame_first, &frame_last, frame_last);
4091 }
4092 
4093 void
frame_update_alloc()4094 frame_update_alloc()
4095 {
4096         FRAME *this_frame = frame_last;
4097 
4098         if (this_frame->stack_offset > function->stack_alloc)
4099                 function->stack_alloc = this_frame->stack_offset;
4100 }
4101 
4102 void
frame_free_all()4103 frame_free_all()
4104 {
4105         obj_free_all(&frame_bkt);
4106         frame_first = frame_last = NULL;
4107 }
4108 
4109 void
frame_unwind_all()4110 frame_unwind_all()
4111 {
4112         while (frame_last)
4113                 rw_list_remove(&frame_first, &frame_last, frame_last);
4114         frame_push();
4115 }
4116 
4117 
4118 /* **************************************************************************
4119  * Loops
4120  */
4121 
4122 void
loop_init()4123 loop_init()
4124 {
4125         loop_bkt.alloc_list = NULL;
4126         loop_first = loop_last = NULL;
4127 }
4128 
4129 void
loop_free_all()4130 loop_free_all()
4131 {
4132         obj_free_all(&loop_bkt);
4133         loop_first = loop_last = NULL;
4134 }
4135 
4136 void
loop_unwind_all()4137 loop_unwind_all()
4138 {
4139         loop_first = loop_last = NULL;
4140 }
4141 
4142 /*ARGSUSED*/
4143 void
loop_push(MTX * mtx)4144 loop_push(MTX *mtx)
4145 {
4146         LOOP *this_loop = obj_alloc(&loop_bkt);
4147         rw_list_append(&loop_first, &loop_last, this_loop);
4148 }
4149 
4150 void
loop_pop()4151 loop_pop()
4152 {
4153         rw_list_remove(&loop_first, &loop_last, loop_last);
4154 }
4155 
4156 void
loop_fixup(JUMP_MTX * list,MTX * target)4157 loop_fixup(JUMP_MTX *list, MTX *target)
4158 {
4159         JUMP_MTX *jp;
4160 
4161         for (jp = list; jp; jp = (JUMP_MTX*)jp->link)
4162                 jp->dest = target;
4163 }
4164 
4165 
4166 /* **************************************************************************
4167  * Variables
4168  */
4169 OBUCKET var_bucket = { sizeof(VAR), NULL };
4170 
4171 void
var_init()4172 var_init()
4173 {
4174         var_bucket.alloc_list = NULL;
4175         var_first = var_last = NULL;
4176 }
4177 
4178 VAR *
var_alloc(grad_data_type_t type,char * name,int grow)4179 var_alloc(grad_data_type_t type, char *name, int grow)
4180 {
4181         VAR *var;
4182 
4183         var = (VAR*) obj_alloc(&var_bucket);
4184         rw_list_append(&var_first, &var_last, var);
4185 
4186         /* Initialize fields */
4187         var->name     = name;
4188         var->datatype = type;
4189         var->level    = curframe->level;
4190         var->offset   = curframe->stack_offset;
4191         curframe->stack_offset += grow;
4192 
4193         return var;
4194 }
4195 
4196 void
var_unwind_level()4197 var_unwind_level()
4198 {
4199         int cnt = 0;
4200 
4201         while (var_last && var_last->level == curframe->level) {
4202                 rw_list_remove(&var_first, &var_last, var_last);
4203                 cnt++;
4204         }
4205 
4206         if (cnt)
4207                 frame_update_alloc();
4208 }
4209 
4210 void
var_unwind_all()4211 var_unwind_all()
4212 {
4213         while (var_last)
4214                 rw_list_remove(&var_first, &var_last, var_last);
4215 }
4216 
4217 void
var_type(grad_data_type_t type,VAR * var)4218 var_type(grad_data_type_t type, VAR *var)
4219 {
4220         for (; var; var = var->dcllink)
4221                 var->datatype = type;
4222 }
4223 
4224 void
var_free_all()4225 var_free_all()
4226 {
4227         obj_free_all(&var_bucket);
4228         var_first = var_last = NULL;
4229 }
4230 
4231 VAR *
var_lookup(char * name)4232 var_lookup(char *name)
4233 {
4234         VAR *var;
4235 
4236         var = var_last;
4237         while (var && strcmp(var->name, name))
4238                 var = var->prev;
4239         return var;
4240 }
4241 
4242 
4243 /* **************************************************************************
4244  * Matrix generation
4245  */
4246 OBUCKET mtx_bucket = { sizeof(MTX), NULL };
4247 #if defined(MAINTAINER_MODE)
4248 int mtx_current_id ;
4249 #endif
4250 
4251 /*
4252  * Insert a matrix into list
4253  */
4254 #define mtx_remove(mtx) rw_list_remove(&mtx_first, &mtx_last, mtx)
4255 #define mtx_append(mtx) rw_list_append(&mtx_first, &mtx_last, mtx)
4256 
4257 void
mtx_insert(MTX * prev,MTX * mtx)4258 mtx_insert(MTX *prev, MTX *mtx)
4259 {
4260         MTX *up;
4261 
4262         rw_list_insert(&mtx_first, &mtx_last, prev, mtx, 0);
4263         if (up = prev->gen.uplink) {
4264                 switch (up->gen.type) {
4265                 case Unary:
4266                         up->un.arg = mtx;
4267                         break;
4268                 case Binary:
4269                         if (up->bin.arg[0] == prev)
4270                                 up->bin.arg[0] = mtx;
4271                         else
4272                                 up->bin.arg[1] = mtx;
4273                         break;
4274                 case Return:
4275                         up->ret.expr = mtx;
4276                         break;
4277                 default:
4278                         /*should not happen*/
4279                         break;
4280                 }
4281         }
4282 }
4283 
4284 void
mtx_init()4285 mtx_init()
4286 {
4287         mtx_bucket.alloc_list = NULL;
4288         mtx_first = mtx_last = NULL;
4289 }
4290 
4291 void
mtx_unwind_all()4292 mtx_unwind_all()
4293 {
4294         while (mtx_last)
4295                 rw_list_remove(&mtx_first, &mtx_last, mtx_last);
4296 }
4297 
4298 void
mtx_free_all()4299 mtx_free_all()
4300 {
4301         obj_free_all(&mtx_bucket);
4302         mtx_first = mtx_last = NULL;
4303 }
4304 
4305 MTX *
mtx_cur()4306 mtx_cur()
4307 {
4308         return mtx_last;
4309 }
4310 
4311 MTX *
mtx_frame(Mtxtype type,stkoff_t stksize)4312 mtx_frame(Mtxtype type, stkoff_t stksize)
4313 {
4314         FRAME_MTX *mtx = (FRAME_MTX *)mtx_alloc(type);
4315         mtx_append(mtx);
4316         mtx->stacksize = stksize;
4317         return (MTX*)mtx;
4318 }
4319 
4320 MTX *
mtx_nop()4321 mtx_nop()
4322 {
4323         MTX *mtx = mtx_alloc(Nop);
4324         mtx_append(mtx);
4325         return mtx;
4326 }
4327 
4328 MTX *
mtx_jump()4329 mtx_jump()
4330 {
4331         MTX *mtx = mtx_alloc(Jump);
4332         mtx_append(mtx);
4333         return mtx;
4334 }
4335 
4336 MTX *
mtx_stop()4337 mtx_stop()
4338 {
4339         MTX *mtx = mtx_alloc(Stop);
4340         mtx_append(mtx);
4341         return mtx;
4342 }
4343 
4344 MTX *
mtx_pop()4345 mtx_pop()
4346 {
4347         MTX *mtx = mtx_alloc(Pop);
4348         mtx_append(mtx);
4349         return mtx;
4350 }
4351 
4352 
4353 MTX *
mtx_return(MTX * arg)4354 mtx_return(MTX *arg)
4355 {
4356         MTX *mtx = mtx_alloc(Return);
4357 
4358         mtx_append(mtx);
4359         mtx->ret.expr = arg;
4360         arg->gen.uplink = (MTX*)mtx;
4361         return (MTX*)mtx;
4362 }
4363 
4364 /*
4365  * Allocate a matrix of given type and append it to the list
4366  */
4367 MTX *
mtx_alloc(Mtxtype type)4368 mtx_alloc(Mtxtype type)
4369 {
4370         MTX *mtx = obj_alloc(&mtx_bucket);
4371 
4372         mtx->gen.type  = type;
4373         mtx->gen.loc   = locus;
4374 #if defined(MAINTAINER_MODE)
4375         mtx->gen.id    = mtx_current_id++;
4376 #endif
4377         return mtx;
4378 }
4379 
4380 /*
4381  * Create a Constant matrix
4382  */
4383 MTX *
mtx_const(grad_value_t * val)4384 mtx_const(grad_value_t *val)
4385 {
4386         CONST_MTX *mtx = (CONST_MTX *)mtx_alloc(Constant);
4387 
4388         mtx_append(mtx);
4389         mtx->datatype = val->type;
4390 	mtx->datum = val->datum;
4391         return (MTX*)mtx;
4392 }
4393 
4394 /*
4395  * Create a Reference matrix
4396  */
4397 MTX *
mtx_ref(int num)4398 mtx_ref(int num)
4399 {
4400         MATCHREF_MTX *mtx = (MATCHREF_MTX*)mtx_alloc(Matchref);
4401         mtx_append(mtx);
4402         mtx->datatype = String;
4403         mtx->num = num;
4404         return (MTX*)mtx;
4405 }
4406 
4407 MTX *
mtx_var(VAR * var)4408 mtx_var(VAR *var)
4409 {
4410         VAR_MTX *mtx = (VAR_MTX*)mtx_alloc(Variable);
4411         mtx_append(mtx);
4412         mtx->datatype = var->datatype;
4413         mtx->var = var;
4414         return (MTX*)mtx;
4415 }
4416 
4417 MTX *
mtx_asgn(VAR * var,MTX * arg)4418 mtx_asgn(VAR *var, MTX *arg)
4419 {
4420         ASGN_MTX *mtx = (ASGN_MTX*)mtx_alloc(Asgn);
4421 
4422         mtx_append(mtx);
4423         if (var->datatype != arg->gen.datatype)
4424                 coerce(arg, var->datatype);
4425         mtx->datatype = var->datatype;
4426         mtx->lval = var;
4427         mtx->arg  = arg;
4428         return (MTX*)mtx;
4429 }
4430 
4431 
4432 grad_data_type_t
attr_datatype(grad_dict_attr_t * attr)4433 attr_datatype(grad_dict_attr_t *attr)
4434 {
4435         switch (attr->type) {
4436         case GRAD_TYPE_STRING:
4437 		/* FIXME: It could be a nice move to do
4438 
4439 		     (attr->prop & GRAD_AP_BINARY_STRING) ? Binstr : String;
4440 
4441 	           instead... */
4442 		return String;
4443         case GRAD_TYPE_DATE:
4444                 return String;
4445         case GRAD_TYPE_INTEGER:
4446         case GRAD_TYPE_IPADDR:
4447                 return Integer;
4448         default:
4449                 grad_insist_fail("unknown attribute type");
4450         }
4451         /*NOTREACHED*/
4452 }
4453 
4454 MTX *
mtx_attr(grad_dict_attr_t * attr,MTX * index)4455 mtx_attr(grad_dict_attr_t *attr, MTX *index)
4456 {
4457         ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr);
4458         mtx_append(mtx);
4459         mtx->attrno   = attr->value;
4460         mtx->datatype = attr_datatype(attr);
4461 	mtx->index = index;
4462         return (MTX*)mtx;
4463 }
4464 
4465 MTX *
mtx_attr_check(grad_dict_attr_t * attr,MTX * index)4466 mtx_attr_check(grad_dict_attr_t *attr,	MTX *index)
4467 {
4468         ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_check);
4469         mtx_append(mtx);
4470         mtx->attrno   = attr->value;
4471         mtx->datatype = Integer;
4472 	mtx->index = index;
4473         return (MTX*)mtx;
4474 }
4475 
4476 
4477 void
rw_coercion_warning(grad_data_type_t from,grad_data_type_t to,char * pref)4478 rw_coercion_warning(grad_data_type_t from, grad_data_type_t to, char *pref)
4479 {
4480 	grad_log_loc(GRAD_LOG_WARN, &locus,
4481 		     _("%s implicit coercion %s %s"),
4482 		     pref ? pref : "",
4483 		     datatype_str_abl(from),
4484 		     datatype_str_acc(to));
4485 }
4486 
4487 
4488 MTX *
mtx_attr_asgn(grad_dict_attr_t * attr,MTX * index,MTX * rval)4489 mtx_attr_asgn(grad_dict_attr_t *attr, MTX *index, MTX *rval)
4490 {
4491         ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_asgn);
4492         mtx_append(mtx);
4493         mtx->attrno   = attr->value;
4494         mtx->datatype = attr_datatype(attr);
4495         if (rval->gen.datatype != mtx->datatype) {
4496 		rw_coercion_warning(rval->gen.datatype, mtx->datatype, NULL);
4497                 rval = coerce(rval, mtx->datatype);
4498         }
4499 	mtx->index = index;
4500         mtx->rval = rval;
4501         return (MTX*)mtx;
4502 }
4503 
4504 MTX *
mtx_attr_delete(grad_dict_attr_t * attr,MTX * index)4505 mtx_attr_delete(grad_dict_attr_t *attr, MTX *index)
4506 {
4507         ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_delete);
4508         mtx_append(mtx);
4509         mtx->attrno   = attr->value;
4510         mtx->datatype = attr_datatype(attr);
4511 	mtx->index = index;
4512         return (MTX*)mtx;
4513 }
4514 
4515 MTX *
mtx_bin(Bopcode opcode,MTX * arg1,MTX * arg2)4516 mtx_bin(Bopcode opcode, MTX *arg1, MTX *arg2)
4517 {
4518         BIN_MTX *mtx = (BIN_MTX*)mtx_alloc(Binary);
4519 
4520         mtx_append(mtx);
4521         if (arg1->gen.datatype != arg2->gen.datatype) {
4522 		rw_coercion_warning(String, Integer, NULL);
4523                 if (arg1->gen.datatype == String)
4524                         arg1 = coerce(arg1, Integer);
4525                 else
4526                         arg2 = coerce(arg2, Integer);
4527         }
4528 
4529         switch (arg1->gen.datatype) {
4530         case String:
4531                 switch (opcode) {
4532                 case Add:
4533                         mtx->datatype = String;
4534                         break;
4535                 case Eq:
4536                 case Ne:
4537                 case Lt:
4538                 case Le:
4539                 case Gt:
4540                 case Ge:
4541                         mtx->datatype = Integer;
4542                         break;
4543                 default:
4544                         grad_log_loc(GRAD_LOG_ERR, &locus,
4545 				     "%s",
4546 				     _("operation not applicable to strings"));
4547                         errcnt++;
4548                         return (MTX*)mtx;
4549                 }
4550                 break;
4551 
4552         case Integer:
4553                 mtx->datatype = Integer;
4554 		break;
4555 
4556 	default:
4557 		grad_insist_fail("unknown data type");
4558         }
4559 
4560         mtx->opcode = opcode;
4561         mtx->arg[0] = arg1;
4562         mtx->arg[1] = arg2;
4563         arg1->gen.uplink = arg2->gen.uplink = (MTX*)mtx;
4564         return (MTX*)mtx;
4565 }
4566 
4567 MTX *
mtx_un(Uopcode opcode,MTX * arg)4568 mtx_un(Uopcode opcode, MTX *arg)
4569 {
4570         UN_MTX *mtx = (UN_MTX*)mtx_alloc(Unary);
4571 
4572         mtx_append(mtx);
4573         if (arg->gen.datatype != Integer) {
4574 		rw_coercion_warning(String, Integer, NULL);
4575                 coerce(arg, Integer);
4576         }
4577         mtx->datatype = Integer;
4578         mtx->opcode = opcode;
4579         mtx->arg = arg;
4580         arg->gen.uplink = (MTX*)mtx;
4581         return (MTX*)mtx;
4582 }
4583 
4584 MTX *
mtx_match(int negated,MTX * arg,COMP_REGEX * rx)4585 mtx_match(int negated, MTX *arg, COMP_REGEX *rx)
4586 {
4587         MATCH_MTX *mtx = (MATCH_MTX*)mtx_alloc(Match);
4588 
4589         mtx_append(mtx);
4590         if (arg->gen.datatype != String) {
4591 		rw_coercion_warning(Integer, String, NULL);
4592                 coerce(arg, String);
4593         }
4594         mtx->datatype = Integer;
4595         mtx->negated = negated;
4596         mtx->arg = arg;
4597         mtx->rx  = rx;
4598         return (MTX*)mtx;
4599 }
4600 
4601 MTX *
mtx_cond(MTX * cond,MTX * if_true,MTX * if_false)4602 mtx_cond(MTX *cond, MTX *if_true, MTX *if_false)
4603 {
4604         COND_MTX *mtx = (COND_MTX*)mtx_alloc(Cond);
4605 
4606         mtx_append(mtx);
4607         mtx->expr = cond;
4608         mtx->if_true   = if_true;
4609         mtx->if_false  = if_false;
4610         return (MTX*)mtx;
4611 }
4612 
4613 MTX *
mtx_coerce(grad_data_type_t type,MTX * arg)4614 mtx_coerce(grad_data_type_t type, MTX *arg)
4615 {
4616         if (type == arg->gen.datatype)
4617                 return mtx_cur();
4618         return coerce(arg, type);
4619 }
4620 
4621 MTX *
coerce(MTX * arg,grad_data_type_t type)4622 coerce(MTX *arg, grad_data_type_t type)
4623 {
4624         COERCE_MTX *mtx = (COERCE_MTX*)mtx_alloc(Coercion);
4625 
4626         mtx_insert(arg, (MTX*) mtx);
4627         mtx->datatype = type;
4628         mtx->arg = arg;
4629         return (MTX*)mtx;
4630 }
4631 
4632 MTX *
mtx_call(FUNCTION * fun,MTX * args)4633 mtx_call(FUNCTION *fun, MTX *args)
4634 {
4635         MTX       *argp;
4636         CALL_MTX  *call;
4637         PARAMETER *parmp;
4638         int       argn;
4639 
4640         /*
4641          * Test the number and types of arguments. Insert reasonable
4642          * typecasts.
4643          */
4644         argn = 0;
4645         argp = args;
4646         parmp = fun->parm;
4647         while (argp && parmp) {
4648                 if (argp->gen.datatype != parmp->datatype) {
4649 			char buf[24];
4650 			snprintf(buf, sizeof buf, _("(argument %d)"), argn);
4651 			rw_coercion_warning(argp->gen.datatype,
4652 					    parmp->datatype, buf);
4653                         coerce(argp, parmp->datatype);
4654                 }
4655                 argn++;
4656                 argp  = argp->gen.arglink;
4657                 parmp = parmp->next;
4658         }
4659 
4660         /*
4661          * Note that the argument count mismatch is not an error!
4662          */
4663         if (argp) {
4664                 grad_log_loc(GRAD_LOG_ERR, &locus,
4665 			     _("too many arguments in call to %s"),
4666 			     fun->name);
4667 		errcnt++;
4668         } else if (parmp) {
4669                 grad_log_loc(GRAD_LOG_ERR, &locus,
4670 			     _("too few arguments in call to %s"),
4671 			     fun->name);
4672 		errcnt++;
4673         }
4674 
4675         call = (CALL_MTX*) mtx_alloc(Call);
4676         mtx_append((MTX*)call);
4677 
4678         call->datatype = fun->rettype;
4679         call->fun  = fun;
4680         call->args = args;
4681         call->nargs = argn;
4682 
4683         return (MTX*) call;
4684 }
4685 
4686 MTX *
mtx_builtin(builtin_t * bin,MTX * args)4687 mtx_builtin(builtin_t *bin, MTX *args)
4688 {
4689         MTX          *argp;
4690         BTIN_MTX     *call;
4691         int          argn;
4692         char         *parmp;
4693         grad_data_type_t     type;
4694         /*
4695          * Test the number and types of arguments. Insert reasonable
4696          * typecasts.
4697          */
4698         argn = 0;
4699         argp = args;
4700         parmp = bin->parms;
4701 
4702         while (argp && parmp) {
4703                 switch (parmp[0]) {
4704                 case 'i':
4705                         type = Integer;
4706                         break;
4707                 case 's':
4708                         type = String;
4709                         break;
4710                 default:
4711                         grad_insist_fail("malformed builtin");
4712                 }
4713 
4714                 if (argp->gen.datatype != type) {
4715 			char buf[24];
4716 			snprintf(buf, sizeof buf, _("(argument %d)"), argn);
4717 			rw_coercion_warning(argp->gen.datatype, type, buf);
4718                         coerce(argp, type);
4719                 }
4720                 argn++;
4721                 argp  = argp->gen.arglink;
4722                 parmp++;
4723         }
4724 
4725         if (argp) {
4726                 grad_log_loc(GRAD_LOG_ERR, &locus,
4727 			     _("too many arguments in call to %s"),
4728 			     bin->name);
4729                 errcnt++;
4730         } else if (*parmp) {
4731                 grad_log_loc(GRAD_LOG_ERR, &locus,
4732 			     _("too few arguments in call to %s"),
4733 			     bin->name);
4734                 errcnt++;
4735         }
4736 
4737         call = (BTIN_MTX*) mtx_alloc(Builtin);
4738         mtx_append((MTX*)call);
4739 
4740         call->datatype = bin->rettype;
4741         call->fun  = bin->handler;
4742         call->args = args;
4743         call->nargs = argn;
4744 
4745         return (MTX*) call;
4746 }
4747 
4748 
4749 /* ****************************************************************************
4750  * Code optimizer (rudimentary)
4751  */
4752 
4753 const char *
datatype_str_nom(grad_data_type_t type)4754 datatype_str_nom(grad_data_type_t type)
4755 {
4756         switch (type) {
4757         case Undefined:
4758                 return _("Undefined");
4759         case Integer:
4760                 return _("integer");
4761         case String:
4762                 return _("string");
4763         default:
4764                 return _("UNKNOWN");
4765         }
4766 }
4767 
4768 const char *
datatype_str_abl(grad_data_type_t type)4769 datatype_str_abl(grad_data_type_t type)
4770 {
4771         switch (type) {
4772         case Undefined:
4773                 return _("from Undefined");
4774         case Integer:
4775                 return _("from integer");
4776         case String:
4777                 return _("from string");
4778         default:
4779                 return _("from UNKNOWN");
4780         }
4781 }
4782 
4783 const char *
datatype_str_acc(grad_data_type_t type)4784 datatype_str_acc(grad_data_type_t type)
4785 {
4786         switch (type) {
4787         case Undefined:
4788                 return _("to Undefined");
4789         case Integer:
4790                 return _("to integer");
4791         case String:
4792                 return _("to string");
4793         default:
4794                 return _("to UNKNOWN");
4795         }
4796 }
4797 
4798 FILE *
debug_open_file()4799 debug_open_file()
4800 {
4801         FILE *fp;
4802         char *path;
4803 
4804         path = grad_mkfilename(grad_log_dir, "radius.mtx");
4805         if ((fp = fopen(path, "a")) == NULL) {
4806                 grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
4807                          _("can't open file `%s'"),
4808                          path);
4809         }
4810         grad_free(path);
4811         return fp;
4812 }
4813 
4814 #if defined(MAINTAINER_MODE)
4815 
4816 static void debug_print_datum(FILE *fp, grad_data_type_t type,  grad_datum_t *datum);
4817 static void debug_print_var(FILE *fp, VAR *var);
4818 static void debug_print_unary(FILE *fp, UN_MTX *mtx);
4819 static void debug_print_binary(FILE *fp, BIN_MTX *mtx);
4820 static void debug_print_mtxlist();
4821 
4822 static char *b_opstr[] = {
4823         "Eq",
4824         "Ne",
4825         "Lt",
4826         "Le",
4827         "Gt",
4828         "Ge",
4829         "&",
4830         "^",
4831         "|",
4832         "And",
4833         "Or",
4834         "Shl",
4835         "Shr",
4836         "Add",
4837         "Sub",
4838         "Mul",
4839         "Div",
4840         "Rem",
4841 };
4842 
4843 static char *u_opstr[] = {
4844         "Neg",
4845         "Not"
4846 };
4847 
4848 #define LINK(m) (m ? m->gen.id : 0)
4849 
4850 void
debug_print_datum(FILE * fp,grad_data_type_t type,grad_datum_t * datum)4851 debug_print_datum(FILE *fp, grad_data_type_t type, grad_datum_t *datum)
4852 {
4853         fprintf(fp, "%3.3s ", datatype_str_nom(type));
4854         switch (type) {
4855         case Integer:
4856                 fprintf(fp, "%d", datum->ival);
4857                 break;
4858 
4859         case String:
4860                 fprintf(fp, "%s", datum->sval);
4861 		break;
4862 
4863 	default:
4864 		grad_insist_fail("unknown data type");
4865         }
4866 }
4867 
4868 void
debug_print_var(FILE * fp,VAR * var)4869 debug_print_var(FILE *fp, VAR *var)
4870 {
4871         fprintf(fp, "%3.3s %s L:%d S:%d",
4872                 datatype_str_nom(var->datatype),
4873                 var->name,
4874                 var->level,
4875                 var->offset);
4876         if (var->constant) {
4877                 fprintf(fp, "CONST ");
4878                 debug_print_datum(fp, var->datatype, &var->datum);
4879         }
4880 }
4881 
4882 void
debug_print_unary(FILE * fp,UN_MTX * mtx)4883 debug_print_unary(FILE *fp, UN_MTX *mtx)
4884 {
4885         fprintf(fp, "OP:%s M:%d",
4886                 u_opstr[mtx->opcode], LINK(mtx->arg));
4887 }
4888 
4889 void
debug_print_binary(FILE * fp,BIN_MTX * mtx)4890 debug_print_binary(FILE *fp, BIN_MTX *mtx)
4891 {
4892         fprintf(fp, "OP:%s M1:%d M2:%d",
4893                 b_opstr[mtx->opcode],
4894                 LINK(mtx->arg[0]),
4895                 LINK(mtx->arg[1]));
4896 }
4897 
4898 
4899 void
debug_print_mtxlist(char * s)4900 debug_print_mtxlist(char *s)
4901 {
4902         FILE *fp;
4903         MTX  *mtx, *tmp;
4904 
4905         if ((fp = debug_open_file()) == NULL)
4906                 return;
4907 
4908         #define CASE(c) case c: fprintf(fp, "%-10.10s", #c);
4909 
4910         fprintf(fp, "%s\n", s);
4911         for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
4912                 fprintf(fp, "%4d: %4d %4d ",
4913                         mtx->gen.id,
4914                         LINK(mtx->gen.prev),
4915                         LINK(mtx->gen.next));
4916                 switch (mtx->gen.type) {
4917                 CASE (Generic)
4918                         break;
4919                 CASE (Nop)
4920                         break;
4921                 CASE (Enter)
4922                         fprintf(fp, "%3.3s %d",
4923                                 "",
4924                                 mtx->frame.stacksize);
4925                         break;
4926                 CASE (Leave)
4927                         fprintf(fp, "%3.3s %d",
4928                                 "",
4929                                 mtx->frame.stacksize);
4930                         break;
4931                 CASE (Stop)
4932                         break;
4933                 CASE (Constant)
4934                         debug_print_datum(fp, mtx->cnst.datatype,
4935                                           &mtx->cnst.datum);
4936                         break;
4937                 CASE (Matchref)
4938                         fprintf(fp, "%3.3s %d",
4939                                 datatype_str_nom(String),
4940                                 mtx->ref.num);
4941                         break;
4942                 CASE (Variable)
4943                         debug_print_var(fp, mtx->var.var);
4944                         break;
4945                 CASE (Unary)
4946                         fprintf(fp, "%3.3s ", datatype_str_nom(mtx->gen.datatype));
4947                         debug_print_unary(fp, &mtx->un);
4948                         break;
4949                 CASE (Binary)
4950                         fprintf(fp, "%3.3s ", datatype_str_nom(mtx->gen.datatype));
4951                         debug_print_binary(fp, &mtx->bin);
4952                         break;
4953                 CASE (Cond)
4954                         fprintf(fp, "%3.3s ", "");
4955                         fprintf(fp, "C:%4d T:%4d F:%4d",
4956                                 LINK(mtx->cond.expr),
4957                                 LINK(mtx->cond.if_true),
4958                                 LINK(mtx->cond.if_false));
4959                         break;
4960                 CASE (Asgn)
4961                         fprintf(fp, "%3.3s ",
4962                                 datatype_str_nom(mtx->gen.datatype));
4963                         fprintf(fp, "V:%s,%d,%d M:%4d",
4964                                 mtx->asgn.lval->name,
4965                                 mtx->asgn.lval->level,
4966                                 mtx->asgn.lval->offset,
4967                                 LINK(mtx->asgn.arg));
4968                                 break;
4969                 CASE (Match)
4970                         fprintf(fp, "    N:%1d M:%4d RX:%p",
4971                                 mtx->match.negated,
4972                                 LINK(mtx->match.arg),
4973                                 mtx->match.rx);
4974                         break;
4975                 CASE (Coercion)
4976                         fprintf(fp, "%3.3s M:%4d",
4977                                 datatype_str_nom(mtx->coerce.datatype),
4978                                 LINK(mtx->coerce.arg));
4979                         break;
4980                 CASE (Return)
4981                         fprintf(fp, "%3.3s M:%4d",
4982                                 datatype_str_nom(mtx->ret.expr->gen.datatype),
4983                                 LINK(mtx->ret.expr));
4984                         break;
4985                 CASE (Jump)
4986                         fprintf(fp, "%3.3s M:%4d",
4987                                 "",
4988                                 LINK(mtx->jump.dest));
4989                         break;
4990                 CASE (Branch)
4991                         fprintf(fp, "%3.3s M:%4d",
4992                                 mtx->branch.cond ? "NE" : "EQ",
4993                                 LINK(mtx->branch.dest));
4994                         break;
4995                 CASE (Call)
4996                         fprintf(fp, "%3.3s F:%s, A:%d:",
4997                                 datatype_str_nom(mtx->call.datatype),
4998                                 mtx->call.fun->name,
4999                                 mtx->call.fun->nparm);
5000                         for (tmp = mtx->call.args; tmp; tmp = tmp->gen.arglink)
5001                                 fprintf(fp, "%d,", tmp->gen.id);
5002                         break;
5003 
5004                 CASE(Builtin)
5005                         fprintf(fp, "%3.3s F:%p, A:%d:",
5006                                 datatype_str_nom(mtx->btin.datatype),
5007                                 mtx->btin.fun,
5008                                 mtx->btin.nargs);
5009                         for (tmp = mtx->btin.args; tmp; tmp = tmp->gen.arglink)
5010                                 fprintf(fp, "%d,", tmp->gen.id);
5011                         break;
5012 
5013                 CASE (Pop)
5014                         break;
5015 
5016                 CASE (Pusha)
5017                         break;
5018 
5019                 CASE (Popa)
5020                         break;
5021 
5022                 CASE (Attr)
5023                         fprintf(fp, "%3.3s A:%d I:%d",
5024                                 datatype_str_nom(mtx->gen.datatype),
5025                                 mtx->attr.attrno,
5026 				mtx->attr.index ? mtx->attr.index->gen.id : 0);
5027                         break;
5028 
5029                 CASE (Attr_check)
5030                         fprintf(fp, "%3.3s A:%d I:%d",
5031                                 datatype_str_nom(mtx->gen.datatype),
5032                                 mtx->attr.attrno,
5033 				mtx->attr.index ? mtx->attr.index->gen.id : 0);
5034                         break;
5035 
5036                 CASE (Attr_asgn)
5037                         fprintf(fp, "%3.3s A:%d I:%d M:%d",
5038                                 datatype_str_nom(mtx->gen.datatype),
5039                                 mtx->attr.attrno,
5040 				mtx->attr.index ? mtx->attr.index->gen.id : 0,
5041 				LINK(mtx->attr.rval));
5042                         break;
5043 
5044 		CASE (Attr_delete)
5045 			fprintf(fp, "%3.3s A:%d I:%d",
5046 				datatype_str_nom(mtx->gen.datatype),
5047 				mtx->attr.attrno,
5048 				mtx->attr.index ? mtx->attr.index->gen.id : 0);
5049 		        break;
5050 
5051                 default:
5052                         fprintf(fp, "UNKNOWN: %d", mtx->gen.type);
5053                 }
5054                 fprintf(fp, "\n");
5055         }
5056 
5057         fclose(fp);
5058 }
5059 
5060 void
debug_print_function()5061 debug_print_function()
5062 {
5063         FILE      *fp;
5064         PARAMETER *parm;
5065         int        n;
5066 
5067         if ((fp = debug_open_file()) == NULL)
5068                 return;
5069 
5070         fprintf(fp, "FUNCTION: %s\n", function->name);
5071         fprintf(fp, "RETURNS : %s\n", datatype_str_nom(function->rettype));
5072         fprintf(fp, "NPARMS  : %d\n", function->nparm);
5073         fprintf(fp, "PARMS   :\n");
5074 
5075         for (parm = function->parm, n = 0; parm; parm = parm->next, n++)
5076                 fprintf(fp, "    %4d: %s at %4d\n",
5077                         n, datatype_str_nom(parm->datatype),
5078                         parm->offset);
5079 
5080         fclose(fp);
5081 }
5082 
5083 #endif /* MAINTAINER_MODE */
5084 
5085 #if defined(MAINTAINER_MODE)
5086 # define DEBUG_MTX(c) if (GRAD_DEBUG_LEVEL(30)) debug_print_mtxlist(c);
5087 # define DEBUG_FUN()  if (GRAD_DEBUG_LEVEL(25)) debug_print_function();
5088 #else
5089 # define DEBUG_MTX(c)
5090 # define DEBUG_FUN()
5091 #endif
5092 
5093 static void pass1();
5094 static int pass2_unary(MTX *mtx);
5095 static int pass2_binary(MTX *mtx);
5096 
5097 void
pass1()5098 pass1()
5099 {
5100         MTX *mtx;
5101         MTX *end;
5102 
5103         /*
5104          * Create an entry matrix
5105          */
5106         mtx = mtx_alloc(Enter);
5107         rw_list_insert(&mtx_first, &mtx_last, mtx_first, mtx, 1);
5108         mtx->frame.stacksize = function->stack_alloc;
5109 
5110         /*
5111          * Provide a default return statement if necessary
5112          */
5113         if (mtx_last->gen.type != Return) {
5114                 grad_value_t val;
5115                 grad_log_loc(GRAD_LOG_WARN, &mtx_last->gen.loc,
5116 			     _("missing return statement"));
5117 
5118 		val.type = function->rettype;
5119                 switch (function->rettype) {
5120                 case Integer:
5121                         val.datum.ival = 0;
5122                         break;
5123 
5124                 case String:
5125                         val.datum.sval.data = "";
5126 			val.datum.sval.size = 0;
5127 			break;
5128 
5129 		default:
5130 			grad_insist_fail("Unknown data type");
5131                 }
5132                 mtx_const(&val);
5133                 mtx_frame(Leave, function->stack_alloc);
5134         } else {
5135                 mtx_last->gen.type = Leave;
5136                 mtx_last->frame.stacksize = function->stack_alloc;
5137         }
5138 
5139         /*
5140          * Insert a no-op matrix before the `leave' one
5141          */
5142         end = mtx_alloc(Nop);
5143         rw_list_insert(&mtx_first, &mtx_last, mtx_last, end, 1);
5144 
5145         for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
5146                 if (mtx->gen.type == Return) {
5147                         if (mtx->ret.expr->gen.datatype != function->rettype) {
5148 				rw_coercion_warning(
5149 					mtx->ret.expr->gen.datatype,
5150 					function->rettype, NULL);
5151                                 coerce(mtx->ret.expr, function->rettype);
5152                         }
5153                         mtx->gen.type = Jump;
5154                         mtx->jump.dest = end;
5155                 }
5156         }
5157 }
5158 
5159 /*
5160  * Second pass: elimination of constant sub-expressions
5161  */
5162 
5163 /*
5164  * Perform immediate unary calculations
5165  */
5166 int
pass2_unary(MTX * mtx)5167 pass2_unary(MTX *mtx)
5168 {
5169         MTX *arg = mtx->un.arg;
5170 
5171         switch (mtx->un.opcode) {
5172         case Not:
5173                 arg->cnst.datum.ival = !arg->cnst.datum.ival;
5174                 break;
5175 
5176         case Neg:
5177                 arg->cnst.datum.ival = -arg->cnst.datum.ival;
5178                 break;
5179 
5180 	default:
5181 		grad_insist_fail("Unexpected opcode");
5182         }
5183         mtx->gen.type = Constant;
5184         mtx->cnst.datum = arg->cnst.datum;
5185         mtx_remove(arg);
5186         return 0;
5187 }
5188 
5189 /*
5190  * Perform immediate binary computations
5191  */
5192 int
pass2_binary(MTX * mtx)5193 pass2_binary(MTX *mtx)
5194 {
5195         MTX *arg0 = mtx->bin.arg[0];
5196         MTX *arg1 = mtx->bin.arg[1];
5197         grad_datum_t dat;
5198 
5199         switch (mtx->bin.opcode) {
5200         case Eq:
5201                 dat.ival = arg0->cnst.datum.ival == arg1->cnst.datum.ival;
5202                 break;
5203 
5204         case Ne:
5205                 dat.ival = arg0->cnst.datum.ival != arg1->cnst.datum.ival;
5206                 break;
5207 
5208         case Lt:
5209                 dat.ival = arg0->cnst.datum.ival < arg1->cnst.datum.ival;
5210                 break;
5211 
5212         case Le:
5213                 dat.ival = arg0->cnst.datum.ival <= arg1->cnst.datum.ival;
5214                 break;
5215 
5216         case Gt:
5217                 dat.ival = arg0->cnst.datum.ival > arg1->cnst.datum.ival;
5218                 break;
5219 
5220         case Ge:
5221                 dat.ival = arg0->cnst.datum.ival >= arg1->cnst.datum.ival;
5222                 break;
5223 
5224         case BAnd:
5225                 dat.ival = arg0->cnst.datum.ival & arg1->cnst.datum.ival;
5226                 break;
5227 
5228         case BOr:
5229                 dat.ival = arg0->cnst.datum.ival | arg1->cnst.datum.ival;
5230                 break;
5231 
5232         case BXor:
5233                 dat.ival = arg0->cnst.datum.ival ^ arg1->cnst.datum.ival;
5234                 break;
5235 
5236         case And:
5237                 dat.ival = arg0->cnst.datum.ival && arg1->cnst.datum.ival;
5238                 break;
5239 
5240         case Or:
5241                 dat.ival = arg0->cnst.datum.ival || arg1->cnst.datum.ival;
5242                 break;
5243 
5244         case Shl:
5245                 dat.ival = arg0->cnst.datum.ival << arg1->cnst.datum.ival;
5246                 break;
5247 
5248         case Shr:
5249                 dat.ival = arg0->cnst.datum.ival >> arg1->cnst.datum.ival;
5250                 break;
5251 
5252         case Add:
5253                 dat.ival = arg0->cnst.datum.ival + arg1->cnst.datum.ival;
5254                 break;
5255 
5256         case Sub:
5257                 dat.ival = arg0->cnst.datum.ival - arg1->cnst.datum.ival;
5258                 break;
5259 
5260         case Mul:
5261                 dat.ival = arg0->cnst.datum.ival * arg1->cnst.datum.ival;
5262                 break;
5263 
5264         case Div:
5265                 if (arg1->cnst.datum.ival == 0) {
5266                         grad_log_loc(GRAD_LOG_ERR, &arg1->cnst.loc,
5267 				     _("divide by zero"));
5268                         errcnt++;
5269                 } else
5270                         dat.ival =
5271                                 arg0->cnst.datum.ival / arg1->cnst.datum.ival;
5272                 break;
5273 
5274         case Rem:
5275                 if (arg1->cnst.datum.ival == 0) {
5276                         grad_log_loc(GRAD_LOG_ERR, &arg1->cnst.loc,
5277 				     _("divide by zero"));
5278                         errcnt++;
5279                 } else
5280                         dat.ival =
5281                                 arg0->cnst.datum.ival % arg1->cnst.datum.ival;
5282                 break;
5283 
5284 	default:
5285 		grad_insist_fail("Unexpected opcode");
5286         }
5287         mtx->gen.type = Constant;
5288         mtx->cnst.datum = dat;
5289         mtx_remove(arg0);
5290         mtx_remove(arg1);
5291         return 0;
5292 }
5293 
5294 MTX *
mtx_branch(int cond,MTX * target)5295 mtx_branch(int cond, MTX *target)
5296 {
5297         MTX *nop = mtx_alloc(Nop);
5298         MTX *mtx = mtx_alloc(Branch);
5299         mtx_insert(target, nop);
5300         mtx->branch.cond = cond;
5301         mtx->branch.dest = nop;
5302         return mtx;
5303 }
5304 
5305 void
mtx_bool(MTX * mtx)5306 mtx_bool(MTX *mtx)
5307 {
5308         MTX *j_mtx, *p, *p1;
5309 
5310         /* Insert after first operand:
5311 	   popa
5312 	   pusha
5313 	   pusha      ;; Duplicate tos value
5314 	   j?e   L10
5315 	   popa       ;; Pop up the unneded value */
5316 
5317 	p = mtx_alloc(Popa);
5318 	mtx_insert(mtx->bin.arg[0], p);
5319 	p1 = mtx_alloc(Pusha);
5320 	mtx_insert(p, p1);
5321 	p = mtx_alloc(Pusha);
5322 	mtx_insert(p1, p);
5323         j_mtx = mtx_branch(mtx->bin.opcode == Or, mtx);
5324         mtx_insert(p, j_mtx);
5325 	p1 = mtx_alloc(Popa);
5326 	mtx_insert(j_mtx, p1);
5327         /* Remove the op matrix
5328 	   Note that the mtx->cond.expr is not correct after this
5329 	   operation, but this does not affect the functionality */
5330         mtx_remove(mtx);
5331 }
5332 
5333 /*
5334  * Second optimization pass: immediate computations
5335  */
5336 int
pass2()5337 pass2()
5338 {
5339         MTX *mtx, *next;
5340         int optcnt;
5341         int errcnt = 0;
5342 
5343         do {
5344                 optcnt = 0;
5345                 mtx = mtx_first;
5346                 while (mtx) {
5347                         next = mtx->gen.next;
5348                         switch (mtx->gen.type) {
5349                         case Unary:
5350                                 if (mtx->un.arg->gen.type != Constant)
5351                                         break;
5352                                 if (pass2_unary(mtx))
5353                                         errcnt++;
5354                                 else
5355                                         optcnt++;
5356                                 break;
5357 
5358                         case Binary:
5359                                 if (mtx->bin.arg[0]->gen.type == Constant
5360 				    && mtx->bin.arg[1]->gen.type == Constant) {
5361                                         switch (mtx->bin.datatype) {
5362                                         case Integer:
5363                                                 if (pass2_binary(mtx))
5364                                                         errcnt++;
5365                                                 else
5366                                                         optcnt++;
5367                                                 break;
5368 
5369                                         case String:
5370                                                 /*NO STRING OPS SO FAR */;
5371 					        break;
5372 
5373 					default:
5374 						grad_insist_fail("Unknown data type");
5375                                         }
5376                                 } else if (mtx->bin.opcode == And
5377 					   || mtx->bin.opcode == Or) {
5378                                         mtx_bool(mtx);
5379                                 }
5380                                 break;
5381                                 /*FIXME: ADD `if (1)'/`if 0' evaluation */
5382                         case Jump:
5383                                 if (mtx->jump.dest == mtx->jump.next)
5384                                         mtx_remove(mtx);
5385 				break;
5386 
5387 			case Attr:
5388 			case Attr_asgn:
5389 			case Attr_check:
5390 			case Attr_delete:
5391 				/*FIXME: the rw_attr.0 functions should
5392 				  expect an immediate value after the
5393 				  attribute number */
5394 				break;
5395 
5396 			default:
5397 				break;
5398                         }
5399                         mtx = next;
5400                 }
5401         } while (errcnt == 0 && optcnt > 0);
5402         return errcnt;
5403 }
5404 
5405 int
optimize()5406 optimize()
5407 {
5408         DEBUG_FUN();
5409         DEBUG_MTX("on entry to optimize");
5410         pass1();
5411         DEBUG_MTX("after first pass");
5412         if (pass2())
5413                 return -1;
5414         DEBUG_MTX("after second pass (immediate computations)");
5415         return 0;
5416 }
5417 
5418 
5419 /* ****************************************************************************
5420  * Code generator
5421  */
5422 
5423 
5424 static INSTR *rw_code;          /* Code segment */
5425 static pctr_t rw_pc;            /* PC when compiling the code */
5426 static size_t rw_codesize;      /* Length of code segment */
5427 
5428 void
code_check()5429 code_check()
5430 {
5431         if (rw_code == NULL) {
5432                 rw_codesize  = 4096;
5433                 rw_code  = grad_emalloc(rw_codesize * sizeof(rw_code[0]));
5434         }
5435 }
5436 
5437 void
code_init()5438 code_init()
5439 {
5440 	code_check();
5441         /* code cell #0 is the default return address */
5442 	rw_code[0] = 0;
5443 	rw_pc = 1;
5444 }
5445 
5446 #if defined(MAINTAINER_MODE)
5447 void
debug_dump_code()5448 debug_dump_code()
5449 {
5450         FILE    *fp;
5451         pctr_t  pc;
5452         int     i;
5453 
5454         if ((fp = debug_open_file()) == NULL)
5455                 return;
5456         fprintf(fp, "Code size: %d\n", rw_codesize);
5457         fprintf(fp, "Code dump:\n");
5458 
5459         pc = 0;
5460         do {
5461                 fprintf(fp, "%4d:", pc);
5462                 for (i = 0; i < 8 && pc < rw_codesize; i++, pc++)
5463                         fprintf(fp, " %8x", (u_int) rw_code[pc]);
5464                 fprintf(fp, "\n");
5465         } while (pc < rw_codesize);
5466 
5467         fclose(fp);
5468 }
5469 #endif
5470 /*
5471  * Runtime function prototypes
5472  */
5473 static int pushn(RWSTYPE n);
5474 static int cpopn(RWSTYPE *np);
5475 static RWSTYPE popn();
5476 static void checkpop(int cnt);
5477 static void pushref(char *str, int from, int to);
5478 static RWSTYPE *heap_reserve(int size);
5479 static void pushs(RWSTYPE *sptr, size_t size, int len);
5480 static void pushstr(const char *str, int len);
5481 
5482 static void rw_pushn();
5483 static void rw_pushs();
5484 static void rw_pushref();
5485 static void rw_pushv();
5486 static void rw_i2s();
5487 static void rw_s2i();
5488 static void rw_eq();
5489 static void rw_ne();
5490 static void rw_lt();
5491 static void rw_le();
5492 static void rw_gt();
5493 static void rw_ge();
5494 static void rw_eqs();
5495 static void rw_nes();
5496 static void rw_lts();
5497 static void rw_les();
5498 static void rw_gts();
5499 static void rw_ges();
5500 static void rw_b_xor();
5501 static void rw_b_and();
5502 static void rw_b_or();
5503 static void rw_shl();
5504 static void rw_shr();
5505 static void rw_add();
5506 static void rw_sub();
5507 static void rw_mul();
5508 static void rw_div();
5509 static void rw_rem();
5510 static void rw_not();
5511 static void rw_neg();
5512 static void rw_asgn();
5513 static void rw_enter();
5514 static void rw_leave();
5515 static void rw_match();
5516 static void rw_jmp();
5517 static void rw_jne();
5518 static void rw_je();
5519 static void rw_adds();
5520 static void rw_adjstk();
5521 static void rw_popn();
5522 static void rw_pusha();
5523 static void rw_popa();
5524 static void rw_call();
5525 static void rw_builtin();
5526 static void rw_attrs();
5527 static void rw_attrs0();
5528 static void rw_attrn();
5529 static void rw_attrn0();
5530 static void rw_attrcheck();
5531 static void rw_attrcheck0();
5532 static void rw_attrasgn();
5533 static void rw_attrasgn0();
5534 static void rw_attr_delete();
5535 static void rw_attr_delete0();
5536 
5537 INSTR bin_codetab[] = {
5538         rw_eq,
5539         rw_ne,
5540         rw_lt,
5541         rw_le,
5542         rw_gt,
5543         rw_ge,
5544         rw_b_and,
5545         rw_b_xor,
5546         rw_b_or,
5547         NULL,
5548         NULL,
5549         rw_shl,
5550         rw_shr,
5551         rw_add,
5552         rw_sub,
5553         rw_mul,
5554         rw_div,
5555         rw_rem,
5556 };
5557 
5558 INSTR bin_string_codetab[] = {
5559         rw_eqs,
5560         rw_nes,
5561         rw_lts,
5562         rw_les,
5563         rw_gts,
5564         rw_ges,
5565         NULL,
5566         NULL,
5567         NULL,
5568         NULL,
5569         NULL,
5570         NULL,
5571         NULL,
5572         rw_adds,
5573         NULL,
5574         NULL,
5575         NULL,
5576         NULL
5577 };
5578 
5579 INSTR coerce_tab[Max_datatype][Max_datatype] = {
5580 /*                Undefined  Integer  String */
5581 /* Undefined */ {  NULL,      NULL,    NULL   },
5582 /* Integer */   {  NULL,      NULL,    rw_i2s },
5583 /* String */    {  NULL,      rw_s2i,  NULL   },
5584 };
5585 
5586 static void check_codesize(int delta);
5587 static int  code(INSTR instr);
5588 static int  data(int val);
5589 static int data_str(char *ptr);
5590 static void add_target(NOP_MTX *mtx, pctr_t pc);
5591 
5592 
5593 void
add_target(NOP_MTX * mtx,pctr_t pc)5594 add_target(NOP_MTX *mtx, pctr_t pc)
5595 {
5596         TGT_MTX *tgt = (TGT_MTX *)mtx_alloc(Target);
5597         tgt->next = (MTX*)mtx->tgt;
5598         mtx->tgt = tgt;
5599         tgt->pc = pc;
5600 }
5601 
5602 void
fixup_target(NOP_MTX * mtx,pctr_t pc)5603 fixup_target(NOP_MTX *mtx, pctr_t pc)
5604 {
5605         TGT_MTX   *tgt;
5606 
5607         for (tgt = (TGT_MTX*)mtx->tgt; tgt; tgt = (TGT_MTX*)tgt->next)
5608                 rw_code[tgt->pc] = (INSTR)pc;
5609         mtx->tgt = NULL;
5610 }
5611 
5612 pctr_t
codegen()5613 codegen()
5614 {
5615         MTX       *mtx;
5616 
5617         function->entry = rw_pc;
5618         for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
5619                 switch (mtx->gen.type) {
5620                 case Generic:
5621                 case Return:
5622                 default:
5623                         grad_log(GRAD_LOG_CRIT,
5624                                  "INTERNAL ERROR: codegen stumbled accross generic matrix!");
5625                         errcnt++;
5626                         return 0;
5627                 case Nop:
5628                         /* Fix-up the references */
5629                         fixup_target(&mtx->nop, rw_pc);
5630                         mtx->nop.pc = rw_pc;
5631                         break;
5632                 case Stop:
5633                         break;
5634                 case Enter:
5635                         code(rw_enter);
5636                         data(mtx->frame.stacksize);
5637                         break;
5638                 case Leave:
5639                         code(rw_leave);
5640                         break;
5641                 case Constant:
5642                         switch (mtx->cnst.datatype) {
5643                         case Integer:
5644                                 code(rw_pushn);
5645                                 data(mtx->cnst.datum.ival);
5646                                 break;
5647 
5648                         case String:
5649                                 code(rw_pushs);
5650                                 data_str(mtx->cnst.datum.sval.data);
5651                                 break;
5652 
5653 			default:
5654 				grad_insist_fail("Unknown data type");
5655                         }
5656                         break;
5657                 case Matchref:
5658                         code(rw_pushref);
5659                         data(mtx->ref.num);
5660                         break;
5661                 case Variable:
5662                         /* Variable dereference.
5663                          */
5664                         code(rw_pushv);
5665                         data(mtx->var.var->offset);
5666                         break;
5667                 case Unary:
5668                         switch (mtx->un.opcode) {
5669                         case Not:
5670                                 code(rw_not);
5671                                 break;
5672 
5673                         case Neg:
5674                                 code(rw_neg);
5675                                 break;
5676 
5677 			default:
5678 				grad_insist_fail("Unexpected opcode");
5679                         }
5680                         break;
5681                 case Binary:
5682                         if (mtx->bin.arg[0]->gen.datatype == String)
5683                                 code(bin_string_codetab[mtx->bin.opcode]);
5684                         else
5685                                 code(bin_codetab[mtx->bin.opcode]);
5686                         break;
5687                 case Cond:
5688                         /*FIXME: this needs optimization */
5689                         code(rw_jne);
5690                         add_target(&mtx->cond.if_true->nop, rw_pc);
5691                         code(NULL);
5692                         if (mtx->cond.if_false) {
5693                                 code(rw_jmp);
5694                                 add_target(&mtx->cond.if_false->nop, rw_pc);
5695                                 code(NULL);
5696                         }
5697                         break;
5698 
5699                 case Asgn:
5700                         code(rw_asgn);
5701                         data(mtx->asgn.lval->offset);
5702                         break;
5703 
5704                 case Match:
5705                         code(rw_match);
5706                         code((INSTR)mtx->match.rx);
5707                         if (mtx->match.negated)
5708                                 code(rw_not);
5709                         break;
5710 
5711                 case Coercion:
5712                         code(coerce_tab[mtx->coerce.arg->gen.datatype][mtx->coerce.datatype]);
5713                         break;
5714 
5715                 case Jump:
5716                         code(rw_jmp);
5717                         add_target(&mtx->jump.dest->nop, rw_pc);
5718                         code(NULL);
5719                         break;
5720 
5721                 case Branch:
5722                         code(mtx->branch.cond ? rw_jne : rw_je);
5723                         add_target(&mtx->branch.dest->nop, rw_pc);
5724                         code(NULL);
5725                         break;
5726 
5727                 case Call:
5728                         code(rw_call);
5729                         code((INSTR) mtx->call.fun->entry);
5730                         code(rw_adjstk);
5731                         data(mtx->call.nargs);
5732                         break;
5733 
5734                 case Builtin:
5735                         code(rw_builtin);
5736                         code(mtx->btin.fun);
5737                         code(rw_adjstk);
5738                         data(mtx->btin.nargs);
5739                         break;
5740 
5741                 case Pop:
5742                         code(rw_popn);
5743                         break;
5744 
5745                 case Popa:
5746                         code(rw_popa);
5747                         break;
5748 
5749                 case Pusha:
5750                         code(rw_pusha);
5751                         break;
5752 
5753                 case Attr:
5754                         switch (mtx->attr.datatype) {
5755                         case Integer:
5756 				if (mtx->attr.index)
5757 					code(rw_attrn);
5758 				else
5759 					code(rw_attrn0);
5760                                 break;
5761 
5762                         case String:
5763 				if (mtx->attr.index)
5764 					code(rw_attrs);
5765 				else
5766 					code(rw_attrs0);
5767                                 break;
5768 
5769 			default:
5770 				grad_insist_fail("Unknown data type");
5771                         }
5772                         data(mtx->attr.attrno);
5773                         break;
5774 
5775                 case Attr_check:
5776 			if (mtx->attr.index)
5777 				code(rw_attrcheck);
5778 			else
5779 				code(rw_attrcheck0);
5780                         data(mtx->attr.attrno);
5781                         break;
5782 
5783                 case Attr_asgn:
5784 			if (mtx->attr.index)
5785 				code(rw_attrasgn);
5786 			else
5787 				code(rw_attrasgn0);
5788                         data(mtx->attr.attrno);
5789                         break;
5790 
5791 		case Attr_delete:
5792 			if (mtx->attr.index)
5793 				code(rw_attr_delete);
5794 			else
5795 				code(rw_attr_delete0);
5796 			data(mtx->attr.attrno);
5797 			break;
5798                 }
5799         }
5800 
5801         /*
5802          * Second pass: fixup backward references
5803          */
5804         for (mtx = mtx_first; mtx; mtx = mtx->gen.next) {
5805                 if (mtx->gen.type == Nop)
5806                         fixup_target(&mtx->nop, mtx->nop.pc);
5807         }
5808 
5809 #if defined(MAINTAINER_MODE)
5810         if (GRAD_DEBUG_LEVEL(25)) {
5811                 FILE *fp = debug_open_file();
5812                 fprintf(fp, "entry: %d, size %d\n",
5813                         function->entry, rw_pc - function->entry);
5814                 fclose(fp);
5815         }
5816 #endif
5817         return function->entry;
5818 }
5819 
5820 void
check_codesize(int delta)5821 check_codesize(int delta)
5822 {
5823         if (rw_pc + delta >= rw_codesize) {
5824                 INSTR *p = grad_emalloc((rw_codesize + 4096) * sizeof(rw_code[0]));
5825                 memcpy(p, rw_code, rw_codesize * sizeof(rw_code[0]));
5826                 grad_free(rw_code);
5827                 rw_code = p;
5828                 rw_codesize += 4096;
5829         }
5830 }
5831 
5832 int
code(INSTR instr)5833 code(INSTR instr)
5834 {
5835         check_codesize(1);
5836         rw_code[rw_pc] = instr;
5837         return rw_pc++;
5838 }
5839 
5840 int
data(int val)5841 data(int val)
5842 {
5843         return code((INSTR)(RWSTYPE)val);
5844 }
5845 
5846 int
data_str(char * ptr)5847 data_str(char *ptr)
5848 {
5849         int  len   = strlen(ptr) + 1;
5850         RWSTYPE delta = (len + sizeof(rw_code[0])) / sizeof(rw_code[0]);
5851 
5852         check_codesize(delta+1);
5853         rw_code[rw_pc++] = (INSTR)delta;
5854         memcpy(rw_code + rw_pc, ptr, len);
5855         rw_pc += delta;
5856         return rw_pc;
5857 }
5858 
5859 
5860 /* ****************************************************************************
5861  * Regular expressions
5862  */
5863 
5864 COMP_REGEX *
rx_alloc(regex_t * regex,int nmatch)5865 rx_alloc(regex_t *regex, int nmatch)
5866 {
5867         COMP_REGEX *rx;
5868 
5869         rx = grad_emalloc(sizeof(*rx));
5870         rx->regex  = *regex;
5871         rx->nmatch = nmatch;
5872         rw_list_insert(&function->rx_list, NULL, function->rx_list, rx, 1);
5873         return rx;
5874 }
5875 
5876 void
rx_free(COMP_REGEX * rx)5877 rx_free(COMP_REGEX *rx)
5878 {
5879         COMP_REGEX *next;
5880 
5881         while (rx) {
5882                 next = rx->next;
5883                 regfree(&rx->regex);
5884                 grad_free(rx);
5885                 rx = next;
5886         }
5887 }
5888 
5889 COMP_REGEX *
compile_regexp(char * str)5890 compile_regexp(char *str)
5891 {
5892         char     *p;
5893         regex_t  regex;
5894         int      nmatch;
5895 
5896         int rc = regcomp(&regex, str, regcomp_flags);
5897         if (rc) {
5898                 char errbuf[512];
5899                 regerror(rc, &regex, errbuf, sizeof(errbuf));
5900                 grad_log_loc(GRAD_LOG_ERR, &locus,
5901 			     _("regexp error: %s"),
5902 			     errbuf);
5903                 return NULL;
5904         }
5905         /* count the number of matches */
5906         nmatch = 0;
5907         for (p = str; *p; ) {
5908                 if (*p == '\\')
5909                         if (p[1] == '(') {
5910                                 nmatch++;
5911                                 p += 2;
5912                                 continue;
5913                         }
5914                 p++;
5915         }
5916 
5917         return rx_alloc(&regex, nmatch);
5918 }
5919 
5920 void
function_delete()5921 function_delete()
5922 {
5923         if (function) {
5924                 grad_symtab_delete(rewrite_tab, (grad_symbol_t*)function);
5925                 function_cleanup();
5926         }
5927 }
5928 
5929 void
function_cleanup()5930 function_cleanup()
5931 {
5932         function = NULL;
5933 }
5934 
5935 
5936 /* ****************************************************************************
5937  * Runtime functions
5938  */
5939 
5940 /*
5941  * Push a number on stack
5942  */
5943 int
pushn(RWSTYPE n)5944 pushn(RWSTYPE n)
5945 {
5946         if (mach.st >= mach.ht) {
5947                 /*FIXME: gc();*/
5948                 GRAD_DEBUG2(1, "st=%d, ht=%d", mach.st, mach.ht);
5949                 rw_error(_("out of pushdown space"));
5950         }
5951         mach.stack[mach.st++] = n;
5952         return 0;
5953 }
5954 
5955 /*
5956  * Push a string on stack
5957  */
5958 void
pushs(RWSTYPE * sptr,size_t size,int len)5959 pushs(RWSTYPE *sptr, size_t size, int len)
5960 {
5961 	if (mach.ht - len - 1 <= mach.st) {
5962                 /* Heap overrun: */
5963                 /*gc(); */
5964                 rw_error(_("heap overrun"));
5965         }
5966 
5967         while (len)
5968                 mach.stack[mach.ht--] = sptr[--len];
5969 	mach.stack[mach.ht--] = size;
5970         pushn((RWSTYPE) (mach.stack + mach.ht + 1));
5971 }
5972 
5973 void
pushstr(const char * str,int len)5974 pushstr(const char *str, int len)
5975 {
5976         RWSTYPE *p = heap_reserve(sizeof(RWSTYPE) + len + 1);
5977 	char *s = (char*)(p + 1);
5978         memcpy(s, str, len);
5979         s[len] = 0;
5980 	p[0] = len;
5981         pushn((RWSTYPE)p);
5982 }
5983 
5984 #define B2RW(s) (s + sizeof(mach.stack[0]) - 1) / sizeof(mach.stack[0])
5985 
5986 RWSTYPE *
heap_reserve(int size)5987 heap_reserve(int size)
5988 {
5989 	size_t words = B2RW(size);
5990 
5991         if (mach.ht - words <= mach.st) {
5992                 /* Heap overrun: */
5993                 gc();
5994                 if (mach.ht - words <= mach.st)
5995                         rw_error(_("heap overrun"));
5996         }
5997         mach.ht -= words;
5998         return mach.stack + mach.ht--;
5999 }
6000 
6001 
6002 /* Temporary space functions */
6003 char *
temp_space_create()6004 temp_space_create()
6005 {
6006 	return (char*)(mach.stack + mach.st);
6007 }
6008 
6009 size_t
temp_space_size()6010 temp_space_size()
6011 {
6012 	return (mach.ht - mach.st)*sizeof(mach.stack[0]);
6013 }
6014 
6015 void
temp_space_copy(char ** baseptr,char * text,size_t size)6016 temp_space_copy(char **baseptr, char *text, size_t size)
6017 {
6018         size_t len = (size + sizeof(mach.stack[0])) / sizeof(mach.stack[0]);
6019 	if (*baseptr + len >= (char*)(mach.stack + mach.ht))
6020 		rw_error(_("out of heap space"));
6021 	memcpy(*baseptr, text, size);
6022 	*baseptr += size;
6023 }
6024 
6025 RWSTYPE *
temp_space_fix(char * end)6026 temp_space_fix(char *end)
6027 {
6028 	size_t len, size;
6029 	char *base = (char*)(mach.stack + mach.st);
6030 
6031 	temp_space_copy(&end, "", 0);
6032 	size = end - base;
6033 	len = B2RW(size);
6034         mach.ht -= len;
6035 	memmove(mach.stack + mach.ht, base, size);
6036 	mach.stack[--mach.ht] = strlen(base);
6037         return mach.stack + mach.ht--;
6038 }
6039 
6040 
6041 /*
6042  * Pop number from stack and store into NP.
6043  */
6044 int
cpopn(RWSTYPE * np)6045 cpopn(RWSTYPE *np)
6046 {
6047         if (mach.st <= 0) {
6048                 rw_error(_("out of popup"));
6049         }
6050         *np = mach.stack[--mach.st];
6051         return 0;
6052 }
6053 
6054 /*
6055  * Pop the number from stack without error checking. checkpop() function
6056  * should be called before calling this one.
6057  */
6058 RWSTYPE
popn()6059 popn()
6060 {
6061         return mach.stack[--mach.st];
6062 }
6063 
6064 void
mem2string(grad_string_t * p,RWSTYPE * loc)6065 mem2string(grad_string_t *p, RWSTYPE *loc)
6066 {
6067 	p->size = loc[0];
6068 	p->data = (unsigned char*) (loc + 1);
6069 }
6070 
6071 void
poparr(grad_string_t * p)6072 poparr(grad_string_t *p)
6073 {
6074 	mem2string(p, (RWSTYPE*) popn());
6075 }
6076 
6077 RWSTYPE
tos()6078 tos()
6079 {
6080         return mach.stack[mach.st-1];
6081 }
6082 
6083 /*
6084  * Check if the stack contains at list CNT elements.
6085  */
6086 void
checkpop(int cnt)6087 checkpop(int cnt)
6088 {
6089         if (mach.st < cnt)
6090 		rw_error(_("out of popup"));
6091 }
6092 
6093 /*
6094  * Push a backreference value on stack.
6095  * Arguments: str     --    input string
6096  *            from    --    start of reference in string
6097  *            to      --    end of reference in string
6098  */
6099 void
pushref(char * str,int from,int to)6100 pushref(char *str, int from, int to)
6101 {
6102 	pushstr(str + from, to - from);
6103 }
6104 
6105 /*
6106  * Create a stack frame and enter the function
6107  */
6108 void
enter(int n)6109 enter(int n)
6110 {
6111         pushn(mach.sb);
6112         mach.sb = mach.st;
6113         mach.st += n;
6114 }
6115 
6116 /*
6117  * Destroy the stack frame and leave the function
6118  */
6119 void
leave()6120 leave()
6121 {
6122         /* Save return value */
6123         mach.rA = popn();
6124         /* Restore stack frame */
6125         mach.st = mach.sb;
6126         mach.sb = popn();
6127         mach.pc = (pctr_t) popn();
6128 }
6129 
6130 RWSTYPE
getarg(int num)6131 getarg(int num)
6132 {
6133         return mach.stack[mach.sb - (STACK_BASE + num)];
6134 }
6135 
6136 
6137 /* ****************************************************************************
6138  * Instructions
6139  */
6140 
6141 static int
rw_error(const char * msg)6142 rw_error(const char *msg)
6143 {
6144         grad_log(GRAD_LOG_ERR,
6145 	         "%s: %s",
6146                  _("rewrite runtime error"), msg);
6147         longjmp(mach.jmp, 1);
6148         /*NOTREACHED*/
6149 }
6150 
6151 static int
rw_error_free(char * msg)6152 rw_error_free(char *msg)
6153 {
6154         grad_log(GRAD_LOG_ERR,
6155 	         "%s: %s",
6156                  _("rewrite runtime error"), msg);
6157 	free(msg);
6158         longjmp(mach.jmp, 1);
6159         /*NOTREACHED*/
6160 }
6161 
6162 void
rw_call()6163 rw_call()
6164 {
6165         pctr_t  pc = (pctr_t) rw_code[mach.pc++];
6166         pushn(mach.pc); /* save return address */
6167         mach.pc = pc;
6168 }
6169 
6170 void
rw_adjstk()6171 rw_adjstk()
6172 {
6173         int delta = (int) rw_code[mach.pc++];
6174         mach.st -= delta;
6175         pushn(mach.rA);   /* Push the return back on stack */
6176 }
6177 
6178 void
rw_enter()6179 rw_enter()
6180 {
6181         /*FIXME: runtime checking */
6182         int n = (int) rw_code[mach.pc++];
6183         enter(n);
6184 }
6185 
6186 void
rw_leave()6187 rw_leave()
6188 {
6189         leave();
6190 }
6191 
6192 /*
6193  * Push a number on stack
6194  */
6195 void
rw_pushn()6196 rw_pushn()
6197 {
6198         RWSTYPE n = (RWSTYPE) rw_code[mach.pc++];
6199         pushn(n);
6200 }
6201 
6202 /*
6203  * Push a reference value on stack
6204  */
6205 void
rw_pushref()6206 rw_pushref()
6207 {
6208         int i = (int) rw_code[mach.pc++];
6209 
6210         pushref(mach.sA, mach.pmatch[i].rm_so, mach.pmatch[i].rm_eo);
6211 }
6212 
6213 /*
6214  * Push a variable on stack
6215  */
6216 void
rw_pushv()6217 rw_pushv()
6218 {
6219         stkoff_t n = (stkoff_t) rw_code[mach.pc++];
6220 
6221         pushn(mach.stack[mach.sb + n]);
6222 }
6223 
6224 void
rw_pushs()6225 rw_pushs()
6226 {
6227         int   len = (int) rw_code[mach.pc++];
6228         RWSTYPE *sptr = (RWSTYPE*) (rw_code + mach.pc);
6229 
6230         mach.pc += len;
6231         pushs(sptr, strlen((char*)sptr), len);
6232 }
6233 
6234 /*
6235  * Assign a value to a variable
6236  */
6237 void
rw_asgn()6238 rw_asgn()
6239 {
6240         stkoff_t off = (stkoff_t) rw_code[mach.pc++];
6241         RWSTYPE n;
6242 
6243         cpopn(&n);
6244 
6245         mach.stack[mach.sb + off] = n;
6246         pushn(n);
6247 }
6248 
6249 void
assert_request_presence()6250 assert_request_presence()
6251 {
6252 	if (!mach.req)
6253 		rw_error(_("no request supplied"));
6254 }
6255 
6256 /* Check if the A/V pair is supplied in the request
6257  */
6258 void
rw_attrcheck0()6259 rw_attrcheck0()
6260 {
6261         int attr = (int) rw_code[mach.pc++];
6262 
6263 	pushn(grad_avl_find(AVPLIST(&mach), attr) != NULL);
6264 }
6265 
6266 void
rw_attrcheck()6267 rw_attrcheck()
6268 {
6269         int attr = (int) rw_code[mach.pc++];
6270 	RWSTYPE index;
6271 
6272 	cpopn(&index);
6273 	pushn(grad_avl_find_n(AVPLIST(&mach), attr, index) != NULL);
6274 }
6275 
6276 /*
6277  * Assign a value to an A/V pair
6278  */
6279 void
attrasgn_internal(int attr,grad_avp_t * pair,RWSTYPE val)6280 attrasgn_internal(int attr, grad_avp_t *pair, RWSTYPE val)
6281 {
6282 	grad_string_t str;
6283 
6284 	assert_request_presence();
6285 	if (!pair) {
6286                  pair = grad_avp_create(attr);
6287                  if (!pair)
6288                         rw_error(_("can't create A/V pair"));
6289                  grad_avl_add_pair(&mach.req->avlist, pair);
6290          }
6291 
6292 	switch (pair->type) {
6293 	case GRAD_TYPE_STRING:
6294 	case GRAD_TYPE_DATE:
6295 		mem2string(&str, (RWSTYPE*)val);
6296 		grad_free(pair->avp_strvalue);
6297 		pair->avp_strvalue = grad_malloc(str.size+1);
6298 		memcpy(pair->avp_strvalue, str.data, str.size);
6299 		pair->avp_strvalue[str.size] = 0;
6300 		pair->avp_strlength = str.size;
6301 		break;
6302 
6303 	case GRAD_TYPE_INTEGER:
6304 	case GRAD_TYPE_IPADDR:
6305 		pair->avp_lvalue = val;
6306 		break;
6307 	}
6308 
6309 	pushn(val);
6310 }
6311 
6312 void
rw_attrasgn0()6313 rw_attrasgn0()
6314 {
6315         int attr = (int) rw_code[mach.pc++];
6316         RWSTYPE val;
6317 
6318         cpopn(&val);
6319 	attrasgn_internal(attr, grad_avl_find(AVPLIST(&mach), attr), val);
6320 }
6321 
6322 void
rw_attrasgn()6323 rw_attrasgn()
6324 {
6325         int attr = (int) rw_code[mach.pc++];
6326         RWSTYPE val;
6327 	RWSTYPE index;
6328 
6329         cpopn(&val);
6330 	cpopn(&index);
6331 	attrasgn_internal(attr, grad_avl_find_n(AVPLIST(&mach), attr, index),
6332 			  val);
6333 }
6334 
6335 void
rw_attrs0()6336 rw_attrs0()
6337 {
6338         int attr = (int) rw_code[mach.pc++];
6339         grad_avp_t *pair;
6340 
6341         if ((pair = grad_avl_find(AVPLIST(&mach), attr)) == NULL)
6342                 pushstr("", 0);
6343         else if (pair->prop & GRAD_AP_ENCRYPT) {
6344 		char string[GRAD_STRING_LENGTH+1];
6345 		int len;
6346 		req_decrypt_password(string, mach.req, pair);
6347 		len = strlen(string);
6348 		pushstr(string, len);
6349 	} else
6350                 pushstr(pair->avp_strvalue, pair->avp_strlength);
6351 }
6352 
6353 void
rw_attrn0()6354 rw_attrn0()
6355 {
6356         int attr = (int) rw_code[mach.pc++];
6357         grad_avp_t *pair;
6358 
6359         if ((pair = grad_avl_find(AVPLIST(&mach), attr)) == NULL)
6360                 pushn(0);
6361         else
6362                 pushn(pair->avp_lvalue);
6363 }
6364 
6365 void
rw_attrs()6366 rw_attrs()
6367 {
6368         int attr = (int) rw_code[mach.pc++];
6369         grad_avp_t *pair;
6370 	RWSTYPE index;
6371 
6372 	cpopn(&index);
6373         if ((pair = grad_avl_find_n(AVPLIST(&mach), attr, index)) == NULL)
6374                 pushstr("", 0);
6375         else
6376                 pushstr(pair->avp_strvalue, pair->avp_strlength);
6377 }
6378 
6379 void
rw_attrn()6380 rw_attrn()
6381 {
6382         int attr = (int) rw_code[mach.pc++];
6383         grad_avp_t *pair;
6384 	RWSTYPE index;
6385 
6386 	cpopn(&index);
6387         if ((pair = grad_avl_find_n(AVPLIST(&mach), attr, index)) == NULL)
6388                 pushn(0);
6389         else
6390                 pushn(pair->avp_lvalue);
6391 }
6392 
6393 void
rw_attr_delete0()6394 rw_attr_delete0()
6395 {
6396         int attr = (int) rw_code[mach.pc++];
6397 	grad_avl_delete(&mach.req->avlist, attr);
6398 }
6399 
6400 void
rw_attr_delete()6401 rw_attr_delete()
6402 {
6403         int attr = (int) rw_code[mach.pc++];
6404 	RWSTYPE index;
6405 
6406 	assert_request_presence();
6407 	cpopn(&index);
6408 	grad_avl_delete_n(&mach.req->avlist, attr, index);
6409 }
6410 
6411 /*
6412  * Pop (and discard) a value from stack
6413  */
6414 void
rw_popn()6415 rw_popn()
6416 {
6417         RWSTYPE n;
6418         cpopn(&n);
6419 }
6420 
6421 /*
6422  * Pop a value from stack into the accumulator
6423  */
6424 void
rw_popa()6425 rw_popa()
6426 {
6427         cpopn(&mach.rA);
6428 }
6429 
6430 /*
6431  * Push accumulator on stack
6432  */
6433 void
rw_pusha()6434 rw_pusha()
6435 {
6436         pushn(mach.rA);
6437 }
6438 
6439 /*
6440  * String concatenation
6441  */
6442 void
rw_adds()6443 rw_adds()
6444 {
6445         grad_string_t s1, s2;
6446 	RWSTYPE *p;
6447 	char *s;
6448 
6449         checkpop(2);
6450         poparr(&s2);
6451         poparr(&s1);
6452         p = heap_reserve(sizeof(RWSTYPE) + s1.size + s2.size + 1);
6453 	s = (char*)(p + 1);
6454 	memcpy(s, s1.data, s1.size);
6455 	s += s1.size;
6456 	memcpy(s, s2.data, s2.size);
6457 	s += s2.size;
6458 	*s = 0;
6459 	p[0] = s1.size + s2.size;
6460         pushn((RWSTYPE)p);
6461 }
6462 
6463 /*
6464  * Unary negation
6465  */
6466 void
rw_neg()6467 rw_neg()
6468 {
6469         checkpop(1);
6470         pushn(-popn());
6471 }
6472 
6473 /*
6474  * Bitwise operations
6475  */
6476 void
rw_b_and()6477 rw_b_and()
6478 {
6479         int n1, n2;
6480 
6481         checkpop(2);
6482         n2 = popn();
6483         n1 = popn();
6484         pushn(n1 & n2);
6485 }
6486 
6487 void
rw_b_or()6488 rw_b_or()
6489 {
6490         int n1, n2;
6491 
6492         checkpop(2);
6493         n2 = popn();
6494         n1 = popn();
6495         pushn(n1 | n2);
6496 }
6497 
6498 void
rw_b_xor()6499 rw_b_xor()
6500 {
6501         int n1, n2;
6502 
6503         checkpop(2);
6504         n2 = popn();
6505         n1 = popn();
6506         pushn(n1 ^ n2);
6507 }
6508 
6509 void
rw_shl()6510 rw_shl()
6511 {
6512         int n1, n2;
6513 
6514         checkpop(2);
6515         n2 = popn();
6516         n1 = popn();
6517         pushn(n1 << n2);
6518 }
6519 
6520 void
rw_shr()6521 rw_shr()
6522 {
6523         int n1, n2;
6524 
6525         checkpop(2);
6526         n2 = popn();
6527         n1 = popn();
6528         pushn(n1 >> n2);
6529 }
6530 
6531 /*
6532  * Addition
6533  */
6534 void
rw_add()6535 rw_add()
6536 {
6537         int n1, n2;
6538 
6539         checkpop(2);
6540         n2 = popn();
6541         n1 = popn();
6542         pushn(n1+n2);
6543 }
6544 
6545 /*
6546  * Subtraction
6547  */
6548 void
rw_sub()6549 rw_sub()
6550 {
6551         int n1, n2;
6552 
6553         checkpop(2);
6554         n2 = popn();
6555         n1 = popn();
6556         pushn(n1-n2);
6557 }
6558 
6559 /*
6560  * Multiplication
6561  */
6562 void
rw_mul()6563 rw_mul()
6564 {
6565         int n1, n2;
6566 
6567         checkpop(2);
6568         n2 = popn();
6569         n1 = popn();
6570         pushn(n1*n2);
6571 }
6572 
6573 /*
6574  * Division
6575  */
6576 void
rw_div()6577 rw_div()
6578 {
6579         int n1, n2;
6580 
6581         checkpop(2);
6582         n2 = popn();
6583         n1 = popn();
6584         if (n2 == 0)
6585                 rw_error(_("division by zero!"));
6586         pushn(n1/n2);
6587 }
6588 
6589 /*
6590  * Remainder
6591  */
6592 void
rw_rem()6593 rw_rem()
6594 {
6595         int n1, n2;
6596 
6597         checkpop(2);
6598         n2 = popn();
6599         n1 = popn();
6600         if (n2 == 0)
6601                 rw_error(_("division by zero!"));
6602         pushn(n1%n2);
6603 }
6604 
6605 
6606 /* Type conversion */
6607 void
rw_i2s()6608 rw_i2s()
6609 {
6610         int n = popn();
6611         char buf[64];
6612 
6613         snprintf(buf, sizeof(buf), "%d", n);
6614         pushstr(buf, strlen(buf));
6615 }
6616 
6617 void
rw_s2i()6618 rw_s2i()
6619 {
6620 	grad_string_t s;
6621 	mem2string(&s, (RWSTYPE *)popn());
6622         pushn(strtol(s.data, NULL, 0));
6623 }
6624 
6625 
6626 
6627 void
rw_eq()6628 rw_eq()
6629 {
6630         int n1, n2;
6631 
6632         checkpop(2);
6633         n2 = popn();
6634         n1 = popn();
6635         pushn(n1 == n2);
6636 }
6637 
6638 void
rw_ne()6639 rw_ne()
6640 {
6641         int n1, n2;
6642 
6643         checkpop(2);
6644         n2 = popn();
6645         n1 = popn();
6646         pushn(n1 != n2);
6647 }
6648 
6649 void
rw_lt()6650 rw_lt()
6651 {
6652         int n1, n2;
6653 
6654         checkpop(2);
6655         n2 = popn();
6656         n1 = popn();
6657         pushn(n1 < n2);
6658 }
6659 
6660 void
rw_le()6661 rw_le()
6662 {
6663         int n1, n2;
6664 
6665         checkpop(2);
6666         n2 = popn();
6667         n1 = popn();
6668         pushn(n1 <= n2);
6669 }
6670 
6671 void
rw_gt()6672 rw_gt()
6673 {
6674         int n1, n2;
6675 
6676         checkpop(2);
6677         n2 = popn();
6678         n1 = popn();
6679         pushn(n1 > n2);
6680 }
6681 
6682 void
rw_ge()6683 rw_ge()
6684 {
6685         int n1, n2;
6686 
6687         checkpop(2);
6688         n2 = popn();
6689         n1 = popn();
6690         pushn(n1 >= n2);
6691 }
6692 
6693 void
rw_eqs()6694 rw_eqs()
6695 {
6696         grad_string_t s1, s2;
6697 
6698         checkpop(2);
6699 	poparr(&s2);
6700 	poparr(&s1);
6701 
6702         pushn(s1.size == s2.size && memcmp(s1.data, s2.data, s1.size) == 0);
6703 }
6704 
6705 void
rw_nes()6706 rw_nes()
6707 {
6708         grad_string_t s1, s2;
6709 
6710         checkpop(2);
6711 	poparr(&s2);
6712 	poparr(&s1);
6713 
6714         pushn(!(s1.size == s2.size && memcmp(s1.data, s2.data, s1.size) == 0));
6715 }
6716 
6717 void
rw_lts()6718 rw_lts()
6719 {
6720         grad_string_t s1, s2;
6721 	size_t size;
6722 
6723         checkpop(2);
6724 	poparr(&s2);
6725 	poparr(&s1);
6726 	size = RW_MIN(s1.size, s2.size);
6727 	pushn(memcmp(s1.data, s2.data, size < 0) || s1.size < s2.size);
6728 }
6729 
6730 void
rw_les()6731 rw_les()
6732 {
6733         grad_string_t s1, s2;
6734 	size_t size;
6735 
6736         checkpop(2);
6737 	poparr(&s2);
6738 	poparr(&s1);
6739 	size = RW_MIN(s1.size, s2.size);
6740 	pushn(memcmp(s1.data, s2.data, size <= 0) || s1.size <= s2.size);
6741 }
6742 
6743 void
rw_gts()6744 rw_gts()
6745 {
6746         grad_string_t s1, s2;
6747 	size_t size;
6748 
6749         checkpop(2);
6750 	poparr(&s2);
6751 	poparr(&s1);
6752 	size = RW_MIN(s1.size, s2.size);
6753 	pushn(memcmp(s1.data, s2.data, size > 0) || s1.size > s2.size);
6754 }
6755 
6756 void
rw_ges()6757 rw_ges()
6758 {
6759         grad_string_t s1, s2;
6760 	size_t size;
6761 
6762         checkpop(2);
6763 	poparr(&s2);
6764 	poparr(&s1);
6765 	size = RW_MIN(s1.size, s2.size);
6766 	pushn(memcmp(s1.data, s2.data, size >= 0) || s1.size >= s2.size);
6767 }
6768 
6769 void
rw_not()6770 rw_not()
6771 {
6772         int n;
6773 
6774         checkpop(1);
6775         n = popn();
6776         pushn(!n);
6777 }
6778 
6779 static void
need_pmatch(size_t n)6780 need_pmatch(size_t n)
6781 {
6782 	n++;
6783         if (mach.nmatch < n) {
6784                 grad_free(mach.pmatch);
6785                 mach.nmatch = n;
6786                 mach.pmatch = grad_emalloc(n * sizeof(mach.pmatch[0]));
6787         }
6788 }
6789 
6790 void
rw_match()6791 rw_match()
6792 {
6793         COMP_REGEX *rx = (COMP_REGEX *)rw_code[mach.pc++];
6794         grad_string_t s;
6795         int rc;
6796 
6797 	poparr(&s);
6798 	need_pmatch(rx->nmatch);
6799         mach.sA = s.data;
6800 
6801         rc = regexec(&rx->regex, mach.sA,
6802                      rx->nmatch + 1, mach.pmatch, 0);
6803         if (rc && GRAD_DEBUG_LEVEL(1)) {
6804                 char errbuf[512];
6805                 regerror(rc, &rx->regex,
6806                          errbuf, sizeof(errbuf));
6807                 grad_log(GRAD_LOG_DEBUG,
6808 		         _("rewrite regex failure: %s. Input: %s"),
6809                          errbuf, (char*)mach.rA);
6810         }
6811         pushn(rc == 0);
6812 }
6813 
6814 void
rw_jmp()6815 rw_jmp()
6816 {
6817         pctr_t pc = (pctr_t) rw_code[mach.pc++];
6818         mach.pc = pc;
6819 }
6820 
6821 void
rw_jne()6822 rw_jne()
6823 {
6824         int n;
6825         pctr_t pc = (pctr_t) rw_code[mach.pc++];
6826 
6827         n = popn();
6828         if (n != 0)
6829                 mach.pc = pc;
6830 }
6831 
6832 void
rw_je()6833 rw_je()
6834 {
6835         int n;
6836         pctr_t pc = (pctr_t) rw_code[mach.pc++];
6837 
6838         n = popn();
6839         if (n == 0)
6840                 mach.pc = pc;
6841 }
6842 
6843 void
rw_builtin()6844 rw_builtin()
6845 {
6846         INSTR fun = (INSTR) rw_code[mach.pc++];
6847         pushn(mach.pc);
6848         enter(0);
6849         fun();
6850         leave();
6851 }
6852 
6853 void
run(pctr_t pc)6854 run(pctr_t pc)
6855 {
6856         mach.pc = pc;
6857         while (rw_code[mach.pc]) {
6858                 if (mach.pc >= rw_codesize)
6859                         rw_error(_("pc out of range"));
6860                 (*(rw_code[mach.pc++]))();
6861         }
6862 }
6863 
6864 
6865 /* ****************************************************************************
6866  * A placeholder for the garbage collector
6867  */
6868 
6869 void
gc()6870 gc()
6871 {
6872 }
6873 
6874 
6875 /* ****************************************************************************
6876  * Built-in functions
6877  */
6878 
6879 /*
6880  * integer length(string s)
6881  */
6882 static void
bi_length()6883 bi_length()
6884 {
6885 	grad_string_t s;
6886 	mem2string(&s, (RWSTYPE*)getarg(1));
6887         pushn(s.size);
6888 }
6889 
6890 /*
6891  * integer index(string s, integer a)
6892  */
6893 static void
bi_index()6894 bi_index()
6895 {
6896         grad_string_t s;
6897 	char *p;
6898         int   c;
6899 
6900         mem2string(&s, (RWSTYPE*) getarg(2));
6901         c = (int) getarg(1);
6902         p = memchr(s.data, c, s.size);
6903         pushn(p ? p - s.data : -1);
6904 }
6905 
6906 /*
6907  * integer rindex(string s, integer a)
6908  */
6909 static void
bi_rindex()6910 bi_rindex()
6911 {
6912         grad_string_t s;
6913 	int i;
6914         int c;
6915 
6916 	mem2string(&s, (RWSTYPE*) getarg(2));
6917 	for (i = s.size - 1; i >= 0; i--)
6918 		if (s.data[i] == c)
6919 			break;
6920         pushn(i);
6921 }
6922 
6923 /*
6924  * string substr(string s, int start, int length)
6925  */
6926 static void
bi_substr()6927 bi_substr()
6928 {
6929         grad_string_t src;
6930 	RWSTYPE *p;
6931 	char *dest;
6932         int   start, length;
6933 
6934         mem2string(&src, (RWSTYPE*)getarg(3));
6935         start  = getarg(2);
6936         length = getarg(1);
6937         if (length < 0)
6938                 length = src.size - start;
6939 
6940         p = heap_reserve(sizeof(RWSTYPE) + length + 1);
6941 	dest = (char *)(p + 1);
6942         if (length > 0)
6943                 memcpy(dest, src.data + start, length);
6944         dest[length] = 0;
6945 	p[0] = length;
6946         pushn((RWSTYPE)p);
6947 }
6948 
6949 static void
bi_field()6950 bi_field()
6951 {
6952         grad_string_t str;
6953 	char *p, *endp;
6954         int fn = getarg(1);
6955         char *s = "";
6956         int len = 1;
6957 
6958 	mem2string(&str, (RWSTYPE*) getarg(2));
6959 	endp = str.data + str.size;
6960 	for (p = str.data; p < endp && fn--; ) {
6961                 /* skip initial whitespace */
6962                 while (p < endp && isspace(*p))
6963                         p++;
6964 
6965                 s = p;
6966                 len = 0;
6967                 while (p < endp && !isspace(*p)) {
6968                         p++;
6969                         len++;
6970                 }
6971         }
6972 
6973 	if (p == endp && fn)
6974 		pushstr("", 0);
6975 	else
6976 		pushstr(s, len);
6977 }
6978 
6979 static void
bi_logit()6980 bi_logit()
6981 {
6982         grad_string_t msg;
6983 	mem2string(&msg, (RWSTYPE*) getarg(1));
6984         grad_log(GRAD_LOG_INFO, "%s", msg.data);
6985         pushn(0);
6986 }
6987 
6988 static void
bi_htonl()6989 bi_htonl()
6990 {
6991 	pushn(htonl(getarg(1)));
6992 }
6993 
6994 static void
bi_ntohl()6995 bi_ntohl()
6996 {
6997 	pushn(ntohl(getarg(1)));
6998 }
6999 
7000 static void
bi_htons()7001 bi_htons()
7002 {
7003 	pushn(htons(getarg(1) & 0xffff));
7004 }
7005 
7006 static void
bi_ntohs()7007 bi_ntohs()
7008 {
7009 	pushn(ntohs(getarg(1) & 0xffff));
7010 }
7011 
7012 static void
bi_inet_ntoa()7013 bi_inet_ntoa()
7014 {
7015 	char buffer[GRAD_IPV4_STRING_LENGTH];
7016 	char *s = grad_ip_iptostr(getarg(1), buffer);
7017 	pushstr(s, strlen(s));
7018 }
7019 
7020 static void
bi_inet_aton()7021 bi_inet_aton()
7022 {
7023 	grad_string_t s;
7024 	mem2string(&s, (RWSTYPE*)getarg(1));
7025 	/* Note: inet_aton is not always present. See lib/iputils.c */
7026 	pushn(grad_ip_strtoip(s.data));
7027 }
7028 
7029 static void
bi_tolower()7030 bi_tolower()
7031 {
7032 	grad_string_t src;
7033 	grad_string_t dest;
7034 	int i;
7035 
7036 	mem2string(&src, (RWSTYPE*) getarg(1));
7037 	pushstr(src.data, src.size);
7038 	mem2string(&dest, (RWSTYPE*) tos());
7039 	for (i = 0; i < dest.size; i++)
7040 		dest.data[i] = tolower(dest.data[i]);
7041 }
7042 
7043 static void
bi_toupper()7044 bi_toupper()
7045 {
7046 	grad_string_t src;
7047 	grad_string_t dest;
7048 	int i;
7049 
7050 	mem2string(&src, (RWSTYPE*) getarg(1));
7051 	pushstr(src.data, src.size);
7052 	mem2string(&dest, (RWSTYPE*) tos());
7053 	for (i = 0; i < dest.size; i++)
7054 		dest.data[i] = toupper(dest.data[i]);
7055 }
7056 
7057 static void
bi_request_code_string()7058 bi_request_code_string()
7059 {
7060         int code = (int) getarg(1);
7061 	const char *s = grad_request_code_to_name(code);
7062 	pushstr(s, strlen(s));
7063 }
7064 
7065 static void
bi_request_source_ip()7066 bi_request_source_ip()
7067 {
7068 	assert_request_presence();
7069 	pushn((RWSTYPE) mach.req->ipaddr);
7070 }
7071 
7072 static void
bi_request_source_port()7073 bi_request_source_port()
7074 {
7075 	assert_request_presence();
7076 	pushn((RWSTYPE) mach.req->udp_port);
7077 }
7078 
7079 static void
bi_request_id()7080 bi_request_id()
7081 {
7082 	assert_request_presence();
7083 	pushn((RWSTYPE) mach.req->id);
7084 }
7085 
7086 static void
bi_request_code()7087 bi_request_code()
7088 {
7089 	assert_request_presence();
7090 	pushn((RWSTYPE) mach.req->code);
7091 }
7092 
7093 static void
bi_nas_name()7094 bi_nas_name()
7095 {
7096         grad_nas_t *nas;
7097 	grad_uint32_t ip = (grad_uint32_t) getarg(1);
7098 
7099 	if ((nas = grad_nas_lookup_ip(ip)) != NULL) {
7100 		char *s = nas->shortname[0] ? nas->shortname : nas->longname;
7101 		pushstr(s, strlen(s));
7102         } else {
7103 		char nasname[GRAD_MAX_LONGNAME];
7104 
7105 		grad_ip_gethostname(ip, nasname, sizeof(nasname));
7106 		pushstr(nasname, strlen(nasname));
7107 	}
7108 }
7109 
7110 static void
bi_nas_short_name()7111 bi_nas_short_name()
7112 {
7113         grad_nas_t *nas;
7114 	grad_uint32_t ip = (grad_uint32_t) getarg(1);
7115 
7116 	if ((nas = grad_nas_lookup_ip(ip)) && nas->shortname[0]) {
7117 		pushstr(nas->shortname, strlen(nas->shortname));
7118         } else {
7119 		char nasname[GRAD_MAX_LONGNAME];
7120 
7121 		grad_ip_gethostname(ip, nasname, sizeof(nasname));
7122 		pushstr(nasname, strlen(nasname));
7123 	}
7124 }
7125 
7126 static void
bi_nas_full_name()7127 bi_nas_full_name()
7128 {
7129         grad_nas_t *nas;
7130 	grad_uint32_t ip = (grad_uint32_t) getarg(1);
7131 
7132 	if ((nas = grad_nas_lookup_ip(ip)) != NULL) {
7133 		pushstr(nas->longname, strlen(nas->longname));
7134         } else {
7135 		char nasname[GRAD_MAX_LONGNAME];
7136 
7137 		grad_ip_gethostname(ip, nasname, sizeof(nasname));
7138 		pushstr(nasname, strlen(nasname));
7139 	}
7140 }
7141 
7142 static void
bi_gethostbyaddr()7143 bi_gethostbyaddr()
7144 {
7145 	grad_uint32_t ip = (grad_uint32_t) getarg(1);
7146 	char nasname[GRAD_MAX_LONGNAME];
7147 
7148 	grad_ip_gethostname(ip, nasname, sizeof(nasname));
7149 	pushstr(nasname, strlen(nasname));
7150 }
7151 
7152 static void
bi_gethostbyname()7153 bi_gethostbyname()
7154 {
7155 	grad_string_t s;
7156 	mem2string(&s, (RWSTYPE*)getarg(1));
7157 	pushn((RWSTYPE) grad_ip_gethostaddr(s.data));
7158 }
7159 
7160 static void
bi_time()7161 bi_time()
7162 {
7163 	pushn((RWSTYPE) time(NULL));
7164 }
7165 
7166 static void
bi_strftime()7167 bi_strftime()
7168 {
7169 	struct tm *tm;
7170 	char *base;
7171 	time_t t = (time_t) getarg(1);
7172 	grad_string_t fmt;
7173 	size_t n;
7174 
7175 	mem2string(&fmt, (RWSTYPE*) getarg(2));
7176 	tm = localtime(&t);
7177 	base = temp_space_create();
7178 	n = strftime(base, temp_space_size(), fmt.data, tm);
7179 	pushstr(base, n);
7180 }
7181 
7182 static void
rw_regerror(const char * prefix,regex_t * rx,int rc)7183 rw_regerror(const char *prefix, regex_t *rx, int rc)
7184 {
7185 	size_t sz = regerror(rc, rx, NULL, 0);
7186 	char *errbuf = malloc(sz + strlen (prefix) + 1);
7187 	if (!errbuf)
7188 		rw_error(prefix);
7189 	else {
7190 		strcpy (errbuf, prefix);
7191 		regerror(rc, rx, errbuf + strlen(prefix), sz);
7192 		rw_error_free(errbuf);
7193 	}
7194 }
7195 
7196 enum subst_segment_type {
7197 	subst_text,       /* pure text */
7198 	subst_ref,        /* back reference (\NN) */
7199 	subst_match       /* substitute whole match (&) */
7200 };
7201 
7202 struct subst_segment {
7203 	enum subst_segment_type type;
7204 	union {
7205 		struct {
7206 			char *ptr;
7207 			size_t len;
7208 		} text;      /* type == subst_text */
7209 		size_t ref;  /* type == subst_ref */
7210 	} v;
7211 };
7212 
7213 static void
add_text_segment(grad_list_t * lst,char * ptr,char * end)7214 add_text_segment(grad_list_t *lst, char *ptr, char *end)
7215 {
7216 	struct subst_segment *seg;
7217 	if (ptr >= end)
7218 		return;
7219 	seg = grad_emalloc(sizeof(*seg));
7220 	seg->type = subst_text;
7221 	seg->v.text.ptr = ptr;
7222 	seg->v.text.len = end - ptr;
7223 	grad_list_append(lst, seg);
7224 }
7225 
7226 static void
add_match_segment(grad_list_t * lst)7227 add_match_segment(grad_list_t *lst)
7228 {
7229 	struct subst_segment *seg = grad_emalloc(sizeof(*seg));
7230 	seg->type = subst_match;
7231 	grad_list_append(lst, seg);
7232 }
7233 
7234 static void
add_ref_segment(grad_list_t * lst,size_t ref)7235 add_ref_segment(grad_list_t *lst, size_t ref)
7236 {
7237 	struct subst_segment *seg = grad_emalloc(sizeof(*seg));
7238 	seg->type = subst_ref;
7239 	seg->v.ref = ref;
7240 	grad_list_append(lst, seg);
7241 }
7242 
7243 grad_list_t *
subst_create(char * text)7244 subst_create(char *text)
7245 {
7246 	char *p;
7247 	grad_list_t *lst = grad_list_create();
7248 	if (!lst)
7249 		return lst;
7250 
7251 	p = text;
7252 	while (*p) {
7253 		if (*p == '\\' && p[1]) {
7254 			if (p[1] == '&') {
7255 				add_text_segment(lst, text, p);
7256 				text = ++p;
7257 				p++;
7258 			} else if (p[1] == '\\') {
7259 				add_text_segment(lst, text, p+1);
7260 				p += 2;
7261 				text = p;
7262 			} else if (isdigit(p[1])) {
7263 				size_t ref;
7264 				char *q;
7265 
7266 				add_text_segment(lst, text, p);
7267 				ref = strtoul(p+1, &q, 10);
7268 				add_ref_segment(lst, ref);
7269 				text = p = q;
7270 			} else {
7271 				add_text_segment(lst, text, p);
7272 				text = ++p;
7273 			}
7274 		} else if (*p == '&') {
7275 			add_text_segment(lst, text, p);
7276 			add_match_segment(lst);
7277 			text = ++p;
7278 		} else
7279 			p++;
7280 	}
7281 	add_text_segment(lst, text, p);
7282 	return lst;
7283 }
7284 
7285 int
seg_free(void * item,void * data ARG_UNUSED)7286 seg_free(void *item, void *data ARG_UNUSED)
7287 {
7288 	grad_free(item);
7289 	return 0;
7290 }
7291 
7292 void
subst_destroy(grad_list_t * lst)7293 subst_destroy(grad_list_t *lst)
7294 {
7295 	grad_list_destroy(&lst, seg_free, NULL);
7296 }
7297 
7298 void
subst_run(grad_list_t * subst,size_t nsub,char ** baseptr,char * arg)7299 subst_run(grad_list_t *subst, size_t nsub,
7300 	  char **baseptr, char *arg)
7301 {
7302 	grad_iterator_t *itr = grad_iterator_create(subst);
7303 	struct subst_segment *seg;
7304 
7305 	for (seg = grad_iterator_first(itr); seg; seg = grad_iterator_next(itr)) {
7306 		switch (seg->type) {
7307 		case subst_text:
7308 			temp_space_copy(baseptr,
7309 					seg->v.text.ptr, seg->v.text.len);
7310 			break;
7311 
7312 		case subst_ref:
7313 			if (seg->v.ref >= nsub)
7314 				rw_error(_("Invalid backreference"));
7315 			temp_space_copy(baseptr,
7316 					arg + mach.pmatch[seg->v.ref].rm_so,
7317 					mach.pmatch[seg->v.ref].rm_eo -
7318 					  mach.pmatch[seg->v.ref].rm_so);
7319 			break;
7320 
7321 		case subst_match:
7322 			temp_space_copy(baseptr,
7323 					arg + mach.pmatch[0].rm_so,
7324 					mach.pmatch[0].rm_eo -
7325 					  mach.pmatch[0].rm_so);
7326 		}
7327 	}
7328 	grad_iterator_destroy(&itr);
7329 }
7330 
7331 static void
bi_gsub()7332 bi_gsub()
7333 {
7334 	grad_string_t re_str;
7335 	grad_string_t repl;
7336 	grad_string_t arg;
7337 	char *p;
7338 	char *base;
7339 	regex_t rx;
7340 	grad_list_t *subst;
7341 	int rc;
7342 
7343 	mem2string(&re_str, (RWSTYPE*) getarg(3));
7344 	mem2string(&repl, (RWSTYPE*) getarg(2));
7345 	mem2string(&arg, (RWSTYPE*) getarg(1));
7346 	p = arg.data;
7347 
7348         rc = regcomp(&rx, re_str.data, regcomp_flags);
7349         if (rc)
7350 		rw_regerror(_("regexp compile error: "), &rx, rc);
7351 
7352 	need_pmatch(rx.re_nsub);
7353 
7354 	subst = subst_create(repl.data);
7355 	if (!subst)
7356 		rw_error(_("gsub: not enough memory"));
7357 
7358 	base = temp_space_create();
7359 	while (*p
7360 	       && regexec(&rx, p, rx.re_nsub + 1, mach.pmatch, 0) == 0) {
7361 		temp_space_copy(&base, p, mach.pmatch[0].rm_so);
7362 		subst_run(subst, rx.re_nsub + 1, &base, p);
7363 		p += mach.pmatch[0].rm_eo;
7364 		if (mach.pmatch[0].rm_eo == 0)
7365 			p++;
7366 	}
7367 	temp_space_copy(&base, p, strlen(p) + 1);
7368 	subst_destroy(subst);
7369 	regfree(&rx);
7370 
7371 	pushn((RWSTYPE)temp_space_fix(base));
7372 }
7373 
7374 static void
bi_sub()7375 bi_sub()
7376 {
7377 	grad_string_t re_str;
7378 	grad_string_t repl;
7379 	grad_string_t arg;
7380 	char *p;
7381 	char *base;
7382 	regex_t rx;
7383 	grad_list_t *subst;
7384 	int rc;
7385 
7386 	mem2string(&re_str, (RWSTYPE*) getarg(3));
7387 	mem2string(&repl, (RWSTYPE*) getarg(2));
7388 	mem2string(&arg, (RWSTYPE*) getarg(1));
7389 
7390         rc = regcomp(&rx, re_str.data, regcomp_flags);
7391         if (rc)
7392 		rw_regerror(_("regexp compile error: "), &rx, rc);
7393 
7394 	need_pmatch(rx.re_nsub);
7395 
7396 	subst = subst_create(repl.data);
7397 	if (!subst)
7398 		rw_error(_("sub: not enough memory"));
7399 
7400 	base = temp_space_create();
7401 	p = arg.data;
7402 	if (regexec(&rx, p, rx.re_nsub + 1, mach.pmatch, 0) == 0) {
7403 		temp_space_copy(&base, p, mach.pmatch[0].rm_so);
7404 		subst_run(subst, rx.re_nsub + 1, &base, p);
7405 		p += mach.pmatch[0].rm_eo;
7406 	}
7407 	temp_space_copy(&base, p, strlen(p) + 1);
7408 	subst_destroy(subst);
7409 	regfree(&rx);
7410 
7411 	pushn((RWSTYPE)temp_space_fix(base));
7412 }
7413 
7414 #define ISPRINT(c) (((unsigned char)c) < 128 && (isalnum(c) || c == '-'))
7415 
7416 static void
bi_qprn()7417 bi_qprn()
7418 {
7419 	grad_string_t arg;
7420 	char *p, *s, *end;
7421 	size_t count;
7422 	RWSTYPE *sp;
7423 
7424 	mem2string(&arg, (RWSTYPE*)getarg(1));
7425 	end = arg.data + arg.size;
7426 	for (count = 0, p = arg.data; p < end; p++)
7427 		if (!ISPRINT(*p))
7428 			count++;
7429 
7430 	/* Each encoded character takes 3 bytes. */
7431 	sp = heap_reserve(sizeof(RWSTYPE) + arg.size + 2*count + 1);
7432 	sp[0] = arg.size + 2*count;
7433 	pushn((RWSTYPE) sp);
7434 
7435 	for (p = (char*)(sp + 1), s = arg.data; s < end; s++) {
7436 		if (ISPRINT(*s))
7437 			*p++ = *s;
7438 		else {
7439 			char buf[3];
7440 			snprintf(buf, sizeof buf, "%02X", *(unsigned char*)s);
7441 			*p++ = '%';
7442 			*p++ = buf[0];
7443 			*p++ = buf[1];
7444 		}
7445 	}
7446 	*p = 0;
7447 }
7448 
7449 static void
bi_quote_string()7450 bi_quote_string()
7451 {
7452 	int quote;
7453 	grad_string_t arg;
7454 	RWSTYPE *sp;
7455 	char *p;
7456 	size_t size;
7457 
7458 	mem2string(&arg, (RWSTYPE*)getarg(1));
7459 	size = grad_argcv_quoted_length_n(arg.data, arg.size, &quote);
7460 	sp = heap_reserve(sizeof(RWSTYPE) + size + 1);
7461 	sp[0] = size;
7462 	pushn((RWSTYPE)sp);
7463 	p = (char*)(sp + 1);
7464 	grad_argcv_quote_copy_n(p, arg.data, arg.size);
7465 }
7466 
7467 static void
bi_unquote_string()7468 bi_unquote_string()
7469 {
7470 	int quote;
7471 	grad_string_t arg;
7472 	RWSTYPE *sp;
7473 	char *p;
7474 	size_t size;
7475 
7476 	mem2string(&arg, (RWSTYPE*)getarg(1));
7477 	sp = heap_reserve(sizeof(RWSTYPE) +  arg.size + 1);
7478 	p = (char*)(sp + 1);
7479 	grad_argcv_unquote_copy(p, arg.data, arg.size);
7480 	sp[0] = strlen(p);
7481 	pushn((RWSTYPE)sp);
7482 }
7483 
7484 static void
bi_textdomain()7485 bi_textdomain()
7486 {
7487 	grad_string_t s;
7488 	mem2string(&s, (RWSTYPE*)getarg(1));
7489 	pushstr(default_gettext_domain, strlen (default_gettext_domain));
7490 	grad_string_replace(&default_gettext_domain, s.data);
7491 }
7492 
7493 static void
bi_gettext()7494 bi_gettext()
7495 {
7496 	grad_string_t s;
7497 	const char *p;
7498 
7499 	mem2string(&s, (RWSTYPE*)getarg(1));
7500 	p = dgettext(default_gettext_domain, s.data);
7501 	pushstr(p, strlen(p));
7502 }
7503 
7504 static void
bi_dgettext()7505 bi_dgettext()
7506 {
7507 	grad_string_t domain;
7508 	grad_string_t text;
7509 	const char *p;
7510 
7511 	mem2string(&domain, (RWSTYPE*)getarg(2));
7512 	mem2string(&text, (RWSTYPE*)getarg(1));
7513 	p = dgettext(domain.data, text.data);
7514 	pushstr(p, strlen(p));
7515 }
7516 
7517 
7518 static void
bi_ngettext()7519 bi_ngettext()
7520 {
7521 	grad_string_t s;
7522 	grad_string_t pl;
7523 	unsigned long n;
7524 	const char *p;
7525 
7526 	mem2string(&s, (RWSTYPE*)getarg(3));
7527 	mem2string(&pl, (RWSTYPE*)getarg(2));
7528 	n = (unsigned long) getarg(1);
7529 	p = dngettext(default_gettext_domain,
7530 		      s.data,
7531 		      pl.data,
7532 		      n);
7533 	pushstr(p, strlen(p));
7534 }
7535 
7536 static void
bi_dngettext()7537 bi_dngettext()
7538 {
7539 	grad_string_t domain;
7540 	grad_string_t s;
7541 	grad_string_t pl;
7542 	unsigned long n;
7543 	const char *p;
7544 
7545 	mem2string(&domain, (RWSTYPE*)getarg(4));
7546 	mem2string(&s, (RWSTYPE*)getarg(3));
7547 	mem2string(&pl, (RWSTYPE*)getarg(2));
7548 	n = (unsigned long) getarg(1);
7549 
7550         p = dngettext(domain.data, s.data, pl.data, n);
7551 	pushstr(p, strlen(p));
7552 }
7553 
7554 static builtin_t builtin[] = {
7555         { bi_length,  "length", Integer, "s" },
7556 	{ bi_index,   "index",  Integer, "si" },
7557         { bi_rindex,  "rindex", Integer, "si" },
7558         { bi_substr,  "substr", String,  "sii" },
7559         { bi_logit,   "logit",  Integer, "s" },
7560         { bi_field,   "field",  String,  "si" },
7561 	{ bi_ntohl, "ntohl", Integer, "i" },
7562 	{ bi_htonl, "htonl", Integer, "i" },
7563 	{ bi_ntohs, "ntohs", Integer, "i" },
7564 	{ bi_htons, "htons", Integer, "i" },
7565 	{ bi_inet_ntoa, "inet_ntoa", String, "i" },
7566 	{ bi_inet_aton, "inet_aton", Integer, "s" },
7567 	{ bi_sub, "sub", String, "sss" },
7568 	{ bi_gsub, "gsub", String, "sss" },
7569 	{ bi_qprn, "qprn", String, "s" },
7570 	{ bi_tolower, "tolower", String, "s" },
7571 	{ bi_toupper, "toupper", String, "s" },
7572 	{ bi_unquote_string, "unquote_string", String, "s" },
7573 	{ bi_quote_string, "quote_string", String, "s" },
7574 	{ bi_request_code_string, "request_code_string", String, "i" },
7575 	/* i18n support */
7576 	{ bi_gettext, "gettext", String, "s" },
7577 	{ bi_gettext, "_", String, "s" },
7578 	{ bi_dgettext, "dgettext", String, "ss" },
7579 	{ bi_ngettext, "ngettext", String, "ssi" },
7580 	{ bi_dngettext, "dngettext", String, "sssi" },
7581 	{ bi_textdomain, "textdomain", String, "s" },
7582 	/* Request internals */
7583 	{ bi_request_source_ip,   "request_source_ip", Integer, "" },
7584 	{ bi_request_source_port, "request_source_port", Integer, "" },
7585 	{ bi_request_id, "request_id", Integer, "" },
7586 	{ bi_request_code, "request_code", Integer, "" },
7587 	/* Radius database */
7588 	{ bi_nas_name, "nas_name", String, "i" },
7589 	{ bi_nas_short_name, "nas_short_name", String, "i" },
7590 	{ bi_nas_full_name, "nas_full_name", String, "i" },
7591 	/* DNS lookups */
7592 	{ bi_gethostbyaddr, "gethostbyaddr", Integer, "s" },
7593 	{ bi_gethostbyname, "gethostbyname", String, "i" },
7594 	/* Time functions */
7595 	{ bi_time, "time", Integer, "" },
7596 	{ bi_strftime, "strftime", String, "si" },
7597 	{ NULL }
7598 };
7599 
7600 builtin_t *
builtin_lookup(char * name)7601 builtin_lookup(char *name)
7602 {
7603         int i;
7604 
7605         for (i = 0; builtin[i].handler; i++)
7606                 if (strcmp(name, builtin[i].name) == 0)
7607                         return &builtin[i];
7608         return NULL;
7609 }
7610 
7611 
7612 /* ****************************************************************************
7613  * Function registering/unregistering
7614  */
7615 
7616 int
function_free(FUNCTION * f)7617 function_free(FUNCTION *f)
7618 {
7619         PARAMETER *parm, *next;
7620 
7621         rx_free(f->rx_list);
7622         parm = f->parm;
7623         while (parm) {
7624                 next = parm->next;
7625                 grad_free(parm);
7626                 parm = next;
7627         }
7628         return 0;
7629 }
7630 
7631 FUNCTION *
function_install(FUNCTION * fun)7632 function_install(FUNCTION *fun)
7633 {
7634         FUNCTION *fp;
7635 
7636         if (fp = (FUNCTION *)grad_sym_lookup(rewrite_tab, fun->name)) {
7637                 grad_log_loc(GRAD_LOG_ERR, &fun->loc,
7638 			     _("redefinition of function %s"));
7639                 grad_log_loc(GRAD_LOG_ERR, &fp->loc,
7640 			     _("previously defined here"));
7641                 errcnt++;
7642                 return fp;
7643         }
7644         fp = (FUNCTION*)grad_sym_install(rewrite_tab, fun->name);
7645 
7646         fp->rettype = fun->rettype;
7647         fp->entry   = fun->entry;
7648         fp->rx_list = fun->rx_list;
7649         fp->nparm   = fun->nparm;
7650         fp->parm    = fun->parm;
7651         fp->stack_alloc = fun->stack_alloc;
7652 	fp->loc     = fun->loc;
7653         return fp;
7654 }
7655 
7656 
7657 /* ****************************************************************************
7658  * Runtime functions
7659  */
7660 
7661 static char pair_print_prefix[] = "    ";
7662 
7663 static void
rw_mach_init()7664 rw_mach_init()
7665 {
7666 	memset(&mach, 0, sizeof(mach));
7667 
7668 	if (!runtime_stack)
7669 		runtime_stack = grad_emalloc(rewrite_stack_size *
7670 					     sizeof(runtime_stack[0]));
7671 
7672 	mach.stack = runtime_stack;
7673         mach.st = 0;                      /* Stack top */
7674         mach.ht = rewrite_stack_size - 1; /* Heap top */
7675 
7676 	grad_string_replace(&default_gettext_domain, PACKAGE);
7677 }
7678 
7679 static void
rw_mach_destroy()7680 rw_mach_destroy()
7681 {
7682 	grad_free(mach.pmatch);
7683 	mach.pmatch = NULL;
7684 }
7685 
7686 FUNCTION *
rewrite_check_function(const char * name,grad_data_type_t rettype,char * typestr)7687 rewrite_check_function(const char *name, grad_data_type_t rettype, char *typestr)
7688 {
7689 	int i;
7690 	PARAMETER *p;
7691 
7692 	FUNCTION *fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, name);
7693         if (!fun) {
7694                 grad_log(GRAD_LOG_ERR, _("function %s not defined"), name);
7695                 return NULL;
7696         }
7697 	if (fun->rettype != rettype) {
7698 		grad_log(GRAD_LOG_ERR, _("function %s returns wrong data type"), name);
7699 		return NULL;
7700 	}
7701 
7702 	for (i = 0, p = fun->parm; i < fun->nparm; i++, p = p->next) {
7703                 switch (typestr[i]) {
7704 		case 0:
7705 			grad_log(GRAD_LOG_ERR,
7706 			         _("function %s takes too many arguments"),
7707 			         name);
7708 			return NULL;
7709 
7710                 case 'i':
7711                         if (p->datatype != Integer) {
7712 				grad_log(GRAD_LOG_ERR,
7713 				         _("function %s: argument %d must be integer"),
7714 				         name, i+1);
7715 				return NULL;
7716 			}
7717                         break;
7718 
7719                 case 's':
7720                         if (p->datatype != String) {
7721 				grad_log(GRAD_LOG_ERR,
7722 				         _("function %s: argument %d must be string"),
7723 				         name, i+1);
7724 				return NULL;
7725 			}
7726                         break;
7727 
7728                 default:
7729                         grad_insist_fail("bad datatype");
7730                 }
7731         }
7732 
7733 	if (typestr[i]) {
7734 		grad_log(GRAD_LOG_ERR,
7735 		         _("function %s takes too few arguments"),
7736 		         name);
7737 		return NULL;
7738 	}
7739 
7740 	return fun;
7741 }
7742 
7743 int
run_init(pctr_t pc,grad_request_t * request)7744 run_init(pctr_t pc, grad_request_t *request)
7745 {
7746         FILE *fp;
7747 
7748 	rw_mach_init();
7749         if (setjmp(mach.jmp)) {
7750 		rw_mach_destroy();
7751                 return -1;
7752 	}
7753 
7754         mach.req = request;
7755         if (GRAD_DEBUG_LEVEL(2)) {
7756                 fp = debug_open_file();
7757                 fprintf(fp, "Before rewriting:\n");
7758                 grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
7759                 fclose(fp);
7760         }
7761 
7762         /* Imitate a function call */
7763         pushn(0);                  /* Return address */
7764         run(pc);                   /* call function */
7765         if (GRAD_DEBUG_LEVEL(2)) {
7766                 fp = debug_open_file();
7767                 fprintf(fp, "After rewriting\n");
7768                 grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
7769                 fclose(fp);
7770         }
7771 	rw_mach_destroy();
7772 	return 0;
7773 }
7774 
7775 static void
return_value(grad_value_t * val)7776 return_value(grad_value_t *val)
7777 {
7778 	u_char *p;
7779 
7780 	switch (val->type) {
7781 	case Integer:
7782 		val->datum.ival = mach.rA;
7783 		break;
7784 
7785 	case String:
7786 		mem2string(&val->datum.sval, (RWSTYPE*) mach.rA);
7787 		p = grad_emalloc (val->datum.sval.size + 1);
7788 		memcpy (p, val->datum.sval.data, val->datum.sval.size);
7789 		p[val->datum.sval.size] = 0;
7790 		val->datum.sval.data = p;
7791 		break;
7792 
7793 	default:
7794 		abort();
7795 	}
7796 }
7797 
7798 static int
evaluate(pctr_t pc,grad_request_t * req,grad_value_t * val)7799 evaluate(pctr_t pc, grad_request_t *req, grad_value_t *val)
7800 {
7801         if (run_init(pc, req))
7802 		return -1;
7803 	if (val)
7804 		return_value(val);
7805         return 0;
7806 }
7807 
7808 int
rewrite_invoke(grad_data_type_t rettype,grad_value_t * val,const char * name,grad_request_t * request,char * typestr,...)7809 rewrite_invoke(grad_data_type_t rettype, grad_value_t *val,
7810 	       const char *name,
7811 	       grad_request_t *request, char *typestr, ...)
7812 {
7813         FILE *fp;
7814         va_list ap;
7815         FUNCTION *fun;
7816         int nargs;
7817         char *s;
7818 
7819         fun = rewrite_check_function(name, rettype, typestr);
7820 	if (!fun)
7821 		return -1;
7822 
7823 	rw_mach_init();
7824         if (setjmp(mach.jmp)) {
7825                 rw_mach_destroy();
7826                 return -1;
7827         }
7828 
7829         mach.req = request;
7830         if (GRAD_DEBUG_LEVEL(2)) {
7831                 fp = debug_open_file();
7832                 fprintf(fp, "Before rewriting:\n");
7833                 grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
7834                 fclose(fp);
7835         }
7836 
7837         /* Pass arguments */
7838         nargs = 0;
7839 
7840 	va_start(ap, typestr);
7841         while (*typestr) {
7842                 nargs++;
7843                 switch (*typestr++) {
7844                 case 'i':
7845                         pushn(va_arg(ap, int));
7846                         break;
7847                 case 's':
7848                         s = va_arg(ap, char*);
7849                         pushstr(s, strlen(s));
7850                         break;
7851                 default:
7852                         grad_insist_fail("bad datatype");
7853                 }
7854         }
7855         va_end(ap);
7856 
7857         /* Imitate a function call */
7858         pushn(0);                  /* Return address */
7859         run(fun->entry);           /* call function */
7860         if (GRAD_DEBUG_LEVEL(2)) {
7861                 fp = debug_open_file();
7862                 fprintf(fp, "After rewriting\n");
7863                 grad_avl_fprint(fp, pair_print_prefix, 1, AVPLIST(&mach));
7864                 fclose(fp);
7865         }
7866 	val->type = fun->rettype;
7867 	return_value(val);
7868         rw_mach_destroy();
7869         return 0;
7870 }
7871 
7872 char *
rewrite_compile(char * expr)7873 rewrite_compile(char *expr)
7874 {
7875 	int rc;
7876 	FUNCTION *fun;
7877 	char *name = grad_emalloc(strlen(expr) + 3);
7878 
7879 	sprintf(name, "$%s$", expr);
7880         fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, name);
7881         if (!fun) {
7882 		rc = parse_rewrite_string(expr);
7883 		if (rc) {
7884 			grad_free(name);
7885 			return NULL;
7886 		}
7887 		function->name = name;
7888 		function_install(function);
7889 	}
7890 	return name;
7891 }
7892 
7893 int
rewrite_interpret(char * expr,grad_request_t * req,grad_value_t * val)7894 rewrite_interpret(char *expr, grad_request_t *req, grad_value_t *val)
7895 {
7896 	pctr_t save_pc = rw_pc;
7897 	int rc;
7898 
7899 	rc = parse_rewrite_string(expr);
7900 	rw_pc = save_pc;
7901 	if (rc)
7902 		return rc;
7903 
7904 	val->type = return_type;
7905 	if (return_type == Undefined)
7906 		return -1;
7907 
7908 	return evaluate(rw_pc, req, val);
7909 }
7910 
7911 int
rewrite_eval(char * symname,grad_request_t * req,grad_value_t * val)7912 rewrite_eval(char *symname, grad_request_t *req, grad_value_t *val)
7913 {
7914         FUNCTION *fun;
7915 
7916         fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, symname);
7917         if (!fun)
7918 		return -1;
7919 
7920 	if (fun->nparm) {
7921 		grad_log(GRAD_LOG_ERR,
7922 		         ngettext("function %s() requires %d parameter",
7923 				  "function %s() requires %d parameters",
7924 				  fun->nparm),
7925 		         fun->name, fun->nparm);
7926 		return -1;
7927 	}
7928 
7929 	if (val)
7930 		val->type = fun->rettype;
7931 	return evaluate(fun->entry, req, val);
7932 }
7933 
7934 
7935 /* ****************************************************************************
7936  * Configuration
7937  */
7938 
7939 static grad_list_t *source_list;        /* List of loaded source files */
7940 static grad_list_t *rewrite_load_path;  /* Load path list */
7941 
7942 /* Add a path to load path */
7943 static void
rewrite_add_load_path(const char * str)7944 rewrite_add_load_path(const char *str)
7945 {
7946 	if (!rewrite_load_path)
7947 		rewrite_load_path = grad_list_create();
7948 	grad_list_append(rewrite_load_path, grad_estrdup(str));
7949 }
7950 
7951 void
register_source_name(char * path)7952 register_source_name(char *path)
7953 {
7954 	if (!source_list)
7955 		source_list = grad_list_create();
7956 	grad_list_append(source_list, path);
7957 }
7958 
7959 struct load_data {
7960 	int rc;
7961 	char *name;
7962 };
7963 
7964 /* Try to load a source file.
7965    ITEM is a directory name, DATA is struct load_data.
7966    Return 1 if the file was found (no matter was it loaded or not) */
7967 static int
try_load(void * item,void * data)7968 try_load(void *item, void *data)
7969 {
7970 	int rc = 0;
7971 	struct load_data *lp = data;
7972 	char *path = grad_mkfilename((char*)item, lp->name);
7973 
7974 	lp->rc = parse_rewrite(path);
7975 	if (lp->rc >= 0) {
7976 		register_source_name(path);
7977 		rc = 1;
7978 	} else
7979 		grad_free(path);
7980 	return rc;
7981 }
7982 
7983 /* Load the given rewrite module. */
7984 int
rewrite_load_module(char * name)7985 rewrite_load_module(char *name)
7986 {
7987 	int rc;
7988 	if (name[0] == '/') {
7989 		register_source_name(grad_estrdup(name));
7990 		rc = parse_rewrite(name);
7991 	} else {
7992 		struct load_data ld;
7993 		ld.rc = 1;
7994 		ld.name = name;
7995 		grad_list_iterate(rewrite_load_path, try_load, &ld);
7996 		rc = ld.rc;
7997 	}
7998 	return rc;
7999 }
8000 
8001 static int
free_path(void * item,void * data ARG_UNUSED)8002 free_path(void *item, void *data ARG_UNUSED)
8003 {
8004 	grad_free(item);
8005 	return 0;
8006 }
8007 
8008 static grad_list_t *source_candidate_list; /* List of modules that are to
8009 					      be loaded */
8010 
8011 int
rewrite_stmt_term(int finish,void * block_data,void * handler_data)8012 rewrite_stmt_term(int finish, void *block_data, void *handler_data)
8013 {
8014 	if (!finish) {
8015 		grad_symtab_clear(rewrite_tab);
8016 
8017 		rw_yydebug = GRAD_DEBUG_LEVEL(50);
8018 		grad_list_destroy(&source_list, free_path, NULL);
8019 		grad_list_destroy(&rewrite_load_path, free_path, NULL);
8020 		rewrite_add_load_path(grad_config_dir);
8021 		rewrite_add_load_path(RADIUS_DATADIR "/rewrite");
8022 
8023 		grad_free(runtime_stack);
8024 		runtime_stack = NULL;
8025 	}
8026 	return 0;
8027 }
8028 
8029 static int
rewrite_cfg_add_load_path(int argc,cfg_value_t * argv,void * block_data,void * handler_data)8030 rewrite_cfg_add_load_path(int argc, cfg_value_t *argv,
8031 			  void *block_data, void *handler_data)
8032 {
8033 	if (argc > 2) {
8034 		cfg_argc_error(0);
8035 		return 0;
8036 	}
8037 
8038  	if (argv[1].type != CFG_STRING) {
8039 		cfg_type_error(CFG_STRING);
8040 		return 0;
8041 	}
8042 
8043 	rewrite_add_load_path(argv[1].v.string);
8044 	return 0;
8045 }
8046 
8047 static int
rewrite_cfg_load(int argc,cfg_value_t * argv,void * block_data,void * handler_data)8048 rewrite_cfg_load(int argc, cfg_value_t *argv,
8049 		 void *block_data, void *handler_data)
8050 {
8051 	if (argc > 2) {
8052 		cfg_argc_error(0);
8053 		return 0;
8054 	}
8055 
8056  	if (argv[1].type != CFG_STRING) {
8057 		cfg_type_error(CFG_STRING);
8058 		return 0;
8059 	}
8060 
8061 	grad_list_append(source_candidate_list, grad_estrdup(argv[1].v.string));
8062 	return 0;
8063 }
8064 
8065 /* Configuration hooks and initialization */
8066 
8067 static void
rewrite_before_config_hook(void * a ARG_UNUSED,void * b ARG_UNUSED)8068 rewrite_before_config_hook(void *a ARG_UNUSED, void *b ARG_UNUSED)
8069 {
8070 	grad_list_destroy(&source_candidate_list, free_path, NULL);
8071 	source_candidate_list = grad_list_create();
8072 	code_init();
8073 }
8074 
8075 static int
_load_module(void * item,void * data ARG_UNUSED)8076 _load_module(void *item, void *data ARG_UNUSED)
8077 {
8078 	if (rewrite_load_module(item) == -2)
8079 		grad_log(GRAD_LOG_ERR, _("file not found: %s"), item);
8080 	return 0;
8081 }
8082 
8083 void
rewrite_load_all(void * a ARG_UNUSED,void * b ARG_UNUSED)8084 rewrite_load_all(void *a ARG_UNUSED, void *b ARG_UNUSED)
8085 {
8086 	if (!source_candidate_list)
8087 		return;
8088 
8089 	/* For compatibility with previous versions load the
8090 	   file $grad_config_dir/rewrite, if no explicit "load" statements
8091 	   were given */
8092 	if (grad_list_count(source_candidate_list) == 0)
8093 		rewrite_load_module("rewrite");
8094 
8095 	grad_list_iterate(source_candidate_list, _load_module, NULL);
8096 #if defined(MAINTAINER_MODE)
8097         if (GRAD_DEBUG_LEVEL(100))
8098                 debug_dump_code();
8099 #endif
8100 }
8101 
8102 void
rewrite_init()8103 rewrite_init()
8104 {
8105 	rewrite_tab = grad_symtab_create(sizeof(FUNCTION), function_free);
8106 	radiusd_set_preconfig_hook(rewrite_before_config_hook, NULL, 0);
8107 }
8108 
8109 
8110 struct cfg_stmt rewrite_stmt[] = {
8111 	{ "stack-size", CS_STMT, NULL, cfg_get_number, &rewrite_stack_size,
8112 	  NULL, NULL },
8113 	{ "load-path", CS_STMT, NULL, rewrite_cfg_add_load_path, NULL, NULL, NULL },
8114 	{ "load", CS_STMT, NULL, rewrite_cfg_load, NULL, NULL, NULL },
8115 	{ NULL, }
8116 };
8117 
8118 size_t
rewrite_get_stack_size()8119 rewrite_get_stack_size()
8120 {
8121 	return rewrite_stack_size;
8122 }
8123 
8124 void
rewrite_set_stack_size(size_t s)8125 rewrite_set_stack_size(size_t s)
8126 {
8127 	if (s == rewrite_stack_size)
8128 		return;
8129 	rewrite_stack_size = s;
8130 	grad_free(runtime_stack);
8131 	runtime_stack = NULL;
8132 }
8133 
8134 void
grad_value_free(grad_value_t * val)8135 grad_value_free(grad_value_t *val)
8136 {
8137 	if (val->type == String)
8138 		grad_free(val->datum.sval.data);
8139 }
8140 
8141 
8142 /* ****************************************************************************
8143  * Guile interface
8144  */
8145 #ifdef USE_SERVER_GUILE
8146 
8147 SCM
radscm_datum_to_scm(grad_value_t * val)8148 radscm_datum_to_scm(grad_value_t *val)
8149 {
8150         switch (val->type) {
8151         case Integer:
8152                 return scm_from_long(val->datum.ival);
8153 
8154         case String:
8155 		/* FIXME! */
8156                 return scm_makfrom0str(val->datum.sval.data);
8157 
8158 	default:
8159 		grad_insist_fail("Unknown data type");
8160         }
8161         return SCM_UNSPECIFIED;
8162 }
8163 
8164 int
radscm_scm_to_ival(SCM cell,int * val)8165 radscm_scm_to_ival(SCM cell, int *val)
8166 {
8167         if (SCM_IMP(cell)) {
8168                 if (SCM_INUMP(cell))
8169                         *val = SCM_INUM(cell);
8170                 else if (SCM_BIGP(cell))
8171                         *val = (grad_uint32_t) scm_i_big2dbl(cell);
8172                 else if (SCM_CHARP(cell))
8173                         *val = SCM_CHAR(cell);
8174                 else if (cell == SCM_BOOL_F)
8175                         *val = 0;
8176                 else if (cell == SCM_BOOL_T)
8177                         *val = 1;
8178                 else if (cell == SCM_EOL)
8179                         *val =0;
8180                 else
8181                         return -1;
8182         } else {
8183                 if (scm_is_string(cell)) {
8184                         char *p;
8185                         *val = strtol(scm_i_string_chars(cell), &p, 0);
8186                         if (*p)
8187                                 return -1;
8188                 } else
8189                         return -1;
8190         }
8191         return 0;
8192 }
8193 
8194 SCM
radscm_rewrite_execute(const char * func_name,SCM ARGS)8195 radscm_rewrite_execute(const char *func_name, SCM ARGS)
8196 {
8197         const char *name;
8198         FUNCTION *fun;
8199         PARAMETER *parm;
8200         int nargs;
8201         int n, rc;
8202         grad_value_t value;
8203         SCM cell;
8204         SCM FNAME;
8205 	SCM retval;
8206 
8207         FNAME = SCM_CAR(ARGS);
8208         ARGS  = SCM_CDR(ARGS);
8209         SCM_ASSERT(scm_is_string(FNAME), FNAME, SCM_ARG1, func_name);
8210 
8211         name = scm_i_string_chars(FNAME);
8212         fun = (FUNCTION*) grad_sym_lookup(rewrite_tab, name);
8213         if (!fun)
8214                 scm_misc_error(func_name,
8215                                _("function ~S not defined"),
8216                                scm_list_1(FNAME));
8217 
8218         rw_mach_init();
8219 
8220         /* Pass arguments */
8221         nargs = 0;
8222         parm = fun->parm;
8223 
8224         for (cell = ARGS; cell != SCM_EOL;
8225 	     cell = SCM_CDR(cell), parm = parm->next) {
8226                 SCM car = SCM_CAR(cell);
8227 
8228                 if (++nargs > fun->nparm) {
8229                         rw_code_unlock();
8230                         scm_misc_error(func_name,
8231                                        _("too many arguments for ~S"),
8232                                        scm_list_1(FNAME));
8233                 }
8234 
8235                 switch (parm->datatype) {
8236                 case Integer:
8237                         rc = radscm_scm_to_ival(car, &n);
8238                         if (!rc)
8239                                 pushn(n);
8240                         break;
8241 
8242                 case String:
8243                         if (scm_is_string(car)) {
8244                                 const char *p = scm_i_string_chars(car);
8245                                 pushstr(p, strlen(p));
8246                                 rc = 0;
8247                         } else
8248                                 rc = 1;
8249 			break;
8250 
8251 		default:
8252 			grad_insist_fail("Unknown data type");
8253                 }
8254 
8255                 if (rc) {
8256                         rw_mach_destroy();
8257                         scm_misc_error(func_name,
8258 				       _("type mismatch in argument ~S(~S) in call to ~S"),
8259                                        scm_list_3(scm_from_int(nargs),
8260 						  car,
8261 						  FNAME));
8262                 }
8263         }
8264 
8265         if (fun->nparm != nargs) {
8266 		rw_mach_destroy();
8267                 scm_misc_error(func_name,
8268                                _("too few arguments for ~S"),
8269                                scm_list_1(FNAME));
8270         }
8271 
8272         /* Imitate a function call */
8273         if (setjmp(mach.jmp)) {
8274                 rw_mach_destroy();
8275                 return SCM_BOOL_F;
8276         }
8277 
8278         pushn(0);                         /* Return address */
8279         run(fun->entry);                  /* call function */
8280 
8281 	value.type = fun->rettype;
8282 	return_value(&value);
8283 	retval = radscm_datum_to_scm(&value);
8284 	grad_value_free(&value);
8285 	rw_mach_destroy();
8286         return retval;
8287 }
8288 
8289 
8290 #endif
8291 
8292         /*HONY SOIT QUI MAL Y PENSE*/
8293 
8294