Exemplo n.º 1
0
/*--------
  target is big enough to hold size + 1 chars
  on exit the back of the target is zero terminated
 *--------------*/
size_t
fillbuff(int fd, char *target, size_t size)
{
    register int r;
    size_t entry_size = size;

    while (size)
	switch (r = (int) read(fd, target, size)) {
	case -1:
	    errmsg(errno, "read error");
	    mawk_exit(2);

	case 0:
	    goto out;

	default:
	    target += r;
	    size -= (unsigned) r;
	    break;
	}

  out:
    *target = 0;
    return (size_t) (entry_size - size);
}
Exemplo n.º 2
0
void
scan_init(const char *cmdline_program)
{
    if (cmdline_program) {
	program_fd = -1;	/* command line program */
	program_string = new_STRING0(strlen(cmdline_program) + 1);
	strcpy(program_string->str, cmdline_program);
	/* simulate file termination */
	program_string->str[program_string->len - 1] = '\n';
	buffp = (UChar *) program_string->str;
	eof_flag = 1;
    } else {			/* program from file[s] */
	scan_open();
	buffp = buffer = (UChar *) zmalloc((size_t) (BUFFSZ + 1));
	scan_fillbuff();
    }

#ifdef OS2			/* OS/2 "extproc" is similar to #! */
    if (strnicmp(buffp, "extproc ", 8) == 0)
	eat_comment();
#endif
    eat_nl();			/* scan to first token */
    if (next() == 0) {
	/* no program */
	mawk_exit(0);
    }

    un_next();

}
Exemplo n.º 3
0
static char *
enlarge_fin_buffer(FIN * fin)
{
    size_t r;
    size_t oldsize = fin->nbuffs * BUFFSZ + 1;
    size_t limit = (size_t) (fin->limit - fin->buff);

#ifdef  MSDOS
    /* I'm not sure this can really happen:
       avoid "16bit wrap" */
    if (fin->nbuffs == MAX_BUFFS) {
	errmsg(0, "out of input buffer space");
	mawk_exit(2);
    }
#endif

    fin->buffp =
	fin->buff = (char *) zrealloc(fin->buff, oldsize, oldsize + BUFFSZ);
    fin->nbuffs++;

    r = fillbuff(fin->fd, fin->buff + (oldsize - 1), (size_t) BUFFSZ);
    if (r < BUFFSZ)
	fin->flags |= EOF_FLAG;

    fin->limit = fin->buff + limit + r;
    return fin->buff;
}
Exemplo n.º 4
0
static void
output_failed(const char *name)
{
    errmsg(errno, "cannot open \"%s\" for output", name);
    mawk_exit(2);
    /* NOTREACHED */
}
Exemplo n.º 5
0
/* 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;
}
Exemplo n.º 6
0
RT_STATE *
RE_new_run_stack(void)
{
    size_t oldsize = (size_t) (RE_run_stack_limit - RE_run_stack_base);
    size_t newsize = oldsize + STACKGROWTH;

#ifdef	LMDOS			/* large model DOS */
    /* have to worry about overflow on multiplication (ugh) */
    if (newsize >= 4096)
	RE_run_stack_base = (RT_STATE *) 0;
    else
#endif

	RE_run_stack_base = (RT_STATE *) realloc(RE_run_stack_base,
						 newsize * sizeof(RT_STATE));

    if (!RE_run_stack_base) {
	fprintf(stderr, "out of memory for RE run time stack\n");
	/* this is pretty unusual, I've only seen it happen on
	   weird input to REmatch() under 16bit DOS , the same
	   situation worked easily on 32bit machine.  */
	mawk_exit(100);
    }

    RE_run_stack_limit = RE_run_stack_base + newsize;
    RE_run_stack_empty = RE_run_stack_base - 1;

    /* return the new stackp */
    return RE_run_stack_base + oldsize;
}
Exemplo n.º 7
0
static void
scan_open(void)			/* open pfile_name */
{
    if (pfile_name[0] == '-' && pfile_name[1] == 0) {
	program_fd = 0;
    } else if ((program_fd = open(pfile_name, O_RDONLY, 0)) == -1) {
	errmsg(errno, "cannot open %s", pfile_name);
	mawk_exit(2);
    }
}
Exemplo n.º 8
0
static void
out_of_mem()
{
   static char out[] = "out of memory" ;

   if (mawk_state == EXECUTION)	 rt_error(out) ;
   else
   {
      /* I don't think this will ever happen */
      compile_error(out) ; mawk_exit(2) ; 
   }
}
Exemplo n.º 9
0
static void
bad_option(char *s)
{
    errmsg(0, "not an option: %s", s);
    if (strcmp(s, "--lint") &&
	strcmp(s, "--lint-old") &&
	strcmp(s, "--posix") &&
	strcmp(s, "--re-interval") &&
	strcmp(s, "--traditional")) {
	mawk_exit(2);
    }
}
Exemplo n.º 10
0
static int
collect_string(void)
{
    register char *p = string_buff;
    int c;
    int e_flag = 0;		/* on if have an escape char */
    size_t len_buff;

    while (1) {
	CheckStringSize(p);
	switch (scan_code[NextUChar(*p++)]) {
	case SC_DQUOTE:	/* done */
	    *--p = 0;
	    goto out;

	case SC_NL:
	    p[-1] = 0;
	    /* FALLTHRU */

	case 0:		/* unterminated string */
	    compile_error(
			     "runaway string constant \"%.10s ...",
			     string_buff);
	    mawk_exit(2);

	case SC_ESCAPE:
	    if ((c = next()) == '\n') {
		p--;
		lineno++;
	    } else if (c == 0)
		un_next();
	    else {
		*p++ = (char) c;
		e_flag = 1;
	    }

	    break;

	default:
	    break;
	}
    }

  out:
    if (e_flag)
	rm_escape(string_buff, &len_buff);
    else
	len_buff = (unsigned) ((char *) p - string_buff);
    yylval.ptr = (PTR) new_STRING1(string_buff, len_buff);
    return STRING_;
}
Exemplo n.º 11
0
void
eat_nl(void)			/* eat all space including newlines */
{
    while (1) {
	switch (scan_code[(UChar) next()]) {
	case SC_COMMENT:
	    eat_comment();
	    break;

	case SC_NL:
	    lineno++;
	    /* FALLTHRU  */

	case SC_SPACE:
	    break;

	case SC_ESCAPE:
	    /* bug fix - surprised anyone did this,
	       a csh user with backslash dyslexia.(Not a joke)
	     */
	    {
		int c;

		while (scan_code[NextUChar(c)] == SC_SPACE) {
		    ;		/* empty */
		}
		if (c == '\n')
		    token_lineno = ++lineno;
		else if (c == 0) {
		    un_next();
		    return;
		} else {	/* error */
		    un_next();
		    /* can't un_next() twice so deal with it */
		    yylval.ival = '\\';
		    unexpected_char();
		    if (++compile_error_count == MAX_COMPILE_ERRORS)
			mawk_exit(2);
		    return;
		}
	    }
	    break;

	default:
	    un_next();
	    return;
	}
    }
}
Exemplo n.º 12
0
static void
usage(void)
{
    static const char *msg[] =
    {
	"Usage: mawk [Options] [Program] [file ...]",
	"",
	"Program:",
	"    The -f option value is the name of a file containing program text.",
	"    If no -f option is given, a \"--\" ends option processing; the following",
	"    parameters are the program text.",
	"",
	"Options:",
	"    -f program-file  Program  text is read from file instead of from the",
	"                     command-line.  Multiple -f options are accepted.",
	"    -F value         sets the field separator, FS, to value.",
	"    -v var=value     assigns value to program variable var.",
	"    --               unambiguous end of options.",
	"",
	"    Implementation-specific options are prefixed with \"-W\".  They can be",
	"    abbreviated:",
	"",
	"    -W version       show version information and exit.",
#if USE_BINMODE
	"    -W binmode",
#endif
	"    -W dump          show assembler-like listing of program and exit.",
	"    -W help          show this message and exit.",
	"    -W interactive   set unbuffered output, line-buffered input.",
	"    -W exec file     use file as program as well as last option.",
	"    -W random=number set initial random seed.",
	"    -W sprintf=number adjust size of sprintf buffer.",
	"    -W posix_space   do not consider \"\\n\" a space.",
	"    -W usage         show this message and exit.",
    };
    size_t n;
    for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n) {
	fprintf(stderr, "%s\n", msg[n]);
    }
    mawk_exit(0);
}
Exemplo n.º 13
0
RT_POS_ENTRY *
RE_new_pos_stack(void)
{
    size_t oldsize = (size_t) (RE_pos_stack_limit - RE_pos_stack_base);
    size_t newsize = oldsize + STACKGROWTH;

    /* FIXME: handle overflow on multiplication for large model DOS
     * (see RE_new_run_stack()).
     */
    RE_pos_stack_base = (RT_POS_ENTRY *)
	realloc(RE_pos_stack_base, newsize * sizeof(RT_POS_ENTRY));

    if (!RE_pos_stack_base) {
	fprintf(stderr, "out of memory for RE string position stack\n");
	mawk_exit(100);
    }

    RE_pos_stack_limit = RE_pos_stack_base + newsize;
    RE_pos_stack_empty = RE_pos_stack_base;

    /* return the new stackp */
    return RE_pos_stack_base + oldsize;
}
Exemplo n.º 14
0
/* 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;
}
Exemplo n.º 15
0
static void eval_overflow()
{ overflow("eval stack" , EVAL_STACK_SIZE) ; mawk_exit(1) ; }
Exemplo n.º 16
0
static void
string_too_long(void)
{
    compile_error("string too long \"%.10s ...", string_buff);
    mawk_exit(2);
}
Exemplo n.º 17
0
/* getting here means a logic flaw or unforeseen case */
void
RE_panic(const char *s)
{
    fprintf(stderr, "REcompile() - panic:  %s\n", s);
    mawk_exit(100);
}
Exemplo n.º 18
0
static int
collect_RE(void)
{
    char *p = string_buff;
    const char *first = NULL;
    int limit = sizeof(string_buff) - 2;
    int c;
    int boxed = 0;
    STRING *sval;

    while (1) {
	if (p >= (string_buff + limit)) {
	    compile_error(
			     "regular expression /%.10s ..."
			     " exceeds implementation size limit (%d)",
			     string_buff,
			     limit);
	    mawk_exit(2);
	}
	CheckStringSize(p);
	switch (scan_code[NextUChar(c = *p++)]) {
	case SC_POW:
	    /* Handle [^]] and [^^] correctly. */
	    if ((p - 1) == first && first != 0 && first[-1] == '[') {
		first = p;
	    }
	    break;

	case SC_LBOX:
	    /*
	     * If we're starting a bracket expression, remember where that
	     * started, so we can make comparisons to handle things like
	     * "[]xxxx]" and "[^]xxxx]".
	     */
	    if (!boxed) {
		first = p;
		++boxed;
	    } else {
		/* XXX. Does not handle collating symbols or equivalence
		 * class expressions. */
		/* XXX. Does not match logic used in rexp0.c to check for
		 * a character class expression, though probably the
		 * latter should be adjusted.
		 * POSIX and common sense give us license to complain about
		 * expressions such as '[[:not a special character class]]'.
		 */
		if (next() == ':') {
		    ++boxed;
		}
		un_next();
	    }
	    break;

	case SC_RBOX:
	    /*
	     * A right square-bracket loses its special meaning if it occurs
	     * first in the list (after an optional "^").
	     */
	    if (boxed && p - 1 != first) {
		--boxed;
	    }
	    break;

	case SC_DIV:		/* done */
	    if (!boxed) {
		*--p = 0;
		goto out;
	    }
	    break;

	case SC_NL:
	    p[-1] = 0;
	    /* FALLTHRU */

	case 0:		/* unterminated re */
	    compile_error(
			     "runaway regular expression /%.10s ...",
			     string_buff);
	    mawk_exit(2);

	case SC_ESCAPE:
	    switch (c = next()) {
	    case '/':
		p[-1] = '/';
		break;

	    case '\n':
		p--;
		break;

	    case 0:
		un_next();
		break;

	    default:
		*p++ = (char) c;
		break;
	    }
	    break;
	}
    }

  out:
    /* now we've got the RE, so compile it */
    sval = new_STRING(string_buff);
    yylval.ptr = re_compile(sval);
    free_STRING(sval);
    return RE;
}
Exemplo n.º 19
0
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  */
    }
}
Exemplo n.º 20
0
static void
write_error(void)
{
    errmsg(errno, "write failure");
    mawk_exit(2);
}
Exemplo n.º 21
0
static void
no_program(void)
{
    mawk_exit(0);
}
Exemplo n.º 22
0
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");
	}
    }
}
Exemplo n.º 23
0
static void
bad_option(char *s)
{
    errmsg(0, "not an option: %s", s);
    mawk_exit(2);
}