void ctxtRenumberItems(const Context_Tag tag) { ctxtCheckInfoTag(tag); assert(ctxtFromTag(tag) != CTXT_INVALID); CTXT_INFO(tag, nummin) = CTXT_INFO(tag, nummax) = 0; env_forAll(ctxtFromTag(tag), renumber, (void*)tag); }
int ctxtSet(const Context_Tag tag , const unsigned num , const char * const value) { char name[CTXT_LENGTH_ITEMNAME]; int rc; ctxtMkItemName(name, tag, num); if((rc = chgCtxt(tag, name, value)) == E_None) { /* Update min/max to reflect the added value */ if(num && CTXT_INFO(tag, nummin) >= num) CTXT_INFO(tag, nummin) = num - 1; if(CTXT_INFO(tag, nummax) < num) CTXT_INFO(tag, nummax) = num; } return rc; }
static mk(ecTag_t tag) { char buf[2 + CTXT_LENGTH_ID]; sprintf(buf, "%c%u" , tag, CTXT_INFO(CTXT_TAG_STRING, nummax)); return ctxtPush(CTXT_TAG_EXEC, buf); }
int ctxtAddStatus(const Context_Tag tag) { char value[3]; ctxtCheckInfoTag(tag); *(unsigned*)value = CTXT_INFO(tag, sizemax) | 0x8001; value[sizeof(unsigned)] = 0; return ctxtSet(tag, 0, value); }
static int renumber(void *arg, word segm, word ofs) { char buf[CTXT_ITEMNAME_LENGTH]; #define tag (Context_Tag)(int)arg assert(segm); assert(ofs != (word)-1); if(ctxtProbeItemTag(segm, ofs, arg)) { ctxtMkItemName(buf, tag, ++CTXT_INFO(tag, nummax)); assert(peekb(segm , ofs + strlen(buf)) == '='); _fmemcpy(MK_FP(segm, ofs), TO_FP(buf), strlen(buf)); } #undef tag return 0; }
int cmd_history(char *param) { if(param && *param) { unsigned long x; x = atol(param); if(x < 10 || x > 32768U) { error_history_size(param); return 1; } CTXT_INFO(CTXT_TAG_HISTORY, sizemax) = (unsigned)x; ctxtCreate(); return 0; } return ctxtView(CTXT_TAG_HISTORY, TEXT_HISTORY_EMPTY); }
static int scan (void * arg, word segm, word ofs) { Context_Tag tag; ctxt_info_t *info; (void)arg; assert(segm); assert(ofs != (word)-1); redo: if((tag = peekb(segm, ofs), ctxtIsInfoTag(tag))) { info = &CTXT_INFO_STRUCT(tag); if(peekb(segm, ofs + 1) == '=' && peekb(segm, ofs + 4) == 0) { /* status entry */ info->c_sizemax = peekw(segm, ofs + 2) & ~0x8001; } else { /* normal entry */ char far *p = MK_FP(segm, ofs + 1); unsigned num; for(num = 0; isxdigit(*p); ++p) { num <<= 8; if(isdigit(*p)) num |= *p & 0xf; else { assert(islower(*p)); num |= *p - 'a' + 10; } } if(*p == '=') { info->c_sizecur += env_varlen(segm, ofs); if(num < info->c_nummin) info->c_nummin = num; if(num > info->c_nummax) info->c_nummax = num; } else { /* Invalid entry -> remove to make room for useful stuff */ env_subVarOffset(segm, ofs); goto redo; } } } else if(tag > ' ') { /* Alias */ CTXT_INFO(CTXT_TAG_ALIAS, sizecur) += env_varlen(segm ,ofs); } return 0; /* proceed */ }
static int renumber(void *arg, word segm, word ofs) { char buf[CTXT_LENGTH_ITEMNAME]; char *p; #define tag (Context_Tag)arg assert(segm); assert(ofs != (word)-1); p = ctxtP(segm, ofs); if(ctxtProbeItemTag(p, arg)) { ctxtMkItemName(buf, tag, ++CTXT_INFO(tag, nummax)); assert(p[strlen(buf)] == '='); /* do not copy trailing '\0' */ memcpy(p, buf, strlen(buf)); } #undef tag return 0; }
int ecMkI_S(const byte tag) { char buf[2 + CTXT_LENGTH_ID]; sprintf(buf, "%c%u" , tag, CTXT_INFO(CTXT_TAG_STRING, nummax)); return ctxtPush(CTXT_TAG_EXEC, buf); }
int chgCtxt(const Context_Tag tag, const char * const name, const char * const value) { word segm, ofs; int newlen; assert(name); ctxtCheckInfoTag(tag); segm = ctxtFromTag(tag); assert(segm); newlen = value? strlen(name) + strlen(value) + 2: 0; if((ofs = env_findVar(segm, name)) != (word)-1) newlen -= env_varlen(segm, ofs); /* Make sure the context has enough room to add the value to */ if(newlen > 0) { /* contents size will grow */ ctxt_info_t *hinfo, *dinfo; /* aliases may not exceed sizemax */ if(tag == CTXT_TAG_ALIAS) { if(CTXT_INFO(CTXT_TAG_ALIAS, sizemax) - CTXT_INFO(CTXT_TAG_ALIAS, sizecur) < newlen) { error_alias_out_of_memory(); return E_NoMem; } } /* Otherwise a removeable entry is removed; those are: oldest item of history oldest item of dirstack */ hinfo = segm == ctxtFromTag(CTXT_TAG_HISTORY) ? &CTXT_INFO_STRUCT(CTXT_TAG_HISTORY): 0; dinfo = segm == ctxtFromTag(CTXT_TAG_DIRSTACK) ? &CTXT_INFO_STRUCT(CTXT_TAG_DIRSTACK): 0; while(env_freeCount(segm) < newlen) { /* There are two structures that can shrink: history & dirstack */ if(hinfo && (hinfo->c_sizecur <= hinfo->c_sizemax /* inconsitency of redundant info */ || hinfo->c_nummin >= hinfo->c_nummax)) /* in range -> ignore */ hinfo = 0; if(dinfo && (dinfo->c_sizecur <= dinfo->c_sizemax /* inconsitency of redundant info */ || dinfo->c_nummin >= dinfo->c_nummax)) /* in range -> ignore */ dinfo = 0; if(hinfo && dinfo) { /* Choose one */ if(weight(hinfo) < weight(dinfo)) ctxtGet(1, CTXT_TAG_DIRSTACK, ++dinfo->c_nummin, 0); else ctxtGet(1, CTXT_TAG_HISTORY, ++hinfo->c_nummin, 0); } else if(dinfo) ctxtGet(1, CTXT_TAG_DIRSTACK, ++dinfo->c_nummin, 0); else if(hinfo) ctxtGet(1, CTXT_TAG_HISTORY, ++hinfo->c_nummin, 0); else { /* no space left */ error_context_out_of_memory(); return E_NoMem; } } } /* return values 1 and 3 are OK */ switch(env_change(segm, name, value)) { case 2: /* variable to delete not found <-> no problem */ case 1: case 3: /* var replaced | deleted | inserted ==> OK */ CTXT_INFO(tag, sizecur) += newlen; return 0; case 0: /* Cannot insert */ dprintf(("chgCtxt(): out-of-mem shouldn't occure here!\n")); error_context_out_of_memory(); return E_NoMem; default: return E_Syntax; } }