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(®ex, str, regcomp_flags);
5897 if (rc) {
5898 char errbuf[512];
5899 regerror(rc, ®ex, 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(®ex, 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, "e);
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