/*\ |*| array_demote_only |*| array demote discards the values of a dictionary, and |*| returns a packed list of the keys. |*| (Useful because keys are ordered and unique, presumably.) |*| (This allows the keys to be abused as sets.) \*/ stk_array * array_demote_only(stk_array *arr, int threshold) { stk_array *demoted_array = NULL; int items_left = 0; array_iter current_key; array_iter *current_value; array_iter new_index; if (!arr || ARRAY_DICTIONARY != arr->type) return NULL; new_index.type = PROG_INTEGER;; new_index.data.number = 0; demoted_array = new_array_packed(0); items_left = array_first(arr, ¤t_key); while (items_left) { current_value = array_getitem(arr, ¤t_key); if (PROG_INTEGER == current_value->type && current_value->data.number >= threshold) { array_insertitem(&demoted_array, &new_index, ¤t_key); new_index.data.number++; } items_left = array_next(arr, ¤t_key); } return demoted_array; }
stk_array * get_pids(dbref ref) { struct inst temp1, temp2; stk_array *nw; int count = 0; timequeue ptr = tqhead; nw = new_array_packed(0); while (ptr) { if (((ptr->typ != TQ_MPI_TYP) ? (ptr->called_prog == ref) : (ptr->trig == ref)) || (ptr->uid == ref) || (ref < 0) ) { temp2.type = PROG_INTEGER; temp2.data.number = ptr->eventnum; temp1.type = PROG_INTEGER; temp1.data.number = count++; array_setitem(&nw, &temp1, &temp2); CLEAR(&temp1); CLEAR(&temp2); } ptr = ptr->next; } nw = get_mufevent_pids(nw, ref); return nw; }
void prim_forcedby_array(PRIM_PROTOTYPE) { stk_array *nu; int count = 0; CHECKOFLOW(1); if (mlev < 4) abort_interp("Wizbit only primitive."); if (!forcelist) { PushArrayRaw(new_array_packed(0, fr->pinning)); return; } nu = new_array_packed(force_level, fr->pinning); for (objnode *tmp = forcelist; tmp; tmp = tmp->next) { array_set_intkey_refval(&nu, count++, tmp->data); } PushArrayRaw(nu); }
void prim_shallow_copy(PRIM_PROTOTYPE) { EXPECT_READ_STACK(1); CHECKOFLOW(1); if (arg[*top - 1].type != PROG_ARRAY) { copyinst(&arg[*top - 1], &arg[*top]); (*top)++; } else { stk_array *nu; stk_array *arr = arg[*top - 1].data.array; if (!arr) { nu = new_array_packed(0, fr->pinning); } else { nu = array_decouple(arr); } PushArrayRaw(nu); } }
void prim_regfind_array(PRIM_PROTOTYPE) { struct flgchkdat check; dbref ref, who; const char *name; stk_array *nw; muf_re* re; char* text = NULL; int flags; int matchcnt = 0; const char* errstr = NULL; CHECKOP(4); oper4 = POP(); /* int:pcreflags */ oper3 = POP(); /* str:objflags */ oper2 = POP(); /* str:namepattern */ oper1 = POP(); /* ref:owner */ if (mlev < LMAGE) abort_interp("MAGE prim."); if (oper4->type != PROG_INTEGER) abort_interp("Non-integer argument (4)"); if (oper3->type != PROG_STRING) abort_interp("Expected string argument. (3)"); if (oper2->type != PROG_STRING) abort_interp("Expected string argument. (2)"); if (oper1->type != PROG_OBJECT) abort_interp("Expected dbref argument. (1)"); if (oper1->data.objref < NOTHING || oper1->data.objref >= db_top) abort_interp("Bad object. (1)"); flags = PCRE_NO_AUTO_CAPTURE; if (oper4->data.number & MUF_RE_ICASE) flags |= PCRE_CASELESS; if (oper4->data.number & MUF_RE_EXTENDED) flags |= PCRE_EXTENDED; re = regmatch_re_get(oper2->data.string, flags, &errstr); if (errstr) abort_interp(errstr) /* We're scanning a chunk of the DB, so studying should pay off. * A null return is fine, it just means we can't optimize further. */ if (re && !re->extra) { re->extra = pcre_study(re->re, 0, &errstr); if (errstr) abort_interp(errstr); } who = oper1->data.objref; name = DoNullInd(oper2->data.string); init_checkflags(PSafe, DoNullInd(oper3->data.string), &check); nw = new_array_packed(0); /* The "result = array_appendref" stuff was copied from find_array. I'm * making sure these alterations work as-is before attempting to remove it. * -brevantes */ for (ref = (dbref) 0; ref < db_top; ref++) { if (((who == NOTHING) ? 1 : (OWNER(ref) == who)) && checkflags(ref, check) && NAME(ref)) { if (!*name) result = array_appendref(&nw, ref); else text = (char *)NAME(ref); if ((matchcnt = regmatch_exec(re, text)) < 0) { if (matchcnt != PCRE_ERROR_NOMATCH) abort_interp(muf_re_error(matchcnt)); } else { result = array_appendref(&nw, ref); } } } CLEAR(oper1); CLEAR(oper2); CLEAR(oper3); CLEAR(oper4); PushArrayRaw(nw); }
void prim_array_regfilter_prop(PRIM_PROTOTYPE) { char buf[BUFFER_LEN]; struct inst *in; stk_array *arr; stk_array *nu; char* prop; const char* ptr; muf_re* re; int flags; int matchcnt = 0; const char* errstr = NULL; CHECKOP(4); oper4 = POP(); /* int pcreflags */ oper3 = POP(); /* str pattern */ oper2 = POP(); /* str propname */ oper1 = POP(); /* refarr Array */ if (oper1->type != PROG_ARRAY) abort_interp("Argument not an array. (1)"); if (!array_is_homogenous(oper1->data.array, PROG_OBJECT)) abort_interp("Argument not an array of dbrefs. (1)"); if (oper2->type != PROG_STRING || !oper2->data.string) abort_interp("Argument not a non-null string. (2)"); if (oper3->type != PROG_STRING) abort_interp("Argument not a string pattern. (3)"); if (oper4->type != PROG_INTEGER) abort_interp("Non-integer argument (4)"); ptr = oper2->data.string->data; while ((ptr = index(ptr, PROPDIR_DELIMITER))) if (!(*(++ptr))) abort_interp("Cannot access a propdir directly."); nu = new_array_packed(0); arr = oper1->data.array; flags = PCRE_NO_AUTO_CAPTURE; if (oper4->data.number & MUF_RE_ICASE) flags |= PCRE_CASELESS; if (oper4->data.number & MUF_RE_EXTENDED) flags |= PCRE_EXTENDED; re = regmatch_re_get(oper3->data.string, flags, &errstr); if (errstr) abort_interp(errstr) if (re && !re->extra && array_count(arr) > 2) { /* This pattern is getting used 3 or more times, let's study it. A null * return is okay, that just means there's nothing to optimize. */ re->extra = pcre_study(re->re, 0, &errstr); if (errstr) abort_interp(errstr); } prop = (char *) DoNullInd(oper2->data.string); if (array_first(arr, &temp1)) { do { in = array_getitem(arr, &temp1); if (valid_object(in)) { ref = in->data.objref; CHECKREMOTE(ref); if (prop_read_perms(ProgUID, ref, prop, mlev)) { ptr = get_property_class(ref, prop); if (ptr) strcpy(buf, ptr); else strcpy(buf, ""); if ((matchcnt = regmatch_exec(re, buf)) < 0) { if (matchcnt != PCRE_ERROR_NOMATCH) abort_interp(muf_re_error(matchcnt)); } else { array_appenditem(&nu, in); } } } } while (array_next(arr, &temp1)); } CLEAR(oper4); CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushArrayRaw(nu); }
void prim_regexp(PRIM_PROTOTYPE) { stk_array* nu_val = 0; stk_array* nu_idx = 0; int matches[MATCH_ARR_SIZE]; muf_re* re; char* text; int flags = 0; int len, i; int matchcnt = 0; const char* errstr; CHECKOP(3); oper3 = POP(); /* int:Flags */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_INTEGER) abort_interp("Non-integer argument (3)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper3->data.number & MUF_RE_ICASE) flags |= PCRE_CASELESS; if (oper3->data.number & MUF_RE_EXTENDED) flags |= PCRE_EXTENDED; if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL) abort_interp(errstr); text = (char *)DoNullInd(oper1->data.string); len = strlen(text); if ((matchcnt = pcre_exec(re->re, re->extra, text, len, 0, 0, matches, MATCH_ARR_SIZE)) < 0) { if (matchcnt != PCRE_ERROR_NOMATCH) { abort_interp(muf_re_error(matchcnt)); } if (((nu_val = new_array_packed(0)) == NULL) || ((nu_idx = new_array_packed(0)) == NULL)) { if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } } else { if (((nu_val = new_array_packed(matchcnt)) == NULL) || ((nu_idx = new_array_packed(matchcnt)) == NULL)) { if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } for(i = 0; i < matchcnt; i++) { int substart = matches[i*2]; int subend = matches[i*2+1]; struct inst idx, val; stk_array* nu; if ((substart >= 0) && (subend >= 0) && (substart < len)) snprintf(buf, BUFFER_LEN, "%.*s", (int)(subend - substart), &text[substart]); else buf[0] = '\0'; idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_STRING; val.data.string = alloc_prog_string(buf); array_setitem(&nu_val, &idx, &val); CLEAR(&idx); CLEAR(&val); if ((nu = new_array_packed(2)) == NULL) { array_free(nu_val); array_free(nu_idx); abort_interp("Out of memory"); } idx.type = PROG_INTEGER; idx.data.number = 0; val.type = PROG_INTEGER; val.data.number = substart + 1; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = 1; val.type = PROG_INTEGER; val.data.number = subend - substart; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_ARRAY; val.data.array = nu; array_setitem(&nu_idx, &idx, &val); CLEAR(&idx); CLEAR(&val); } } CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushArrayRaw(nu_val); PushArrayRaw(nu_idx); }
stk_array * array_getrange(stk_array *arr, array_iter *start, array_iter *end) { stk_array *new2; array_data *tmp; int sidx, eidx; if (!arr) { return NULL; } switch (arr->type) { case ARRAY_PACKED:{ array_iter idx; array_iter didx; if (start->type != PROG_INTEGER) { return NULL; } if (end->type != PROG_INTEGER) { return NULL; } sidx = start->data.number; eidx = end->data.number; if (sidx < 0) { sidx = 0; } else if (sidx > arr->items) { return NULL; } if (eidx >= arr->items) { eidx = arr->items - 1; } else if (eidx < 0) { return NULL; } if (sidx > eidx) { return NULL; } idx.type = PROG_INTEGER; idx.data.number = sidx; didx.type = PROG_INTEGER; didx.data.number = 0; new2 = new_array_packed(eidx - sidx + 1); while (idx.data.number <= eidx) { tmp = array_getitem(arr, &idx); if (!tmp) break; array_setitem(&new2, &didx, tmp); didx.data.number++; idx.data.number++; } return new2; break; } case ARRAY_DICTIONARY:{ stk_array *new2; array_tree *s; array_tree *e; new2 = new_array_dictionary(); s = array_tree_find(arr->data.dict, start); if (!s) { s = array_tree_next_node(arr->data.dict, start); if (!s) { return new2; } } e = array_tree_find(arr->data.dict, end); if (!e) { e = array_tree_prev_node(arr->data.dict, end); if (!e) { return new2; } } if (array_tree_compare(&s->key, &e->key, 0, 0, 0) > 0) { return new2; } while (s) { array_setitem(&new2, &s->key, &s->data); if (s == e) break; s = array_tree_next_node(arr->data.dict, &s->key); } return new2; break; } default: break; } return NULL; }
stk_array * tune_parms_array(const char *pattern, int mlev) { struct tune_str_entry *tstr = tune_str_list; struct tune_time_entry *ttim = tune_time_list; struct tune_val_entry *tval = tune_val_list; struct tune_ref_entry *tref = tune_ref_list; struct tune_bool_entry *tbool = tune_bool_list; stk_array *nu = new_array_packed(0); struct inst temp1; char pat[BUFFER_LEN]; char buf[BUFFER_LEN]; int i = 0; strcpy(pat, pattern); while (tbool->name) { if (tbool->readmlev <= mlev) { strcpy(buf, tbool->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "boolean"); array_set_strkey_strval(&item, "group", tbool->group); array_set_strkey_strval(&item, "name", tbool->name); array_set_strkey_intval(&item, "value", *tbool->boolv ? 1 : 0); array_set_strkey_intval(&item, "readmlev", tbool->readmlev); array_set_strkey_intval(&item, "writemlev", tbool->writemlev); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tbool++; } while (ttim->name) { if (ttim->readmlev <= mlev) { strcpy(buf, ttim->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "timespan"); array_set_strkey_strval(&item, "group", ttim->group); array_set_strkey_strval(&item, "name", ttim->name); array_set_strkey_intval(&item, "value", *ttim->tim); array_set_strkey_intval(&item, "readmlev", ttim->readmlev); array_set_strkey_intval(&item, "writemlev", ttim->writemlev); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } ttim++; } while (tval->name) { if (tval->readmlev <= mlev) { strcpy(buf, tval->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "integer"); array_set_strkey_strval(&item, "group", tval->group); array_set_strkey_strval(&item, "name", tval->name); array_set_strkey_intval(&item, "value", *tval->val); array_set_strkey_intval(&item, "readmlev", tval->readmlev); array_set_strkey_intval(&item, "writemlev", tval->writemlev); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tval++; } while (tref->name) { if (tref->readmlev <= mlev) { strcpy(buf, tref->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "dbref"); array_set_strkey_strval(&item, "group", tref->group); array_set_strkey_strval(&item, "name", tref->name); array_set_strkey_refval(&item, "value", *tref->ref); array_set_strkey_intval(&item, "readmlev", tref->readmlev); array_set_strkey_intval(&item, "writemlev", tref->writemlev); switch (tref->typ) { case NOTYPE: array_set_strkey_strval(&item, "objtype", "any"); break; case TYPE_PLAYER: array_set_strkey_strval(&item, "objtype", "player"); break; case TYPE_THING: array_set_strkey_strval(&item, "objtype", "thing"); break; case TYPE_ROOM: array_set_strkey_strval(&item, "objtype", "room"); break; case TYPE_EXIT: array_set_strkey_strval(&item, "objtype", "exit"); break; case TYPE_PROGRAM: array_set_strkey_strval(&item, "objtype", "program"); break; case TYPE_GARBAGE: array_set_strkey_strval(&item, "objtype", "garbage"); break; default: array_set_strkey_strval(&item, "objtype", "unknown"); break; } temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tref++; } while (tstr->name) { if (tstr->readmlev <= mlev) { strcpy(buf, tstr->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "string"); array_set_strkey_strval(&item, "group", tstr->group); array_set_strkey_strval(&item, "name", tstr->name); array_set_strkey_strval(&item, "value", *tstr->str); array_set_strkey_intval(&item, "readmlev", tstr->readmlev); array_set_strkey_intval(&item, "writemlev", tstr->writemlev); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tstr++; } return nu; }
void prim_regexp(PRIM_PROTOTYPE) { stk_array *nu_val = 0; stk_array *nu_idx = 0; regmatch_t *matches = 0; muf_re *re; char *text; int flags = 0; int nosubs, err, len, i; CHECKOP(3); oper3 = POP(); /* int:Flags */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_INTEGER) abort_interp("Non-integer argument (3)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper3->data.number & MUF_RE_ICASE) flags |= REG_ICASE; if ((re = muf_re_get(oper2->data.string, flags, &err)) == NULL) abort_interp(muf_re_error(err)); text = DoNullInd(oper1->data.string); len = strlen(text); nosubs = re->re.re_nsub + 1; if ((matches = (regmatch_t *) malloc(sizeof(regmatch_t) * nosubs)) == NULL) abort_interp("Out of memory"); if ((err = regexec(&re->re, text, nosubs, matches, 0)) != 0) { if (err != REG_NOMATCH) { free(matches); abort_interp(muf_re_error(err)); } if (((nu_val = new_array_packed(0)) == NULL) || ((nu_idx = new_array_packed(0)) == NULL)) { free(matches); if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } } else { if (((nu_val = new_array_packed(nosubs)) == NULL) || ((nu_idx = new_array_packed(nosubs)) == NULL)) { free(matches); if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } for (i = 0; i < nosubs; i++) { regmatch_t *cm = &matches[i]; struct inst idx, val; stk_array *nu; if ((cm->rm_so >= 0) && (cm->rm_eo >= 0) && (cm->rm_so < len)) snprintf(buf, BUFFER_LEN, "%.*s", cm->rm_eo - cm->rm_so, &text[cm->rm_so]); else buf[0] = '\0'; idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_STRING; val.data.string = alloc_prog_string(buf); array_setitem(&nu_val, &idx, &val); CLEAR(&idx); CLEAR(&val); if ((nu = new_array_packed(2)) == NULL) { free(matches); array_free(nu_val); array_free(nu_idx); abort_interp("Out of memory"); } idx.type = PROG_INTEGER; idx.data.number = 0; val.type = PROG_INTEGER; val.data.number = cm->rm_so + 1; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = 1; val.type = PROG_INTEGER; val.data.number = cm->rm_eo - cm->rm_so; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_ARRAY; val.data.array = nu; array_setitem(&nu_idx, &idx, &val); CLEAR(&idx); CLEAR(&val); } } free(matches); CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushArrayRaw(nu_val); PushArrayRaw(nu_idx); }
void prim_array_filter_prop(PRIM_PROTOTYPE) { char pattern[BUFFER_LEN]; char tname[BUFFER_LEN]; struct inst *in; struct inst temp1; stk_array *arr; stk_array *nu; char* prop; int len; CHECKOP(3); oper3 = POP(); /* str pattern */ oper2 = POP(); /* str propname */ oper1 = POP(); /* refarr Array */ if (oper1->type != PROG_ARRAY) abort_interp("Argument not an array. (1)"); if (!array_is_homogenous(oper1->data.array, PROG_OBJECT)) abort_interp("Argument not an array of dbrefs. (1)"); if (oper2->type != PROG_STRING || !oper2->data.string) abort_interp("Argument not a non-null string. (2)"); if (oper3->type != PROG_STRING) abort_interp("Argument not a string pattern. (3)"); len = oper2->data.string ? oper2->data.string->length : 0; strcpyn(tname, sizeof(tname), DoNullInd(oper2->data.string)); while (len-- > 0 && tname[len] == PROPDIR_DELIMITER) { tname[len] = '\0'; } nu = new_array_packed(0); arr = oper1->data.array; prop = tname; strcpyn(pattern, sizeof(pattern), DoNullInd(oper3->data.string)); if (array_first(arr, &temp1)) { do { in = array_getitem(arr, &temp1); if (valid_object(in)) { ref = in->data.objref; CHECKREMOTE(ref); if (prop_read_perms(ProgUID, ref, prop, mlev)) { PropPtr pptr = get_property(ref, prop); if (pptr) { switch(PropType(pptr)) { case PROP_STRTYP: strncpy(buf, PropDataStr(pptr), BUFFER_LEN); break; case PROP_LOKTYP: if (PropFlags(pptr) & PROP_ISUNLOADED) { strncpy(buf, "*UNLOCKED*", BUFFER_LEN); } else { strncpy(buf, unparse_boolexp(ProgUID, PropDataLok(pptr), 0), BUFFER_LEN); } break; case PROP_REFTYP: snprintf(buf, BUFFER_LEN, "#%i", PropDataRef(pptr)); break; case PROP_INTTYP: snprintf(buf, BUFFER_LEN, "%i", PropDataVal(pptr)); break; case PROP_FLTTYP: snprintf(buf, BUFFER_LEN, "%g", PropDataFVal(pptr)); break; default: strncpy(buf, "", BUFFER_LEN); break; } } else strncpy(buf, "", BUFFER_LEN); if (equalstr(pattern, buf)) { array_appenditem(&nu, in); } } } } while (array_next(arr, &temp1)); } CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushArrayRaw(nu); }