home *** CD-ROM | disk | FTP | other *** search
- /*
- o_stack.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_copy()
- {
- load_1_arg(ei, ep);
-
- if ((eptype(ep) == T_STRING || eptype(ep) == T_ARRAY ||
- eptype(ep) == T_DICT) && !(epattr(ep) & A_READ))
- return ERR_ACCESS_CHECK;
-
- current->os[current->osp-1] = element_copy(current, ei);
- decrefp(current, ei, ep);
-
- return OK;
- }
-
-
- retcode
- o_count()
- {
- eindex *ip;
- ushort i;
-
- load_1_arg(ei, ep);
-
- if (eptype(ep) != T_INT)
- return ERR_TYPE_CHECK;
- switch (ep->V.i) {
- case 0:
- for (i=current->osp, ip=current->os+i-1; i > 0; i--, ip--)
- if (*ip == mark)
- break;
- i = current->osp - i - 1;
- break;
- case 1: i = current->osp-1; break;
- case 2: i = current->dsp; break;
- case 3: i = current->esp; break;
- default:
- return ERR_RANGE_CHECK;
- }
- decrefp(current, ei, ep);
- ei = current->os[current->osp-1] = new_element(current, T_INT);
- eaddr(current,ei)->V.i = i;
- return OK;
- }
-
-
- retcode
- o_exch()
- {
- eindex ei, *ip;
-
- if (current->osp < 2)
- return ERR_STACK_UNDERFLOW;
- ip = current->os + current->osp - 1;
- ei = *ip;
- *ip = *(ip-1);
- *(ip-1) = ei;
- return OK;
- }
-
-
- retcode
- o_pop()
- {
- if (current->osp < 1)
- return ERR_STACK_UNDERFLOW;
- decref(current, current->os[current->osp-1]);
- current->osp -= 1;
- return OK;
- }
-
-
- retcode
- o_index()
- {
- eindex ei, i;
- eptr ep;
-
- if (current->osp < 2)
- return ERR_STACK_UNDERFLOW;
- ei = current->os[current->osp-1];
- ep = eaddr(current, ei);
- if (eptype(ep) != T_INT)
- return ERR_TYPE_CHECK;
- if (ep->V.i < 0)
- return ERR_RANGE_CHECK;
- if (current->osp < 2 + ep->V.i)
- return ERR_STACK_UNDERFLOW;
- i = current->os[current->osp - 2 - ep->V.i];
- decrefp(current, ei, ep);
- current->os[current->osp-1] = i;
- incref(current, i);
-
- return OK;
- }
-
-
- retcode
- o_roll()
- {
- sshort d, m;
-
- load_2_args(e1, e2, ep1, ep2);
-
- if (eptype(ep1) != T_INT || eptype(ep2) != T_INT)
- return ERR_TYPE_CHECK;
- m = ep1->V.i;
- if (m < 1)
- return ERR_RANGE_CHECK;
- if (current->osp < 2 + m)
- return ERR_STACK_UNDERFLOW;
-
- d = (m - ep2->V.i) % m;
- if (d < 0)
- d += m;
-
- if (d != 0) {
- eindex *s = current->os + current->osp - 2 - m;
- ushort n, root;
-
- for (root=0, n=m; n > 0; root++) {
- ushort i, j;
- eindex ei;
-
- n--;
- for (i=root, ei=s[root], j=(i+d)%m; j != root;
- n--, i=j, j=(i+d)%m)
- s[i] = s[j];
- s[i] = ei;
- }
- }
- decrefp(current, e1, ep1);
- decrefp(current, e2, ep2);
- current->osp -= 2;
-
- return OK;
- }
-
-
- retcode
- o_stack()
- {
- eindex r, *ip;
- eptr rp;
- uint i;
-
- load_1_arg(ei, ep);
-
- if (eptype(ep) != T_INT)
- return ERR_TYPE_CHECK;
- switch (ep->V.i) {
- case 1:
- r = make_array(current, current->os, current->osp);
- break;
- case 2:
- r = make_array(current, current->ds, current->dsp);
- break;
- case 3:
- r = make_array(current, current->es, current->esp);
- break;
- default:
- return ERR_RANGE_CHECK;
- }
- rp = eaddr(current, r);
- for (i = eplen(rp), ip = rp->V.arr.a; i > 0; i--, ip++)
- incref(current, *ip);
- epattr(rp) &= ~A_WRITE;
- decrefp(current, ei, ep);
- current->os[current->osp-1] = r;
-
- return OK;
- }
-