📄 htstring.c
字号:
}/* * 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 to a system command that we are constructing, without quoting. * 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 HTAddToCmd ARGS4( char **, result, CONST char *, command, int, number, CONST char *, string){ if (number > 0) { CONST char *last = HTAfterCommandArg(command, number - 1); CONST char *next = last; if (number <= 1) { FREE(*result); } if (string == 0) string = ""; 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, string); CTRACE((tfp, "PARAM-ADD:%s\n", *result)); return; } next++; } }}/* * 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). */PUBLIC void HTAddParam ARGS4( char **, result, CONST char *, command, int, number, CONST char *, parameter){ if (number > 0) {#if USE_QUOTED_PARAMETER char *quoted = HTQuoteParameter(parameter); HTAddToCmd(result, command, number, quoted); FREE(quoted);#else HTAddToCmd(result, command, number, parameter);#endif }}/* * 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));}/* Binary-strings (may have embedded nulls). * Some modules (HTGopher) assume there is a null on the end, anyway. *//* Allocate a new bstring, and return it.*/PUBLIC void HTSABCopy ARGS3( bstring**, dest, CONST char *, src, int, len){ bstring *t; unsigned need = len + 1; CTRACE2(TRACE_BSTRING, (tfp, "HTSABCopy(%p, %p, %d)\n", dest, src, len)); HTSABFree(dest); if (src) { if (TRACE_BSTRING) { CTRACE((tfp, "=== %4d:", len)); trace_bstring2(src, len); CTRACE((tfp, "\n")); } if ((t = (bstring*) malloc(sizeof(bstring))) == NULL) outofmem(__FILE__, "HTSABCopy"); if ((t->str = (char *) malloc (need)) == NULL) outofmem(__FILE__, "HTSABCopy"); memcpy (t->str, src, len); t->len = len; t->str[t->len] = '\0'; *dest = t; } if (TRACE_BSTRING) { CTRACE((tfp, "=> %4d:", BStrLen(*dest))); trace_bstring(*dest); CTRACE((tfp, "\n")); }}/* * Initialize with a null-terminated string (discards the null). */PUBLIC void HTSABCopy0 ARGS2( bstring**, dest, CONST char *, src){ HTSABCopy(dest, src, strlen(src));}/* * Append a block of memory to a bstring. */PUBLIC void HTSABCat ARGS3( bstring **, dest, CONST char *, src, int, len){ bstring *t = *dest; CTRACE2(TRACE_BSTRING, (tfp, "HTSABCat(%p, %p, %d)\n", dest, src, len)); if (src) { unsigned need = len + 1; if (TRACE_BSTRING) { CTRACE((tfp, "=== %4d:", len)); trace_bstring2(src, len); CTRACE((tfp, "\n")); } if (t) { unsigned length = t->len + need; if ((t->str = (char *)realloc(t->str, length)) == NULL) outofmem(__FILE__, "HTSACat"); } else { if ((t = typecalloc(bstring)) == NULL) outofmem(__FILE__, "HTSACat"); t->str = (char *)malloc(need); } if (t->str == NULL) outofmem(__FILE__, "HTSACat"); memcpy (t->str + t->len, src, len); t->len += len; t->str[t->len] = '\0'; *dest = t; } if (TRACE_BSTRING) { CTRACE((tfp, "=> %4d:", BStrLen(*dest))); trace_bstring(*dest); CTRACE((tfp, "\n")); }}/* * Append a null-terminated string (discards the null). */PUBLIC void HTSABCat0 ARGS2( bstring**, dest, CONST char *, src){ HTSABCat(dest, src, strlen(src));}/* * Compare two bstring's for equality */PUBLIC BOOL HTSABEql ARGS2( bstring *, a, bstring *, b){ unsigned len_a = (a != 0) ? a->len : 0; unsigned len_b = (b != 0) ? b->len : 0; if (len_a == len_b) { if (len_a == 0 || memcmp(a->str, b->str, a->len) == 0) return TRUE; } return FALSE;}/* * Deallocate a bstring. */PUBLIC void HTSABFree ARGS1( bstring **, ptr){ if (*ptr != NULL) { FREE((*ptr)->str); FREE(*ptr); *ptr = NULL; }}/* * Use this function to perform formatted sprintf's onto the end of a bstring. * The bstring may contain embedded nulls; the formatted portions must not. */#ifdef ANSI_VARARGSPUBLIC bstring * HTBprintf (bstring ** pstr, CONST char * fmt, ...)#elsePUBLIC bstring * HTBprintf (va_alist) va_dcl#endif{ bstring *result = 0; char *temp = 0; va_list ap; LYva_start(ap,fmt); {#if !ANSI_VARARGS bstring ** pstr = va_arg(ap, char **); CONST char * fmt = va_arg(ap, CONST char *);#endif temp = StrAllocVsprintf(&temp, 0, fmt, &ap); if (!isEmpty(temp)) { HTSABCat (pstr, temp, strlen(temp)); } FREE(temp); result = *pstr; } va_end(ap); return (result);}/* * Write binary-data to the logfile, making it safe for most editors to view. * That is most, since we do not restrict line-length. Nulls and other * non-printing characters are addressed. */PUBLIC void trace_bstring2 ARGS2( CONST char *, text, int, size){ int n; if (text != 0) { for (n = 0; n < size; ++n) { int ch = UCH(text[n]); switch (ch) { case '\\': fputs("\\\\", tfp); break; case '\r': fputs("\\r", tfp); break; case '\t': fputs("\\t", tfp); break; case '\f': fputs("\\f", tfp); break; default: if (isprint(ch) || isspace(ch)) { fputc(ch, tfp); } else { fprintf(tfp, "\\%03o", ch); } break; } } }}PUBLIC void trace_bstring ARGS1( bstring *, data){ trace_bstring2(BStrData(data), BStrLen(data));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -