diff options
| author | 2000-03-25 18:16:41 +0000 | |
|---|---|---|
| committer | 2000-03-25 18:16:41 +0000 | |
| commit | 05e9de5ac11bf4eb5b700d64593e66bf62b6167f (patch) | |
| tree | 4b0f8191aef831df789ac65b9bfac3d70d0ffbdd /gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c | |
| parent | if_gm attaches on pci, not macobio. (diff) | |
| download | wireguard-openbsd-05e9de5ac11bf4eb5b700d64593e66bf62b6167f.tar.xz wireguard-openbsd-05e9de5ac11bf4eb5b700d64593e66bf62b6167f.zip | |
Upgrade to Lynx 2.8.2. -moj
Diffstat (limited to 'gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c')
| -rw-r--r-- | gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c | 578 |
1 files changed, 563 insertions, 15 deletions
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c index 5f358b9775f..90b6665bb3e 100644 --- a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c +++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c @@ -5,15 +5,13 @@ ** 02-Dec-91 (JFG) Added stralloccopy and stralloccat ** 23 Jan 92 (TBL) Changed strallocc* to 8 char HTSAC* for VM and suchlike ** 6 Oct 92 (TBL) Moved WWW_TraceFlag in here to be in library +** 15 Nov 98 (TD) Added HTSprintf. */ -#include <ctype.h> -#include "HTUtils.h" -#include "tcp.h" -#include "LYLeaks.h" -#include "LYStrings.h" +#include <HTUtils.h> -#define FREE(x) if (x) {free(x); x = NULL;} +#include <LYLeaks.h> +#include <LYStrings.h> PUBLIC int WWW_TraceFlag = 0; /* Global trace flag for ALL W3 code */ @@ -124,18 +122,81 @@ PUBLIC int strncasecomp ARGS3( } #endif /* VM */ +#ifdef NOT_ASCII + +/* Case-insensitive with ASCII collating sequence +** ---------------- +*/ +PUBLIC int AS_casecomp ARGS2( + CONST char*, p, + CONST char*, q) +{ + int diff; + + for ( ; ; p++, q++) { + if (!(*p && *q)) + return ((unsigned char) *p - (unsigned char) *q); + diff = TOASCII(TOLOWER(*p)) + - TOASCII(TOLOWER(*q)); + if (diff) + return diff; + } + /*NOTREACHED*/ +} + + +/* With count limit and ASCII collating sequence +** ---------------- +** AS_cmp uses n == -1 to compare indefinite length. +*/ +PUBLIC int AS_ncmp ARGS3( + CONST char *, p, + CONST char *, q, + unsigned int, n) +{ + CONST char *a = p; + int diff; + + for ( ; (p-a) < n; p++, q++) { + if (!(*p && *q)) + return ((unsigned char) *p - (unsigned char) *q); + diff = TOASCII(*p) + - TOASCII(*q); + if (diff) + return diff; + } + return 0; /* Match up to n characters */ +} + + +/* With ASCII collating sequence +** ---------------- +*/ +PUBLIC int AS_cmp ARGS2( + CONST char *, p, + CONST char *, q) +{ + return( AS_ncmp( p, q, -1 ) ); +} +#endif /* NOT_ASCII */ + + /* Allocate a new copy of a string, and returns it */ PUBLIC char * HTSACopy ARGS2( char **, dest, CONST char *, src) { - FREE(*dest); - if (src) { - *dest = (char *) malloc (strlen(src) + 1); - if (*dest == NULL) - outofmem(__FILE__, "HTSACopy"); - strcpy (*dest, src); + if (src != 0) { + if (src != *dest) { + FREE(*dest); + *dest = (char *) malloc (strlen(src) + 1); + if (*dest == NULL) + outofmem(__FILE__, "HTSACopy"); + strcpy (*dest, src); + } + } else { + FREE(*dest); } return *dest; } @@ -146,7 +207,7 @@ PUBLIC char * HTSACat ARGS2( char **, dest, CONST char *, src) { - if (src && *src) { + if (src && *src && (src != *dest)) { if (*dest) { int length = strlen(*dest); *dest = (char *)realloc(*dest, length + strlen(src) + 1); @@ -235,8 +296,8 @@ PUBLIC char * HTNextField ARGS1( */ PUBLIC char * HTNextTok ARGS4( char **, pstr, - const char *, delims, - const char *, bracks, + CONST char *, delims, + CONST char *, bracks, char *, found) { char * p = *pstr; @@ -342,3 +403,490 @@ PUBLIC char * HTNextTok ARGS4( *pstr = p; return start; } + +PRIVATE char *HTAlloc ARGS2(char *, ptr, size_t, length) +{ + if (ptr != 0) + ptr = (char *)realloc(ptr, length); + else + ptr = (char *)malloc(length); + if (ptr == 0) + outofmem(__FILE__, "HTAlloc"); + return ptr; +} + +/* + * 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, so we do not have to provide both flavors. + */ +typedef enum { Flags, Width, Prec, Type, Format } PRINTF; + +#define VA_INTGR(type) ival = va_arg((*ap), type) +#define VA_FLOAT(type) fval = va_arg((*ap), type) +#define VA_POINT(type) pval = (void *)va_arg((*ap), type) + +#define NUM_WIDTH 10 /* allow for width substituted for "*" in "%*s" */ + /* also number of chars assumed to be needed in addition + to a given precision in floating point formats */ + +#define GROW_EXPR(n) (((n) * 3) / 2) +#define GROW_SIZE 256 + +PRIVATE char * StrAllocVsprintf ARGS4( + char **, pstr, + size_t, dst_len, + CONST char *, fmt, + va_list *, ap) +{ + size_t tmp_len = GROW_SIZE; + size_t have, need; + char *tmp_ptr = 0; + char *fmt_ptr; + char *dst_ptr = *pstr; + CONST char *format = fmt; + + if (fmt == 0 || *fmt == '\0') + return 0; + + need = strlen(fmt) + 1; + if ((fmt_ptr = malloc(need*NUM_WIDTH)) == 0 + || (tmp_ptr = malloc(tmp_len)) == 0) { + outofmem(__FILE__, "StrAllocVsprintf"); + } + + 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(*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(*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 */ +#if 0 /* we don't need this, it doesn't work on SunOS 4.x */ + if (type == 'L') + VA_FLOAT(long double); + else +#endif + 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; + case 'i': + case 'p': + if (width < prec + 2) + width = prec + 2; /* leading sign/space/zero, "0x" */ + case 'c': + case '%': + break; + default: + if (width < prec) + width = prec; + } + } + 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++; + } + } + + FREE(tmp_ptr); + FREE(fmt_ptr); + dst_ptr[dst_len] = '\0'; + if (pstr) + *pstr = dst_ptr; + return (dst_ptr); +} + +/* + * 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. + */ +#if ANSI_VARARGS +PUBLIC char * HTSprintf (char ** pstr, CONST char * fmt, ...) +#else +PUBLIC 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. + */ +#if ANSI_VARARGS +PUBLIC char * HTSprintf0 (char ** pstr, CONST char * fmt, ...) +#else +PUBLIC 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 + 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(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 if (parameter[i] == '\\') { + result[n++] = parameter[i]; + result[n++] = parameter[i]; + } else { + 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_PARAMETER +PUBLIC 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; + char *quoted; + + 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); +} |
