char far*ctxtAddress(const Context_Tag tag, const unsigned num) { char name[CTXT_ITEMNAME_LENGTH]; word ofs, segm; ctxtMkItemName(name, tag, num); segm = ctxtFromTag(tag); assert(segm && segm != CTXT_INVALID); if((ofs = env_findVar(segm, name)) != (word)-1) return MK_FP(segm, ofs + strlen(name) + 1); return 0; }
int is_alias(const char * const name) { assert(name); return env_findVar(ctxtAlias, name) != (unsigned)-1; }
void aliasexpand(char * const cmd, const int maxlen) { char *hbuf; /* work buffer */ char *cp, *p; unsigned ofs, *expanded, *he; int i, numExpanded; assert(cmd); assert(strlen(cmd) < maxlen); if((hbuf = malloc(maxlen)) == 0) { error_out_of_memory(); return; } numExpanded = 0; expanded = 0; redo: /* iteration to expand all aliases */ cp = ltrimcl(cmd); /* skip leading whitespaces */ /* Check if the user disabled alias expansion */ if(*cp == '*') { memmove(cmd, cp + 1, strlen(cp)); goto errRet; } /* Get the name of this command */ for(p = hbuf; is_fnchar(*cp) || *cp == '.';) *p++ = *cp++; if(p == hbuf || is_pathdelim(*cp) || is_quote(*cp)) /* no name || part of path -> no alias */ goto errRet; *p = 0; StrFUpr(hbuf); /* all aliases are uppercased */ if((ofs = env_findVar(ctxtAlias, hbuf)) == (unsigned)-1) /* not found -> no alias */ goto errRet; /* Prevent recursion by recording the offset of the found variable */ for(i = 0; i < numExpanded; ++i) if(expanded[i] == ofs) /* already used -> ignore */ goto errRet; if((he = realloc(expanded, ++numExpanded)) == 0) { error_out_of_memory(); goto errRet; } expanded = he; expanded[numExpanded - 1] = ofs; /************ Expand the command line "cp" with the alias at MK_FP(ctxtAlias, ofs) ***********************/ ofs += strlen(hbuf) + 1; /* advance to value */ if(_fstrlen(MK_FP(ctxtAlias, ofs)) < maxlen - strlen(cp)) { /* prepend alias value to remaining command line */ _fstrcpy(TO_FP(hbuf), MK_FP(ctxtAlias, ofs)); strcat(hbuf, cp); assert(strlen(hbuf) < maxlen); strcpy(cmd, hbuf); goto redo; /* next expansion */ } error_command_too_long(); errRet: /* return to caller */ free(expanded); free(hbuf); }
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; } }
char *aliasexpand(const char * const Xcmd) { char *cmd; /* work buffer */ char *cp, *name, *alias; unsigned ofs, *expanded, *he; int i, numExpanded, newlen, len; assert(Xcmd); if((cmd = estrdup(Xcmd)) == 0) return (char*)Xcmd; numExpanded = 0; expanded = 0; name = 0; redo: /* iteration to expand all aliases */ cp = ltrimcl(cmd); /* skip leading whitespaces */ /* Check if the user disabled alias expansion */ if(*cp == '*') { *cp = ' '; goto errRet; } myfree(name); /* Get the name of this command */ if((name = getCmdName(&(const char*)cp)) == 0 || is_pathdelim(*cp)) goto errRet; StrFUpr(name); /* all aliases are uppercased */ if((ofs = env_findVar(ctxtAlias, name)) == (unsigned)-1) /* not found -> no alias */ goto errRet; /* Prevent recursion by recording the offset of the found variable */ for(i = 0; i < numExpanded; ++i) if(expanded[i] == ofs) /* already used -> ignore */ goto errRet; if((he = realloc(expanded, ++numExpanded)) == 0) { error_out_of_memory(); goto errRet; } expanded = he; expanded[numExpanded - 1] = ofs; /************ Expand the command line "cp" with the alias at MK_FP(ctxtAlias, ofs) ***********************/ alias = ctxtP(ctxtAlias, ofs + strlen(name) + 1); /* Check that the total command line won't overflow MAX_INT */ if((newlen = strlen(alias)) >= 0 && (len = strlen(cp)) >= 0 && ++len > 0 && newlen + len > 0) { int dst = cp - cmd; /* destination index within cmd[] */ if(newlen > dst) { /* need to increase the buffer */ char *p; if((p = realloc(cmd, newlen + len)) == 0) goto errRet1; cmd = p; } /* else ignore to shrink the buffer; it will be done automatically with the next ALIAS expansion or when this function returns */ assert(len); if(newlen != dst) /* need to move the command tail */ memmove(&cmd[newlen], &cmd[dst], len); /* prepend alias value to remaining command line */ memcpy(cmd, alias, newlen); goto redo; /* next expansion */ } errRet1: error_long_internal_line(); errRet: /* return to caller */ myfree(expanded); myfree(name); return StrTrim(cmd); }