int histGet(const int num, char * const str, const unsigned len) { char *p; assert(str); assert(len); if(ctxtIsValid() && ctxtGet(0, CTXT_TAG_HISTORY, realNum(CTXT_TAG_HISTORY, num), &p) == 0) { assert(p); strncpy(str, p, len); str[len - 1] = 0; /* Make sure the string is terminated */ free(p); return 1; } return 0; }
int ctxtPop(const Context_Tag tag, char ** const Xbuf) { ctxt_info_t *info; char *buf; ctxtCheckInfoTag(tag); assert(Xbuf); info = &CTXT_INFO_STRUCT(tag); while(info->c_nummax > info->c_nummin) switch(ctxtGet(1, tag, info->c_nummax--, &buf)) { case 0: /* OK */ *Xbuf = buf; return 1; case 1: /* no such entry */ break; /* --> ifgnore silently */ case 2: /* out of memory */ error_out_of_memory(); return 0; /* will case "context empty" message */ } /* Nothing in the stack ==> make sure it's consistent */ ctxtClear(tag); return 0; }
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; } }