1 /********************************************
2 execute.c
3 copyright 2008-2017,2018, Thomas E. Dickey
4 copyright 1991-1995,1996, Michael D. Brennan
5 
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
8 
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
12 
13 /*
14  * $MawkId: execute.c,v 1.44 2018/11/15 01:20:01 tom Exp $
15  */
16 
17 #include "mawk.h"
18 #include "files.h"
19 #include "code.h"
20 #include "memory.h"
21 #include "symtype.h"
22 #include "field.h"
23 #include "bi_funct.h"
24 #include "bi_vars.h"
25 #include "regexp.h"
26 #include "repl.h"
27 #include "fin.h"
28 
29 #include <math.h>
30 
31 static int compare(CELL *);
32 static UInt d_to_index(double);
33 
34 #ifdef	 NOINFO_SIGFPE
35 static char dz_msg[] = "division by zero";
36 #define	 CHECK_DIVZERO(x) do { if ((x) == 0.0 ) rt_error(dz_msg); } while (0)
37 #endif
38 
39 #define	 inc_sp()   if ( ++sp == stack_danger) eval_overflow()
40 #define  dec_sp()   if ( sp-- == (stack_base - 1)) eval_underflow()
41 
42 #define	 SAFETY	   16
43 #define	 DANGER	   (EVAL_STACK_SIZE-SAFETY)
44 
45 /*  The stack machine that executes the code */
46 
47 CELL eval_stack[EVAL_STACK_SIZE];
48 /* these can move for deep recursion */
49 static CELL *stack_base = eval_stack;
50 static CELL *stack_danger = eval_stack + DANGER;
51 
52 static void
eval_overflow(void)53 eval_overflow(void)
54 {
55     overflow("eval stack", EVAL_STACK_SIZE);
56 }
57 
58 static void
eval_underflow(void)59 eval_underflow(void)
60 {
61     bozo("eval stack underflow");
62 }
63 
64 /* holds info for array loops (on a stack) */
65 typedef struct aloop_state {
66     struct aloop_state *link;
67     CELL *var;			/* for(var in A) */
68     STRING **base;
69     STRING **ptr;
70     STRING **limit;
71 } ALOOP_STATE;
72 
73 /* clean up aloop stack on next, return, exit */
74 #define CLEAR_ALOOP_STACK() \
75 	do { \
76 	    if (aloop_state) { \
77 		    clear_aloop_stack(aloop_state); \
78 		    aloop_state = (ALOOP_STATE *) 0; \
79 	    } \
80 	} while (0)
81 
82 static void
clear_aloop_stack(ALOOP_STATE * top)83 clear_aloop_stack(ALOOP_STATE * top)
84 {
85     ALOOP_STATE *q;
86 
87     do {
88 	while (top->ptr < top->limit) {
89 	    free_STRING(*top->ptr);
90 	    top->ptr++;
91 	}
92 	if (top->base < top->limit) {
93 	    zfree(top->base,
94 		  (unsigned) (top->limit - top->base) * sizeof(STRING *));
95 	}
96 	q = top;
97 	top = q->link;
98 	ZFREE(q);
99     } while (top);
100 }
101 
102 static INST *restart_label;	/* control flow labels */
103 INST *next_label;
104 static CELL tc;			/*useful temp */
105 
106 void
execute(INST * cdp,CELL * sp,CELL * fp)107 execute(INST * cdp,		/* code ptr, start execution here */
108 	CELL *sp,		/* eval_stack pointer */
109 	CELL *fp)		/* frame ptr into eval_stack for
110 				   user defined functions */
111 {
112     /* some useful temporaries */
113     CELL *cp;
114     int t;
115     unsigned tu;
116 
117     /* save state for array loops via a stack */
118     ALOOP_STATE *aloop_state = (ALOOP_STATE *) 0;
119 
120     /* for moving the eval stack on deep recursion */
121     CELL *old_stack_base = 0;
122     CELL *old_sp = 0;
123 
124 #ifdef	DEBUG
125     CELL *entry_sp = sp;
126 #endif
127 
128     if (fp) {
129 	/* we are a function call, check for deep recursion */
130 	if (sp > stack_danger) {	/* change stacks */
131 	    old_stack_base = stack_base;
132 	    old_sp = sp;
133 	    stack_base = (CELL *) zmalloc(sizeof(CELL) * EVAL_STACK_SIZE);
134 	    stack_danger = stack_base + DANGER;
135 	    sp = stack_base;
136 	    /* waste 1 slot for ANSI, actually large model msdos breaks in
137 	       RET if we don't */
138 #ifdef	DEBUG
139 	    entry_sp = sp;
140 #endif
141 	} else
142 	    old_stack_base = (CELL *) 0;
143     }
144 
145     while (1) {
146 
147 	TRACE(("execute %s sp(%ld:%s)\n",
148 	       da_op_name(cdp),
149 	       (long) (sp - stack_base),
150 	       da_type_name(sp)));
151 
152 	switch ((cdp++)->op) {
153 
154 /* HALT only used by the disassemble now ; this remains
155    so compilers don't offset the jump table */
156 	case _HALT:
157 
158 	case _STOP:		/* only for range patterns */
159 #ifdef	DEBUG
160 	    if (sp != entry_sp + 1)
161 		bozo("stop0");
162 #endif
163 	    return;
164 
165 	case _PUSHC:
166 	    inc_sp();
167 	    cellcpy(sp, (cdp++)->ptr);
168 	    break;
169 
170 	case _PUSHD:
171 	    inc_sp();
172 	    sp->type = C_DOUBLE;
173 	    sp->dval = *(double *) (cdp++)->ptr;
174 	    break;
175 
176 	case _PUSHS:
177 	    inc_sp();
178 	    sp->type = C_STRING;
179 	    sp->ptr = (cdp++)->ptr;
180 	    string(sp)->ref_cnt++;
181 	    break;
182 
183 	case F_PUSHA:
184 	    cp = (CELL *) cdp->ptr;
185 	    if (cp != field) {
186 		if (nf < 0)
187 		    split_field0();
188 
189 		if (!(cp >= NF && cp <= LAST_PFIELD)) {
190 		    /* it is a real field $1, $2 ...
191 		       If it is greater than $NF, we have to
192 		       make sure it is set to ""  so that
193 		       (++|--) and g?sub() work right
194 		     */
195 		    t = field_addr_to_index(cp);
196 		    if (t > nf) {
197 			cp->type = C_STRING;
198 			cp->ptr = (PTR) & null_str;
199 			null_str.ref_cnt++;
200 		    }
201 		}
202 	    }
203 	    /* FALLTHRU */
204 
205 	case _PUSHA:
206 	case A_PUSHA:
207 	    inc_sp();
208 	    sp->ptr = (cdp++)->ptr;
209 	    break;
210 
211 	case _PUSHI:
212 	    /* put contents of next address on stack */
213 	    inc_sp();
214 	    cellcpy(sp, (cdp++)->ptr);
215 	    break;
216 
217 	case L_PUSHI:
218 	    /* put the contents of a local var on stack,
219 	       cdp->op holds the offset from the frame pointer */
220 	    inc_sp();
221 	    cellcpy(sp, fp + (cdp++)->op);
222 	    break;
223 
224 	case L_PUSHA:
225 	    /* put a local address on eval stack */
226 	    inc_sp();
227 	    sp->ptr = (PTR) (fp + (cdp++)->op);
228 	    break;
229 
230 	case F_PUSHI:
231 
232 	    /* push contents of $i
233 	       cdp[0] holds & $i , cdp[1] holds i */
234 
235 	    inc_sp();
236 	    if (nf < 0)
237 		split_field0();
238 	    cp = (CELL *) cdp->ptr;
239 	    t = (cdp + 1)->op;
240 	    cdp += 2;
241 
242 	    if (t <= nf)
243 		cellcpy(sp, cp);
244 	    else {		/* an unset field */
245 		sp->type = C_STRING;
246 		sp->ptr = (PTR) & null_str;
247 		null_str.ref_cnt++;
248 	    }
249 	    break;
250 
251 	case NF_PUSHI:
252 
253 	    inc_sp();
254 	    if (nf < 0)
255 		split_field0();
256 	    cellcpy(sp, NF);
257 	    break;
258 
259 	case FE_PUSHA:
260 
261 	    if (sp->type != C_DOUBLE)
262 		cast1_to_d(sp);
263 
264 	    tu = d_to_index(sp->dval);
265 	    if (tu && nf < 0)
266 		split_field0();
267 	    sp->ptr = (PTR) field_ptr((int) tu);
268 	    if ((int) tu > nf) {
269 		/* make sure it is set to "" */
270 		cp = (CELL *) sp->ptr;
271 		cell_destroy(cp);
272 		cp->type = C_STRING;
273 		cp->ptr = (PTR) & null_str;
274 		null_str.ref_cnt++;
275 	    }
276 	    break;
277 
278 	case FE_PUSHI:
279 
280 	    if (sp->type != C_DOUBLE)
281 		cast1_to_d(sp);
282 
283 	    tu = d_to_index(sp->dval);
284 
285 	    if (nf < 0)
286 		split_field0();
287 	    if ((int) tu <= nf) {
288 		cellcpy(sp, field_ptr((int) tu));
289 	    } else {
290 		sp->type = C_STRING;
291 		sp->ptr = (PTR) & null_str;
292 		null_str.ref_cnt++;
293 	    }
294 	    break;
295 
296 	case AE_PUSHA:
297 	    /* top of stack has an expr, cdp->ptr points at an
298 	       array, replace the expr with the cell address inside
299 	       the array */
300 
301 	    cp = array_find((ARRAY) (cdp++)->ptr, sp, CREATE);
302 	    cell_destroy(sp);
303 	    sp->ptr = (PTR) cp;
304 	    break;
305 
306 	case AE_PUSHI:
307 	    /* top of stack has an expr, cdp->ptr points at an
308 	       array, replace the expr with the contents of the
309 	       cell inside the array */
310 
311 	    cp = array_find((ARRAY) (cdp++)->ptr, sp, CREATE);
312 	    cell_destroy(sp);
313 	    cellcpy(sp, cp);
314 	    break;
315 
316 	case LAE_PUSHI:
317 	    /*  sp[0] is an expression
318 	       cdp->op is offset from frame pointer of a CELL which
319 	       has an ARRAY in the ptr field, replace expr
320 	       with  array[expr]
321 	     */
322 	    if (fp != 0) {
323 		cp = array_find((ARRAY) fp[(cdp++)->op].ptr, sp, CREATE);
324 		cell_destroy(sp);
325 		cellcpy(sp, cp);
326 	    }
327 	    break;
328 
329 	case LAE_PUSHA:
330 	    /*  sp[0] is an expression
331 	       cdp->op is offset from frame pointer of a CELL which
332 	       has an ARRAY in the ptr field, replace expr
333 	       with  & array[expr]
334 	     */
335 	    if (fp != 0) {
336 		cp = array_find((ARRAY) fp[(cdp++)->op].ptr, sp, CREATE);
337 		cell_destroy(sp);
338 		sp->ptr = (PTR) cp;
339 	    }
340 	    break;
341 
342 	case LA_PUSHA:
343 	    /*  cdp->op is offset from frame pointer of a CELL which
344 	       has an ARRAY in the ptr field. Push this ARRAY
345 	       on the eval stack
346 	     */
347 	    if (fp != 0) {
348 		inc_sp();
349 		sp->ptr = fp[(cdp++)->op].ptr;
350 	    }
351 	    break;
352 
353 	case SET_ALOOP:
354 	    {
355 		ALOOP_STATE *ap = ZMALLOC(ALOOP_STATE);
356 		size_t vector_size;
357 
358 		ap->var = (CELL *) sp[-1].ptr;
359 		ap->base = ap->ptr = array_loop_vector((ARRAY) sp->ptr, &vector_size);
360 		ap->limit = ap->base + vector_size;
361 		sp -= 2;
362 
363 		/* push onto aloop stack */
364 		ap->link = aloop_state;
365 		aloop_state = ap;
366 		cdp += cdp->op;
367 	    }
368 	    break;
369 
370 	case ALOOP:
371 	    {
372 		ALOOP_STATE *ap = aloop_state;
373 		if (ap != 0 && (ap->ptr < ap->limit)) {
374 		    cell_destroy(ap->var);
375 		    ap->var->type = C_STRING;
376 		    ap->var->ptr = (PTR) * ap->ptr++;
377 		    cdp += cdp->op;
378 		} else {
379 		    cdp++;
380 		}
381 	    }
382 	    break;
383 
384 	case POP_AL:
385 	    {
386 		/* finish up an array loop */
387 		ALOOP_STATE *ap = aloop_state;
388 		if (ap != 0) {
389 		    aloop_state = ap->link;
390 		    while (ap->ptr < ap->limit) {
391 			free_STRING(*ap->ptr);
392 			ap->ptr++;
393 		    }
394 		    if (ap->base < ap->limit) {
395 			zfree(ap->base,
396 			      ((unsigned) (ap->limit - ap->base)
397 			       * sizeof(STRING *)));
398 		    }
399 		    ZFREE(ap);
400 		}
401 	    }
402 	    break;
403 
404 	case _POP:
405 	    cell_destroy(sp);
406 	    dec_sp();
407 	    break;
408 
409 	case _ASSIGN:
410 	    /* top of stack has an expr, next down is an
411 	       address, put the expression in *address and
412 	       replace the address with the expression */
413 
414 	    /* don't propagate type C_MBSTRN */
415 	    if (sp->type == C_MBSTRN)
416 		check_strnum(sp);
417 	    dec_sp();
418 	    cell_destroy(((CELL *) sp->ptr));
419 	    cellcpy(sp, cellcpy(sp->ptr, sp + 1));
420 	    cell_destroy(sp + 1);
421 	    break;
422 
423 	case F_ASSIGN:
424 	    /* assign to a field  */
425 	    if (sp->type == C_MBSTRN)
426 		check_strnum(sp);
427 	    dec_sp();
428 	    field_assign((CELL *) sp->ptr, sp + 1);
429 	    cell_destroy(sp + 1);
430 	    cellcpy(sp, (CELL *) sp->ptr);
431 	    break;
432 
433 	case _ADD_ASG:
434 	    if (sp->type != C_DOUBLE)
435 		cast1_to_d(sp);
436 	    cp = (CELL *) (sp - 1)->ptr;
437 	    if (cp->type != C_DOUBLE)
438 		cast1_to_d(cp);
439 
440 #ifdef SW_FP_CHECK		/* specific to V7 and XNX23A */
441 	    clrerr();
442 #endif
443 	    cp->dval += sp->dval;
444 	    dec_sp();
445 #ifdef SW_FP_CHECK
446 	    fpcheck();
447 #endif
448 	    sp->type = C_DOUBLE;
449 	    sp->dval = cp->dval;
450 	    break;
451 
452 	case _SUB_ASG:
453 	    if (sp->type != C_DOUBLE)
454 		cast1_to_d(sp);
455 	    cp = (CELL *) (sp - 1)->ptr;
456 	    if (cp->type != C_DOUBLE)
457 		cast1_to_d(cp);
458 #ifdef SW_FP_CHECK
459 	    clrerr();
460 #endif
461 	    cp->dval -= sp->dval;
462 	    dec_sp();
463 #ifdef SW_FP_CHECK
464 	    fpcheck();
465 #endif
466 	    sp->type = C_DOUBLE;
467 	    sp->dval = cp->dval;
468 	    break;
469 
470 	case _MUL_ASG:
471 	    if (sp->type != C_DOUBLE)
472 		cast1_to_d(sp);
473 	    cp = (CELL *) (sp - 1)->ptr;
474 	    if (cp->type != C_DOUBLE)
475 		cast1_to_d(cp);
476 #ifdef SW_FP_CHECK
477 	    clrerr();
478 #endif
479 	    cp->dval *= sp->dval;
480 	    dec_sp();
481 #ifdef SW_FP_CHECK
482 	    fpcheck();
483 #endif
484 	    sp->type = C_DOUBLE;
485 	    sp->dval = cp->dval;
486 	    break;
487 
488 	case _DIV_ASG:
489 	    if (sp->type != C_DOUBLE)
490 		cast1_to_d(sp);
491 	    cp = (CELL *) (sp - 1)->ptr;
492 	    if (cp->type != C_DOUBLE)
493 		cast1_to_d(cp);
494 
495 #ifdef  NOINFO_SIGFPE
496 	    CHECK_DIVZERO(sp->dval);
497 #endif
498 
499 #ifdef SW_FP_CHECK
500 	    clrerr();
501 #endif
502 	    cp->dval /= sp->dval;
503 	    dec_sp();
504 #ifdef SW_FP_CHECK
505 	    fpcheck();
506 #endif
507 	    sp->type = C_DOUBLE;
508 	    sp->dval = cp->dval;
509 	    break;
510 
511 	case _MOD_ASG:
512 	    if (sp->type != C_DOUBLE)
513 		cast1_to_d(sp);
514 	    cp = (CELL *) (sp - 1)->ptr;
515 	    if (cp->type != C_DOUBLE)
516 		cast1_to_d(cp);
517 
518 #ifdef  NOINFO_SIGFPE
519 	    CHECK_DIVZERO(sp->dval);
520 #endif
521 
522 	    cp->dval = fmod(cp->dval, sp->dval);
523 	    dec_sp();
524 	    sp->type = C_DOUBLE;
525 	    sp->dval = cp->dval;
526 	    break;
527 
528 	case _POW_ASG:
529 	    if (sp->type != C_DOUBLE)
530 		cast1_to_d(sp);
531 	    cp = (CELL *) (sp - 1)->ptr;
532 	    if (cp->type != C_DOUBLE)
533 		cast1_to_d(cp);
534 	    cp->dval = pow(cp->dval, sp->dval);
535 	    dec_sp();
536 	    sp->type = C_DOUBLE;
537 	    sp->dval = cp->dval;
538 	    break;
539 
540 	    /* will anyone ever use these ? */
541 
542 	case F_ADD_ASG:
543 	    if (sp->type != C_DOUBLE)
544 		cast1_to_d(sp);
545 	    cp = (CELL *) (sp - 1)->ptr;
546 	    cast1_to_d(cellcpy(&tc, cp));
547 #ifdef SW_FP_CHECK
548 	    clrerr();
549 #endif
550 	    tc.dval += sp->dval;
551 	    dec_sp();
552 #ifdef SW_FP_CHECK
553 	    fpcheck();
554 #endif
555 	    sp->type = C_DOUBLE;
556 	    sp->dval = tc.dval;
557 	    field_assign(cp, &tc);
558 	    break;
559 
560 	case F_SUB_ASG:
561 	    if (sp->type != C_DOUBLE)
562 		cast1_to_d(sp);
563 	    cp = (CELL *) (sp - 1)->ptr;
564 	    cast1_to_d(cellcpy(&tc, cp));
565 #ifdef SW_FP_CHECK
566 	    clrerr();
567 #endif
568 	    tc.dval -= sp->dval;
569 	    dec_sp();
570 #ifdef SW_FP_CHECK
571 	    fpcheck();
572 #endif
573 	    sp->type = C_DOUBLE;
574 	    sp->dval = tc.dval;
575 	    field_assign(cp, &tc);
576 	    break;
577 
578 	case F_MUL_ASG:
579 	    if (sp->type != C_DOUBLE)
580 		cast1_to_d(sp);
581 	    cp = (CELL *) (sp - 1)->ptr;
582 	    cast1_to_d(cellcpy(&tc, cp));
583 #ifdef SW_FP_CHECK
584 	    clrerr();
585 #endif
586 	    tc.dval *= sp->dval;
587 	    dec_sp();
588 #ifdef SW_FP_CHECK
589 	    fpcheck();
590 #endif
591 	    sp->type = C_DOUBLE;
592 	    sp->dval = tc.dval;
593 	    field_assign(cp, &tc);
594 	    break;
595 
596 	case F_DIV_ASG:
597 	    if (sp->type != C_DOUBLE)
598 		cast1_to_d(sp);
599 	    cp = (CELL *) (sp - 1)->ptr;
600 	    cast1_to_d(cellcpy(&tc, cp));
601 
602 #ifdef  NOINFO_SIGFPE
603 	    CHECK_DIVZERO(sp->dval);
604 #endif
605 
606 #ifdef SW_FP_CHECK
607 	    clrerr();
608 #endif
609 	    tc.dval /= sp->dval;
610 	    dec_sp();
611 #ifdef SW_FP_CHECK
612 	    fpcheck();
613 #endif
614 	    sp->type = C_DOUBLE;
615 	    sp->dval = tc.dval;
616 	    field_assign(cp, &tc);
617 	    break;
618 
619 	case F_MOD_ASG:
620 	    if (sp->type != C_DOUBLE)
621 		cast1_to_d(sp);
622 	    cp = (CELL *) (sp - 1)->ptr;
623 	    cast1_to_d(cellcpy(&tc, cp));
624 
625 #ifdef  NOINFO_SIGFPE
626 	    CHECK_DIVZERO(sp->dval);
627 #endif
628 
629 	    tc.dval = fmod(tc.dval, sp->dval);
630 	    dec_sp();
631 	    sp->type = C_DOUBLE;
632 	    sp->dval = tc.dval;
633 	    field_assign(cp, &tc);
634 	    break;
635 
636 	case F_POW_ASG:
637 	    if (sp->type != C_DOUBLE)
638 		cast1_to_d(sp);
639 	    cp = (CELL *) (sp - 1)->ptr;
640 	    cast1_to_d(cellcpy(&tc, cp));
641 	    tc.dval = pow(tc.dval, sp->dval);
642 	    dec_sp();
643 	    sp->type = C_DOUBLE;
644 	    sp->dval = tc.dval;
645 	    field_assign(cp, &tc);
646 	    break;
647 
648 	case _ADD:
649 	    dec_sp();
650 	    if (TEST2(sp) != TWO_DOUBLES)
651 		cast2_to_d(sp);
652 #ifdef SW_FP_CHECK
653 	    clrerr();
654 #endif
655 	    sp[0].dval += sp[1].dval;
656 #ifdef SW_FP_CHECK
657 	    fpcheck();
658 #endif
659 	    break;
660 
661 	case _SUB:
662 	    dec_sp();
663 	    if (TEST2(sp) != TWO_DOUBLES)
664 		cast2_to_d(sp);
665 #ifdef SW_FP_CHECK
666 	    clrerr();
667 #endif
668 	    sp[0].dval -= sp[1].dval;
669 #ifdef SW_FP_CHECK
670 	    fpcheck();
671 #endif
672 	    break;
673 
674 	case _MUL:
675 	    dec_sp();
676 	    if (TEST2(sp) != TWO_DOUBLES)
677 		cast2_to_d(sp);
678 #ifdef SW_FP_CHECK
679 	    clrerr();
680 #endif
681 	    sp[0].dval *= sp[1].dval;
682 #ifdef SW_FP_CHECK
683 	    fpcheck();
684 #endif
685 	    break;
686 
687 	case _DIV:
688 	    dec_sp();
689 	    if (TEST2(sp) != TWO_DOUBLES)
690 		cast2_to_d(sp);
691 
692 #ifdef  NOINFO_SIGFPE
693 	    CHECK_DIVZERO(sp[1].dval);
694 #endif
695 
696 #ifdef SW_FP_CHECK
697 	    clrerr();
698 #endif
699 	    sp[0].dval /= sp[1].dval;
700 #ifdef SW_FP_CHECK
701 	    fpcheck();
702 #endif
703 	    break;
704 
705 	case _MOD:
706 	    dec_sp();
707 	    if (TEST2(sp) != TWO_DOUBLES)
708 		cast2_to_d(sp);
709 
710 #ifdef  NOINFO_SIGFPE
711 	    CHECK_DIVZERO(sp[1].dval);
712 #endif
713 
714 	    sp[0].dval = fmod(sp[0].dval, sp[1].dval);
715 	    break;
716 
717 	case _POW:
718 	    dec_sp();
719 	    if (TEST2(sp) != TWO_DOUBLES)
720 		cast2_to_d(sp);
721 	    sp[0].dval = pow(sp[0].dval, sp[1].dval);
722 	    break;
723 
724 	case _NOT:
725 	    /* evaluates to 0.0 or 1.0 */
726 	  reswitch_1:
727 	    switch (sp->type) {
728 	    case C_NOINIT:
729 		sp->dval = 1.0;
730 		break;
731 	    case C_DOUBLE:
732 		sp->dval = sp->dval != 0.0 ? 0.0 : 1.0;
733 		break;
734 	    case C_STRING:
735 		sp->dval = string(sp)->len ? 0.0 : 1.0;
736 		free_STRING(string(sp));
737 		break;
738 	    case C_STRNUM:	/* test as a number */
739 		sp->dval = sp->dval != 0.0 ? 0.0 : 1.0;
740 		free_STRING(string(sp));
741 		break;
742 	    case C_MBSTRN:
743 		check_strnum(sp);
744 		goto reswitch_1;
745 	    default:
746 		bozo("bad type on eval stack");
747 	    }
748 	    sp->type = C_DOUBLE;
749 	    break;
750 
751 	case _TEST:
752 	    /* evaluates to 0.0 or 1.0 */
753 	  reswitch_2:
754 	    switch (sp->type) {
755 	    case C_NOINIT:
756 		sp->dval = 0.0;
757 		break;
758 	    case C_DOUBLE:
759 		sp->dval = sp->dval != 0.0 ? 1.0 : 0.0;
760 		break;
761 	    case C_STRING:
762 		sp->dval = string(sp)->len ? 1.0 : 0.0;
763 		free_STRING(string(sp));
764 		break;
765 	    case C_STRNUM:	/* test as a number */
766 		sp->dval = sp->dval != 0.0 ? 1.0 : 0.0;
767 		free_STRING(string(sp));
768 		break;
769 	    case C_MBSTRN:
770 		check_strnum(sp);
771 		goto reswitch_2;
772 	    default:
773 		bozo("bad type on eval stack");
774 	    }
775 	    sp->type = C_DOUBLE;
776 	    break;
777 
778 	case _UMINUS:
779 	    if (sp->type != C_DOUBLE)
780 		cast1_to_d(sp);
781 	    sp->dval = -sp->dval;
782 	    break;
783 
784 	case _UPLUS:
785 	    if (sp->type != C_DOUBLE)
786 		cast1_to_d(sp);
787 	    break;
788 
789 	case _CAT:
790 	    {
791 		size_t len1, len2;
792 		char *str1, *str2;
793 		STRING *b;
794 
795 		dec_sp();
796 		if (TEST2(sp) != TWO_STRINGS)
797 		    cast2_to_s(sp);
798 		str1 = string(sp)->str;
799 		len1 = string(sp)->len;
800 		str2 = string(sp + 1)->str;
801 		len2 = string(sp + 1)->len;
802 
803 		b = new_STRING0(len1 + len2);
804 		memcpy(b->str, str1, len1);
805 		memcpy(b->str + len1, str2, len2);
806 		free_STRING(string(sp));
807 		free_STRING(string(sp + 1));
808 
809 		sp->ptr = (PTR) b;
810 		break;
811 	    }
812 
813 	case _PUSHINT:
814 	    inc_sp();
815 	    sp->type = (short) (cdp++)->op;
816 	    break;
817 
818 	case _BUILTIN:
819 	case _PRINT:
820 	    sp = (*(PF_CP) (cdp++)->ptr) (sp);
821 	    break;
822 
823 	case _POST_INC:
824 	    cp = (CELL *) sp->ptr;
825 	    if (cp->type != C_DOUBLE)
826 		cast1_to_d(cp);
827 	    sp->type = C_DOUBLE;
828 	    sp->dval = cp->dval;
829 	    cp->dval += 1.0;
830 	    break;
831 
832 	case _POST_DEC:
833 	    cp = (CELL *) sp->ptr;
834 	    if (cp->type != C_DOUBLE)
835 		cast1_to_d(cp);
836 	    sp->type = C_DOUBLE;
837 	    sp->dval = cp->dval;
838 	    cp->dval -= 1.0;
839 	    break;
840 
841 	case _PRE_INC:
842 	    cp = (CELL *) sp->ptr;
843 	    if (cp->type != C_DOUBLE)
844 		cast1_to_d(cp);
845 	    sp->dval = cp->dval += 1.0;
846 	    sp->type = C_DOUBLE;
847 	    break;
848 
849 	case _PRE_DEC:
850 	    cp = (CELL *) sp->ptr;
851 	    if (cp->type != C_DOUBLE)
852 		cast1_to_d(cp);
853 	    sp->dval = cp->dval -= 1.0;
854 	    sp->type = C_DOUBLE;
855 	    break;
856 
857 	case F_POST_INC:
858 	    cp = (CELL *) sp->ptr;
859 	    cellcpy(&tc, cp);
860 	    cast1_to_d(&tc);
861 	    sp->type = C_DOUBLE;
862 	    sp->dval = tc.dval;
863 	    tc.dval += 1.0;
864 	    field_assign(cp, &tc);
865 	    break;
866 
867 	case F_POST_DEC:
868 	    cp = (CELL *) sp->ptr;
869 	    cellcpy(&tc, cp);
870 	    cast1_to_d(&tc);
871 	    sp->type = C_DOUBLE;
872 	    sp->dval = tc.dval;
873 	    tc.dval -= 1.0;
874 	    field_assign(cp, &tc);
875 	    break;
876 
877 	case F_PRE_INC:
878 	    cp = (CELL *) sp->ptr;
879 	    cast1_to_d(cellcpy(sp, cp));
880 	    sp->dval += 1.0;
881 	    field_assign(cp, sp);
882 	    break;
883 
884 	case F_PRE_DEC:
885 	    cp = (CELL *) sp->ptr;
886 	    cast1_to_d(cellcpy(sp, cp));
887 	    sp->dval -= 1.0;
888 	    field_assign(cp, sp);
889 	    break;
890 
891 	case _JMP:
892 	    cdp += cdp->op;
893 	    break;
894 
895 	case _JNZ:
896 	    /* jmp if top of stack is non-zero and pop stack */
897 	    if (test(sp))
898 		cdp += cdp->op;
899 	    else
900 		cdp++;
901 	    cell_destroy(sp);
902 	    dec_sp();
903 	    break;
904 
905 	case _JZ:
906 	    /* jmp if top of stack is zero and pop stack */
907 	    if (!test(sp))
908 		cdp += cdp->op;
909 	    else
910 		cdp++;
911 	    cell_destroy(sp);
912 	    dec_sp();
913 	    break;
914 
915 	case _LJZ:
916 	    /* special jump for logical and */
917 	    /* this is always preceded by _TEST */
918 	    if (sp->dval == 0.0) {
919 		/* take jump, but don't pop stack */
920 		cdp += cdp->op;
921 	    } else {
922 		/* pop and don't jump */
923 		dec_sp();
924 		cdp++;
925 	    }
926 	    break;
927 
928 	case _LJNZ:
929 	    /* special jump for logical or */
930 	    /* this is always preceded by _TEST */
931 	    if (sp->dval != 0.0) {
932 		/* take jump, but don't pop stack */
933 		cdp += cdp->op;
934 	    } else {
935 		/* pop and don't jump */
936 		dec_sp();
937 		cdp++;
938 	    }
939 	    break;
940 
941 	    /*  the relation operations */
942 	    /*  compare() makes sure string ref counts are OK */
943 	case _EQ:
944 	    dec_sp();
945 	    t = compare(sp);
946 	    sp->type = C_DOUBLE;
947 	    sp->dval = t == 0 ? 1.0 : 0.0;
948 	    break;
949 
950 	case _NEQ:
951 	    dec_sp();
952 	    t = compare(sp);
953 	    sp->type = C_DOUBLE;
954 	    sp->dval = t ? 1.0 : 0.0;
955 	    break;
956 
957 	case _LT:
958 	    dec_sp();
959 	    t = compare(sp);
960 	    sp->type = C_DOUBLE;
961 	    sp->dval = t < 0 ? 1.0 : 0.0;
962 	    break;
963 
964 	case _LTE:
965 	    dec_sp();
966 	    t = compare(sp);
967 	    sp->type = C_DOUBLE;
968 	    sp->dval = t <= 0 ? 1.0 : 0.0;
969 	    break;
970 
971 	case _GT:
972 	    dec_sp();
973 	    t = compare(sp);
974 	    sp->type = C_DOUBLE;
975 	    sp->dval = t > 0 ? 1.0 : 0.0;
976 	    break;
977 
978 	case _GTE:
979 	    dec_sp();
980 	    t = compare(sp);
981 	    sp->type = C_DOUBLE;
982 	    sp->dval = t >= 0 ? 1.0 : 0.0;
983 	    break;
984 
985 	case _MATCH0:
986 	    /* does $0 match, the RE at cdp? */
987 
988 	    inc_sp();
989 	    if (field->type >= C_STRING) {
990 		sp->type = C_DOUBLE;
991 		sp->dval = (REtest(string(field)->str,
992 				   string(field)->len,
993 				   cast_to_re((cdp++)->ptr))
994 			    ? 1.0
995 			    : 0.0);
996 
997 		break /* the case */ ;
998 	    }
999 	    cellcpy(sp, field);
1000 	    /* FALLTHRU */
1001 
1002 	case _MATCH1:
1003 	    /* does expr at sp[0] match RE at cdp */
1004 	    if (sp->type < C_STRING)
1005 		cast1_to_s(sp);
1006 	    t = REtest(string(sp)->str,
1007 		       string(sp)->len,
1008 		       cast_to_re((cdp++)->ptr));
1009 	    free_STRING(string(sp));
1010 	    sp->type = C_DOUBLE;
1011 	    sp->dval = t ? 1.0 : 0.0;
1012 	    break;
1013 
1014 	case _MATCH2:
1015 	    /* does sp[-1] match sp[0] as re */
1016 	    cast_to_RE(sp);
1017 
1018 	    dec_sp();
1019 	    if (sp->type < C_STRING)
1020 		cast1_to_s(sp);
1021 	    t = REtest(string(sp)->str,
1022 		       string(sp)->len,
1023 		       cast_to_re((sp + 1)->ptr));
1024 
1025 	    free_STRING(string(sp));
1026 	    no_leaks_re_ptr((sp + 1)->ptr);
1027 	    sp->type = C_DOUBLE;
1028 	    sp->dval = t ? 1.0 : 0.0;
1029 	    break;
1030 
1031 	case A_LENGTH:
1032 	    dec_sp();
1033 	    sp->type = C_DOUBLE;
1034 	    sp->dval = (double) (((ARRAY) ((sp + 0)->ptr))->size);
1035 	    break;
1036 
1037 	case A_TEST:
1038 	    /* entry :  sp[0].ptr-> an array
1039 	       sp[-1]  is an expression
1040 
1041 	       we compute       (expression in array)  */
1042 	    dec_sp();
1043 	    cp = array_find((sp + 1)->ptr, sp, NO_CREATE);
1044 	    cell_destroy(sp);
1045 	    sp->type = C_DOUBLE;
1046 	    sp->dval = (cp != (CELL *) 0) ? 1.0 : 0.0;
1047 	    break;
1048 
1049 	case A_DEL:
1050 	    /* sp[0].ptr ->  array
1051 	       sp[-1] is an expr
1052 	       delete  array[expr]      */
1053 
1054 	    array_delete(sp->ptr, sp - 1);
1055 	    cell_destroy(sp - 1);
1056 	    sp -= 2;
1057 	    break;
1058 
1059 	case DEL_A:
1060 	    /* free all the array at once */
1061 	    array_clear(sp->ptr);
1062 	    dec_sp();
1063 	    break;
1064 
1065 	    /* form a multiple array index */
1066 	case A_CAT:
1067 	    sp = array_cat(sp, (cdp++)->op);
1068 	    break;
1069 
1070 	case _EXIT:
1071 	    if (sp->type != C_DOUBLE)
1072 		cast1_to_d(sp);
1073 	    exit_code = d_to_i(sp->dval);
1074 	    dec_sp();
1075 	    /* FALLTHRU */
1076 
1077 	case _EXIT0:
1078 
1079 	    if (!end_start)
1080 		mawk_exit(exit_code);
1081 
1082 	    cdp = end_start;
1083 	    end_start = (INST *) 0;	/* makes sure next exit exits */
1084 
1085 	    if (begin_start) {
1086 		free_codes("BEGIN", begin_start, begin_size);
1087 		begin_start = 0;
1088 		begin_size = 0;
1089 	    }
1090 	    if (main_start) {
1091 		free_codes("MAIN", main_start, main_size);
1092 		main_start = 0;
1093 		main_size = 0;
1094 	    }
1095 	    sp = eval_stack - 1;	/* might be in user function */
1096 	    CLEAR_ALOOP_STACK();	/* ditto */
1097 	    break;
1098 
1099 	case _JMAIN:		/* go from BEGIN code to MAIN code */
1100 	    free_codes("BEGIN", begin_start, begin_size);
1101 	    begin_start = 0;
1102 	    begin_size = 0;
1103 	    cdp = main_start;
1104 	    break;
1105 
1106 	case _OMAIN:
1107 	    if (!main_fin)
1108 		open_main();
1109 	    restart_label = cdp;
1110 	    cdp = next_label;
1111 	    break;
1112 
1113 	case _NEXT:
1114 	    /* next might be inside an aloop -- clear stack */
1115 	    CLEAR_ALOOP_STACK();
1116 	    cdp = next_label;
1117 	    break;
1118 
1119 	case _NEXTFILE:
1120 	    /* nextfile might be inside an aloop -- clear stack */
1121 	    CLEAR_ALOOP_STACK();
1122 	    FINsemi_close(main_fin);
1123 	    cdp = next_label;
1124 	    break;
1125 
1126 	case OL_GL:
1127 	    {
1128 		char *p;
1129 		size_t len;
1130 
1131 		if (!(p = FINgets(main_fin, &len))) {
1132 		    if (!end_start)
1133 			mawk_exit(0);
1134 
1135 		    cdp = end_start;
1136 		    zfree(main_start, main_size);
1137 		    main_start = end_start = (INST *) 0;
1138 		} else {
1139 		    set_field0(p, len);
1140 		    cdp = restart_label;
1141 		    rt_nr++;
1142 		    rt_fnr++;
1143 		}
1144 	    }
1145 	    break;
1146 
1147 	    /* two kinds of OL_GL is a historical stupidity from working on
1148 	       a machine with very slow floating point emulation */
1149 	case OL_GL_NR:
1150 	    {
1151 		char *p;
1152 		size_t len;
1153 
1154 		if (!(p = FINgets(main_fin, &len))) {
1155 		    if (!end_start)
1156 			mawk_exit(0);
1157 
1158 		    cdp = end_start;
1159 		    zfree(main_start, main_size);
1160 		    main_start = end_start = (INST *) 0;
1161 		} else {
1162 		    set_field0(p, len);
1163 		    cdp = restart_label;
1164 
1165 		    if (TEST2(NR) != TWO_DOUBLES)
1166 			cast2_to_d(NR);
1167 
1168 		    NR->dval += 1.0;
1169 		    rt_nr++;
1170 		    FNR->dval += 1.0;
1171 		    rt_fnr++;
1172 		}
1173 	    }
1174 	    break;
1175 
1176 	case _RANGE:
1177 /* test a range pattern:  pat1, pat2 { action }
1178    entry :
1179        cdp[0].op -- a flag, test pat1 if on else pat2
1180        cdp[1].op -- offset of pat2 code from cdp
1181        cdp[2].op -- offset of action code from cdp
1182        cdp[3].op -- offset of code after the action from cdp
1183        cdp[4] -- start of pat1 code
1184 */
1185 
1186 #define FLAG      cdp[0].op
1187 #define PAT2      cdp[1].op
1188 #define ACTION    cdp[2].op
1189 #define FOLLOW    cdp[3].op
1190 #define PAT1      4
1191 
1192 	    if (FLAG)		/* test against pat1 */
1193 	    {
1194 		execute(cdp + PAT1, sp, fp);
1195 		t = test(sp + 1);
1196 		cell_destroy(sp + 1);
1197 		if (t)
1198 		    FLAG = 0;
1199 		else {
1200 		    cdp += FOLLOW;
1201 		    break;	/* break the switch */
1202 		}
1203 	    }
1204 
1205 	    /* test against pat2 and then perform the action */
1206 	    execute(cdp + PAT2, sp, fp);
1207 	    FLAG = test(sp + 1);
1208 	    cell_destroy(sp + 1);
1209 	    cdp += ACTION;
1210 	    break;
1211 
1212 /* function calls  */
1213 
1214 	case _RET0:
1215 	    inc_sp();
1216 	    sp->type = C_NOINIT;
1217 	    /* FALLTHRU */
1218 
1219 	case _RET:
1220 
1221 #ifdef	DEBUG
1222 	    if (sp != entry_sp + 1)
1223 		bozo("ret");
1224 #endif
1225 	    if (old_stack_base)	/* reset stack */
1226 	    {
1227 		/* move the return value */
1228 		cellcpy(old_sp + 1, sp);
1229 		cell_destroy(sp);
1230 		zfree(stack_base, sizeof(CELL) * EVAL_STACK_SIZE);
1231 		stack_base = old_stack_base;
1232 		stack_danger = old_stack_base + DANGER;
1233 	    }
1234 
1235 	    /* return might be inside an aloop -- clear stack */
1236 	    CLEAR_ALOOP_STACK();
1237 
1238 	    return;
1239 
1240 	case _CALL:
1241 
1242 	    /*  cdp[0] holds ptr to "function block"
1243 	       cdp[1] holds number of input arguments
1244 	     */
1245 
1246 	    {
1247 		FBLOCK *fbp = (FBLOCK *) (cdp++)->ptr;
1248 		int a_args = (cdp++)->op;	/* actual number of args */
1249 		CELL *nfp = sp - a_args + 1;	/* new fp for callee */
1250 		CELL *local_p = sp + 1;		/* first local argument on stack */
1251 		char *type_p = 0;	/* pts to type of an argument */
1252 
1253 		if (fbp->nargs)
1254 		    type_p = fbp->typev + a_args - 1;
1255 
1256 		/* create space for locals */
1257 		t = fbp->nargs - a_args;	/* t is number of locals */
1258 		while (t > 0) {
1259 		    t--;
1260 		    inc_sp();
1261 		    type_p++;
1262 		    sp->type = C_NOINIT;
1263 		    if ((type_p) != 0 && (*type_p == ST_LOCAL_ARRAY))
1264 			sp->ptr = (PTR) new_ARRAY();
1265 		}
1266 
1267 		execute(fbp->code, sp, nfp);
1268 
1269 		/* cleanup the callee's arguments */
1270 		/* putting return value at top of eval stack */
1271 		if ((type_p != 0) && (sp >= nfp)) {
1272 		    cp = sp + 1;	/* cp -> the function return */
1273 
1274 		    do {
1275 			if (*type_p == ST_LOCAL_ARRAY) {
1276 			    if (sp >= local_p) {
1277 				array_clear(sp->ptr);
1278 				ZFREE((ARRAY) sp->ptr);
1279 			    }
1280 			} else {
1281 			    cell_destroy(sp);
1282 			}
1283 
1284 			type_p--;
1285 			dec_sp();
1286 
1287 		    }
1288 		    while (sp >= nfp);
1289 
1290 		    inc_sp();
1291 		    cellcpy(sp, cp);
1292 		    cell_destroy(cp);
1293 		} else {
1294 		    inc_sp();	/* no arguments passed */
1295 		}
1296 	    }
1297 	    break;
1298 
1299 	default:
1300 	    bozo("bad opcode");
1301 	}
1302     }
1303 }
1304 
1305 /*
1306   return 0 if a numeric is zero else return non-zero
1307   return 0 if a string is "" else return non-zero
1308 */
1309 int
test(CELL * cp)1310 test(CELL *cp)
1311 {
1312   reswitch:
1313 
1314     switch (cp->type) {
1315     case C_NOINIT:
1316 	return 0;
1317     case C_STRNUM:		/* test as a number */
1318     case C_DOUBLE:
1319 	return cp->dval != 0.0;
1320     case C_STRING:
1321 	return (string(cp)->len != 0);
1322     case C_MBSTRN:
1323 	check_strnum(cp);
1324 	goto reswitch;
1325     default:
1326 	bozo("bad cell type in call to test");
1327     }
1328     return 0;			/*can't get here: shutup */
1329 }
1330 
1331 /* compare cells at cp and cp+1 and
1332    frees STRINGs at those cells
1333 */
1334 static int
compare(CELL * cp)1335 compare(CELL *cp)
1336 {
1337     int result;
1338     size_t len;
1339 
1340   reswitch:
1341     result = 0;
1342 
1343     switch (TEST2(cp)) {
1344     case TWO_NOINITS:
1345 	break;
1346 
1347     case TWO_DOUBLES:
1348       two_d:
1349 	result = ((cp->dval > (cp + 1)->dval)
1350 		  ? 1
1351 		  : ((cp->dval < (cp + 1)->dval)
1352 		     ? -1
1353 		     : 0));
1354 	break;
1355 
1356     case TWO_STRINGS:
1357     case STRING_AND_STRNUM:
1358       two_s:
1359 	len = string(cp)->len;
1360 	if (len > string(cp + 1)->len)
1361 	    len = string(cp + 1)->len;
1362 	result = memcmp(string(cp)->str, string(cp + 1)->str, len);
1363 	if (result == 0) {
1364 	    if (len != string(cp)->len) {
1365 		result = 1;
1366 	    } else if (len != string(cp + 1)->len) {
1367 		result = -1;
1368 	    }
1369 	}
1370 	free_STRING(string(cp));
1371 	free_STRING(string(cp + 1));
1372 	break;
1373 
1374     case NOINIT_AND_DOUBLE:
1375     case NOINIT_AND_STRNUM:
1376     case DOUBLE_AND_STRNUM:
1377     case TWO_STRNUMS:
1378 	cast2_to_d(cp);
1379 	goto two_d;
1380     case NOINIT_AND_STRING:
1381     case DOUBLE_AND_STRING:
1382 	cast2_to_s(cp);
1383 	goto two_s;
1384     case TWO_MBSTRNS:
1385 	check_strnum(cp);
1386 	check_strnum(cp + 1);
1387 	goto reswitch;
1388 
1389     case NOINIT_AND_MBSTRN:
1390     case DOUBLE_AND_MBSTRN:
1391     case STRING_AND_MBSTRN:
1392     case STRNUM_AND_MBSTRN:
1393 	check_strnum(cp->type == C_MBSTRN ? cp : cp + 1);
1394 	goto reswitch;
1395 
1396     default:			/* there are no default cases */
1397 	bozo("bad cell type passed to compare");
1398 	break;
1399     }
1400     return result;
1401 }
1402 
1403 /* does not assume target was a cell, if so
1404    then caller should have made a previous
1405    call to cell_destroy	 */
1406 
1407 CELL *
cellcpy(CELL * target,CELL * source)1408 cellcpy(CELL *target, CELL *source)
1409 {
1410     switch (target->type = source->type) {
1411     case C_NOINIT:
1412     case C_SPACE:
1413     case C_SNULL:
1414 	break;
1415 
1416     case C_DOUBLE:
1417 	target->dval = source->dval;
1418 	break;
1419 
1420     case C_STRNUM:
1421 	target->dval = source->dval;
1422 	/* FALLTHRU */
1423 
1424     case C_REPL:
1425     case C_MBSTRN:
1426     case C_STRING:
1427 	string(source)->ref_cnt++;
1428 	/* FALLTHRU */
1429 
1430     case C_RE:
1431 	target->ptr = source->ptr;
1432 	break;
1433 
1434     case C_REPLV:
1435 	replv_cpy(target, source);
1436 	break;
1437 
1438     default:
1439 	bozo("bad cell passed to cellcpy()");
1440 	break;
1441     }
1442     return target;
1443 }
1444 
1445 #ifdef	 DEBUG
1446 
1447 void
DB_cell_destroy(CELL * cp)1448 DB_cell_destroy(CELL *cp)
1449 {
1450     switch (cp->type) {
1451     case C_NOINIT:
1452     case C_DOUBLE:
1453 	break;
1454 
1455     case C_MBSTRN:
1456     case C_STRING:
1457     case C_STRNUM:
1458 	free_STRING(string(cp));
1459 	break;
1460 
1461     case C_RE:
1462 	bozo("cell destroy called on RE cell");
1463     default:
1464 	bozo("cell destroy called on bad cell type");
1465     }
1466 }
1467 
1468 #endif
1469 
1470 /*
1471  * convert a double d to a field index	$d -> $i
1472  *
1473  * Note: this used to return (unsigned) d_to_I(d), but is done inline to
1474  * aid static analysis.
1475  */
1476 static UInt
d_to_index(double d)1477 d_to_index(double d)
1478 {
1479     if (d >= Max_Int) {
1480 	return (UInt) Max_Int;
1481     } else if (d >= 0.0) {
1482 	return (UInt) (Int) (d);
1483     } else {
1484 	/* might include nan */
1485 	rt_error("negative field index $%.6g", d);
1486 	return 0;		/* shutup */
1487     }
1488 }
1489