openenvutils/commandshell/shell/src/loop.c
changeset 0 2e3d3ce01487
child 1 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // loop.c - loop execution
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * This file is part of zsh, the Z shell.
       
     7  *
       
     8  * Copyright (c) 1992-1997 Paul Falstad
       
     9  * All rights reserved.
       
    10  *
       
    11  * Permission is hereby granted, without written agreement and without
       
    12  * license or royalty fees, to use, copy, modify, and distribute this
       
    13  * software and to distribute modified versions of this software for any
       
    14  * purpose, provided that the above copyright notice and the following
       
    15  * two paragraphs appear in all copies of this software.
       
    16  *
       
    17  * In no event shall Paul Falstad or the Zsh Development Group be liable
       
    18  * to any party for direct, indirect, special, incidental, or consequential
       
    19  * damages arising out of the use of this software and its documentation,
       
    20  * even if Paul Falstad and the Zsh Development Group have been advised of
       
    21  * the possibility of such damage.
       
    22  *
       
    23  * Paul Falstad and the Zsh Development Group specifically disclaim any
       
    24  * warranties, including, but not limited to, the implied warranties of
       
    25  * merchantability and fitness for a particular purpose.  The software
       
    26  * provided hereunder is on an "as is" basis, and Paul Falstad and the
       
    27  * Zsh Development Group have no obligation to provide maintenance,
       
    28  * support, updates, enhancements, or modifications.
       
    29  *
       
    30  */
       
    31 #include "zsh.mdh"
       
    32 #include "loop.pro"
       
    33 
       
    34 #ifdef __SYMBIAN32__
       
    35 #ifdef __WINSCW__
       
    36 #pragma warn_unusedarg off
       
    37 #pragma warn_possunwant off
       
    38 #endif//__WINSCW__
       
    39 #endif//__SYMBIAN32__
       
    40 
       
    41 /* # of nested loops we are in */
       
    42  
       
    43 /**/
       
    44 int loops;
       
    45  
       
    46 /* # of continue levels */
       
    47  
       
    48 /**/
       
    49 mod_export int contflag;
       
    50  
       
    51 /* # of break levels */
       
    52  
       
    53 /**/
       
    54 mod_export int breaks;
       
    55 
       
    56 /**/
       
    57 int
       
    58 execfor(Estate state, int do_exec)
       
    59 {
       
    60     Wordcode end, loop;
       
    61     wordcode code = state->pc[-1];
       
    62     int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0;
       
    63     int last = 0;
       
    64     char *name, *str, *cond = NULL, *advance = NULL;
       
    65     zlong val = 0;
       
    66     LinkList vars = NULL, args = NULL;
       
    67 
       
    68     end = state->pc + WC_FOR_SKIP(code);
       
    69 
       
    70     if (iscond) {
       
    71 	str = dupstring(ecgetstr(state, EC_NODUP, NULL));
       
    72 	singsub(&str);
       
    73 	if (isset(XTRACE)) {
       
    74 	    char *str2 = dupstring(str);
       
    75 	    untokenize(str2);
       
    76 	    printprompt4();
       
    77 	    fprintf(xtrerr, "%s\n", str2);
       
    78 	    fflush(xtrerr);
       
    79 	}
       
    80 	if (!errflag)
       
    81 	    matheval(str);
       
    82 	if (errflag) {
       
    83 	    state->pc = end;
       
    84 	    return lastval = errflag;
       
    85 	}
       
    86 	cond = ecgetstr(state, EC_NODUP, &ctok);
       
    87 	advance = ecgetstr(state, EC_NODUP, &atok);
       
    88     } else {
       
    89 	vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL);
       
    90 
       
    91 	if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
       
    92 	    int htok = 0;
       
    93 
       
    94 	    if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
       
    95 		state->pc = end;
       
    96 		return 0;
       
    97 	    }
       
    98 	    if (htok)
       
    99 		execsubst(args);
       
   100 	} else {
       
   101 	    char **x;
       
   102 
       
   103 	    args = newlinklist();
       
   104 	    for (x = pparams; *x; x++)
       
   105 		addlinknode(args, dupstring(*x));
       
   106 	}
       
   107     }
       
   108     lastval = 0;
       
   109     loops++;
       
   110     pushheap();
       
   111     cmdpush(CS_FOR);
       
   112     loop = state->pc;
       
   113     while (!last) {
       
   114 	if (iscond) {
       
   115 	    if (ctok) {
       
   116 		str = dupstring(cond);
       
   117 		singsub(&str);
       
   118 	    } else
       
   119 		str = cond;
       
   120 	    if (!errflag) {
       
   121 		while (iblank(*str))
       
   122 		    str++;
       
   123 		if (*str) {
       
   124 		    if (isset(XTRACE)) {
       
   125 			printprompt4();
       
   126 			fprintf(xtrerr, "%s\n", str);
       
   127 			fflush(xtrerr);
       
   128 		    }
       
   129 		    val = mathevali(str);
       
   130 		} else
       
   131 		    val = 1;
       
   132 	    }
       
   133 	    if (errflag) {
       
   134 		if (breaks)
       
   135 		    breaks--;
       
   136 		lastval = 1;
       
   137 		break;
       
   138 	    }
       
   139 	    if (!val)
       
   140 		break;
       
   141 	} else {
       
   142 	    LinkNode node;
       
   143 	    int count = 0;
       
   144 	    for (node = firstnode(vars); node; incnode(node))
       
   145 	    {
       
   146 		name = (char *)getdata(node);
       
   147 		if (!args || !(str = (char *) ugetnode(args)))
       
   148 		{
       
   149 		    if (count) { 
       
   150 			str = "";
       
   151 			last = 1;
       
   152 		    } else
       
   153 			break;
       
   154 		}
       
   155 		if (isset(XTRACE)) {
       
   156 		    printprompt4();
       
   157 		    fprintf(xtrerr, "%s=%s\n", name, str);
       
   158 		    fflush(xtrerr);
       
   159 		}
       
   160 		setsparam(name, ztrdup(str));
       
   161 		count++;
       
   162 	    }
       
   163 	    if (!count)
       
   164 		break;
       
   165 	}
       
   166 	state->pc = loop;
       
   167 	execlist(state, 1, do_exec && args && empty(args));
       
   168 	if (breaks) {
       
   169 	    breaks--;
       
   170 	    if (breaks || !contflag)
       
   171 		break;
       
   172 	    contflag = 0;
       
   173 	}
       
   174 	if (retflag)
       
   175 	    break;
       
   176 	if (iscond && !errflag) {
       
   177 	    if (atok) {
       
   178 		str = dupstring(advance);
       
   179 		singsub(&str);
       
   180 	    } else
       
   181 		str = advance;
       
   182 	    if (isset(XTRACE)) {
       
   183 		printprompt4();
       
   184 		fprintf(xtrerr, "%s\n", str);
       
   185 		fflush(xtrerr);
       
   186 	    }
       
   187 	    if (!errflag)
       
   188 		matheval(str);
       
   189 	}
       
   190 	if (errflag) {
       
   191 	    if (breaks)
       
   192 		breaks--;
       
   193 	    lastval = 1;
       
   194 	    break;
       
   195 	}
       
   196 	freeheap();
       
   197     }
       
   198     popheap();
       
   199     cmdpop();
       
   200     loops--;
       
   201     state->pc = end;
       
   202     return lastval;
       
   203 }
       
   204 
       
   205 /**/
       
   206 int
       
   207 execselect(Estate state, UNUSED(int do_exec))
       
   208 {
       
   209     Wordcode end, loop;
       
   210     wordcode code = state->pc[-1];
       
   211     char *str, *s, *name;
       
   212     LinkNode n;
       
   213     int i, usezle;
       
   214     FILE *inp;
       
   215     size_t more;
       
   216     LinkList args;
       
   217 
       
   218     end = state->pc + WC_FOR_SKIP(code);
       
   219     name = ecgetstr(state, EC_NODUP, NULL);
       
   220 
       
   221     if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
       
   222 	char **x;
       
   223 
       
   224 	args = newlinklist();
       
   225 	for (x = pparams; *x; x++)
       
   226 	    addlinknode(args, dupstring(*x));
       
   227     } else {
       
   228 	int htok = 0;
       
   229 
       
   230 	if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
       
   231 	    state->pc = end;
       
   232 	    return 0;
       
   233 	}
       
   234 	if (htok)
       
   235 	    execsubst(args);
       
   236     }
       
   237     if (!args || empty(args)) {
       
   238 	state->pc = end;
       
   239 	return 1;
       
   240     }
       
   241     loops++;
       
   242     lastval = 0;
       
   243     pushheap();
       
   244     cmdpush(CS_SELECT);
       
   245     usezle = interact && SHTTY != -1 && isset(USEZLE);
       
   246     inp = fdopen(dup(usezle ? SHTTY : 0), "r");
       
   247     more = selectlist(args, 0);
       
   248     loop = state->pc;
       
   249     for (;;) {
       
   250 	for (;;) {
       
   251 	    if (empty(bufstack)) {
       
   252 	    	if (usezle) {
       
   253 		    int oef = errflag;
       
   254 
       
   255 		    isfirstln = 1;
       
   256 		    str = (char *)zleread(&prompt3, NULL, 0, ZLCON_SELECT);
       
   257 		    if (errflag)
       
   258 			str = NULL;
       
   259 		    errflag = oef;
       
   260 	    	} else {
       
   261 		    str = promptexpand(prompt3, 0, NULL, NULL);
       
   262 		    zputs(str, stderr);
       
   263 		    free(str);
       
   264 		    fflush(stderr);
       
   265 		    str = fgets(zalloc(256), 256, inp);
       
   266 	    	}
       
   267 	    } else
       
   268 		str = (char *)getlinknode(bufstack);
       
   269 	    if (!str || errflag) {
       
   270 		if (breaks)
       
   271 		    breaks--;
       
   272 		fprintf(stderr, "\n");
       
   273 		fflush(stderr);
       
   274 		goto done;
       
   275 	    }
       
   276 	    if ((s = strchr(str, '\n')))
       
   277 		*s = '\0';
       
   278 	    if (*str)
       
   279 	      break;
       
   280 	    more = selectlist(args, more);
       
   281 	}
       
   282 	setsparam("REPLY", ztrdup(str));
       
   283 	i = atoi(str);
       
   284 	if (!i)
       
   285 	    str = "";
       
   286 	else {
       
   287 	    for (i--, n = firstnode(args); n && i; incnode(n), i--);
       
   288 	    if (n)
       
   289 		str = (char *) getdata(n);
       
   290 	    else
       
   291 		str = "";
       
   292 	}
       
   293 	setsparam(name, ztrdup(str));
       
   294 	state->pc = loop;
       
   295 	execlist(state, 1, 0);
       
   296 	freeheap();
       
   297 	if (breaks) {
       
   298 	    breaks--;
       
   299 	    if (breaks || !contflag)
       
   300 		break;
       
   301 	    contflag = 0;
       
   302 	}
       
   303 	if (retflag || errflag)
       
   304 	    break;
       
   305     }
       
   306   done:
       
   307     cmdpop();
       
   308     popheap();
       
   309     fclose(inp);
       
   310     loops--;
       
   311     state->pc = end;
       
   312     return lastval;
       
   313 }
       
   314 
       
   315 /* And this is used to print select lists. */
       
   316 
       
   317 /**/
       
   318 size_t
       
   319 selectlist(LinkList l, size_t start)
       
   320 {
       
   321     size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct;
       
   322     LinkNode n;
       
   323     char **arr, **ap;
       
   324 
       
   325     trashzle();
       
   326     ct = countlinknodes(l);
       
   327     ap = arr = (char **) zhalloc((countlinknodes(l) + 1) * sizeof(char **));
       
   328 
       
   329     for (n = (LinkNode) firstnode(l); n; incnode(n))
       
   330 	*ap++ = (char *)getdata(n);
       
   331     *ap = NULL;
       
   332     for (ap = arr; *ap; ap++)
       
   333 	if (strlen(*ap) > longest)
       
   334 	    longest = strlen(*ap);
       
   335     t0 = ct;
       
   336     longest++;
       
   337     while (t0)
       
   338 	t0 /= 10, longest++;
       
   339     /* to compensate for added ')' */
       
   340     fct = (columns - 1) / (longest + 3);
       
   341     if (fct == 0)
       
   342 	fct = 1;
       
   343     else
       
   344 	fw = (columns - 1) / fct;
       
   345     colsz = (ct + fct - 1) / fct;
       
   346     for (t1 = start; t1 != colsz && t1 - start < lines - 2; t1++) {
       
   347 	ap = arr + t1;
       
   348 	do {
       
   349 	    size_t t2 = strlen(*ap) + 2;
       
   350 	    int t3;
       
   351 
       
   352 	    fprintf(stderr, "%d) %s", t3 = ap - arr + 1, *ap);
       
   353 	    while (t3)
       
   354 		t2++, t3 /= 10;
       
   355 	    for (; t2 < fw; t2++)
       
   356 		fputc(' ', stderr);
       
   357 	    for (t0 = colsz; t0 && *ap; t0--, ap++);
       
   358 	}
       
   359 	while (*ap);
       
   360 	fputc('\n', stderr);
       
   361     }
       
   362 
       
   363  /* Below is a simple attempt at doing it the Korn Way..
       
   364        ap = arr;
       
   365        t0 = 0;
       
   366        do {
       
   367            t0++;
       
   368            fprintf(stderr,"%d) %s\n",t0,*ap);
       
   369            ap++;
       
   370        }
       
   371        while (*ap);*/
       
   372     fflush(stderr);
       
   373 
       
   374     return t1 < colsz ? t1 : 0;
       
   375 }
       
   376 
       
   377 /**/
       
   378 int
       
   379 execwhile(Estate state, UNUSED(int do_exec))
       
   380 {
       
   381     Wordcode end, loop;
       
   382     wordcode code = state->pc[-1];
       
   383     int olderrexit, oldval, isuntil = (WC_WHILE_TYPE(code) == WC_WHILE_UNTIL);
       
   384 
       
   385     end = state->pc + WC_WHILE_SKIP(code);
       
   386     olderrexit = noerrexit;
       
   387     oldval = 0;
       
   388     pushheap();
       
   389     cmdpush(isuntil ? CS_UNTIL : CS_WHILE);
       
   390     loops++;
       
   391     loop = state->pc;
       
   392 
       
   393     if (loop[0] == WC_END && loop[1] == WC_END) {
       
   394 
       
   395         /* This is an empty loop.  Make sure the signal handler sets the
       
   396         * flags and then just wait for someone hitting ^C. */
       
   397 
       
   398         int old_simple_pline = simple_pline;
       
   399 
       
   400         simple_pline = 1;
       
   401 
       
   402         while (!breaks)
       
   403             ;
       
   404         breaks--;
       
   405 
       
   406         simple_pline = old_simple_pline;
       
   407     } else
       
   408         for (;;) {
       
   409             state->pc = loop;
       
   410             noerrexit = 1;
       
   411             execlist(state, 1, 0);
       
   412             noerrexit = olderrexit;
       
   413             if (!((lastval == 0) ^ isuntil)) {
       
   414                 if (breaks)
       
   415                     breaks--;
       
   416                 lastval = oldval;
       
   417                 break;
       
   418             }
       
   419             if (retflag) {
       
   420                 lastval = oldval;
       
   421                 break;
       
   422             }
       
   423             execlist(state, 1, 0);
       
   424             if (breaks) {
       
   425                 breaks--;
       
   426                 if (breaks || !contflag)
       
   427                     break;
       
   428                 contflag = 0;
       
   429             }
       
   430             if (errflag) {
       
   431                 lastval = 1;
       
   432                 break;
       
   433             }
       
   434             if (retflag)
       
   435                 break;
       
   436             freeheap();
       
   437             oldval = lastval;
       
   438         }
       
   439     cmdpop();
       
   440     popheap();
       
   441     loops--;
       
   442     state->pc = end;
       
   443     return lastval;
       
   444 }
       
   445 
       
   446 /**/
       
   447 int
       
   448 execrepeat(Estate state, UNUSED(int do_exec))
       
   449 {
       
   450     Wordcode end, loop;
       
   451     wordcode code = state->pc[-1];
       
   452     int count, htok = 0;
       
   453     char *tmp;
       
   454 
       
   455     end = state->pc + WC_REPEAT_SKIP(code);
       
   456 
       
   457     lastval = 0;
       
   458     tmp = ecgetstr(state, EC_DUPTOK, &htok);
       
   459     if (htok)
       
   460 	singsub(&tmp);
       
   461     count = atoi(tmp);
       
   462     pushheap();
       
   463     cmdpush(CS_REPEAT);
       
   464     loops++;
       
   465     loop = state->pc;
       
   466     while (count-- > 0) {
       
   467 	state->pc = loop;
       
   468 	execlist(state, 1, 0);
       
   469 	freeheap();
       
   470 	if (breaks) {
       
   471 	    breaks--;
       
   472 	    if (breaks || !contflag)
       
   473 		break;
       
   474 	    contflag = 0;
       
   475 	}
       
   476 	if (errflag) {
       
   477 	    lastval = 1;
       
   478 	    break;
       
   479 	}
       
   480 	if (retflag)
       
   481 	    break;
       
   482     }
       
   483     cmdpop();
       
   484     popheap();
       
   485     loops--;
       
   486     state->pc = end;
       
   487     return lastval;
       
   488 }
       
   489 
       
   490 /**/
       
   491 int
       
   492 execif(Estate state, int do_exec)
       
   493 {
       
   494     Wordcode end, next;
       
   495     wordcode code = state->pc[-1];
       
   496     int olderrexit, s = 0, run = 0;
       
   497 
       
   498     olderrexit = noerrexit;
       
   499     end = state->pc + WC_IF_SKIP(code);
       
   500 
       
   501     if (!noerrexit)
       
   502 	noerrexit = 1;
       
   503     while (state->pc < end) {
       
   504 	code = *state->pc++;
       
   505 	if (wc_code(code) != WC_IF ||
       
   506 	    (run = (WC_IF_TYPE(code) == WC_IF_ELSE))) {
       
   507 	    if (run)
       
   508 		run = 2;
       
   509 	    break;
       
   510 	}
       
   511 	next = state->pc + WC_IF_SKIP(code);
       
   512 	cmdpush(s ? CS_ELIF : CS_IF);
       
   513 	execlist(state, 1, 0);
       
   514 	cmdpop();
       
   515 	if (!lastval) {
       
   516 	    run = 1;
       
   517 	    break;
       
   518 	}
       
   519 	if (retflag)
       
   520 	    break;
       
   521 	s = 1;
       
   522 	state->pc = next;
       
   523     }
       
   524     noerrexit = olderrexit;
       
   525 
       
   526     if (run) {
       
   527 	cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
       
   528 	execlist(state, 1, do_exec);
       
   529 	cmdpop();
       
   530     } else
       
   531 	lastval = 0;
       
   532     state->pc = end;
       
   533 
       
   534     return lastval;
       
   535 }
       
   536 
       
   537 /**/
       
   538 int
       
   539 execcase(Estate state, int do_exec)
       
   540 {
       
   541     Wordcode end, next;
       
   542     wordcode code = state->pc[-1];
       
   543     char *word, *pat;
       
   544     int npat, save;
       
   545     Patprog *spprog, pprog;
       
   546 
       
   547     end = state->pc + WC_CASE_SKIP(code);
       
   548 
       
   549     word = ecgetstr(state, EC_DUP, NULL);
       
   550     singsub(&word);
       
   551     untokenize(word);
       
   552     lastval = 0;
       
   553 
       
   554     cmdpush(CS_CASE);
       
   555     while (state->pc < end) {
       
   556 	code = *state->pc++;
       
   557 	if (wc_code(code) != WC_CASE)
       
   558 	    break;
       
   559 
       
   560 	pat = NULL;
       
   561 	pprog = NULL;
       
   562 	save = 0;
       
   563 	npat = state->pc[1];
       
   564 	spprog = state->prog->pats + npat;
       
   565 
       
   566 	next = state->pc + WC_CASE_SKIP(code);
       
   567 
       
   568 	if (isset(XTRACE)) {
       
   569 	    char *pat2, *opat;
       
   570 
       
   571 	    pat = dupstring(opat = ecrawstr(state->prog, state->pc, NULL));
       
   572 	    singsub(&pat);
       
   573 	    save = (!(state->prog->flags & EF_HEAP) &&
       
   574 		    !strcmp(pat, opat) && *spprog != dummy_patprog2);
       
   575 
       
   576 	    pat2 = dupstring(pat);
       
   577 	    untokenize(pat2);
       
   578 	    printprompt4();
       
   579 	    fprintf(xtrerr, "case %s (%s)\n", word, pat2);
       
   580 	    fflush(xtrerr);
       
   581 	}
       
   582 	state->pc += 2;
       
   583 
       
   584 	if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
       
   585 	    pprog = *spprog;
       
   586 
       
   587 	if (!pprog) {
       
   588 	    if (!pat) {
       
   589 		char *opat;
       
   590 		int htok = 0;
       
   591 
       
   592 		pat = dupstring(opat = ecrawstr(state->prog,
       
   593 						state->pc - 2, &htok));
       
   594 		if (htok)
       
   595 		    singsub(&pat);
       
   596 		save = (!(state->prog->flags & EF_HEAP) &&
       
   597 			!strcmp(pat, opat) && *spprog != dummy_patprog2);
       
   598 	    }
       
   599 	    if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
       
   600 				     NULL)))
       
   601 		zerr("bad pattern: %s", pat, 0);
       
   602 	    else if (save)
       
   603 		*spprog = pprog;
       
   604 	}
       
   605 	if (pprog && pattry(pprog, word)) {
       
   606 	    execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
       
   607 				do_exec));
       
   608 	    while (!retflag && wc_code(code) == WC_CASE &&
       
   609 		   WC_CASE_TYPE(code) == WC_CASE_AND) {
       
   610 		state->pc = next;
       
   611 		code = *state->pc;
       
   612 		state->pc += 3;
       
   613 		next = state->pc + WC_CASE_SKIP(code) - 2;
       
   614 		execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
       
   615 				    do_exec));
       
   616 	    }
       
   617 	    break;
       
   618 	} else
       
   619 	    state->pc = next;
       
   620     }
       
   621     cmdpop();
       
   622 
       
   623     state->pc = end;
       
   624 
       
   625     return lastval;
       
   626 }
       
   627 
       
   628 /*
       
   629  * Errflag from `try' block, may be reset in `always' block.
       
   630  * Accessible from an integer parameter, so needs to be a zlong.
       
   631  */
       
   632 
       
   633 /**/
       
   634 zlong
       
   635 try_errflag = -1;
       
   636 
       
   637 /**/
       
   638 int
       
   639 exectry(Estate state, int do_exec)
       
   640 {
       
   641     Wordcode end, always;
       
   642     int endval;
       
   643     int save_retflag, save_breaks, save_loops, save_contflag;
       
   644     zlong save_try_errflag;
       
   645 
       
   646     end = state->pc + WC_TRY_SKIP(state->pc[-1]);
       
   647     always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
       
   648     state->pc++;
       
   649     pushheap();
       
   650     cmdpush(CS_CURSH);
       
   651 
       
   652     /* The :try clause */
       
   653     execlist(state, 1, do_exec);
       
   654 
       
   655     /* Don't record errflag here, may be reset. */
       
   656     endval = lastval;
       
   657 
       
   658     freeheap();
       
   659 
       
   660     cmdpop();
       
   661     cmdpush(CS_ALWAYS);
       
   662 
       
   663     /* The always clause. */
       
   664     save_try_errflag = try_errflag;
       
   665     try_errflag = (zlong)errflag;
       
   666     errflag = 0;
       
   667     save_retflag = retflag;
       
   668     retflag = 0;
       
   669     save_breaks = breaks;
       
   670     breaks = 0;
       
   671     save_loops = loops;
       
   672     loops = 0;
       
   673     save_contflag = contflag;
       
   674     contflag = 0;
       
   675 
       
   676     state->pc = always;
       
   677     execlist(state, 1, do_exec);
       
   678 
       
   679     errflag = try_errflag ? 1 : 0;
       
   680     try_errflag = save_try_errflag;
       
   681     retflag = save_retflag;
       
   682     breaks = save_breaks;
       
   683     loops = save_loops;
       
   684     contflag = save_contflag;
       
   685 
       
   686     cmdpop();
       
   687     popheap();
       
   688     state->pc = end;
       
   689 
       
   690     return endval;
       
   691 }