home *** CD-ROM | disk | FTP | other *** search
- /*
- o_ctrl.c
- */
- /* Copyright (c) 1994 Christian F. Tschudin. All rights reserved.
-
- Distributed under the terms of the GNU General Public License
- version 2 of june 1991 as published by the Free Software
- Foundation, Inc.
-
- This file is part of M0.
-
- M0 is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY. No author or distributor accepts responsibility to anyone for
- the consequences of using it or for whether it serves any particular
- purpose or works at all, unless he says so in writing. Refer to the GNU
- General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute M0, but
- only under the conditions described in the GNU General Public License.
- A copy of this license is supposed to have been given to you along with
- M0 so you can know your rights and responsibilities. It should be in a
- file named LICENSE. Among other things, the copyright notice and this
- notice must be preserved on all copies. */
-
-
- #include "l_proto.h"
- #include "o_proto.h"
-
-
- retcode
- o_exec()
- {
- load_1_arg(ei, ep);
-
- if (eptype(ep) != T_ARRAY && eptype(ep) != T_STRING &&
- eptype(ep) != T_NAME && eptype(ep) != T_PROC)
- return OK;
-
- if (current->esp >= MAXESTACK)
- return ERR_ESTACK_OVERFLOW;
- if (!(epattr(ep) & A_EXEC))
- return ERR_ACCESS_CHECK;
- current->osp--;
-
- if (!(epattr(ep)&A_EXECUTABLE)) {
- eindex res = make_sub(current, ei, 0);
- decrefp(current, ei, ep);
- ei = res;
- eattr(current,ei) |= A_EXECUTABLE;
- }
- current->es[current->esp++] = ei;
-
- return OK;
- }
-
-
- retcode
- o_exit()
- {
- sshort i, j;
- eindex *ip;
-
- if (current->esp == 0)
- return ERR_NOT_IN_LOOP;
- ip = current->es + current->esp - 1;
- for (i=current->esp; i > 0; i--, ip--)
- if (*ip == loop_mark || *ip == halt_mark)
- break;
- if (i == 0 || *ip == halt_mark)
- return ERR_NOT_IN_LOOP;
- i--;
- for (j = current->esp - i; j > 0; j--)
- decref(current, *ip++);
- current->esp = i;
-
- return OK;
- }
-
-
- retcode
- o_halt()
- {
- eindex ei, *ip;
- sshort i, j;
- eptr ep;
-
- if (current->esp == 0)
- return ERR_NOT_IN_HALTED;
- ip = current->es + current->esp - 1;
- for (i=current->esp; i > 0; i--, ip--)
- if (*ip == halt_mark)
- break;
- if (i == 0)
- return ERR_NOT_IN_HALTED;
- i--;
- for (j = current->esp - i; j > 0; j--)
- decref(current, *ip++);
- current->esp = i;
- ei = new_element(current, T_INT);
- ep = eaddr(current,ei);
- ep->V.i = 1;
- current->es[current->esp++] = ei;
-
- return OK;
- }
-
-
- retcode
- o_halted()
- {
- if (current->osp < 1)
- return ERR_STACK_UNDERFLOW;
- if (current->esp+3 >= MAXESTACK)
- return ERR_ESTACK_OVERFLOW;
- current->es[current->esp++] = halt_mark;
- incref(current,halt_mark);
- current->es[current->esp++] = halted_proc;
- incref(current,halted_proc);
- return o_exec();
- }
-
-
- retcode
- the_halted_proc()
- {
- eindex ei;
- eptr ep;
-
- /* drop halt_mark */
- decref(current, current->es[current->esp-1]);
- ei = new_element(current, T_INT);
- ep = eaddr(current,ei);
- ep->V.i = 0;
- current->es[current->esp-1] = ei;
- return OK;
- }
-
-
- retcode
- o_ifelse()
- {
- eindex ei;
- eptr ep;
- byte flag;
-
- if (current->osp < 3)
- return ERR_STACK_UNDERFLOW;
- ei = current->os[current->osp-3];
- ep = eaddr(current, ei);
- if (eptype(ep)!=T_INT)
- return ERR_TYPE_CHECK;
- flag = ep->V.i != 0;
- decref(current, ei);
- if (flag) {
- current->os[current->osp-3] = current->os[current->osp-2];
- decref(current, current->os[current->osp-1]);
- } else {
- current->os[current->osp-3] = current->os[current->osp-1];
- decref(current, current->os[current->osp-2]);
- }
- current->osp -= 2;
- return o_exec();
- }
-
-
- retcode
- o_loop()
- {
- eindex arg, cnt, proc, loop;
- eptr ep;
-
- if (current->osp < 2)
- return ERR_STACK_UNDERFLOW;
-
- proc = current->os[current->osp-1];
- arg = current->os[current->osp-2];
- ep = eaddr(current, arg);
-
- switch (eptype(ep)) {
- case T_INT:
- cnt = new_element(current, T_INT);
- if (ep->V.i >= 0) /* store the upper limit in the length field */
- elen(current,cnt) = ep->V.i + 1;
- else
- eaddr(current,cnt)->V.i = -1;
- decref(current, arg);
- loop = loop_iproc;
- break;
- case T_ARRAY:
- if (!(epattr(ep) & A_EXEC) || !(epattr(ep) & A_READ))
- return ERR_ACCESS_CHECK;
- cnt = make_sub(current, arg, 0);
- decref(current, arg);
- loop = loop_aproc;
- break;
- case T_DICT:
- if (!(epattr(ep) & A_EXEC) || !(epattr(ep) & A_READ))
- return ERR_ACCESS_CHECK;
- cnt = make_sub(current, arg, 0);
- decref(current, arg);
- loop = loop_dproc;
- break;
- case T_STRING:
- if (!(epattr(ep) & A_EXEC) || !(epattr(ep) & A_READ))
- return ERR_ACCESS_CHECK;
- cnt = make_sub(current, arg, 0);
- decref(current, arg);
- loop = loop_sproc;
- break;
- default:
- return ERR_TYPE_CHECK;
- }
- current->es[current->esp++] = loop_mark;
- incref(current, loop_mark);
- current->es[current->esp++] = cnt;
- current->es[current->esp++] = proc;
- current->es[current->esp++] = loop;
- incref(current, loop);
- current->osp -= 2;
- return OK;
- }
-
-
- retcode
- the_loop_iproc()
- {
- eindex ei = current->es[current->esp-2];
- eptr ep = eaddr(current,ei);
-
- TRACE(5, printf("loop_int_proc %d/%d\n", (int) ep->V.i, (int) eplen(ep)))
-
- if (eplen(ep))
- ep->V.i += 1;
- if (ep->V.i >= (sint) eplen(ep)) { /* end of loop */
- decref(current, current->es[current->esp-1]);
- decref(current, current->es[current->esp-2]);
- decref(current, current->es[current->esp-3]);
- current->esp -= 3;
- return OK;
- }
- if (eplen(ep)) { /* counting loop: push the counter */
- ei = new_element(current, T_INT);
- eaddr(current, ei)->V.i = ep->V.i - 1;
- current->os[current->osp++] = ei;
- }
- current->es[current->esp++] = loop_iproc;
- incref(current, loop_iproc);
- ei = current->es[current->esp-2];
- ep = eaddr(current, ei);
- if (eptype(ep) == T_STRING || eptype(ep) == T_ARRAY)
- ei = make_sub(current, ei, 0);
- else
- increfp(ep);
- current->es[current->esp++] = ei;
-
- return OK;
- }
-
-
- retcode
- the_loop_aproc()
- {
- eindex ei = current->es[current->esp-2], topush;
- eptr ep = eaddr(current,ei);
-
- TRACE(5, printf("loop_arrray_proc %d\n", (int) ep->V.sub.e))
-
- if (eplen(ep) == 0) { /* end of loop */
- decref(current, current->es[current->esp-1]);
- decref(current, current->es[current->esp-2]);
- decref(current, current->es[current->esp-3]);
- current->esp -= 3;
- return OK;
- }
- topush = array_get(current, ei, 0);
- current->os[current->osp++] = topush;
- incref(current, topush);
- ep->V.sub.offset += 1;
- eplen(ep) -= 1;
-
- current->es[current->esp++] = loop_aproc;
- incref(current, loop_aproc);
-
- ei = current->es[current->esp-2];
- ep = eaddr(current, ei);
- if (eptype(ep) == T_STRING || eptype(ep) == T_ARRAY)
- ei = make_sub(current, ei, 0);
- else
- increfp(ep);
- current->es[current->esp++] = ei;
-
- return OK;
- }
-
-
- retcode
- the_loop_dproc()
- {
- eindex ei = current->es[current->esp-2], di, *ip;
- eptr ep = eaddr(current,ei), dp;
-
- TRACE(5, printf("loop_dict_proc %d\n", (int) ep->V.sub.e))
-
- di = ep->V.sub.e;
- dp = eaddr(current, di);
- ip = dp->V.dic.d + 2*ep->V.sub.offset;
- while(ep->V.sub.offset < dp->V.dic.alen) {
- if (!*ip || *ip == DICT_DELETED) {
- ep->V.sub.offset += 1;
- ip += 2;
- continue;
- }
- current->os[current->osp++] = *ip;
- incref(current, *ip);
- current->os[current->osp++] = *(ip+1);
- incref(current, *(ip+1));
- ep->V.sub.offset += 1;
- current->es[current->esp++] = loop_dproc;
- incref(current, loop_dproc);
-
- ei = current->es[current->esp-2];
- ep = eaddr(current, ei);
- if (eptype(ep) == T_STRING || eptype(ep) == T_ARRAY)
- ei = make_sub(current, ei, 0);
- else
- increfp(ep);
- current->es[current->esp++] = ei;
-
- return OK;
- }
- /* end of loop */
- decref(current, current->es[current->esp-1]);
- decref(current, current->es[current->esp-2]);
- decref(current, current->es[current->esp-3]);
- current->esp -= 3;
- return OK;
- }
-
-
- retcode
- the_loop_sproc()
- {
- eindex ei = current->es[current->esp-2], topush;
- eptr ep = eaddr(current,ei);
-
- TRACE(5, printf("loop_string_proc %d\n", (int) ep->V.sub.e))
-
- if (eplen(ep) == 0) { /* end of loop */
- decref(current, current->es[current->esp-1]);
- decref(current, current->es[current->esp-2]);
- decref(current, current->es[current->esp-3]);
- current->esp -= 3;
- return OK;
- }
- topush = new_element(current, T_INT);
- eaddr(current, topush)->V.i = str_get(current, ei, 0);
- current->os[current->osp++] = topush;
- ep->V.sub.offset += 1;
- eplen(ep) -= 1;
-
- current->es[current->esp++] = loop_sproc;
- incref(current, loop_sproc);
-
- ei = current->es[current->esp-2];
- ep = eaddr(current, ei);
- if (eptype(ep) == T_STRING || eptype(ep) == T_ARRAY)
- ei = make_sub(current, ei, 0);
- else
- increfp(ep);
- current->es[current->esp++] = ei;
-
- return OK;
- }
-
-