2 /********************************************
4 copyright 1991-1996, Michael D. Brennan
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
13 /* $Log: execute.c,v $
14 * Revision 1.13 1996/02/01 04:39:40 mike
15 * dynamic array scheme
17 * Revision 1.12 1995/06/06 00:18:24 mike
18 * change mawk_exit(1) to mawk_exit(2)
20 * Revision 1.11 1995/03/08 00:06:24 mike
23 * Revision 1.10 1994/12/13 00:12:10 mike
24 * delete A statement to delete all of A at once
26 * Revision 1.9 1994/10/25 23:36:11 mike
27 * clear aloop stack on _NEXT
29 * Revision 1.8 1994/10/08 19:15:35 mike
32 * Revision 1.7 1993/12/30 19:10:03 mike
33 * minor cleanup to _CALL
35 * Revision 1.6 1993/12/01 14:25:13 mike
36 * reentrant array loops
38 * Revision 1.5 1993/07/22 00:04:08 mike
39 * new op code _LJZ _LJNZ
41 * Revision 1.4 1993/07/14 12:18:21 mike
44 * Revision 1.3 1993/07/14 11:50:17 mike
45 * rm SIZE_T and void casts
47 * Revision 1.2 1993/07/04 12:51:49 mike
48 * start on autoconfig changes
50 * Revision 5.10 1993/02/13 21:57:22 mike
53 * Revision 5.9 1993/01/07 02:50:33 mike
54 * relative vs absolute code
56 * Revision 5.8 1993/01/01 21:30:48 mike
57 * split new_STRING() into new_STRING and new_STRING0
59 * Revision 5.7.1.1 1993/01/15 03:33:39 mike
60 * patch3: safer double to int conversion
62 * Revision 5.7 1992/12/17 02:48:01 mike
63 * 1.1.2d changes for DOS
65 * Revision 5.6 1992/11/29 18:57:50 mike
66 * field expressions convert to long so 16 bit and 32 bit
67 * systems behave the same
69 * Revision 5.5 1992/08/11 15:24:55 brennan
70 * patch2: F_PUSHA and FE_PUSHA
71 * If this is preparation for g?sub(r,s,$expr) or (++|--) on $expr,
72 * then if expr > NF, make sure $expr is set to ""
74 * Revision 5.4 1992/08/11 14:51:54 brennan
75 * patch2: $expr++ is numeric even if $expr is string.
76 * I forgot to do this earlier when handling x++ case.
78 * Revision 5.3 1992/07/08 17:03:30 brennan
80 * revert to version 1.0 comparisons, i.e.
81 * page 44-45 of AWK book
83 * Revision 5.2 1992/04/20 21:40:40 brennan
85 * x++ is numeric, even if x is string
87 * Revision 5.1 1991/12/05 07:55:50 brennan
105 static int PROTO(compare, (CELL *)) ;
106 static int PROTO(d_to_index, (double)) ;
109 static char dz_msg[] = "division by zero" ;
110 #define CHECK_DIVZERO(x) if( (x) == 0.0 )rt_error(dz_msg);else
114 static void PROTO(eval_overflow, (void)) ;
116 #define inc_sp() if( ++sp == eval_stack+EVAL_STACK_SIZE )\
120 /* If things are working, the eval stack should not overflow */
122 #define inc_sp() sp++
126 #define DANGER (EVAL_STACK_SIZE-SAFETY)
128 /* The stack machine that executes the code */
130 CELL eval_stack[EVAL_STACK_SIZE] ;
131 /* these can move for deep recursion */
132 static CELL *stack_base = eval_stack ;
133 static CELL *stack_danger = eval_stack + DANGER ;
139 overflow("eval stack", EVAL_STACK_SIZE) ;
143 /* holds info for array loops (on a stack) */
144 typedef struct aloop_state {
145 struct aloop_state *link ;
146 CELL *var ; /* for(var in A) */
152 /* clean up aloop stack on next, return, exit */
153 #define CLEAR_ALOOP_STACK() if(aloop_state){\
154 clear_aloop_stack(aloop_state);\
155 aloop_state=(ALOOP_STATE*)0;}else
157 static void clear_aloop_stack(top)
163 while(top->ptr<top->limit) {
164 free_STRING(*top->ptr) ;
167 if (top->base < top->limit)
168 zfree(top->base, (top->limit-top->base)*sizeof(STRING*)) ;
169 q = top ; top = q->link ;
175 static INST *restart_label ; /* control flow labels */
177 static CELL tc ; /*useful temp */
181 register INST *cdp ; /* code ptr, start execution here */
182 register CELL *sp ; /* eval_stack pointer */
183 CELL *fp ; /* frame ptr into eval_stack for
184 user defined functions */
186 /* some useful temporaries */
190 /* save state for array loops via a stack */
191 ALOOP_STATE *aloop_state = (ALOOP_STATE*) 0 ;
193 /* for moving the eval stack on deep recursion */
194 CELL *old_stack_base ;
198 CELL *entry_sp = sp ;
204 /* we are a function call, check for deep recursion */
205 if (sp > stack_danger)
206 { /* change stacks */
207 old_stack_base = stack_base ;
209 stack_base = (CELL *) zmalloc(sizeof(CELL) * EVAL_STACK_SIZE) ;
210 stack_danger = stack_base + DANGER ;
212 /* waste 1 slot for ANSI, actually large model msdos breaks in
218 else old_stack_base = (CELL *) 0 ;
225 /* HALT only used by the disassemble now ; this remains
226 so compilers don't offset the jump table */
229 case _STOP: /* only for range patterns */
231 if (sp != entry_sp + 1) bozo("stop0") ;
237 cellcpy(sp, cdp++->ptr) ;
242 sp->type = C_DOUBLE ;
243 sp->dval = *(double *) cdp++->ptr ;
248 sp->type = C_STRING ;
249 sp->ptr = cdp++->ptr ;
250 string(sp)->ref_cnt++ ;
254 cp = (CELL *) cdp->ptr ;
257 if (nf < 0) split_field0() ;
261 SAMESEG(cp, field) &&
263 cp >= NF && cp <= LAST_PFIELD))
265 /* its a real field $1, $2 ...
266 If its greater than $NF, we have to
267 make sure its set to "" so that
268 (++|--) and g?sub() work right
270 t = field_addr_to_index(cp) ;
274 cp->type = C_STRING ;
275 cp->ptr = (PTR) & null_str ;
285 sp->ptr = cdp++->ptr ;
289 /* put contents of next address on stack*/
291 cellcpy(sp, cdp++->ptr) ;
295 /* put the contents of a local var on stack,
296 cdp->op holds the offset from the frame pointer */
298 cellcpy(sp, fp + cdp++->op) ;
302 /* put a local address on eval stack */
304 sp->ptr = (PTR) (fp + cdp++->op) ;
310 /* push contents of $i
311 cdp[0] holds & $i , cdp[1] holds i */
314 if (nf < 0) split_field0() ;
315 cp = (CELL *) cdp->ptr ;
319 if (t <= nf) cellcpy(sp, cp) ;
320 else /* an unset field */
322 sp->type = C_STRING ;
323 sp->ptr = (PTR) & null_str ;
331 if (nf < 0) split_field0() ;
337 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
339 t = d_to_index(sp->dval) ;
340 if (t && nf < 0) split_field0() ;
341 sp->ptr = (PTR) field_ptr(t) ;
344 /* make sure its set to "" */
345 cp = (CELL *) sp->ptr ;
347 cp->type = C_STRING ;
348 cp->ptr = (PTR) & null_str ;
355 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
357 t = d_to_index(sp->dval) ;
359 if (nf < 0) split_field0() ;
360 if (t <= nf) cellcpy(sp, field_ptr(t)) ;
363 sp->type = C_STRING ;
364 sp->ptr = (PTR) & null_str ;
371 /* top of stack has an expr, cdp->ptr points at an
372 array, replace the expr with the cell address inside
375 cp = array_find((ARRAY) cdp++->ptr, sp, CREATE) ;
381 /* top of stack has an expr, cdp->ptr points at an
382 array, replace the expr with the contents of the
383 cell inside the array */
385 cp = array_find((ARRAY) cdp++->ptr, sp, CREATE) ;
391 /* sp[0] is an expression
392 cdp->op is offset from frame pointer of a CELL which
393 has an ARRAY in the ptr field, replace expr
396 cp = array_find((ARRAY) fp[cdp++->op].ptr, sp, CREATE) ;
402 /* sp[0] is an expression
403 cdp->op is offset from frame pointer of a CELL which
404 has an ARRAY in the ptr field, replace expr
407 cp = array_find((ARRAY) fp[cdp++->op].ptr, sp, CREATE) ;
413 /* cdp->op is offset from frame pointer of a CELL which
414 has an ARRAY in the ptr field. Push this ARRAY
418 sp->ptr = fp[cdp++->op].ptr ;
423 ALOOP_STATE *ap = ZMALLOC(ALOOP_STATE) ;
424 unsigned vector_size ;
426 ap->var = (CELL *) sp[-1].ptr ;
427 ap->base = ap->ptr = array_loop_vector(
428 (ARRAY)sp->ptr, &vector_size) ;
429 ap->limit = ap->base + vector_size ;
432 /* push onto aloop stack */
433 ap->link = aloop_state ;
441 ALOOP_STATE *ap = aloop_state ;
442 if (ap->ptr < ap->limit)
444 cell_destroy(ap->var) ;
445 ap->var->type = C_STRING ;
446 ap->var->ptr = (PTR) *ap->ptr++ ;
455 /* finish up an array loop */
456 ALOOP_STATE *ap = aloop_state ;
457 aloop_state = ap->link ;
458 while(ap->ptr < ap->limit) {
459 free_STRING(*ap->ptr) ;
462 if (ap->base < ap->limit)
463 zfree(ap->base,(ap->limit-ap->base)*sizeof(STRING*)) ;
474 /* top of stack has an expr, next down is an
475 address, put the expression in *address and
476 replace the address with the expression */
478 /* don't propagate type C_MBSTRN */
479 if (sp->type == C_MBSTRN) check_strnum(sp) ;
481 cell_destroy(((CELL *) sp->ptr)) ;
482 cellcpy(sp, cellcpy(sp->ptr, sp + 1)) ;
483 cell_destroy(sp + 1) ;
487 /* assign to a field */
488 if (sp->type == C_MBSTRN) check_strnum(sp) ;
490 field_assign((CELL *) sp->ptr, sp + 1) ;
491 cell_destroy(sp + 1) ;
492 cellcpy(sp, (CELL *) sp->ptr) ;
496 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
497 cp = (CELL *) (sp - 1)->ptr ;
498 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
500 #if SW_FP_CHECK /* specific to V7 and XNX23A */
503 cp->dval += sp--->dval ;
507 sp->type = C_DOUBLE ;
508 sp->dval = cp->dval ;
512 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
513 cp = (CELL *) (sp - 1)->ptr ;
514 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
518 cp->dval -= sp--->dval ;
522 sp->type = C_DOUBLE ;
523 sp->dval = cp->dval ;
527 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
528 cp = (CELL *) (sp - 1)->ptr ;
529 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
533 cp->dval *= sp--->dval ;
537 sp->type = C_DOUBLE ;
538 sp->dval = cp->dval ;
542 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
543 cp = (CELL *) (sp - 1)->ptr ;
544 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
547 CHECK_DIVZERO(sp->dval) ;
553 cp->dval /= sp--->dval ;
557 sp->type = C_DOUBLE ;
558 sp->dval = cp->dval ;
562 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
563 cp = (CELL *) (sp - 1)->ptr ;
564 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
567 CHECK_DIVZERO(sp->dval) ;
570 cp->dval = fmod(cp->dval, sp--->dval) ;
571 sp->type = C_DOUBLE ;
572 sp->dval = cp->dval ;
576 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
577 cp = (CELL *) (sp - 1)->ptr ;
578 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
579 cp->dval = pow(cp->dval, sp--->dval) ;
580 sp->type = C_DOUBLE ;
581 sp->dval = cp->dval ;
584 /* will anyone ever use these ? */
587 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
588 cp = (CELL *) (sp - 1)->ptr ;
589 cast1_to_d(cellcpy(&tc, cp)) ;
593 tc.dval += sp--->dval ;
597 sp->type = C_DOUBLE ;
599 field_assign(cp, &tc) ;
603 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
604 cp = (CELL *) (sp - 1)->ptr ;
605 cast1_to_d(cellcpy(&tc, cp)) ;
609 tc.dval -= sp--->dval ;
613 sp->type = C_DOUBLE ;
615 field_assign(cp, &tc) ;
619 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
620 cp = (CELL *) (sp - 1)->ptr ;
621 cast1_to_d(cellcpy(&tc, cp)) ;
625 tc.dval *= sp--->dval ;
629 sp->type = C_DOUBLE ;
631 field_assign(cp, &tc) ;
635 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
636 cp = (CELL *) (sp - 1)->ptr ;
637 cast1_to_d(cellcpy(&tc, cp)) ;
640 CHECK_DIVZERO(sp->dval) ;
646 tc.dval /= sp--->dval ;
650 sp->type = C_DOUBLE ;
652 field_assign(cp, &tc) ;
656 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
657 cp = (CELL *) (sp - 1)->ptr ;
658 cast1_to_d(cellcpy(&tc, cp)) ;
661 CHECK_DIVZERO(sp->dval) ;
664 tc.dval = fmod(tc.dval, sp--->dval) ;
665 sp->type = C_DOUBLE ;
667 field_assign(cp, &tc) ;
671 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
672 cp = (CELL *) (sp - 1)->ptr ;
673 cast1_to_d(cellcpy(&tc, cp)) ;
674 tc.dval = pow(tc.dval, sp--->dval) ;
675 sp->type = C_DOUBLE ;
677 field_assign(cp, &tc) ;
682 if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp) ;
686 sp[0].dval += sp[1].dval ;
694 if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp) ;
698 sp[0].dval -= sp[1].dval ;
706 if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp) ;
710 sp[0].dval *= sp[1].dval ;
718 if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp) ;
721 CHECK_DIVZERO(sp[1].dval) ;
727 sp[0].dval /= sp[1].dval ;
735 if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp) ;
738 CHECK_DIVZERO(sp[1].dval) ;
741 sp[0].dval = fmod(sp[0].dval, sp[1].dval) ;
746 if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp) ;
747 sp[0].dval = pow(sp[0].dval, sp[1].dval) ;
751 /* evaluates to 0.0 or 1.0 */
756 sp->dval = 1.0 ; break ;
758 sp->dval = sp->dval != 0.0 ? 0.0 : 1.0 ;
761 sp->dval = string(sp)->len ? 0.0 : 1.0 ;
762 free_STRING(string(sp)) ;
764 case C_STRNUM: /* test as a number */
765 sp->dval = sp->dval != 0.0 ? 0.0 : 1.0 ;
766 free_STRING(string(sp)) ;
772 bozo("bad type on eval stack") ;
774 sp->type = C_DOUBLE ;
778 /* evaluates to 0.0 or 1.0 */
783 sp->dval = 0.0 ; break ;
785 sp->dval = sp->dval != 0.0 ? 1.0 : 0.0 ;
788 sp->dval = string(sp)->len ? 1.0 : 0.0 ;
789 free_STRING(string(sp)) ;
791 case C_STRNUM: /* test as a number */
792 sp->dval = sp->dval != 0.0 ? 1.0 : 0.0 ;
793 free_STRING(string(sp)) ;
799 bozo("bad type on eval stack") ;
801 sp->type = C_DOUBLE ;
805 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
806 sp->dval = -sp->dval ;
810 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
815 unsigned len1, len2 ;
820 if (TEST2(sp) != TWO_STRINGS) cast2_to_s(sp) ;
821 str1 = string(sp)->str ;
822 len1 = string(sp)->len ;
823 str2 = string(sp + 1)->str ;
824 len2 = string(sp + 1)->len ;
826 b = new_STRING0(len1 + len2) ;
827 memcpy(b->str, str1, len1) ;
828 memcpy(b->str + len1, str2, len2) ;
829 free_STRING(string(sp)) ;
830 free_STRING(string(sp + 1)) ;
838 sp->type = cdp++->op ;
843 sp = (*(PF_CP) cdp++->ptr) (sp) ;
847 cp = (CELL *) sp->ptr ;
848 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
849 sp->type = C_DOUBLE ;
850 sp->dval = cp->dval ;
855 cp = (CELL *) sp->ptr ;
856 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
857 sp->type = C_DOUBLE ;
858 sp->dval = cp->dval ;
863 cp = (CELL *) sp->ptr ;
864 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
865 sp->dval = cp->dval += 1.0 ;
866 sp->type = C_DOUBLE ;
870 cp = (CELL *) sp->ptr ;
871 if (cp->type != C_DOUBLE) cast1_to_d(cp) ;
872 sp->dval = cp->dval -= 1.0 ;
873 sp->type = C_DOUBLE ;
878 cp = (CELL *) sp->ptr ;
881 sp->type = C_DOUBLE ;
884 field_assign(cp, &tc) ;
888 cp = (CELL *) sp->ptr ;
891 sp->type = C_DOUBLE ;
894 field_assign(cp, &tc) ;
898 cp = (CELL *) sp->ptr ;
899 cast1_to_d(cellcpy(sp, cp)) ;
901 field_assign(cp, sp) ;
905 cp = (CELL *) sp->ptr ;
906 cast1_to_d(cellcpy(sp, cp)) ;
908 field_assign(cp, sp) ;
916 /* jmp if top of stack is non-zero and pop stack */
917 if (test(sp)) cdp += cdp->op ;
924 /* jmp if top of stack is zero and pop stack */
925 if (!test(sp)) cdp += cdp->op ;
932 /* special jump for logical and */
933 /* this is always preceded by _TEST */
934 if ( sp->dval == 0.0 )
936 /* take jump, but don't pop stack */
941 /* pop and don't jump */
948 /* special jump for logical or */
949 /* this is always preceded by _TEST */
950 if ( sp->dval != 0.0 )
952 /* take jump, but don't pop stack */
957 /* pop and don't jump */
963 /* the relation operations */
964 /* compare() makes sure string ref counts are OK */
967 sp->type = C_DOUBLE ;
968 sp->dval = t == 0 ? 1.0 : 0.0 ;
973 sp->type = C_DOUBLE ;
974 sp->dval = t ? 1.0 : 0.0 ;
979 sp->type = C_DOUBLE ;
980 sp->dval = t < 0 ? 1.0 : 0.0 ;
985 sp->type = C_DOUBLE ;
986 sp->dval = t <= 0 ? 1.0 : 0.0 ;
991 sp->type = C_DOUBLE ;
992 sp->dval = t > 0 ? 1.0 : 0.0 ;
997 sp->type = C_DOUBLE ;
998 sp->dval = t >= 0 ? 1.0 : 0.0 ;
1002 /* does $0 match, the RE at cdp? */
1005 if (field->type >= C_STRING)
1007 sp->type = C_DOUBLE ;
1008 sp->dval = REtest(string(field)->str, cdp++->ptr)
1011 break /* the case */ ;
1015 cellcpy(sp, field) ;
1020 /* does expr at sp[0] match RE at cdp */
1021 if (sp->type < C_STRING) cast1_to_s(sp) ;
1022 t = REtest(string(sp)->str, cdp++->ptr) ;
1023 free_STRING(string(sp)) ;
1024 sp->type = C_DOUBLE ;
1025 sp->dval = t ? 1.0 : 0.0 ;
1030 /* does sp[-1] match sp[0] as re */
1033 if ((--sp)->type < C_STRING) cast1_to_s(sp) ;
1034 t = REtest(string(sp)->str, (sp + 1)->ptr) ;
1036 free_STRING(string(sp)) ;
1037 sp->type = C_DOUBLE ;
1038 sp->dval = t ? 1.0 : 0.0 ;
1042 /* entry : sp[0].ptr-> an array
1043 sp[-1] is an expression
1045 we compute (expression in array) */
1047 cp = array_find((sp + 1)->ptr, sp, NO_CREATE) ;
1049 sp->type = C_DOUBLE ;
1050 sp->dval = (cp != (CELL *) 0) ? 1.0 : 0.0 ;
1054 /* sp[0].ptr -> array
1056 delete array[expr] */
1058 array_delete(sp->ptr, sp - 1) ;
1059 cell_destroy(sp - 1) ;
1064 /* free all the array at once */
1065 array_clear(sp->ptr) ;
1069 /* form a multiple array index */
1071 sp = array_cat(sp, cdp++->op) ;
1075 if (sp->type != C_DOUBLE) cast1_to_d(sp) ;
1076 exit_code = d_to_i(sp->dval) ;
1082 if (!end_start) mawk_exit(exit_code) ;
1085 end_start = (INST *) 0 ; /* makes sure next exit exits */
1087 if (begin_start) zfree(begin_start, begin_size) ;
1088 if (main_start) zfree(main_start, main_size) ;
1089 sp = eval_stack - 1 ;/* might be in user function */
1090 CLEAR_ALOOP_STACK() ; /* ditto */
1093 case _JMAIN: /* go from BEGIN code to MAIN code */
1094 zfree(begin_start, begin_size) ;
1095 begin_start = (INST *) 0 ;
1100 if (!main_fin) open_main() ;
1101 restart_label = cdp ;
1106 /* next might be inside an aloop -- clear stack */
1107 CLEAR_ALOOP_STACK() ;
1116 if (!(p = FINgets(main_fin, &len)))
1118 if (!end_start) mawk_exit(0) ;
1121 zfree(main_start, main_size) ;
1122 main_start = end_start = (INST *) 0 ;
1126 set_field0(p, len) ;
1127 cdp = restart_label ;
1128 rt_nr++ ; rt_fnr++ ;
1133 /* two kinds of OL_GL is a historical stupidity from working on
1134 a machine with very slow floating point emulation */
1140 if (!(p = FINgets(main_fin, &len)))
1142 if (!end_start) mawk_exit(0) ;
1145 zfree(main_start, main_size) ;
1146 main_start = end_start = (INST *) 0 ;
1150 set_field0(p, len) ;
1151 cdp = restart_label ;
1153 if (TEST2(NR) != TWO_DOUBLES) cast2_to_d(NR) ;
1155 NR->dval += 1.0 ; rt_nr++ ;
1156 FNR->dval += 1.0 ; rt_fnr++ ;
1163 /* test a range pattern: pat1, pat2 { action }
1165 cdp[0].op -- a flag, test pat1 if on else pat2
1166 cdp[1].op -- offset of pat2 code from cdp
1167 cdp[2].op -- offset of action code from cdp
1168 cdp[3].op -- offset of code after the action from cdp
1169 cdp[4] -- start of pat1 code
1172 #define FLAG cdp[0].op
1173 #define PAT2 cdp[1].op
1174 #define ACTION cdp[2].op
1175 #define FOLLOW cdp[3].op
1178 if (FLAG) /* test again pat1 */
1180 execute(cdp + PAT1, sp, fp) ;
1182 cell_destroy(sp + 1) ;
1187 break ; /* break the switch */
1191 /* test against pat2 and then perform the action */
1192 execute(cdp + PAT2, sp, fp) ;
1193 FLAG = test(sp + 1) ;
1194 cell_destroy(sp + 1) ;
1198 /* function calls */
1202 sp->type = C_NOINIT ;
1208 if (sp != entry_sp + 1) bozo("ret") ;
1210 if (old_stack_base) /* reset stack */
1212 /* move the return value */
1213 cellcpy(old_sp + 1, sp) ;
1215 zfree(stack_base, sizeof(CELL) * EVAL_STACK_SIZE) ;
1216 stack_base = old_stack_base ;
1217 stack_danger = old_stack_base + DANGER ;
1220 /* return might be inside an aloop -- clear stack */
1221 CLEAR_ALOOP_STACK() ;
1227 /* cdp[0] holds ptr to "function block"
1228 cdp[1] holds number of input arguments
1232 FBLOCK *fbp = (FBLOCK *) cdp++->ptr ;
1233 int a_args = cdp++->op ; /* actual number of args */
1234 CELL *nfp = sp - a_args + 1 ; /* new fp for callee */
1235 CELL *local_p = sp + 1 ; /* first local argument on stack */
1236 char *type_p ; /* pts to type of an argument */
1238 if (fbp->nargs) type_p = fbp->typev + a_args - 1 ;
1240 /* create space for locals */
1241 t = fbp->nargs - a_args ; /* t is number of locals */
1244 t-- ; sp++ ; type_p++ ;
1245 sp->type = C_NOINIT ;
1246 if (*type_p == ST_LOCAL_ARRAY)
1247 sp->ptr = (PTR) new_ARRAY() ;
1250 execute(fbp->code, sp, nfp) ;
1252 /* cleanup the callee's arguments */
1253 /* putting return value at top of eval stack */
1256 cp = sp + 1 ; /* cp -> the function return */
1260 if (*type_p == ST_LOCAL_ARRAY)
1264 array_clear(sp->ptr) ;
1265 ZFREE((ARRAY)sp->ptr) ;
1268 else cell_destroy(sp) ;
1278 else sp++ ; /* no arguments passed */
1283 bozo("bad opcode") ;
1289 return 0 if a numeric is zero else return non-zero
1290 return 0 if a string is "" else return non-zero
1302 case C_STRNUM: /* test as a number */
1304 return cp->dval != 0.0 ;
1306 return string(cp)->len ;
1307 case C_MBSTRN : check_strnum(cp) ; goto reswitch ;
1309 bozo("bad cell type in call to test") ;
1311 return 0 ; /*can't get here: shutup */
1314 /* compare cells at cp and cp+1 and
1315 frees STRINGs at those cells
1332 return cp->dval > (cp + 1)->dval ? 1 :
1333 cp->dval < (cp + 1)->dval ? -1 : 0 ;
1336 case STRING_AND_STRNUM:
1338 k = strcmp(string(cp)->str, string(cp + 1)->str) ;
1339 free_STRING(string(cp)) ;
1340 free_STRING(string(cp + 1)) ;
1343 case NOINIT_AND_DOUBLE:
1344 case NOINIT_AND_STRNUM:
1345 case DOUBLE_AND_STRNUM:
1347 cast2_to_d(cp) ; goto two_d ;
1348 case NOINIT_AND_STRING:
1349 case DOUBLE_AND_STRING:
1350 cast2_to_s(cp) ; goto two_s ;
1352 check_strnum(cp) ; check_strnum(cp+1) ;
1355 case NOINIT_AND_MBSTRN:
1356 case DOUBLE_AND_MBSTRN:
1357 case STRING_AND_MBSTRN:
1358 case STRNUM_AND_MBSTRN:
1359 check_strnum(cp->type == C_MBSTRN ? cp : cp + 1) ;
1362 default: /* there are no default cases */
1363 bozo("bad cell type passed to compare") ;
1365 return 0 ; /* shut up */
1368 /* does not assume target was a cell, if so
1369 then caller should have made a previous
1370 call to cell_destroy */
1373 cellcpy(target, source)
1374 register CELL *target, *source ;
1376 switch (target->type = source->type)
1384 target->dval = source->dval ;
1388 target->dval = source->dval ;
1394 string(source)->ref_cnt++ ;
1398 target->ptr = source->ptr ;
1402 replv_cpy(target, source) ;
1406 bozo("bad cell passed to cellcpy()") ;
1415 DB_cell_destroy(cp) /* HANGOVER time */
1427 if (--string(cp)->ref_cnt == 0)
1428 zfree(string(cp), string(cp)->len + STRING_OH) ;
1432 bozo("cell destroy called on RE cell") ;
1434 bozo("cell destroy called on bad cell type") ;
1442 /* convert a double d to a field index $d -> $i */
1449 rt_overflow("maximum number of fields", MAX_FIELD) ;
1451 if (d >= 0.0) return (int) d ;
1453 /* might include nan */
1454 rt_error("negative field index $%.6g", d) ;
1455 return 0 ; /* shutup */