register char *StrConcat(int argcnt) { unsigned cnt, *poi; unsigned Xcnt, *Xpoi; unsigned length; char *h, *p; DBG_ENTER1 cnt = nargs(); DBG_ENTER2("StrConcat", "dynstr") DBG_ARGUMENTS( ("argcnt=%u cnt=%u", argcnt, cnt) ) Xpoi = poi = cnt * 2 - 2 + &argcnt; Xcnt = cnt = min(cnt, *poi); for(length = 1; cnt--;) if(*--poi) length += strlen(*poi); chkHeap if((h = p = eno_malloc(length)) == 0) DBG_RETURN_S( 0) chkHeap while(Xcnt--) if(*--Xpoi) p = stpcpy(p, *Xpoi); chkHeap DBG_RETURN_S( h) }
char *dfnsqueeze(const char * const fnam) { char *p, *h, *q; #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnusqueeze", Suppl_dfn) #else DBG_ENTER("dfnsqueeze", Suppl_dfn) #endif DBG_ARGUMENTS( ("fnam=\"%s\"", fnam) ) if(!fnam || (h = q = eno_strdup(fnam)) == 0) DBG_RETURN_S( 0) #ifdef SUPPORT_UNC_PATH if(isUNCpath(q)) /* keep the two backslashes */ q += 2; #endif p = q; /* where to begin to squeeze */ /* First: Flip the slashes */ while((q = strchr(q, '/')) != 0) *q = '\\'; /* Second: Squeeze & upcase */ q = p; chkHeap do { redo: if(*q == '\\') { /* possibly to be squeezed */ if(q[1] == '\\') { /* Squeeze '\\\\' -> '\\' */ ++q; goto redo; } if(q[1] == '.') { if(q[2] == '\\') { /* squeeze '\\.\\' -> '\\' */ q += 2; goto redo; } #if 0 /* this may lead to confusion -- 2000/06/07 ska*/ if(q[2] == '\0') { /* squeeze '\\.\0' -> '\\' */ *p = '\\'; *++p = NUL; break; } #endif } } } while((*p++ = toFUpper(*q++)) != 0); chkHeap DBG_RETURN_BS( StrTrim(h)) }
char *appFile(void) { DBG_ENTER("appFile", Suppl_appName); if(!app_file) { DBG_INFO( ("SUPPL subsystem 'appName' not initialized") ) DBG_RETURN_S(0) } *app_fnam = '\\'; if(app_fext) *app_fext = '.'; DBG_RETURN_BS(app_file) }
char *dfnfilename(const char * const fnam) { const char *p; DBG_ENTER("dfnfilename", Suppl_dfn) if(!fnam) DBG_RETURN_S( 0) DBG_ARGUMENTS( ("fnam=\"%s\"", fnam) ) p = strchr(fnam, '\0'); while(--p >= fnam && !dfndelim2(*p)); DBG_RETURN_S( (char*)p + 1) }
char *StrWord(char *s) { char *p; DBG_ENTER("StrWord", Suppl_dynstr) if(!s) DBG_RETURN_S( 0) if(isspace(*s)) { /* left trim */ p = s; while(*++p && isspace(*p)); memmove(p, s, strlen(p) + 1); /* we need to copy this area anyway */ } /* right trim */ p = strchr(s, '\0'); while(--p >= s && isspace(*p)); p[1] = '\0'; chkHeap DBG_RETURN_BS( StrTrim(s)) }
char *dfnbakname(const char * const fnam) { char *p, *q, *h; DBG_ENTER("dfnbakname", Suppl_dfn) assert(fnam); DBG_ARGUMENTS( ("fnam=\"%s\"", fnam) ) /* Allocate 5 bytes more to be absolutely sure that the ".BAK" can be appended */ chkHeap if((p = eno_malloc(strlen(fnam) + 5)) == 0) DBG_RETURN_S( 0) chkHeap if((h = strrchr(q = dfnfilename(strcpy(p, fnam)), '.')) == 0) h = strchr(q, '\0'); strcpy(h, ".BAK"); chkHeap DBG_RETURN_S( p) }
char *StrConcat(int argcnt, ...) { va_list strings; char *h, *p, *s; unsigned length; DBG_ENTER("StrConcat", Suppl_dynstr) DBG_ARGUMENTS( ("argcnt=%u cnt=%u", argcnt, argcnt) ) va_start(strings, argcnt); chkHeap if((p = eno_strdup("")) == 0) DBG_RETURN_S( 0) chkHeap length = 1; while(argcnt--) { s = va_arg(strings, char *); if(s && *s) { chkHeap if((h = eno_realloc(p, length += strlen(s))) == 0) { free(p); DBG_RETURN_S( 0) } strcat(p = h, s); }
char *dfnmerge(char *fnam, const char * const dr, const char * const Xpath , const char * const nam, const char * const ext) { int len; const char *path; char *p; int delim; /* type of last path component delimiter: 0: none 1: a "real" one ('/' or '\\') or none necessary 2: a colon */ #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnumerge", Suppl_dfn) #else DBG_ENTER("dfnmerge", Suppl_dfn) #endif DBG_ARGUMENTS( ("dr=\"%s\", pa=\"%s\", na=\"%s\", ex=\"%s\", out=%p", dr, Xpath, nam, ext, fnam) ) path = Xpath; if((p = fnam) == 0) { /* determine file nam length */ #ifdef SUPPORT_UNC_PATH len = dr? (*dr == '\\'? strlen(dr) + 1: 3): 1; #else len = dr? 3: 1; /* add the NUL terminator */ #endif if(path) { if(*path) len += strlen(path) + 1; else path = 0; /* no path component specified */ } if(nam) len += strlen(nam); if(ext) len += strlen(ext) + 1; if((fnam = p = eno_malloc(len)) == 0) DBG_RETURN_S( 0) *fnam = NUL; } if(dr) { #ifdef SUPPORT_UNC_PATH if(*dr == '\\') { p = stpcpy(p, dr); /* Test if the drive spec already ends with a delimiter */ delim = isDelim(p[-1]); } else { #endif if(0 != (*p = *dr)) ++p; *p++ = ':'; /* The colon is not a delimiter for root directories */ delim = 2; #ifdef SUPPORT_UNC_PATH } #endif *p = NUL; } else delim = 1; /* no drive --> no delim necessary */ if(path) { switch(delim) { case 0: /* missing delimiter --> need one unless path has one */ if(!isDelim(*path)) *p++ = '\\'; break; } if(!*path) /* The root dir always requires a backslash */ *p++ = '\\'; /* Now, the delimiter is definitely there */ p = stpcpy(p, path); if(0 == (delim = isDelim(p[-1]))) { if(p[-1] == ':') delim = 2; } } if(nam) { if(!delim) { if(!isDelim(*nam)) *p++ = '\\'; delim = 1; } p = stpcpy(p, nam); } if(ext) { if(!delim) { *p++ = '\\'; delim = 1; } *p++ = '.'; strcpy(p, ext); } DBG_RETURN_S( fnam) }
char *dfnfullpath(const char * const fnam) { char *fullpath; char *paths; char *q; /* intermediate pointers */ char *nxtDelim; int cnt; #ifdef OS_WIN32 #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnufullpath2", Suppl_dfn) #else DBG_ENTER("dfnfullpath2", Suppl_dfn) #endif #else #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnufullpath", Suppl_dfn) #else DBG_ENTER("dfnfullpath", Suppl_dfn) #endif #endif assert(fnam); DBG_ARGUMENTS( ("fnam=\"%s\"", fnam) ) chkHeap if((fullpath = dfnexpand(fnam, 0)) == 0) DBG_RETURN_S( 0) assert(*fullpath); #ifdef SUPPORT_UNC_PATH if(isUNCpath(fullpath)) paths = UNCpath(fullpath); else #endif { assert(*fullpath && fullpath[1] == ':'); paths = &fullpath[2]; } chkHeap assert(*paths == '\\'); q = paths; while(*q == '\\' && *++q) { /* Check for special directories */ if((nxtDelim = strchr(q, '\\')) == 0) nxtDelim = strchr(q, '\0'); if((cnt = strspn(q, ".")) == nxtDelim - q #ifndef FEATURE_LONG_FILENAMES && cnt < 3 /* DOS limits to "." and ".." */ #endif ) { /* all dots --> special directory */ /* Relocate "q" (cnt-1) path components to the left */ while(--q > paths && --cnt) { /* search next '\' to the left */ while(*--q != '\\'); ++q; } if(*nxtDelim) { /* some components left, move them up */ /* Note: *nxtDelim == *q == '\\', but by copying over this single character one needs not implement a special handling if nxtDelim[1] == '\0' */ memmove(q, nxtDelim, strlen(nxtDelim) + 1); } else { /* this was the last component, but because this was a special directory, the information must be preserved that it is a directory --> append trailing backslash */ q[1] = '\0'; } } else { q = nxtDelim; } } chkHeap DBG_RETURN_S( StrTrim(fullpath)) }
char *dfnexpand(const char * const fnam, char * const path) { char *h, *p; /* intermediate pointers */ char *dr, *pa, *na, *ex; /* filename components */ char pathDr, *pathPa; /* drive & path of 'path' */ char *dynPath; #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnuexpand", Suppl_dfn) #else DBG_ENTER("dfnexpand", Suppl_dfn) #endif assert(fnam); DBG_ARGUMENTS( ("fnam=\"%s\", path=\"%s\"", fnam, path) ) chkHeap if((h = dfnsqueeze(fnam)) == 0) DBG_RETURN_S( 0) #ifdef SUPPORT_UNC_PATH if(isUNCpath(h)) { /* UNC paths are always fully-qualified */ /* check if the trailing '\\' is present to mark the root direc */ DBG_RETURN_BS((*UNCpath(h) != '\\')? StrAppChr(h, '\\') : h) } #endif chkHeap if(!*h || h[1] != ':' || h[2] != '\\') { /* the spec is not fully-qualified or completely empty */ pathDr = 0; dynPath = 0; if((pathPa = path) != 0 && *pathPa) { if(pathPa[1] == ':') { /* path[] has drive spec */ pathDr = *path; if(!*(pathPa += 2)) { pathPa = 0; goto noPath; } } if(dfndelim(*pathPa) && !pathPa[1]) ++pathPa; /* Trans "/" || "\\" --> "" */ noPath:; } chkHeap if(dfnsplit(h, &dr, &pa, &na, &ex)) { StrFree(h); if(dr) { /* drive specified */ if(pathDr && toFUpper(pathDr) != *dr) /* The specified path is for a different drive */ pathPa = 0; } else { /* drive spec missing */ if((dr = StrChar(pathDr? pathDr: 'A' + getdisk())) == 0) goto errRet; } if(!pa || *pa != '\\' && *pa != NUL) { /* no path or a relative one */ if(!pathPa) { /* path has no path spec in it */ if((dynPath = dfnpath(*dr)) == 0) goto errRet; pathPa = dynPath + 2; } if((p = dfnmerge(0, 0, pathPa, pa, 0)) == 0) goto errRet; StrRepl(pa, p); } h = dfnmerge(0, dr, pa, na, ex); } else StrFree(h); errRet: chkHeap free(dr); free(pa); free(na); free(ex); free(dynPath); }