CELL * bi_srand(CELL *sp) { #ifdef USE_SYSTEM_SRAND static long seed = 1; static CELL cseed = { C_DOUBLE, 0, 0, 1.0 }; #endif CELL c; TRACE_FUNC("bi_srand", sp); if (sp->type == C_NOINIT) /* seed off clock */ { cellcpy(sp, &cseed); cell_destroy(&cseed); cseed.type = C_DOUBLE; cseed.dval = initial_seed(); } else { /* user seed */ sp--; /* swap cseed and *sp ; don't need to adjust ref_cnts */ c = *sp; *sp = cseed; cseed = c; } #ifdef USE_SYSTEM_SRAND seed = d_to_i(cseed.dval); mawk_srand((unsigned) seed); #else /* The old seed is now in *sp ; move the value in cseed to seed in range [1,M) */ cellcpy(&c, &cseed); if (c.type == C_NOINIT) cast1_to_d(&c); seed = ((c.type == C_DOUBLE) ? (long) (d_to_i(c.dval) & M) % M + 1 : (long) hash(string(&c)->str) % M + 1); if (seed == M) seed = M - 1; cell_destroy(&c); /* crank it once so close seeds don't give a close first result */ crank(seed); #endif return_CELL("bi_srand", sp); }
void slow_cell_assign(CELL * target, CELL * source) { if ( #ifdef MSDOS /* the dreaded segment nonsense */ SAMESEG(target, field) && #endif target >= field && target <= LAST_PFIELD) field_assign(target, source); else { CELL **p = fbank + 1; while (*p) { if ( #ifdef MSDOS SAMESEG(target, *p) && #endif target >= *p && target < *p + FBANK_SZ) { field_assign(target, source); return; } p++; } /* its not a field */ cell_destroy(target); cellcpy(target, source); } }
/* this gets called once to get the input stream going. It is called after the execution of the BEGIN block unless there is a getline inside BEGIN {} */ void open_main(void) { CELL argc; #if USE_BINMODE int k = binmode(); if (k & 1) setmode(0, O_BINARY); if (k & 2) { setmode(1, O_BINARY); setmode(2, O_BINARY); } #endif cellcpy(&argc, ARGC); if (argc.type != C_DOUBLE) cast1_to_d(&argc); if (argc.dval == 1.0) set_main_to_stdin(); else next_main(1); }
/* read current value of BINMODE */ int binmode(void) { CELL c; cast1_to_d(cellcpy(&c, BINMODE)); return d_to_i(c.dval); }
cell * cellcat(cell *dst, register cell *src) { register cell *cp = dst; while (*cp) cp++; cellcpy(cp, src); return dst; }
static void set_rs_shadow() { CELL c ; STRING *sval ; char *s ; unsigned len ; if (posix_space_flag && mawk_state == EXECUTION) scan_code['\n'] = SC_UNEXPECTED ; if (rs_shadow.type == SEP_STR) free_STRING((STRING *) rs_shadow.ptr) ; cast_for_split(cellcpy(&c, RS)) ; switch (c.type) { case C_RE: if ( (s = is_string_split(c.ptr, &len)) ) { if (len == 1) { rs_shadow.type = SEP_CHAR ; rs_shadow.c = s[0] ; } else { rs_shadow.type = SEP_STR ; rs_shadow.ptr = (PTR) new_STRING(s) ; } } else { rs_shadow.type = SEP_RE ; rs_shadow.ptr = c.ptr ; } break ; case C_SPACE: rs_shadow.type = SEP_CHAR ; rs_shadow.c = ' ' ; break ; case C_SNULL: /* RS becomes one or more blank lines */ if (mawk_state == EXECUTION) scan_code['\n'] = SC_SPACE ; rs_shadow.type = SEP_MLR ; sval = new_STRING("\n\n+") ; rs_shadow.ptr = re_compile(sval) ; free_STRING(sval) ; break ; default: bozo("bad cell in set_rs_shadow") ; } }
CELL * bi_srand(CELL * sp) { CELL c; if (sp->type == 0) /* seed off clock */ { time_t secs = time((time_t *) 0); cellcpy(sp, &cseed); cell_destroy(&cseed); cseed.type = C_DOUBLE; cseed.dval = (double) secs; } else { /* user seed */ sp--; /* swap cseed and *sp ; don't need to adjust ref_cnts */ c = *sp; *sp = cseed; cseed = c; } /* The old seed is now in *sp ; move the value in cseed to seed in range [1,M) */ cellcpy(&c, &cseed); if (c.type == C_NOINIT) cast1_to_d(&c); seed = ((c.type == C_DOUBLE) ? (long) (d_to_i(c.dval) & M) % M + 1 : (long) hash(string(&c)->str) % M + 1); if (seed == M) seed = M - 1; cell_destroy(&c); /* crank it once so close seeds don't give a close first result */ crank(seed); return sp; }
void split_field0(void) { register CELL *cp; register int cnt; CELL c; /* copy field[0] here if not string */ if (field[0].type < C_STRING) { cast1_to_s(cellcpy(&c, field + 0)); cp = &c; } else cp = &field[0]; if (string(cp)->len == 0) nf = 0; else { switch (fs_shadow.type) { case C_SNULL: /* FS == "" */ nf = (int) null_split(string(cp)->str, string(cp)->len); break; case C_SPACE: nf = (int) space_split(string(cp)->str, string(cp)->len); break; default: nf = (int) re_split(string(cp), fs_shadow.ptr); break; } } cell_destroy(NF); NF->type = C_DOUBLE; NF->dval = (double) nf; if (nf > MAX_SPLIT) { cnt = MAX_SPLIT; load_field_ov(); } else cnt = nf; while (cnt > 0) { cell_destroy(field + cnt); field[cnt].ptr = (PTR) split_buff[cnt - 1]; USED_SPLIT_BUFF(cnt - 1); field[cnt--].type = C_MBSTRN; } if (cp == &c) { free_STRING(string(cp)); } }
void cast_to_REPL(CELL * cp) { register STRING *sval; if (cp->type < C_STRING) cast1_to_s(cp); sval = (STRING *) cp->ptr; cellcpy(cp, repl_compile(sval)); free_STRING(sval); }
CELL *array_cat( CELL *sp, int cnt) { CELL *p ; /* walks the eval stack */ CELL subsep ; /* local copy of SUBSEP */ size_t subsep_len ; /* string length of subsep_str */ char *subsep_str ; size_t total_len ; /* length of cat'ed expression */ CELL *top ; /* value of sp at entry */ char *target ; /* build cat'ed char* here */ STRING *sval ; /* build cat'ed STRING here */ cellcpy(&subsep, SUBSEP) ; if ( subsep.type < C_STRING ) cast1_to_s(&subsep) ; subsep_len = string(&subsep)->len ; subsep_str = string(&subsep)->str ; assert(cnt > 0); top = sp ; sp -= (cnt-1) ; total_len = ((size_t) (cnt-1)) * subsep_len ; for(p = sp ; p <= top ; p++) { if ( p->type < C_STRING ) cast1_to_s(p) ; total_len += string(p)->len ; } sval = new_STRING0(total_len) ; target = sval->str ; for(p = sp ; p < top ; p++) { memcpy(target, string(p)->str, string(p)->len) ; target += string(p)->len ; memcpy(target, subsep_str, subsep_len) ; target += subsep_len ; } /* now p == top */ memcpy(target, string(p)->str, string(p)->len) ; for(p = sp; p <= top ; p++) free_STRING(string(p)) ; free_STRING(string(&subsep)) ; /* set contents of sp , sp->type > C_STRING is possible so reset */ sp->type = C_STRING ; sp->ptr = (PTR) sval ; return sp ; }
CELL * bi_length(CELL * sp) { size_t len; if (sp->type == 0) cellcpy(sp, field); else sp--; if (sp->type < C_STRING) cast1_to_s(sp); len = string(sp)->len; free_STRING(string(sp)); sp->type = C_DOUBLE; sp->dval = (double) len; return sp; }
void execute(INST * cdp, /* code ptr, start execution here */ CELL *sp, /* eval_stack pointer */ CELL *fp) /* frame ptr into eval_stack for user defined functions */ { /* some useful temporaries */ CELL *cp; int t; unsigned tu; /* save state for array loops via a stack */ ALOOP_STATE *aloop_state = (ALOOP_STATE *) 0; /* for moving the eval stack on deep recursion */ CELL *old_stack_base = 0; CELL *old_sp = 0; #ifdef DEBUG CELL *entry_sp = sp; #endif int force_exit = (end_start == 0); if (fp) { /* we are a function call, check for deep recursion */ if (sp > stack_danger) { /* change stacks */ old_stack_base = stack_base; old_sp = sp; stack_base = (CELL *) zmalloc(sizeof(CELL) * EVAL_STACK_SIZE); stack_danger = stack_base + DANGER; sp = stack_base; /* waste 1 slot for ANSI, actually large model msdos breaks in RET if we don't */ #ifdef DEBUG entry_sp = sp; #endif } else old_stack_base = (CELL *) 0; } while (1) { TRACE(("execute %s sp(%ld:%s)\n", da_op_name(cdp), (long) (sp - stack_base), da_type_name(sp))); switch ((cdp++)->op) { /* HALT only used by the disassemble now ; this remains so compilers don't offset the jump table */ case _HALT: case _STOP: /* only for range patterns */ #ifdef DEBUG if (sp != entry_sp + 1) bozo("stop0"); #endif return; case _PUSHC: inc_sp(); cellcpy(sp, (cdp++)->ptr); break; case _PUSHD: inc_sp(); sp->type = C_DOUBLE; sp->dval = *(double *) (cdp++)->ptr; break; case _PUSHS: inc_sp(); sp->type = C_STRING; sp->ptr = (cdp++)->ptr; string(sp)->ref_cnt++; break; case F_PUSHA: cp = (CELL *) cdp->ptr; if (cp != field) { if (nf < 0) split_field0(); if (!(cp >= NF && cp <= LAST_PFIELD)) { /* it is a real field $1, $2 ... If it is greater than $NF, we have to make sure it is set to "" so that (++|--) and g?sub() work right */ t = field_addr_to_index(cp); if (t > nf) { cp->type = C_STRING; cp->ptr = (PTR) & null_str; null_str.ref_cnt++; } } } /* fall thru */ case _PUSHA: case A_PUSHA: inc_sp(); sp->ptr = (cdp++)->ptr; break; case _PUSHI: /* put contents of next address on stack */ inc_sp(); cellcpy(sp, (cdp++)->ptr); break; case L_PUSHI: /* put the contents of a local var on stack, cdp->op holds the offset from the frame pointer */ inc_sp(); cellcpy(sp, fp + (cdp++)->op); break; case L_PUSHA: /* put a local address on eval stack */ inc_sp(); sp->ptr = (PTR) (fp + (cdp++)->op); break; case F_PUSHI: /* push contents of $i cdp[0] holds & $i , cdp[1] holds i */ inc_sp(); if (nf < 0) split_field0(); cp = (CELL *) cdp->ptr; t = (cdp + 1)->op; cdp += 2; if (t <= nf) cellcpy(sp, cp); else { /* an unset field */ sp->type = C_STRING; sp->ptr = (PTR) & null_str; null_str.ref_cnt++; } break; case NF_PUSHI: inc_sp(); if (nf < 0) split_field0(); cellcpy(sp, NF); break; case FE_PUSHA: if (sp->type != C_DOUBLE) cast1_to_d(sp); tu = d_to_index(sp->dval); if (tu && nf < 0) split_field0(); sp->ptr = (PTR) field_ptr((int) tu); if ((int) tu > nf) { /* make sure it is set to "" */ cp = (CELL *) sp->ptr; cell_destroy(cp); cp->type = C_STRING; cp->ptr = (PTR) & null_str; null_str.ref_cnt++; } break; case FE_PUSHI: if (sp->type != C_DOUBLE) cast1_to_d(sp); tu = d_to_index(sp->dval); if (nf < 0) split_field0(); if ((int) tu <= nf) { cellcpy(sp, field_ptr((int) tu)); } else { sp->type = C_STRING; sp->ptr = (PTR) & null_str; null_str.ref_cnt++; } break; case AE_PUSHA: /* top of stack has an expr, cdp->ptr points at an array, replace the expr with the cell address inside the array */ cp = array_find((ARRAY) (cdp++)->ptr, sp, CREATE); cell_destroy(sp); sp->ptr = (PTR) cp; break; case AE_PUSHI: /* top of stack has an expr, cdp->ptr points at an array, replace the expr with the contents of the cell inside the array */ cp = array_find((ARRAY) (cdp++)->ptr, sp, CREATE); cell_destroy(sp); cellcpy(sp, cp); break; case LAE_PUSHI: /* sp[0] is an expression cdp->op is offset from frame pointer of a CELL which has an ARRAY in the ptr field, replace expr with array[expr] */ if (fp != 0) { cp = array_find((ARRAY) fp[(cdp++)->op].ptr, sp, CREATE); cell_destroy(sp); cellcpy(sp, cp); } break; case LAE_PUSHA: /* sp[0] is an expression cdp->op is offset from frame pointer of a CELL which has an ARRAY in the ptr field, replace expr with & array[expr] */ if (fp != 0) { cp = array_find((ARRAY) fp[(cdp++)->op].ptr, sp, CREATE); cell_destroy(sp); sp->ptr = (PTR) cp; } break; case LA_PUSHA: /* cdp->op is offset from frame pointer of a CELL which has an ARRAY in the ptr field. Push this ARRAY on the eval stack */ if (fp != 0) { inc_sp(); sp->ptr = fp[(cdp++)->op].ptr; } break; case SET_ALOOP: { ALOOP_STATE *ap = ZMALLOC(ALOOP_STATE); size_t vector_size; ap->var = (CELL *) sp[-1].ptr; ap->base = ap->ptr = array_loop_vector((ARRAY) sp->ptr, &vector_size); ap->limit = ap->base + vector_size; sp -= 2; /* push onto aloop stack */ ap->link = aloop_state; aloop_state = ap; cdp += cdp->op; } break; case ALOOP: { ALOOP_STATE *ap = aloop_state; if (ap != 0 && (ap->ptr < ap->limit)) { cell_destroy(ap->var); ap->var->type = C_STRING; ap->var->ptr = (PTR) * ap->ptr++; cdp += cdp->op; } else { cdp++; } } break; case POP_AL: { /* finish up an array loop */ ALOOP_STATE *ap = aloop_state; if (ap != 0) { aloop_state = ap->link; while (ap->ptr < ap->limit) { free_STRING(*ap->ptr); ap->ptr++; } if (ap->base < ap->limit) { zfree(ap->base, ((unsigned) (ap->limit - ap->base) * sizeof(STRING *))); } ZFREE(ap); } } break; case _POP: cell_destroy(sp); sp--; break; case _ASSIGN: /* top of stack has an expr, next down is an address, put the expression in *address and replace the address with the expression */ /* don't propagate type C_MBSTRN */ if (sp->type == C_MBSTRN) check_strnum(sp); sp--; cell_destroy(((CELL *) sp->ptr)); cellcpy(sp, cellcpy(sp->ptr, sp + 1)); cell_destroy(sp + 1); break; case F_ASSIGN: /* assign to a field */ if (sp->type == C_MBSTRN) check_strnum(sp); sp--; field_assign((CELL *) sp->ptr, sp + 1); cell_destroy(sp + 1); cellcpy(sp, (CELL *) sp->ptr); break; case _ADD_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); #ifdef SW_FP_CHECK /* specific to V7 and XNX23A */ clrerr(); #endif cp->dval += (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = cp->dval; break; case _SUB_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); #ifdef SW_FP_CHECK clrerr(); #endif cp->dval -= (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = cp->dval; break; case _MUL_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); #ifdef SW_FP_CHECK clrerr(); #endif cp->dval *= (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = cp->dval; break; case _DIV_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); #ifdef NOINFO_SIGFPE CHECK_DIVZERO(sp->dval); #endif #ifdef SW_FP_CHECK clrerr(); #endif cp->dval /= (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = cp->dval; break; case _MOD_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); #ifdef NOINFO_SIGFPE CHECK_DIVZERO(sp->dval); #endif cp->dval = fmod(cp->dval, (sp--)->dval); sp->type = C_DOUBLE; sp->dval = cp->dval; break; case _POW_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); cp->dval = pow(cp->dval, (sp--)->dval); sp->type = C_DOUBLE; sp->dval = cp->dval; break; /* will anyone ever use these ? */ case F_ADD_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; cast1_to_d(cellcpy(&tc, cp)); #ifdef SW_FP_CHECK clrerr(); #endif tc.dval += (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = tc.dval; field_assign(cp, &tc); break; case F_SUB_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; cast1_to_d(cellcpy(&tc, cp)); #ifdef SW_FP_CHECK clrerr(); #endif tc.dval -= (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = tc.dval; field_assign(cp, &tc); break; case F_MUL_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; cast1_to_d(cellcpy(&tc, cp)); #ifdef SW_FP_CHECK clrerr(); #endif tc.dval *= (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = tc.dval; field_assign(cp, &tc); break; case F_DIV_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; cast1_to_d(cellcpy(&tc, cp)); #ifdef NOINFO_SIGFPE CHECK_DIVZERO(sp->dval); #endif #ifdef SW_FP_CHECK clrerr(); #endif tc.dval /= (sp--)->dval; #ifdef SW_FP_CHECK fpcheck(); #endif sp->type = C_DOUBLE; sp->dval = tc.dval; field_assign(cp, &tc); break; case F_MOD_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; cast1_to_d(cellcpy(&tc, cp)); #ifdef NOINFO_SIGFPE CHECK_DIVZERO(sp->dval); #endif tc.dval = fmod(tc.dval, (sp--)->dval); sp->type = C_DOUBLE; sp->dval = tc.dval; field_assign(cp, &tc); break; case F_POW_ASG: if (sp->type != C_DOUBLE) cast1_to_d(sp); cp = (CELL *) (sp - 1)->ptr; cast1_to_d(cellcpy(&tc, cp)); tc.dval = pow(tc.dval, (sp--)->dval); sp->type = C_DOUBLE; sp->dval = tc.dval; field_assign(cp, &tc); break; case _ADD: sp--; if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp); #ifdef SW_FP_CHECK clrerr(); #endif sp[0].dval += sp[1].dval; #ifdef SW_FP_CHECK fpcheck(); #endif break; case _SUB: sp--; if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp); #ifdef SW_FP_CHECK clrerr(); #endif sp[0].dval -= sp[1].dval; #ifdef SW_FP_CHECK fpcheck(); #endif break; case _MUL: sp--; if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp); #ifdef SW_FP_CHECK clrerr(); #endif sp[0].dval *= sp[1].dval; #ifdef SW_FP_CHECK fpcheck(); #endif break; case _DIV: sp--; if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp); #ifdef NOINFO_SIGFPE CHECK_DIVZERO(sp[1].dval); #endif #ifdef SW_FP_CHECK clrerr(); #endif sp[0].dval /= sp[1].dval; #ifdef SW_FP_CHECK fpcheck(); #endif break; case _MOD: sp--; if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp); #ifdef NOINFO_SIGFPE CHECK_DIVZERO(sp[1].dval); #endif sp[0].dval = fmod(sp[0].dval, sp[1].dval); break; case _POW: sp--; if (TEST2(sp) != TWO_DOUBLES) cast2_to_d(sp); sp[0].dval = pow(sp[0].dval, sp[1].dval); break; case _NOT: /* evaluates to 0.0 or 1.0 */ reswitch_1: switch (sp->type) { case C_NOINIT: sp->dval = 1.0; break; case C_DOUBLE: sp->dval = sp->dval != 0.0 ? 0.0 : 1.0; break; case C_FIELDWIDTHS: case C_STRING: sp->dval = string(sp)->len ? 0.0 : 1.0; free_STRING(string(sp)); break; case C_STRNUM: /* test as a number */ sp->dval = sp->dval != 0.0 ? 0.0 : 1.0; free_STRING(string(sp)); break; case C_MBSTRN: check_strnum(sp); goto reswitch_1; default: bozo("bad type on eval stack"); } sp->type = C_DOUBLE; break; case _TEST: /* evaluates to 0.0 or 1.0 */ reswitch_2: switch (sp->type) { case C_NOINIT: sp->dval = 0.0; break; case C_DOUBLE: sp->dval = sp->dval != 0.0 ? 1.0 : 0.0; break; case C_FIELDWIDTHS: case C_STRING: sp->dval = string(sp)->len ? 1.0 : 0.0; free_STRING(string(sp)); break; case C_STRNUM: /* test as a number */ sp->dval = sp->dval != 0.0 ? 1.0 : 0.0; free_STRING(string(sp)); break; case C_MBSTRN: check_strnum(sp); goto reswitch_2; default: bozo("bad type on eval stack"); } sp->type = C_DOUBLE; break; case _UMINUS: if (sp->type != C_DOUBLE) cast1_to_d(sp); sp->dval = -sp->dval; break; case _UPLUS: if (sp->type != C_DOUBLE) cast1_to_d(sp); break; case _CAT: { size_t len1, len2; char *str1, *str2; STRING *b; sp--; if (TEST2(sp) != TWO_STRINGS) cast2_to_s(sp); str1 = string(sp)->str; len1 = string(sp)->len; str2 = string(sp + 1)->str; len2 = string(sp + 1)->len; b = new_STRING0(len1 + len2); memcpy(b->str, str1, len1); memcpy(b->str + len1, str2, len2); free_STRING(string(sp)); free_STRING(string(sp + 1)); sp->ptr = (PTR) b; break; } case _PUSHINT: inc_sp(); sp->type = (short) (cdp++)->op; break; case _BUILTIN: case _PRINT: sp = (*(PF_CP) (cdp++)->ptr) (sp); break; case _POST_INC: cp = (CELL *) sp->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); sp->type = C_DOUBLE; sp->dval = cp->dval; cp->dval += 1.0; break; case _POST_DEC: cp = (CELL *) sp->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); sp->type = C_DOUBLE; sp->dval = cp->dval; cp->dval -= 1.0; break; case _PRE_INC: cp = (CELL *) sp->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); sp->dval = cp->dval += 1.0; sp->type = C_DOUBLE; break; case _PRE_DEC: cp = (CELL *) sp->ptr; if (cp->type != C_DOUBLE) cast1_to_d(cp); sp->dval = cp->dval -= 1.0; sp->type = C_DOUBLE; break; case F_POST_INC: cp = (CELL *) sp->ptr; cellcpy(&tc, cp); cast1_to_d(&tc); sp->type = C_DOUBLE; sp->dval = tc.dval; tc.dval += 1.0; field_assign(cp, &tc); break; case F_POST_DEC: cp = (CELL *) sp->ptr; cellcpy(&tc, cp); cast1_to_d(&tc); sp->type = C_DOUBLE; sp->dval = tc.dval; tc.dval -= 1.0; field_assign(cp, &tc); break; case F_PRE_INC: cp = (CELL *) sp->ptr; cast1_to_d(cellcpy(sp, cp)); sp->dval += 1.0; field_assign(cp, sp); break; case F_PRE_DEC: cp = (CELL *) sp->ptr; cast1_to_d(cellcpy(sp, cp)); sp->dval -= 1.0; field_assign(cp, sp); break; case _JMP: cdp += cdp->op; break; case _JNZ: /* jmp if top of stack is non-zero and pop stack */ if (test(sp)) cdp += cdp->op; else cdp++; cell_destroy(sp); sp--; break; case _JZ: /* jmp if top of stack is zero and pop stack */ if (!test(sp)) cdp += cdp->op; else cdp++; cell_destroy(sp); sp--; break; case _LJZ: /* special jump for logical and */ /* this is always preceded by _TEST */ if (sp->dval == 0.0) { /* take jump, but don't pop stack */ cdp += cdp->op; } else { /* pop and don't jump */ sp--; cdp++; } break; case _LJNZ: /* special jump for logical or */ /* this is always preceded by _TEST */ if (sp->dval != 0.0) { /* take jump, but don't pop stack */ cdp += cdp->op; } else { /* pop and don't jump */ sp--; cdp++; } break; /* the relation operations */ /* compare() makes sure string ref counts are OK */ case _EQ: t = compare(--sp); sp->type = C_DOUBLE; sp->dval = t == 0 ? 1.0 : 0.0; break; case _NEQ: t = compare(--sp); sp->type = C_DOUBLE; sp->dval = t ? 1.0 : 0.0; break; case _LT: t = compare(--sp); sp->type = C_DOUBLE; sp->dval = t < 0 ? 1.0 : 0.0; break; case _LTE: t = compare(--sp); sp->type = C_DOUBLE; sp->dval = t <= 0 ? 1.0 : 0.0; break; case _GT: t = compare(--sp); sp->type = C_DOUBLE; sp->dval = t > 0 ? 1.0 : 0.0; break; case _GTE: t = compare(--sp); sp->type = C_DOUBLE; sp->dval = t >= 0 ? 1.0 : 0.0; break; case _MATCH0: /* does $0 match, the RE at cdp? */ inc_sp(); if (field->type >= C_STRING) { sp->type = C_DOUBLE; sp->dval = (REtest(string(field)->str, string(field)->len, cast_to_re((cdp++)->ptr)) ? 1.0 : 0.0); break /* the case */ ; } else { cellcpy(sp, field); /* and FALL THRU */ } case _MATCH1: /* does expr at sp[0] match RE at cdp */ if (sp->type < C_STRING) cast1_to_s(sp); t = REtest(string(sp)->str, string(sp)->len, cast_to_re((cdp++)->ptr)); free_STRING(string(sp)); sp->type = C_DOUBLE; sp->dval = t ? 1.0 : 0.0; break; case _MATCH2: /* does sp[-1] match sp[0] as re */ cast_to_RE(sp); if ((--sp)->type < C_STRING) cast1_to_s(sp); t = REtest(string(sp)->str, string(sp)->len, cast_to_re((sp + 1)->ptr)); free_STRING(string(sp)); no_leaks_re_ptr((sp + 1)->ptr); sp->type = C_DOUBLE; sp->dval = t ? 1.0 : 0.0; break; case A_LENGTH: sp--; sp->type = C_DOUBLE; sp->dval = (double) (((ARRAY) ((sp + 0)->ptr))->size); break; case A_TEST: /* entry : sp[0].ptr-> an array sp[-1] is an expression we compute (expression in array) */ sp--; cp = array_find((sp + 1)->ptr, sp, NO_CREATE); cell_destroy(sp); sp->type = C_DOUBLE; sp->dval = (cp != (CELL *) 0) ? 1.0 : 0.0; break; case A_DEL: /* sp[0].ptr -> array sp[-1] is an expr delete array[expr] */ array_delete(sp->ptr, sp - 1); cell_destroy(sp - 1); sp -= 2; break; case DEL_A: /* free all the array at once */ array_clear(sp->ptr); sp--; break; /* form a multiple array index */ case A_CAT: sp = array_cat(sp, (cdp++)->op); break; case _EXIT: if (sp->type != C_DOUBLE) cast1_to_d(sp); exit_code = d_to_i(sp->dval); sp--; /* fall thru */ case _EXIT0: if (force_exit) mawk_exit(exit_code); cdp = end_start; force_exit = 1; /* makes sure next exit exits */ if (begin_start) { free_codes("BEGIN", begin_start, begin_size); begin_start = 0; begin_size = 0; } if (main_start) { free_codes("MAIN", main_start, main_size); main_start = 0; main_size = 0; } sp = eval_stack - 1; /* might be in user function */ CLEAR_ALOOP_STACK(); /* ditto */ break; case _JMAIN: /* go from BEGIN code to MAIN code */ free_codes("BEGIN", begin_start, begin_size); begin_start = 0; begin_size = 0; cdp = main_start; break; case _OMAIN: if (!main_fin) open_main(); restart_label = cdp; cdp = next_label; break; case _NEXT: /* next might be inside an aloop -- clear stack */ CLEAR_ALOOP_STACK(); cdp = next_label; break; case _NEXTFILE: /* nextfile might be inside an aloop -- clear stack */ CLEAR_ALOOP_STACK(); FINsemi_close(main_fin); cdp = next_label; break; case OL_GL: { char *p; size_t len; if (!(p = FINgets(main_fin, &len))) { if (force_exit) mawk_exit(0); cdp = end_start; zfree(main_start, main_size); main_start = (INST *) 0; force_exit = 1; } else { set_field0(p, len); cdp = restart_label; rt_nr++; rt_fnr++; } } break; /* two kinds of OL_GL is a historical stupidity from working on a machine with very slow floating point emulation */ case OL_GL_NR: { char *p; size_t len; if (!(p = FINgets(main_fin, &len))) { if (force_exit) mawk_exit(0); cdp = end_start; zfree(main_start, main_size); main_start = (INST *) 0; force_exit = 1; } else { set_field0(p, len); cdp = restart_label; if (TEST2(NR) != TWO_DOUBLES) cast2_to_d(NR); NR->dval += 1.0; rt_nr++; FNR->dval += 1.0; rt_fnr++; } } break; case _RANGE: /* test a range pattern: pat1, pat2 { action } entry : cdp[0].op -- a flag, test pat1 if on else pat2 cdp[1].op -- offset of pat2 code from cdp cdp[2].op -- offset of action code from cdp cdp[3].op -- offset of code after the action from cdp cdp[4] -- start of pat1 code */ #define FLAG cdp[0].op #define PAT2 cdp[1].op #define ACTION cdp[2].op #define FOLLOW cdp[3].op #define PAT1 4 if (FLAG) /* test against pat1 */ { execute(cdp + PAT1, sp, fp); t = test(sp + 1); cell_destroy(sp + 1); if (t) FLAG = 0; else { cdp += FOLLOW; break; /* break the switch */ } } /* test against pat2 and then perform the action */ execute(cdp + PAT2, sp, fp); FLAG = test(sp + 1); cell_destroy(sp + 1); cdp += ACTION; break; /* function calls */ case _RET0: inc_sp(); sp->type = C_NOINIT; /* fall thru */ case _RET: #ifdef DEBUG if (sp != entry_sp + 1) bozo("ret"); #endif if (old_stack_base) /* reset stack */ { /* move the return value */ cellcpy(old_sp + 1, sp); cell_destroy(sp); zfree(stack_base, sizeof(CELL) * EVAL_STACK_SIZE); stack_base = old_stack_base; stack_danger = old_stack_base + DANGER; } /* return might be inside an aloop -- clear stack */ CLEAR_ALOOP_STACK(); return; case _CALL: /* cdp[0] holds ptr to "function block" cdp[1] holds number of input arguments */ { FBLOCK *fbp = (FBLOCK *) (cdp++)->ptr; int a_args = (cdp++)->op; /* actual number of args */ CELL *nfp = sp - a_args + 1; /* new fp for callee */ CELL *local_p = sp + 1; /* first local argument on stack */ char *type_p = 0; /* pts to type of an argument */ if (fbp->nargs) type_p = fbp->typev + a_args - 1; /* create space for locals */ t = fbp->nargs - a_args; /* t is number of locals */ while (t > 0) { t--; sp++; type_p++; sp->type = C_NOINIT; if ((type_p) != 0 && (*type_p == ST_LOCAL_ARRAY)) sp->ptr = (PTR) new_ARRAY(); } execute(fbp->code, sp, nfp); /* cleanup the callee's arguments */ /* putting return value at top of eval stack */ if ((type_p != 0) && (sp >= nfp)) { cp = sp + 1; /* cp -> the function return */ do { if (*type_p == ST_LOCAL_ARRAY) { if (sp >= local_p) { array_clear(sp->ptr); ZFREE((ARRAY) sp->ptr); } } else { cell_destroy(sp); } type_p--; sp--; } while (sp >= nfp); cellcpy(++sp, cp); cell_destroy(cp); } else sp++; /* no arguments passed */ } break; default: bozo("bad opcode"); } } }
/* get the next command line file open */ static FIN * next_main(int open_flag) /* called by open_main() if on */ { register CELL *cp; CELL *cp0; CELL argc; /* copy of ARGC */ CELL c_argi; /* cell copy of argi */ CELL argval; /* copy of ARGV[c_argi] */ int failed = 1; argval.type = C_NOINIT; c_argi.type = C_DOUBLE; if (main_fin) { FINclose(main_fin); main_fin = 0; } /* FILENAME and FNR don't change unless we really open a new file */ /* make a copy of ARGC to avoid side effect */ if (cellcpy(&argc, ARGC)->type != C_DOUBLE) cast1_to_d(&argc); while (argi < argc.dval) { c_argi.dval = argi; argi += 1.0; if (!(cp0 = array_find(Argv, &c_argi, NO_CREATE))) continue; /* its deleted */ /* make a copy so we can cast w/o side effect */ cell_destroy(&argval); cp = cellcpy(&argval, cp0); #ifndef NO_LEAKS cell_destroy(cp0); #endif if (cp->type < C_STRING) cast1_to_s(cp); if (string(cp)->len == 0) { /* file argument is "" */ cell_destroy(cp); continue; } /* it might be a command line assignment */ if (is_cmdline_assign(string(cp)->str)) { continue; } /* try to open it -- we used to continue on failure, but posix says we should quit */ if (!(main_fin = FINopen(string(cp)->str, 1))) { errmsg(errno, "cannot open %s", string(cp)->str); mawk_exit(2); } /* success -- set FILENAME and FNR */ cell_destroy(FILENAME); cellcpy(FILENAME, cp); cell_destroy(cp); cell_destroy(FNR); FNR->type = C_DOUBLE; FNR->dval = 0.0; rt_fnr = 0; failed = 0; break; } if (failed) { cell_destroy(&argval); if (open_flag) { /* all arguments were null or assignment */ set_main_to_stdin(); } else { main_fin = &dead_main; /* since MAIN_FLAG is not set, FINgets won't call next_main() */ } } return main_fin; }
static void process_cmdline(int argc, char **argv) { int i, j, nextarg; char *optArg; char *optNext; PFILE dummy; /* starts linked list of filenames */ PFILE *tail = &dummy; size_t length; if (argc <= 1) usage(); for (i = 1; i < argc && argv[i][0] == '-'; i = nextarg) { if (argv[i][1] == 0) /* - alone */ { if (!pfile_name) no_program(); break; /* the for loop */ } /* safe to look at argv[i][2] */ /* * Check for "long" options and decide how to handle them. */ if (strlen(argv[i]) > 2 && !strncmp(argv[i], "--", (size_t) 2)) { if (!allow_long_options(argv[i])) { nextarg = i + 1; continue; } } if (argv[i][2] == 0) { if (i == argc - 1 && argv[i][1] != '-') { if (strchr("WFvf", argv[i][1])) { errmsg(0, "option %s lacks argument", argv[i]); mawk_exit(2); } bad_option(argv[i]); } optArg = argv[i + 1]; nextarg = i + 2; } else { /* argument glued to option */ optArg = &argv[i][2]; nextarg = i + 1; } switch (argv[i][1]) { case 'W': for (j = 0; j < (int) strlen(optArg); j = (int) (optNext - optArg)) { switch (parse_w_opt(optArg + j, &optNext)) { case W_VERSION: print_version(); break; #if USE_BINMODE case W_BINMODE: if (haveValue(optNext)) { set_binmode(atoi(optNext + 1)); optNext = skipValue(optNext); } else { errmsg(0, "missing value for -W binmode"); mawk_exit(2); } break; #endif case W_DUMP: dump_code_flag = 1; break; case W_EXEC: if (pfile_name) { errmsg(0, "-W exec is incompatible with -f"); mawk_exit(2); } else if (nextarg == argc) { no_program(); } if (haveValue(optNext)) { pfile_name = optNext + 1; i = nextarg; } else { pfile_name = argv[nextarg]; i = nextarg + 1; } goto no_more_opts; case W_INTERACTIVE: interactive_flag = 1; setbuf(stdout, (char *) 0); break; case W_POSIX_SPACE: posix_space_flag = 1; break; case W_RANDOM: if (haveValue(optNext)) { int x = atoi(optNext + 1); CELL c[2]; memset(c, 0, sizeof(c)); c[1].type = C_DOUBLE; c[1].dval = (double) x; /* c[1] is input, c[0] is output */ bi_srand(c + 1); optNext = skipValue(optNext); } else { errmsg(0, "missing value for -W random"); mawk_exit(2); } break; case W_SPRINTF: if (haveValue(optNext)) { int x = atoi(optNext + 1); if (x > (int) sizeof(string_buff)) { if (sprintf_buff != string_buff && sprintf_buff != 0) { zfree(sprintf_buff, (size_t) (sprintf_limit - sprintf_buff)); } sprintf_buff = (char *) zmalloc((size_t) x); sprintf_limit = sprintf_buff + x; } optNext = skipValue(optNext); } else { errmsg(0, "missing value for -W sprintf"); mawk_exit(2); } break; case W_HELP: /* FALLTHRU */ case W_USAGE: usage(); /* NOTREACHED */ break; case W_UNKNOWN: errmsg(0, "vacuous option: -W %s", optArg + j); break; } while (*optNext == '=') { errmsg(0, "unexpected option value %s", optArg + j); optNext = skipValue(optNext); } } break; case 'v': if (!is_cmdline_assign(optArg)) { errmsg(0, "improper assignment: -v %s", optArg); mawk_exit(2); } break; case 'F': rm_escape(optArg, &length); /* recognize escape sequences */ cell_destroy(FS); FS->type = C_STRING; FS->ptr = (PTR) new_STRING1(optArg, length); cast_for_split(cellcpy(&fs_shadow, FS)); break; case '-': if (argv[i][2] != 0) { bad_option(argv[i]); } i++; goto no_more_opts; case 'f': /* first file goes in pfile_name ; any more go on a list */ if (!pfile_name) pfile_name = optArg; else { tail = tail->link = ZMALLOC(PFILE); tail->fname = optArg; } break; default: bad_option(argv[i]); } } no_more_opts: tail->link = (PFILE *) 0; pfile_list = dummy.link; if (pfile_name) { set_ARGV(argc, argv, i); scan_init((char *) 0); } else { /* program on command line */ if (i == argc) no_program(); set_ARGV(argc, argv, i + 1); #if defined(MSDOS) && ! HAVE_REARGV /* reversed quotes */ { char *p; for (p = argv[i]; *p; p++) if (*p == '\'') *p = '\"'; } #endif scan_init(argv[i]); /* #endif */ } }
static void set_rs_shadow(void) { CELL c; STRING *sval; char *s; unsigned len; if (posix_space_flag && mawk_state == EXECUTION) scan_code['\n'] = SC_UNEXPECTED; if (rs_shadow.type == SEP_STR) { free_STRING((STRING *) rs_shadow.ptr); } cast_for_split(cellcpy(&c, RS)); switch (c.type) { case C_RE: if ((s = is_string_split(c.ptr, &len))) { if (len == 1) { rs_shadow.type = SEP_CHAR; rs_shadow.c = s[0]; } else { rs_shadow.type = SEP_STR; rs_shadow.ptr = (PTR) new_STRING(s); } } else { rs_shadow.type = SEP_RE; rs_shadow.ptr = c.ptr; } break; case C_SPACE: rs_shadow.type = SEP_CHAR; rs_shadow.c = ' '; break; case C_SNULL: /* RS becomes one or more blank lines */ if (mawk_state == EXECUTION) scan_code['\n'] = SC_SPACE; rs_shadow.type = SEP_MLR; sval = new_STRING("\n\n+"); rs_shadow.ptr = re_compile(sval); free_STRING(sval); break; case C_STRING: /* * Check for special case where we retained the cell as a string, * bypassing regular-expression compiling. */ if (string(&c)->len == 1) { rs_shadow.type = SEP_CHAR; rs_shadow.c = string(&c)->str[0]; break; } /* FALLTHRU */ default: bozo("bad cell in set_rs_shadow"); } }
static void build_field0(void) { #ifdef DEBUG if (nf < 0) bozo("nf <0 in build_field0"); #endif cell_destroy(field + 0); if (nf == 0) { field[0].type = C_STRING; field[0].ptr = (PTR) & null_str; null_str.ref_cnt++; } else if (nf == 1) { cellcpy(field, field + 1); } else { CELL c; STRING *ofs, *tail; size_t len; register CELL *cp; register char *p, *q; int cnt; CELL **fbp, *cp_limit; cast1_to_s(cellcpy(&c, OFS)); ofs = (STRING *) c.ptr; cast1_to_s(cellcpy(&c, field_ptr(nf))); tail = (STRING *) c.ptr; cnt = nf - 1; len = ((size_t) cnt) * ofs->len + tail->len; fbp = fbank; cp_limit = field + FBANK_SZ; cp = field + 1; while (cnt-- > 0) { if (cp->type < C_STRING) { /* use the string field temporarily */ if (cp->type == C_NOINIT) { cp->ptr = (PTR) & null_str; null_str.ref_cnt++; } else { /* its a double */ Int ival; char xbuff[260]; ival = d_to_I(cp->dval); if (ival == cp->dval) sprintf(xbuff, INT_FMT, ival); else sprintf(xbuff, string(CONVFMT)->str, cp->dval); cp->ptr = (PTR) new_STRING(xbuff); } } len += string(cp)->len; if (++cp == cp_limit) { cp = *++fbp; cp_limit = cp + FBANK_SZ; } } field[0].type = C_STRING; field[0].ptr = (PTR) new_STRING0(len); p = string(field)->str; /* walk it again , putting things together */ cnt = nf - 1; fbp = fbank; cp = field + 1; cp_limit = field + FBANK_SZ; while (cnt-- > 0) { memcpy(p, string(cp)->str, string(cp)->len); p += string(cp)->len; /* if not really string, free temp use of ptr */ if (cp->type < C_STRING) { free_STRING(string(cp)); } if (++cp == cp_limit) { cp = *++fbp; cp_limit = cp + FBANK_SZ; } /* add the separator */ q = ofs->str; while (*q) *p++ = *q++; } /* tack tail on the end */ memcpy(p, tail->str, tail->len); /* cleanup */ free_STRING(tail); free_STRING(ofs); } }
void field_assign(CELL * fp, CELL * cp) { CELL c; int i, j; /* the most common case first */ if (fp == field) { cell_destroy(field); cellcpy(fp, cp); nf = -1; return; } /* its not important to do any of this fast */ if (nf < 0) split_field0(); #ifdef MSDOS if (!SAMESEG(fp, field)) { i = -1; goto lm_dos_label; } #endif switch (i = (int) (fp - field)) { case NF_field: cell_destroy(NF); cellcpy(NF, cellcpy(&c, cp)); if (c.type != C_DOUBLE) cast1_to_d(&c); if ((j = d_to_i(c.dval)) < 0) rt_error("negative value assigned to NF"); if (j > nf) for (i = nf + 1; i <= j; i++) { cp = field_ptr(i); cell_destroy(cp); cp->type = C_STRING; cp->ptr = (PTR) & null_str; null_str.ref_cnt++; } nf = j; build_field0(); break; case RS_field: cell_destroy(RS); cellcpy(RS, cp); set_rs_shadow(); break; case FS_field: cell_destroy(FS); cast_for_split(cellcpy(&fs_shadow, cellcpy(FS, cp))); break; case OFMT_field: case CONVFMT_field: /* If the user does something stupid with OFMT or CONVFMT, we could crash. We'll make an attempt to protect ourselves here. This is why OFMT and CONVFMT are pseudo fields. The ptrs of OFMT and CONVFMT always have a valid STRING, even if assigned a DOUBLE or NOINIT */ free_STRING(string(fp)); cellcpy(fp, cp); if (fp->type < C_STRING) /* !! */ fp->ptr = (PTR) new_STRING("%.6g"); else if (fp == CONVFMT) { /* It's a string, but if it's really goofy and CONVFMT, it could still damage us. Test it . */ char xbuff[512]; xbuff[256] = 0; sprintf(xbuff, string(fp)->str, 3.1459); if (xbuff[256]) rt_error("CONVFMT assigned unusable value"); } break; #ifdef MSDOS lm_dos_label: #endif default: /* $1 or $2 or ... */ cell_destroy(fp); cellcpy(fp, cp); if (i < 0 || i > MAX_SPLIT) i = field_addr_to_index(fp); if (i > nf) { for (j = nf + 1; j < i; j++) { cp = field_ptr(j); cell_destroy(cp); cp->type = C_STRING; cp->ptr = (PTR) & null_str; null_str.ref_cnt++; } nf = i; cell_destroy(NF); NF->type = C_DOUBLE; NF->dval = (double) i; } build_field0(); } }