📄 htstring.c
字号:
if (vasprintf(pstr, fmt, *ap) >= 0) { mark_malloced(*pstr, strlen(*pstr)+1); return(*pstr); } }#endif /* USE_VASPRINTF */ need = strlen(fmt) + 1;#ifdef SAVE_TIME_NOT_SPACE if (!fmt_ptr || fmt_len < need*NUM_WIDTH) { fmt_ptr = HTAlloc(fmt_ptr, fmt_len = need*NUM_WIDTH); } if (!tmp_ptr || tmp_len < GROW_SIZE) { tmp_ptr = HTAlloc(tmp_ptr, tmp_len = GROW_SIZE); }#else if ((fmt_ptr = malloc(need*NUM_WIDTH)) == 0 || (tmp_ptr = malloc(tmp_len)) == 0) { outofmem(__FILE__, "StrAllocVsprintf"); }#endif /* SAVE_TIME_NOT_SPACE */ if (dst_ptr == 0) { dst_ptr = HTAlloc(dst_ptr, have = GROW_SIZE + need); } else { have = strlen(dst_ptr) + 1; need += dst_len; if (have < need) dst_ptr = HTAlloc(dst_ptr, have = GROW_SIZE + need); } while (*fmt != '\0') { if (*fmt == '%') { static char dummy[] = ""; PRINTF state = Flags; char *pval = dummy; /* avoid const-cast */ double fval = 0.0; int done = FALSE; int ival = 0; int prec = -1; int type = 0; int used = 0; int width = -1; size_t f = 0; fmt_ptr[f++] = *fmt; while (*++fmt != '\0' && !done) { fmt_ptr[f++] = *fmt; if (isdigit(UCH(*fmt))) { int num = *fmt - '0'; if (state == Flags && num != 0) state = Width; if (state == Width) { if (width < 0) width = 0; width = (width * 10) + num; } else if (state == Prec) { if (prec < 0) prec = 0; prec = (prec * 10) + num; } } else if (*fmt == '*') { VA_INTGR(int); if (state == Flags) state = Width; if (state == Width) { width = ival; } else if (state == Prec) { prec = ival; } sprintf(&fmt_ptr[--f], "%d", ival); f = strlen(fmt_ptr); } else if (isalpha(UCH(*fmt))) { done = TRUE; switch (*fmt) { case 'Z': /* FALLTHRU */ case 'h': /* FALLTHRU */ case 'l': /* FALLTHRU */ case 'L': /* FALLTHRU */ done = FALSE; type = *fmt; break; case 'o': /* FALLTHRU */ case 'i': /* FALLTHRU */ case 'd': /* FALLTHRU */ case 'u': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ if (type == 'l') VA_INTGR(long); else if (type == 'Z') VA_INTGR(size_t); else VA_INTGR(int); used = 'i'; break; case 'f': /* FALLTHRU */ case 'e': /* FALLTHRU */ case 'E': /* FALLTHRU */ case 'g': /* FALLTHRU */ case 'G': /* FALLTHRU */ VA_FLOAT(double); used = 'f'; break; case 'c': VA_INTGR(int); used = 'c'; break; case 's': VA_POINT(char *); if (prec < 0) prec = strlen(pval); used = 's'; break; case 'p': VA_POINT(void *); used = 'p'; break; case 'n': VA_POINT(int *); used = 0; break; default: CTRACE((tfp, "unknown format character '%c' in %s\n", *fmt, format)); break; } } else if (*fmt == '.') { state = Prec; } else if (*fmt == '%') { done = TRUE; used = '%'; } } fmt_ptr[f] = '\0'; if (prec > 0) { switch (used) { case 'f': if (width < prec + NUM_WIDTH) width = prec + NUM_WIDTH; /* FALLTHRU */ case 'i': /* FALLTHRU */ case 'p': if (width < prec + 2) width = prec + 2; /* leading sign/space/zero, "0x" */ break; case 'c': break; case '%': break; default: if (width < prec) width = prec; break; } } if (width >= (int)tmp_len) { tmp_len = GROW_EXPR(tmp_len + width); tmp_ptr = HTAlloc(tmp_ptr, tmp_len); } switch (used) { case 'i': case 'c': sprintf(tmp_ptr, fmt_ptr, ival); break; case 'f': sprintf(tmp_ptr, fmt_ptr, fval); break; default: sprintf(tmp_ptr, fmt_ptr, pval); break; } need = dst_len + strlen(tmp_ptr) + 1; if (need >= have) { dst_ptr = HTAlloc(dst_ptr, have = GROW_EXPR(need)); } strcpy(dst_ptr + dst_len, tmp_ptr); dst_len += strlen(tmp_ptr); } else { if ((dst_len + 2) >= have) { dst_ptr = HTAlloc(dst_ptr, (have += GROW_SIZE)); } dst_ptr[dst_len++] = *fmt++; } }#ifndef SAVE_TIME_NOT_SPACE FREE(tmp_ptr); FREE(fmt_ptr);#endif dst_ptr[dst_len] = '\0'; if (pstr) *pstr = dst_ptr; return (dst_ptr);}#undef SAVE_TIME_NOT_SPACE/* * Replacement for sprintf, allocates buffer on the fly according to what's needed * for its arguments. Unlike sprintf, this always concatenates to the destination * buffer. *//* Note: if making changes, also check the memory tracking version * LYLeakHTSprintf in LYLeaks.c. - kw */#ifdef HTSprintf /* if hidden by LYLeaks stuff */#undef HTSprintf#endif#if ANSI_VARARGSPUBLIC char * HTSprintf (char ** pstr, CONST char * fmt, ...)#elsePUBLIC char * HTSprintf (va_alist) va_dcl#endif{ char *result = 0; size_t inuse = 0; va_list ap; LYva_start(ap,fmt); {#if !ANSI_VARARGS char ** pstr = va_arg(ap, char **); CONST char * fmt = va_arg(ap, CONST char *);#endif if (pstr != 0 && *pstr != 0) inuse = strlen(*pstr); result = StrAllocVsprintf(pstr, inuse, fmt, &ap); } va_end(ap); return (result);}/* * Replacement for sprintf, allocates buffer on the fly according to what's * needed for its arguments. Like sprintf, this always resets the destination * buffer. *//* Note: if making changes, also check the memory tracking version * LYLeakHTSprintf0 in LYLeaks.c. - kw */#ifdef HTSprintf0 /* if hidden by LYLeaks stuff */#undef HTSprintf0#endif#if ANSI_VARARGSPUBLIC char * HTSprintf0 (char ** pstr, CONST char * fmt, ...)#elsePUBLIC char * HTSprintf0 (va_alist) va_dcl#endif{ char *result = 0; va_list ap; LYva_start(ap,fmt); {#if !ANSI_VARARGS char ** pstr = va_arg(ap, char **); CONST char * fmt = va_arg(ap, CONST char *);#endif#ifdef USE_VASPRINTF if (pstr) { if (*pstr) FREE(*pstr); if (vasprintf(pstr, fmt, ap) >= 0) /* else call outofmem?? */ mark_malloced(*pstr, strlen(*pstr)+1); result = *pstr; } else#endif /* USE_VASPRINTF */ result = StrAllocVsprintf(pstr, 0, fmt, &ap); } va_end(ap); return (result);}/* * Returns a quoted or escaped form of the given parameter, suitable for use in * a command string. */#if USE_QUOTED_PARAMETER#define S_QUOTE '\''#define D_QUOTE '"'PUBLIC char *HTQuoteParameter ARGS1( CONST char *, parameter){ size_t i; size_t last = strlen(parameter); size_t n = 0; size_t quoted = 0; char * result; for (i=0; i < last; ++i) if (strchr("\\&#$^*?(){}<>\"';`|", parameter[i]) != 0 || isspace(UCH(parameter[i]))) ++quoted; result = (char *)malloc(last + 5*quoted + 3); if (result == NULL) outofmem(__FILE__, "HTQuoteParameter"); n = 0; if (quoted) result[n++] = S_QUOTE; for (i = 0; i < last; i++) { if (parameter[i] == S_QUOTE) { result[n++] = S_QUOTE; result[n++] = D_QUOTE; result[n++] = parameter[i]; result[n++] = D_QUOTE; result[n++] = S_QUOTE; } else { /* Note: No special handling of other characters, including backslash, since we are constructing a single-quoted string! Backslash has no special escape meaning within those for sh and compatible shells, so trying to escape a backslash by doubling it is unnecessary and would be interpreted by the shell as an additional data character. - kw 2000-05-02 */ result[n++] = parameter[i]; } } if (quoted) result[n++] = S_QUOTE; result[n] = '\0'; return result;}#endif#define HTIsParam(string) ((string[0] == '%' && string[1] == 's'))/* * Returns the number of "%s" tokens in a system command-template. */PUBLIC int HTCountCommandArgs ARGS1( CONST char *, command){ int number = 0; while (command[0] != 0) { if (HTIsParam(command)) number++; command++; } return number;}/* * Returns a pointer into the given string after the given parameter number */PRIVATE CONST char *HTAfterCommandArg ARGS2( CONST char *, command, int, number){ while (number > 0) { if (command[0] != 0) { if (HTIsParam(command)) { number--; command++; } command++; } else { break; } } return command;}/* * Like HTAddParam, but the parameter may be an environment variable, which we * will expand and append. Do this only for things like the command-verb, * where we obtain the parameter from the user's configuration. Any quoting * required for the environment variable has to be done within its value, e.g., * * setenv EDITOR 'xvile -name "No such class"' * * This is useful only when we quote parameters, of course. */#if USE_QUOTED_PARAMETERPUBLIC void HTAddXpand ARGS4( char **, result, CONST char *, command, int, number, CONST char *, parameter){ if (number > 0) { CONST char *last = HTAfterCommandArg(command, number - 1); CONST char *next = last; if (number <= 1) { FREE(*result); } while (next[0] != 0) { if (HTIsParam(next)) { if (next != last) { size_t len = (next - last) + ((*result != 0) ? strlen(*result) : 0); HTSACat(result, last); (*result)[len] = 0; } HTSACat(result, parameter); CTRACE((tfp, "PARAM-EXP:%s\n", *result)); return; } next++; } }}#endif /* USE_QUOTED_PARAMETER *//* * Append string-parameter to a system command that we are constructing. The * string is a complete parameter (which is a necessary assumption so we can * quote it properly). We're given the index of the newest parameter we're * processing. Zero indicates none, so a value of '1' indicates that we copy * from the beginning of the command string up to the first parameter, * substitute the quoted parameter and return the result. * * Parameters are substituted at "%s" tokens, like printf. Other printf-style * tokens are not substituted; they are passed through without change. */PUBLIC void HTAddParam ARGS4( char **, result, CONST char *, command, int, number, CONST char *, parameter){ if (number > 0) { CONST char *last = HTAfterCommandArg(command, number - 1); CONST char *next = last;#if USE_QUOTED_PARAMETER char *quoted;#endif if (number <= 1) { FREE(*result); } if (parameter == 0) parameter = ""; while (next[0] != 0) { if (HTIsParam(next)) { if (next != last) { size_t len = (next - last) + ((*result != 0) ? strlen(*result) : 0); HTSACat(result, last); (*result)[len] = 0; }#if USE_QUOTED_PARAMETER quoted = HTQuoteParameter(parameter); HTSACat(result, quoted); FREE(quoted);#else HTSACat(result, parameter);#endif CTRACE((tfp, "PARAM-ADD:%s\n", *result)); return; } next++; } }}/* * Append the remaining command-string to a system command (compare with * HTAddParam). Any remaining "%s" tokens are copied as empty strings. */PUBLIC void HTEndParam ARGS3( char **, result, CONST char *, command, int, number){ CONST char *last; int count; count = HTCountCommandArgs (command); if (count < number) number = count; last = HTAfterCommandArg(command, number); if (last[0] != 0) { HTSACat(result, last); } CTRACE((tfp, "PARAM-END:%s\n", *result));}#ifdef EXP_FILE_UPLOAD/* bstring Allocate and Concatenate*//* Allocate a new copy of a bstring, and returns it*/PUBLIC void HTSABCopy ARGS3( bstring**, dest, CONST char *, src, int, len){ bstring *t; CTRACE((tfp, "HTSABCopy(%p, %p, %d)\n", dest, src, len)); /* if we already have a bstring ** ... */ if (dest) { /* ... with a valid bstring *, free it ... */ if (*dest) { FREE((*dest)->str); FREE(*dest); } *dest = malloc(sizeof(bstring)); if (src) { CTRACE((tfp, "%% [%s]\n", src)); t = (bstring*) malloc(sizeof(bstring)); if (t == NULL) outofmem(__FILE__, "HTSABCopy"); t->str = (char *) malloc (len); if (t->str == NULL) outofmem(__FILE__, "HTSABCopy"); memcpy (t->str, src, len); t->len = len; *dest = t; } }}PUBLIC void HTSABCat ARGS3( bstring **, dest, CONST char *, src, int, len){ bstring *t = *dest; if (src) { if (t) { int length = t->len; t->str = (char *)realloc(t->str, length + len); } else { t = typecalloc(bstring); if (t == NULL) outofmem(__FILE__, "HTSACat"); t->str = (char *)malloc(len); } if (t->str == NULL) outofmem(__FILE__, "HTSACat"); memcpy (t->str + t->len, src, len); t->len += len; *dest = t; }}#endif /* EXP_FILE_UPLOAD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -