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