#include "ubermud.h" #include "externs.h" /* Copyright(C) 1990, Marcus J. Ranum, All Rights Reserved. This software may be freely used, modified, and redistributed, as long as this copyright message is left intact, and this software is not used to develop any commercial product, or used in any product that is provided on a pay-for-use basis. */ /* list manipulation functions. there are 2 more listcopy() and listfree() declared in alloc.c - which deal only with memory allocation type stuff. */ /* note - in all these functions, you CANNOT assign a stack value to the result argument, until AFTER you are done processing all the stuff in the stack - because result is ALSO firstarg in some cases, and assigning result will overwrite the argument stack */ /* since we use tmpalloc here, there is no need to worry about freeing stuff up. Lists that get copied into permanent storage will need to re-malloc this amount, and save it. allow a 'hint' as to the size of the list data space that will be needed. */ static ObjList * listnew(nmem) int nmem; { ObjList *ret; if((ret = (ObjList *)tmpalloc((int)sizeof(ObjList))) == 0) return(0); if(nmem > 0) { ret->l_data = (long *)tmpalloc((int)sizeof(long) * nmem); if(ret->l_data == 0) return(0); } ret->l_hi = nmem; ret->l_cnt = 0; return(ret); } /* add elements to an existing list. first arg is (must be) list, remaining are elements to add. */ void blt_listappend(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { ObjList *ret; long *refp; long *olp; long *olp2; int oc; int x; if(m->m_mem[firstarg].typ != TYP_OLIST && m->m_mem[firstarg].typ != TYP_NULL) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } if(m->m_mem[firstarg].typ != TYP_NULL) { olp2 = olp = m->m_mem[firstarg].oper.ol->l_data; oc = m->m_mem[firstarg].oper.ol->l_cnt; } else { olp2 = 0; oc = 0; } if((ret = listnew(oc + argc - 1)) == (ObjList *)0) { m->m_mem[result].typ = TYP_NULL; m->m_mem[result].oper.i = ERR_OOM; return; } ret->l_cnt = 0; refp = ret->l_data; /* copy all the old list elems */ for(x = 0; x < oc; x++) { *refp++ = *olp++; ret->l_cnt++; } /* skip first arg, remember */ for(x = 1; x < argc; x++) { int y; int skip = 0; long *xx = olp2; for(y = 0; y < oc; y++) { if(m->m_mem[firstarg + x].typ != TYP_OBJ || m->m_mem[firstarg + x].oper.l == *xx) { skip++; } xx++; } if(!skip) { *refp++ = m->m_mem[firstarg + x].oper.l; ret->l_cnt++; } } m->m_mem[result].oper.ol = ret; m->m_mem[result].typ = TYP_OLIST; } /* count the # of elements in a list. */ void blt_listcount(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { if(argc != 1 || m->m_mem[firstarg].typ != TYP_OLIST) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } if(m->m_mem[firstarg].oper.ol->l_cnt == 0) { m->m_mem[result].oper.i = ERR_NOTHERE; m->m_mem[result].typ = TYP_NULL; return; } m->m_mem[result].oper.i = m->m_mem[firstarg].oper.ol->l_cnt; m->m_mem[result].typ = TYP_NUM; } /* drop elements from an existing list. first arg is (must be) list, remaining are elements to drop. */ void blt_listdrop(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { ObjList *ret; long *refp; long *olp; int oc; int x; if(m->m_mem[firstarg].typ != TYP_OLIST) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } /* semi-bummer. cannot shrink the list because the elements may not actually be on it. keep it the same size */ oc = m->m_mem[firstarg].oper.ol->l_cnt; if((ret = listnew(oc)) == (ObjList *)0) { m->m_mem[result].typ = TYP_NULL; m->m_mem[result].oper.i = ERR_OOM; return; } ret->l_cnt = 0; refp = ret->l_data; olp = m->m_mem[firstarg].oper.ol->l_data; for(x = 0; x < oc; x++) { int y; int skip = 0; for(y = 1; y < argc; y++) { if(m->m_mem[firstarg + y].typ != TYP_OBJ || m->m_mem[firstarg + y].oper.l == *olp) { skip++; } } if(!skip) { *refp++ = *olp; ret->l_cnt++; } olp++; } if(ret->l_cnt == 0) { m->m_mem[result].oper.i = ERR_NONE; m->m_mem[result].typ = TYP_NULL; } else { m->m_mem[result].oper.ol = ret; m->m_mem[result].typ = TYP_OLIST; } } /* return the N-th element of a list. */ void blt_listelem(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { int x; if(argc != 2 || m->m_mem[firstarg].typ != TYP_OLIST || m->m_mem[firstarg + 1].typ != TYP_NUM) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } x = m->m_mem[firstarg + 1].oper.i; if(x > m->m_mem[firstarg].oper.ol->l_cnt) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } m->m_mem[result].oper.l = m->m_mem[firstarg].oper.ol->l_data[x - 1]; m->m_mem[result].typ = TYP_OBJ; } /* merge 2 lists into one. pack out dupes. */ void blt_listmerge(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { ObjList *ret; ObjList *lp1 = (ObjList *)0; ObjList *lp2 = (ObjList *)0; long *refp; long *olp; int l1c = 0; int l2c = 0; if((m->m_mem[firstarg].typ != TYP_OLIST && m->m_mem[firstarg].typ != TYP_NULL) || (m->m_mem[firstarg + 1].typ != TYP_OLIST && m->m_mem[firstarg + 1].typ != TYP_NULL)) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } /* set pointers */ if(m->m_mem[firstarg].typ != TYP_NULL) { lp1 = m->m_mem[firstarg].oper.ol; l1c = lp1->l_cnt; olp = lp1->l_data; } if(m->m_mem[firstarg + 1].typ != TYP_NULL) { lp2 = m->m_mem[firstarg + 1].oper.ol; l2c = lp2->l_cnt; } /* some memory wastage, but 'tis all temporary */ if((ret = listnew(l1c + l2c)) == (ObjList *)0) { m->m_mem[result].typ = TYP_NULL; m->m_mem[result].oper.i = ERR_OOM; return; } ret->l_cnt = 0; refp = ret->l_data; /* copy all unique elements from list #1 */ while(l1c--) { int y; int skip = 0; for(y = 0; y < l2c; y++) { if(lp2->l_data[y] == *olp) skip++; } if(!skip) { *refp++ = *olp; ret->l_cnt++; } olp++; } if(m->m_mem[firstarg + 1].typ != TYP_NULL) olp = lp2->l_data; /* by def. all elements in list #2 are unique, now. */ while(l2c--) { *refp++ = *olp++; ret->l_cnt++; } m->m_mem[result].oper.ol = ret; m->m_mem[result].typ = TYP_OLIST; } /* create a list. if arguments are provided, initialize it with them. */ void blt_listnew(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { ObjList *ret; long *refp; int x; if((ret = listnew(argc)) == (ObjList *)0) { m->m_mem[result].typ = TYP_NULL; m->m_mem[result].oper.i = ERR_OOM; return; } ret->l_cnt = 0; refp = ret->l_data; for(x = 0; x < argc; x++) { if(m->m_mem[firstarg + x].typ == TYP_OBJ) { *refp++ = m->m_mem[firstarg + x].oper.l; ret->l_cnt++; } } m->m_mem[result].oper.ol = ret; m->m_mem[result].typ = TYP_OLIST; } /* add elements to an existing list. first arg is (must be) list, remaining are elements to add. */ void blt_listprepend(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { ObjList *ret; long *refp; long *olp; int oc; int x; if(m->m_mem[firstarg].typ != TYP_OLIST && m->m_mem[firstarg].typ != TYP_NULL) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } if(m->m_mem[firstarg].typ != TYP_NULL) { olp = m->m_mem[firstarg].oper.ol->l_data; oc = m->m_mem[firstarg].oper.ol->l_cnt; } else { olp = 0; oc = 0; } if((ret = listnew(oc + argc - 1)) == (ObjList *)0) { m->m_mem[result].typ = TYP_NULL; m->m_mem[result].oper.i = ERR_OOM; return; } ret->l_cnt = 0; refp = ret->l_data; /* skip first arg, remember */ for(x = 1; x < argc; x++) { int y; int skip = 0; long *p = olp; for(y = 0; y < oc; y++) { if(m->m_mem[firstarg + x].typ != TYP_OBJ || m->m_mem[firstarg + x].oper.l == *p) { skip++; } p++; } if(!skip) { *refp++ = m->m_mem[firstarg + x].oper.l; ret->l_cnt++; } } for(x = 0; x < oc; x++) { *refp++ = *olp++; ret->l_cnt++; } m->m_mem[result].oper.ol = ret; m->m_mem[result].typ = TYP_OLIST; } /* search the list, returning the # of the slot where the element is, or 0 if it is not in the list */ void blt_listsearch(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { long *olp; int x; if(argc != 2 || m->m_mem[firstarg].typ != TYP_OLIST || m->m_mem[firstarg + 1].typ != TYP_OBJ) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } olp = m->m_mem[firstarg].oper.ol->l_data; for(x = 0; x < m->m_mem[firstarg].oper.ol->l_cnt; x++) { if(*olp == m->m_mem[firstarg + 1].oper.l) { m->m_mem[result].oper.i = x + 1; m->m_mem[result].typ = TYP_NUM; return; } olp++; } m->m_mem[result].oper.i = ERR_NOTHERE; m->m_mem[result].typ = TYP_NULL; } /* set the N-th element of a list to a value. */ void blt_listsetelem(m,argc,firstarg,result,uid,euid) Machine *m; int argc; int firstarg; int result; long *uid; long *euid; { ObjList *ret; long *olp; long *nlp; int oc; int sv; int x; if(argc != 3 || m->m_mem[firstarg].typ != TYP_OLIST || m->m_mem[firstarg + 1].typ != TYP_NUM || m->m_mem[firstarg + 2].typ != TYP_OBJ) { m->m_mem[result].oper.i = ERR_BADARG; m->m_mem[result].typ = TYP_NULL; return; } sv = m->m_mem[firstarg + 1].oper.i - 1; /* do not permit overruns or underruns */ if(sv < 0 || sv >= m->m_mem[firstarg].oper.ol->l_cnt) { m->m_mem[result].oper.i = ERR_NOTHERE; m->m_mem[result].typ = TYP_NULL; return; } oc = m->m_mem[firstarg].oper.ol->l_cnt; if((ret = listnew(oc)) == (ObjList *)0) { m->m_mem[result].oper.i = ERR_OOM; m->m_mem[result].typ = TYP_NULL; return; } olp = m->m_mem[firstarg].oper.ol->l_data; nlp = ret->l_data; for(x = 0; x < oc; x++) { if(x != sv) { *nlp++ = *olp++; } else { *nlp++ = m->m_mem[firstarg + 2].oper.l; olp++; } ret->l_cnt++; } m->m_mem[result].oper.ol = ret; m->m_mem[result].typ = TYP_OLIST; }