/* convert file-descriptor to FIN*. It's the main stream if main_flag is set */ FIN * FINdopen(int fd, int main_flag) { FIN *fin = ZMALLOC(FIN); fin->fd = fd; fin->flags = main_flag ? (MAIN_FLAG | START_FLAG) : START_FLAG; fin->buffp = fin->buff = (char *) zmalloc((size_t) BUFFSZ + 1); fin->limit = fin->buffp; fin->nbuffs = 1; fin->buff[0] = 0; if ((isatty(fd) && rs_shadow.type == SEP_CHAR && rs_shadow.c == '\n') || interactive_flag) { /* interactive, i.e., line buffer this file */ if (fd == 0) { fin->fp = stdin; } else if (!(fin->fp = fdopen(fd, "r"))) { errmsg(errno, "fdopen failed"); free_fin_data(fin); mawk_exit(2); } } else { fin->fp = (FILE *) 0; } return fin; }
static void convert_split_array_to_table(ARRAY A) { CELL *cells = (CELL*) A->ptr ; unsigned i ; /* walks cells */ DUAL_LINK *table ; unsigned j ; /* walks table */ size_t entry_limit = A->limit ; A->hmask = STARTING_HMASK ; A->limit = hmask_to_limit(STARTING_HMASK) ; while(A->size > A->limit) { A->hmask = (A->hmask<<1) + 1 ; /* double the size */ A->limit = hmask_to_limit(A->hmask) ; } { size_t sz = (A->hmask+1)*sizeof(DUAL_LINK) ; A->ptr = memset(zmalloc(sz), 0, sz) ; table = (DUAL_LINK*) A->ptr ; } /* insert each cells[i] in the new hash table on an ilist */ for(i=0, j=1; i < A->size; i++) { ANODE *p = ZMALLOC(ANODE) ; p->sval = (STRING*) 0 ; p->ival = (Int) (i + 1) ; p->cell = cells[i] ; p->ilink = table[j].ilink ; table[j].ilink = p ; j++ ; j &= A->hmask ; } A->type = AY_INT ; zfree(cells, entry_limit*sizeof(CELL)) ; }
void code_push(INST * code, unsigned len, int scope, FBLOCK * fbp) { register MC *p; if (!error_state) { p = ZMALLOC(MC); p->len = len; p->link = mc_top; mc_top = p; if (len) { p->code = (INST *) zmalloc(sizeof(INST) * len); memcpy(p->code, code, sizeof(INST) * len); } if (!resolve_list) p->scope = NO_SCOPE; else { p->scope = scope; p->move_level = code_move_level; p->fbp = fbp; if (code) p->offset = (int) (code - code_base); else p->offset = 0; } } code_move_level++; }
static ANODE* find_by_ival( ARRAY A , Int ival , int create_flag , int *redo ) { DUAL_LINK *table = (DUAL_LINK*) A->ptr ; unsigned indx = (unsigned) ival & A->hmask ; ANODE *p = table[indx].ilink ; /* walks ilist */ ANODE *q = (ANODE*) 0 ; /* trails p */ while(1) { if (!p) { /* search failed */ if (A->type & AY_STR) { /* need to search by string */ char buff[256] ; STRING *sval ; sprintf(buff, INT_FMT, ival) ; sval = new_STRING(buff) ; p = find_by_sval(A, sval, create_flag, redo) ; if (*redo) { table = (DUAL_LINK*) A->ptr ; } free_STRING(sval) ; if (!p) return (ANODE*) 0 ; } else if (create_flag) { p = ZMALLOC(ANODE) ; p->sval = (STRING*) 0 ; p->cell.type = C_NOINIT ; if (++A->size > A->limit) { double_the_hash_table(A) ; /* changes table, may change index */ table = (DUAL_LINK*) A->ptr ; indx = A->hmask & (unsigned) ival ; } } else return (ANODE*) 0 ; p->ival = ival ; A->type |= AY_INT ; break ; } else if (p->ival == ival) { /* found it, now move to the front */ if (!q) /* already at the front */ return p ; /* delete for insertion at the front */ q->ilink = p->ilink ; break ; } q = p ; p = q->ilink ; } /* insert at the front */ p->ilink = table[indx].ilink ; table[indx].ilink = p ; return p ; }
static ANODE* find_by_sval( ARRAY A , STRING *sval , int create_flag , int *redo ) { unsigned hval = ahash(sval) ; char *str = sval->str ; DUAL_LINK *table ; unsigned indx ; ANODE *p ; /* walks list */ ANODE *q = (ANODE*) 0 ; /* trails p */ if (! (A->type & AY_STR)) add_string_associations(A) ; table = (DUAL_LINK*) A->ptr ; indx = hval & A->hmask ; p = table[indx].slink ; *redo = 0 ; while(1) { if (!p) { if (create_flag) { { p = ZMALLOC(ANODE) ; p->sval = sval ; sval->ref_cnt++ ; p->ival = NOT_AN_IVALUE ; p->hval = hval ; p->cell.type = C_NOINIT ; if (++A->size > A->limit) { double_the_hash_table(A) ; /* changes table, may change index */ table = (DUAL_LINK*) A->ptr ; indx = hval & A->hmask ; *redo = 1 ; } } break ; } return (ANODE*) 0 ; } else if (p->hval == hval) { if (strcmp(p->sval->str,str) == 0 ) { /* found */ if (!q) /* already at the front */ return p ; else { /* delete for move to the front */ q->slink = p->slink ; break ; } } } q = p ; p = q->slink ; } p->slink = table[indx].slink ; table[indx].slink = p ; return p ; }
/* the parser has just reduced a function call ; the info needed to type check is passed in. If type checking can not be done yet (most common reason -- function referenced but not defined), a node is added to the resolve list. */ void check_fcall( FBLOCK * callee, int call_scope, int move_level, FBLOCK * call, CA_REC * arg_list) { FCALL_REC *p; if (!callee->code) { /* forward reference to a function to be defined later */ p = ZMALLOC(FCALL_REC); p->callee = callee; p->call_scope = (short) call_scope; p->move_level = (short) move_level; p->call = call; p->arg_list = arg_list; p->arg_cnt_checked = 0; /* add to resolve list */ p->link = resolve_list; resolve_list = p; } else if (arg_list && arg_cnt_ok(callee, arg_list)) { /* usually arg_list disappears here and all is well otherwise add to resolve list */ if ((arg_list = call_arg_check(callee, arg_list, code_base))) { p = ZMALLOC(FCALL_REC); p->callee = callee; p->call_scope = (short) call_scope; p->move_level = (short) move_level; p->call = call; p->arg_list = arg_list; p->arg_cnt_checked = 1; /* add to resolve list */ p->link = resolve_list; resolve_list = p; } } }
static CODEBLOCK * new_code(void) { CODEBLOCK *p = ZMALLOC(CODEBLOCK); p->base = (INST *) zmalloc(INST_BYTES(PAGESZ)); p->limit = p->base + PAGESZ; p->warn = p->limit - CODEWARN; p->ptr = p->base; return p; }
static FILE_NODE * alloc_filenode(void) { FILE_NODE *result; result = ZMALLOC(FILE_NODE); #ifdef NO_LEAKS result->name = 0; #endif result->ptr = 0; return result; }
/* Called by: zxbus_load_ent, zxbus_login_ent, zxbus_login_subj_hash */ struct hi_ent* zxbus_new_ent(struct hiios* shf, int len, const char* eid) { struct hi_ent* ent; if (len == -1) len = strlen(eid); ZMALLOC(ent); ent->n = shf->ents; shf->ents = ent; ZMALLOCN(ent->chs, shf->max_chs); MALLOCN(ent->eid, len+1); memcpy(ent->eid, eid, len); ent->eid[len] = 0; return ent; }
void code_jmp(int jtype, INST * target) { if (error_state) return; /* WARNING: Don't emit any code before using target or relocation might make it invalid */ if (target) code2op(jtype, (int) (target - (code_ptr + 1))); else { register JMP *p = ZMALLOC(JMP); /* stack for back patch */ code2op(jtype, 0); p->source_offset = code_offset - 1; p->link = jmp_top; jmp_top = p; } }
void BC_insert(int type, INST * address) { register BC *p; if (error_state) return; if (type && !bc_top) { compile_error("%s statement outside of loop", type == 'B' ? "break" : "continue"); return; } else { p = ZMALLOC(BC); p->type = type; p->source_offset = (int) (address - code_base); p->link = bc_top; bc_top = p; } }
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"); } } }
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 */ } }
int is_cmdline_assign(char *s) { register char *p; int c; SYMTAB *stp; CELL *cp = 0; size_t len; CELL cell; /* used if command line assign to pseudo field */ CELL *fp = (CELL *) 0; /* ditto */ size_t length; if (scan_code[*(unsigned char *) s] != SC_IDCHAR) return 0; p = s + 1; while ((c = scan_code[*(unsigned char *) p]) == SC_IDCHAR || c == SC_DIGIT) p++; if (*p != '=') return 0; *p = 0; stp = find(s); switch (stp->type) { case ST_NONE: stp->type = ST_VAR; stp->stval.cp = cp = ZMALLOC(CELL); break; case ST_VAR: case ST_NR: /* !! no one will do this */ cp = stp->stval.cp; cell_destroy(cp); break; case ST_FIELD: /* must be pseudo field */ fp = stp->stval.cp; cp = &cell; break; default: rt_error( "cannot command line assign to %s\n\ttype clash or keyword" ,s); } /* we need to keep ARGV[i] intact */ *p++ = '='; len = strlen(p) + 1; /* posix says escape sequences are on from command line */ p = rm_escape(strcpy((char *) zmalloc(len), p), &length); cp->ptr = (PTR) new_STRING1(p, length); zfree(p, len); check_strnum(cp); /* sets cp->type */ if (fp) /* move it from cell to pfield[] */ { field_assign(fp, cp); free_STRING(string(cp)); } return 1; }
/* type checks a list of call arguments, returns a list of arguments whose type is still unknown */ static CA_REC * call_arg_check(FBLOCK * callee, CA_REC * entry_list, INST * start) { register CA_REC *q; CA_REC *exit_list = (CA_REC *) 0; check_progress = 0; /* loop : take q off entry_list test it if OK zfree(q) else put on exit_list */ while ((q = entry_list)) { entry_list = q->link; if (q->type == ST_NONE) { /* try to infer the type */ /* it might now be in symbol table */ if (q->sym_p->type == ST_VAR) { /* set type and patch */ q->type = CA_EXPR; start[q->call_offset + 1].ptr = (PTR) q->sym_p->stval.cp; } else if (q->sym_p->type == ST_ARRAY) { q->type = CA_ARRAY; start[q->call_offset].op = A_PUSHA; start[q->call_offset + 1].ptr = (PTR) q->sym_p->stval.array; } else { /* try to infer from callee */ switch (callee->typev[q->arg_num]) { case ST_LOCAL_VAR: q->type = CA_EXPR; q->sym_p->type = ST_VAR; q->sym_p->stval.cp = ZMALLOC(CELL); q->sym_p->stval.cp->type = C_NOINIT; start[q->call_offset + 1].ptr = (PTR) q->sym_p->stval.cp; break; case ST_LOCAL_ARRAY: q->type = CA_ARRAY; q->sym_p->type = ST_ARRAY; q->sym_p->stval.array = new_ARRAY(); start[q->call_offset].op = A_PUSHA; start[q->call_offset + 1].ptr = (PTR) q->sym_p->stval.array; break; } } } else if (q->type == ST_LOCAL_NONE) { /* try to infer the type */ if (*q->type_p == ST_LOCAL_VAR) { /* set type , don't need to patch */ q->type = CA_EXPR; } else if (*q->type_p == ST_LOCAL_ARRAY) { q->type = CA_ARRAY; start[q->call_offset].op = LA_PUSHA; /* offset+1 op is OK */ } else { /* try to infer from callee */ switch (callee->typev[q->arg_num]) { case ST_LOCAL_VAR: q->type = CA_EXPR; *q->type_p = ST_LOCAL_VAR; /* do not need to patch */ break; case ST_LOCAL_ARRAY: q->type = CA_ARRAY; *q->type_p = ST_LOCAL_ARRAY; start[q->call_offset].op = LA_PUSHA; break; } } } /* if we still do not know the type put on the new list else type check */ if (q->type == ST_NONE || q->type == ST_LOCAL_NONE) { q->link = exit_list; exit_list = q; } else { /* type known */ if (callee->typev[q->arg_num] == ST_LOCAL_NONE) callee->typev[q->arg_num] = (char) q->type; else if (q->type != callee->typev[q->arg_num]) compile_error("type error in arg(%d) in call to %s", q->arg_num + 1, callee->name); ZFREE(q); check_progress = 1; } } /* while */ return exit_list; }