diff options
author | robot-piglet <[email protected]> | 2025-08-28 14:27:58 +0300 |
---|---|---|
committer | robot-piglet <[email protected]> | 2025-08-28 14:57:06 +0300 |
commit | 81d828c32c8d5477cb2f0ce5da06a1a8d9392ca3 (patch) | |
tree | 3081d566f0d5158d76e9093261344f6406fd09f7 /contrib/tools/swig/Source/DOH/string.c | |
parent | 77ea11423f959e51795cc3ef36a48d808b4ffb98 (diff) |
Intermediate changes
commit_hash:d5b1af16dbe9030537a04c27eb410c88c2f496cd
Diffstat (limited to 'contrib/tools/swig/Source/DOH/string.c')
-rw-r--r-- | contrib/tools/swig/Source/DOH/string.c | 1287 |
1 files changed, 1287 insertions, 0 deletions
diff --git a/contrib/tools/swig/Source/DOH/string.c b/contrib/tools/swig/Source/DOH/string.c new file mode 100644 index 00000000000..7ac9b9231a3 --- /dev/null +++ b/contrib/tools/swig/Source/DOH/string.c @@ -0,0 +1,1287 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at https://www.swig.org/legal.html. + * + * string.c + * + * Implements a string object that supports both sequence operations and + * file semantics. + * ----------------------------------------------------------------------------- */ + +#include "dohint.h" + +extern DohObjInfo DohStringType; + +typedef struct String { + DOH *file; + int line; + int maxsize; /* Max size allocated */ + int len; /* Current length */ + int hashkey; /* Hash key value */ + int sp; /* Current position */ + char *str; /* String data */ +} String; + +/* ----------------------------------------------------------------------------- + * String_data() - Return as a 'void *' + * ----------------------------------------------------------------------------- */ + +static void *String_data(DOH *so) { + String *s = (String *) ObjData(so); + s->str[s->len] = 0; + return (void *) s->str; +} + +/* static char *String_char(DOH *so) { + return (char *) String_data(so); +} +*/ + +/* ----------------------------------------------------------------------------- + * String_dump() - Serialize a string onto out + * ----------------------------------------------------------------------------- */ + +static int String_dump(DOH *so, DOH *out) { + int nsent; + int ret; + String *s = (String *) ObjData(so); + nsent = 0; + while (nsent < s->len) { + ret = Write(out, s->str + nsent, (s->len - nsent)); + if (ret < 0) + return ret; + nsent += ret; + } + return nsent; +} + +/* ----------------------------------------------------------------------------- + * CopyString() - Copy a string + * ----------------------------------------------------------------------------- */ + +static DOH *CopyString(DOH *so) { + String *str; + String *s = (String *) ObjData(so); + str = (String *) DohMalloc(sizeof(String)); + str->hashkey = s->hashkey; + str->sp = s->sp; + str->line = s->line; + str->file = s->file; + if (str->file) + Incref(str->file); + str->str = (char *) DohMalloc(s->len + 1); + memcpy(str->str, s->str, s->len); + str->maxsize = s->len; + str->len = s->len; + str->str[str->len] = 0; + + return DohObjMalloc(&DohStringType, str); +} + +/* ----------------------------------------------------------------------------- + * DelString() - Delete a string + * ----------------------------------------------------------------------------- */ + +static void DelString(DOH *so) { + String *s = (String *) ObjData(so); + DohFree(s->str); + DohFree(s); +} + +/* ----------------------------------------------------------------------------- + * DohString_len() - Length of a string + * ----------------------------------------------------------------------------- */ + +static int String_len(DOH *so) { + String *s = (String *) ObjData(so); + return s->len; +} + + +/* ----------------------------------------------------------------------------- + * String_cmp() - Compare two strings + * ----------------------------------------------------------------------------- */ + +static int String_cmp(DOH *so1, DOH *so2) { + String *s1, *s2; + char *c1, *c2; + int maxlen, i; + s1 = (String *) ObjData(so1); + s2 = (String *) ObjData(so2); + maxlen = s1->len; + if (s2->len < maxlen) + maxlen = s2->len; + c1 = s1->str; + c2 = s2->str; + for (i = maxlen; i; --i, c1++, c2++) { + if (*c1 != *c2) + break; + } + if (i != 0) { + if (*c1 < *c2) + return -1; + else + return 1; + } + if (s1->len == s2->len) + return 0; + if (s1->len > s2->len) + return 1; + return -1; +} + +/* ----------------------------------------------------------------------------- + * String_equal() - Say if two string are equal + * ----------------------------------------------------------------------------- */ + +static int String_equal(DOH *so1, DOH *so2) { + String *s1 = (String *) ObjData(so1); + String *s2 = (String *) ObjData(so2); + int len = s1->len; + if (len != s2->len) { + return 0; + } else { + char *c1 = s1->str; + char *c2 = s2->str; +#if 0 + int mlen = len >> 2; + int i = mlen; + for (; i; --i) { + if (*(c1++) != *(c2++)) + return 0; + if (*(c1++) != *(c2++)) + return 0; + if (*(c1++) != *(c2++)) + return 0; + if (*(c1++) != *(c2++)) + return 0; + } + for (i = len - (mlen << 2); i; --i) { + if (*(c1++) != *(c2++)) + return 0; + } + return 1; +#else + return memcmp(c1, c2, len) == 0; +#endif + } +} + +/* ----------------------------------------------------------------------------- + * String_hash() - Compute string hash value + * ----------------------------------------------------------------------------- */ + +static int String_hash(DOH *so) { + String *s = (String *) ObjData(so); + if (s->hashkey >= 0) { + return s->hashkey; + } else { + /* We use the djb2 hash function: https://theartincode.stanis.me/008-djb2/ + * + * One difference is we use initial seed 0. It seems the usual seed value + * is intended to help spread out hash values, which is beneficial if + * linear probing is used but DOH Hash uses a chain of buckets instead, and + * grouped hash values are probably more cache friendly. In tests using + * 0 seems slightly faster anyway. + */ + const char *c = s->str; + unsigned int len = s->len > 50 ? 50 : s->len; + unsigned int h = 0; + unsigned int mlen = len >> 2; + unsigned int i = mlen; + for (; i; --i) { + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + } + for (i = len - (mlen << 2); i; --i) { + h = h + (h << 5) + *(c++); + } + h &= 0x7fffffff; + s->hashkey = (int)h; + return h; + } +} + +/* ----------------------------------------------------------------------------- + * DohString_append() - Append to s + * ----------------------------------------------------------------------------- */ + +static void DohString_append(DOH *so, const DOHString_or_char *str) { + int oldlen, newlen, newmaxsize, l, sp; + char *tc; + String *s = (String *) ObjData(so); + char *newstr = 0; + + if (DohCheck(str)) { + String *ss = (String *) ObjData(str); + newstr = (char *) String_data((DOH *) str); + l = ss->len; + } else { + newstr = (char *) (str); + l = (int) strlen(newstr); + } + if (!newstr) + return; + s->hashkey = -1; + + oldlen = s->len; + newlen = oldlen + l + 1; + if (newlen >= s->maxsize - 1) { + newmaxsize = 2 * s->maxsize; + if (newlen >= newmaxsize - 1) + newmaxsize = newlen + 1; + s->str = (char *) DohRealloc(s->str, newmaxsize); + s->maxsize = newmaxsize; + } + tc = s->str; + memcpy(tc + oldlen, newstr, l + 1); + sp = s->sp; + if (sp >= oldlen) { + int i = oldlen + l - sp; + tc += sp; + for (; i; --i) { + if (*(tc++) == '\n') + s->line++; + } + s->sp = oldlen + l; + } + s->len += l; +} + + +/* ----------------------------------------------------------------------------- + * String_clear() - Clear string contents + * + * File and line numbering info left unmodified. + * ----------------------------------------------------------------------------- */ + +static void String_clear(DOH *so) { + String *s = (String *) ObjData(so); + s->hashkey = -1; + s->len = 0; + *(s->str) = 0; + s->sp = 0; +} + +/* ----------------------------------------------------------------------------- + * String_insert() - Insert a string + * ----------------------------------------------------------------------------- */ + +static int String_insert(DOH *so, int pos, DOH *str) { + String *s; + int len; + char *data; + + if (pos == DOH_END) { + DohString_append(so, str); + return 0; + } + + + s = (String *) ObjData(so); + s->hashkey = -1; + if (DohCheck(str)) { + String *ss = (String *) ObjData(str); + data = (char *) String_data(str); + len = ss->len; + } else { + data = (char *) (str); + len = (int) strlen(data); + } + + if (pos < 0) + pos = 0; + else if (pos > s->len) + pos = s->len; + + /* See if there is room to insert the new data */ + while (s->maxsize <= s->len + len) { + int newsize = 2 * s->maxsize; + s->str = (char *) DohRealloc(s->str, newsize); + s->maxsize = newsize; + } + memmove(s->str + pos + len, s->str + pos, (s->len - pos)); + memcpy(s->str + pos, data, len); + if (s->sp >= pos) { + int i; + + for (i = 0; i < len; i++) { + if (data[i] == '\n') + s->line++; + } + s->sp += len; + } + s->len += len; + s->str[s->len] = 0; + return 0; +} + +/* ----------------------------------------------------------------------------- + * String_delitem() - Delete a character + * ----------------------------------------------------------------------------- */ + +static int String_delitem(DOH *so, int pos) { + String *s = (String *) ObjData(so); + s->hashkey = -1; + if (pos == DOH_END) + pos = s->len - 1; + if (pos == DOH_BEGIN) + pos = 0; + if (s->len == 0) + return 0; + + if (s->sp > pos) { + s->sp--; + assert(s->sp >= 0); + if (s->str[pos] == '\n') + s->line--; + } + memmove(s->str + pos, s->str + pos + 1, ((s->len - 1) - pos)); + s->len--; + s->str[s->len] = 0; + return 0; +} + +/* ----------------------------------------------------------------------------- + * String_delslice() - Delete a range + * ----------------------------------------------------------------------------- */ + +static int String_delslice(DOH *so, int sindex, int eindex) { + String *s = (String *) ObjData(so); + int size; + if (s->len == 0) + return 0; + s->hashkey = -1; + if (eindex == DOH_END) + eindex = s->len; + if (sindex == DOH_BEGIN) + sindex = 0; + + size = eindex - sindex; + if (s->sp > sindex) { + /* Adjust the file pointer and line count */ + int i, end; + if (s->sp > eindex) { + end = eindex; + s->sp -= size; + } else { + end = s->sp; + s->sp = sindex; + } + for (i = sindex; i < end; i++) { + if (s->str[i] == '\n') + s->line--; + } + assert(s->sp >= 0); + } + memmove(s->str + sindex, s->str + eindex, s->len - eindex); + s->len -= size; + s->str[s->len] = 0; + return 0; +} + +/* ----------------------------------------------------------------------------- + * String_str() - Returns a string (used by printing commands) + * ----------------------------------------------------------------------------- */ + +static DOH *String_str(DOH *so) { + String *s = (String *) ObjData(so); + s->str[s->len] = 0; + return NewString(s->str); +} + +/* ----------------------------------------------------------------------------- + * String_read() - Read data from a string + * ----------------------------------------------------------------------------- */ + +static int String_read(DOH *so, void *buffer, int len) { + int reallen, retlen; + char *cb; + String *s = (String *) ObjData(so); + if ((s->sp + len) > s->len) + reallen = (s->len - s->sp); + else + reallen = len; + + cb = (char *) buffer; + retlen = reallen; + + if (reallen > 0) { + memmove(cb, s->str + s->sp, reallen); + s->sp += reallen; + } + return retlen; +} + +/* ----------------------------------------------------------------------------- + * String_write() - Write data to a string + * ----------------------------------------------------------------------------- */ +static int String_write(DOH *so, const void *buffer, int len) { + int newlen; + String *s = (String *) ObjData(so); + s->hashkey = -1; + if (s->sp > s->len) + s->sp = s->len; + newlen = s->sp + len + 1; + if (newlen > s->maxsize) { + s->str = (char *) DohRealloc(s->str, newlen); + s->maxsize = newlen; + s->len = s->sp + len; + } + if ((s->sp + len) > s->len) + s->len = s->sp + len; + memmove(s->str + s->sp, buffer, len); + s->sp += len; + s->str[s->len] = 0; + return len; +} + +/* ----------------------------------------------------------------------------- + * String_seek() - Seek to a new position + * ----------------------------------------------------------------------------- */ + +static int String_seek(DOH *so, long offset, int whence) { + int pos, nsp, inc; + String *s = (String *) ObjData(so); + if (whence == SEEK_SET) + pos = 0; + else if (whence == SEEK_CUR) + pos = s->sp; + else if (whence == SEEK_END) { + pos = s->len; + offset = -offset; + } else + pos = s->sp; + + nsp = pos + offset; + if (nsp < 0) + nsp = 0; + if (s->len > 0 && nsp > s->len) + nsp = s->len; + + inc = (nsp > s->sp) ? 1 : -1; + + { +#if 0 + int sp = s->sp; + char *tc = s->str; + int len = s->len; + while (sp != nsp) { + int prev = sp + inc; + if (prev >= 0 && prev <= len && tc[prev] == '\n') + s->line += inc; + sp += inc; + } +#else + int sp = s->sp; + char *tc = s->str; + if (inc > 0) { + while (sp != nsp) { + if (tc[++sp] == '\n') + ++s->line; + } + } else { + while (sp != nsp) { + if (tc[--sp] == '\n') + --s->line; + } + } +#endif + s->sp = sp; + } + assert(s->sp >= 0); + return 0; +} + +/* ----------------------------------------------------------------------------- + * String_tell() - Return current position + * ----------------------------------------------------------------------------- */ + +static long String_tell(DOH *so) { + String *s = (String *) ObjData(so); + return (long) (s->sp); +} + +/* ----------------------------------------------------------------------------- + * String_putc() + * ----------------------------------------------------------------------------- */ + +static int String_putc(DOH *so, int ch) { + String *s = (String *) ObjData(so); + int len = s->len; + int sp = s->sp; + s->hashkey = -1; + if (sp >= len) { + int maxsize = s->maxsize; + char *tc = s->str; + if (len > (maxsize - 2)) { + maxsize *= 2; + tc = (char *) DohRealloc(tc, maxsize); + s->maxsize = (int) maxsize; + s->str = tc; + } + tc += sp; + *tc = (char) ch; + *(++tc) = 0; + s->len = s->sp = sp + 1; + } else { + s->str[s->sp++] = (char) ch; + } + if (ch == '\n') + s->line++; + return ch; +} + +/* ----------------------------------------------------------------------------- + * String_getc() + * ----------------------------------------------------------------------------- */ + +static int String_getc(DOH *so) { + int c; + String *s = (String *) ObjData(so); + if (s->sp >= s->len) + c = EOF; + else + c = (int)(unsigned char) s->str[s->sp++]; + if (c == '\n') + s->line++; + return c; +} + +/* ----------------------------------------------------------------------------- + * String_ungetc() + * ----------------------------------------------------------------------------- */ + +static int String_ungetc(DOH *so, int ch) { + String *s = (String *) ObjData(so); + if (ch == EOF) + return ch; + if (s->sp <= 0) + return EOF; + s->sp--; + if (ch == '\n') + s->line--; + return ch; +} + +static char *end_quote(char *s) { + char *qs; + char qc; + char *q; + char *nl; + qc = *s; + qs = s; + while (1) { + q = strpbrk(s + 1, "\"\'"); + nl = strchr(s + 1, '\n'); + if (nl && (nl < q)) { + /* A new line appears before the end of the string */ + if (*(nl - 1) == '\\') { + s = nl + 1; + continue; + } + /* String was terminated by a newline. Wing it */ + return qs; + } + if (!q && nl) { + return qs; + } + if (!q) + return 0; + if ((*q == qc) && (*(q - 1) != '\\')) + return q; + s = q; + } +} + +static char *end_comment(char *s) { + char *substring = strstr(s, "*/"); + if (substring) + ++substring; + return substring; +} + +static char *match_simple(char *base, char *s, char *token, int tokenlen) { + (void) base; + (void) tokenlen; + return strstr(s, token); +} + +static char *match_identifier(char *base, char *s, char *token, int tokenlen) { + while (s) { + s = strstr(s, token); + if (!s) + return 0; + if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) { + /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */ + ++s; + continue; + } + if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) { + /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */ + ++s; + continue; + } + return s; + } + return 0; +} + + +static char *match_identifier_begin(char *base, char *s, char *token, int tokenlen) { + (void)tokenlen; + while (s) { + s = strstr(s, token); + if (!s) + return 0; + if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) { + /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */ + ++s; + continue; + } + return s; + } + return 0; +} + +static char *match_identifier_end(char *base, char *s, char *token, int tokenlen) { + (void) base; + while (s) { + s = strstr(s, token); + if (!s) + return 0; + if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) { + /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */ + ++s; + continue; + } + return s; + } + return 0; +} + +static char *match_number_end(char *base, char *s, char *token, int tokenlen) { + (void) base; + while (s) { + s = strstr(s, token); + if (!s) + return 0; + if (isdigit((int) *(s + tokenlen))) { + /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */ + ++s; + continue; + } + return s; + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * replace_simple() + * + * Replaces count non-overlapping occurrences of token with rep in a string. + * ----------------------------------------------------------------------------- */ + +static int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match) (char *, char *, char *, int)) { + int tokenlen; /* Length of the token */ + int replen; /* Length of the replacement */ + int delta, expand = 0; + int ic; + int rcount = 0; + int noquote = 0; + int nocomment = 0; + char *c, *s, *t, *first; + char *q, *q2; + char *base; + int i; + + /* Figure out if anything gets replaced */ + if (!strlen(token)) + return 0; + + base = str->str; + tokenlen = (int)strlen(token); + s = (*match) (base, base, token, tokenlen); + + if (!s) + return 0; /* No matches. Who cares */ + + str->hashkey = -1; + + if (flags & DOH_REPLACE_NOQUOTE) + noquote = 1; + + if (flags & DOH_REPLACE_NOCOMMENT) + nocomment = 1; + + assert(!(noquote && nocomment)); /* quote and comment combination not implemented */ + + /* If we are not replacing inside quotes, we need to do a little extra work */ + if (noquote) { + q = strpbrk(base, "\"\'"); + if (!q) { + noquote = 0; /* Well, no quotes to worry about. Oh well */ + } else { + while (q && (q < s)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + return 0; + } + if (q2 > s) { + /* Find next match */ + s = (*match) (base, q2 + 1, token, tokenlen); + } + if (!s) + return 0; /* Oh well, no matches */ + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; /* No more quotes */ + } + } + } + + /* If we are not replacing inside comments, we need to do a little extra work */ + if (nocomment) { + q = strstr(base, "/*"); + if (!q) { + nocomment = 0; /* Well, no comments to worry about. Oh well */ + } else { + while (q && (q < s)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + return 0; + } + if (q2 > s) { + /* Find next match */ + s = (*match) (base, q2 + 1, token, tokenlen); + } + if (!s) + return 0; /* Oh well, no matches */ + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; /* No more comments */ + } + } + } + + first = s; + replen = (int)strlen(rep); + + delta = (replen - tokenlen); + + if (delta <= 0) { + /* String is either shrinking or staying the same size */ + /* In this case, we do the replacement in place without memory reallocation */ + ic = count; + t = s; /* Target of memory copies */ + while (ic && s) { + if (replen) { + memcpy(t, rep, replen); + t += replen; + } + rcount++; + expand += delta; + /* Find the next location */ + s += tokenlen; + if (ic == 1) + break; + c = (*match) (base, s, token, tokenlen); + + if (noquote) { + q = strpbrk(s, "\"\'"); + if (!q) { + noquote = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; /* No more quotes */ + } + } + } + if (nocomment) { + q = strstr(s, "/*"); + if (!q) { + nocomment = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; /* No more comments */ + } + } + } + if (delta) { + if (c) { + memmove(t, s, c - s); + t += (c - s); + } else { + memmove(t, s, (str->str + str->len) - s + 1); + } + } else { + if (c) { + t += (c - s); + } + } + s = c; + ic--; + } + if (s && delta) { + memmove(t, s, (str->str + str->len) - s + 1); + } + str->len += expand; + str->str[str->len] = 0; + if (str->sp >= str->len) + str->sp += expand; /* Fix the end of file pointer */ + return rcount; + } + /* The string is expanding as a result of the replacement */ + /* Figure out how much expansion is going to occur and allocate a new string */ + { + char *ns; + int newsize; + + rcount++; + ic = count - 1; + s += tokenlen; + while (ic && (c = (*match) (base, s, token, tokenlen))) { + if (noquote) { + q = strpbrk(s, "\"\'"); + if (!q) { + break; + } else { + while (q && (q < c)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; + } + } + } + if (nocomment) { + q = strstr(s, "/*"); + if (!q) { + break; + } else { + while (q && (q < c)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; + } + } + } + if (c) { + rcount++; + ic--; + s = c + tokenlen; + } else { + break; + } + } + + expand = delta * rcount; /* Total amount of expansion for the replacement */ + newsize = str->maxsize; + while ((str->len + expand) >= newsize) + newsize *= 2; + + ns = (char *) DohMalloc(newsize); + t = ns; + s = first; + + /* Copy the first part of the string */ + if (first > str->str) { + memcpy(t, str->str, (first - str->str)); + t += (first - str->str); + } + for (i = 0; i < rcount; i++) { + memcpy(t, rep, replen); + t += replen; + s += tokenlen; + c = (*match) (base, s, token, tokenlen); + if (noquote) { + q = strpbrk(s, "\"\'"); + if (!q) { + noquote = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; /* No more quotes */ + } + } + } + if (nocomment) { + q = strstr(s, "/*"); + if (!q) { + nocomment = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; /* No more comments */ + } + } + } + if (i < (rcount - 1)) { + memcpy(t, s, c - s); + t += (c - s); + } else { + memcpy(t, s, (str->str + str->len) - s + 1); + } + s = c; + } + c = str->str; + str->str = ns; + if (str->sp >= str->len) + str->sp += expand; + str->len += expand; + str->str[str->len] = 0; + str->maxsize = newsize; + DohFree(c); + return rcount; + } +} + +/* ----------------------------------------------------------------------------- + * String_replace() + * ----------------------------------------------------------------------------- */ + +static int String_replace(DOH *stro, const DOHString_or_char *token, const DOHString_or_char *rep, int flags) { + int count = -1; + String *str = (String *) ObjData(stro); + + if (flags & DOH_REPLACE_FIRST) + count = 1; + + if (flags & DOH_REPLACE_ID_END) { + return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_end); + } else if (flags & DOH_REPLACE_ID_BEGIN) { + return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_begin); + } else if (flags & DOH_REPLACE_ID) { + return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier); + } else if (flags & DOH_REPLACE_NUMBER_END) { + return replace_simple(str, Char(token), Char(rep), flags, count, match_number_end); + } else { + return replace_simple(str, Char(token), Char(rep), flags, count, match_simple); + } +} + +/* ----------------------------------------------------------------------------- + * String_chop() + * ----------------------------------------------------------------------------- */ + +static void String_chop(DOH *so) { + char *c; + String *str = (String *) ObjData(so); + /* Replace trailing whitespace */ + c = str->str + str->len - 1; + while ((str->len > 0) && (isspace((int) *c))) { + if (str->sp >= str->len) { + str->sp--; + if (*c == '\n') + str->line--; + } + str->len--; + c--; + } + str->str[str->len] = 0; + assert(str->sp >= 0); + str->hashkey = -1; +} + +static void String_setfile(DOH *so, DOH *file) { + DOH *fo; + String *str = (String *) ObjData(so); + + if (!DohCheck(file)) { + fo = NewString(file); + Decref(fo); + } else + fo = file; + Incref(fo); + Delete(str->file); + str->file = fo; +} + +static DOH *String_getfile(DOH *so) { + String *str = (String *) ObjData(so); + return str->file; +} + +static void String_setline(DOH *so, int line) { + String *str = (String *) ObjData(so); + str->line = line; +} + +static int String_getline(DOH *so) { + String *str = (String *) ObjData(so); + return str->line; +} + +static DohListMethods StringListMethods = { + 0, /* doh_getitem */ + 0, /* doh_setitem */ + String_delitem, /* doh_delitem */ + String_insert, /* doh_insitem */ + String_delslice, /* doh_delslice */ +}; + +static DohFileMethods StringFileMethods = { + String_read, + String_write, + String_putc, + String_getc, + String_ungetc, + String_seek, + String_tell, +}; + +static DohStringMethods StringStringMethods = { + String_replace, + String_chop, +}; + +DohObjInfo DohStringType = { + "String", /* objname */ + DelString, /* doh_del */ + CopyString, /* doh_copy */ + String_clear, /* doh_clear */ + String_str, /* doh_str */ + String_data, /* doh_data */ + String_dump, /* doh_dump */ + String_len, /* doh_len */ + String_hash, /* doh_hash */ + String_cmp, /* doh_cmp */ + String_equal, /* doh_equal */ + 0, /* doh_first */ + 0, /* doh_next */ + String_setfile, /* doh_setfile */ + String_getfile, /* doh_getfile */ + String_setline, /* doh_setline */ + String_getline, /* doh_getline */ + 0, /* doh_mapping */ + &StringListMethods, /* doh_sequence */ + &StringFileMethods, /* doh_file */ + &StringStringMethods, /* doh_string */ + 0, /* doh_position */ + 0 +}; + + +#define INIT_MAXSIZE 16 + +/* ----------------------------------------------------------------------------- + * NewString() - Create a new string + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewString(const DOHString_or_char *so) { + int l = 0, max; + String *str; + char *s; + int hashkey = -1; + if (DohCheck(so)) { + str = (String *) ObjData(so); + s = (char *) String_data((String *) so); + l = s ? str->len : 0; + hashkey = str->hashkey; + } else { + s = (char *) so; + l = s ? (int) strlen(s) : 0; + } + + str = (String *) DohMalloc(sizeof(String)); + str->hashkey = hashkey; + str->sp = 0; + str->line = 0; + str->file = 0; + max = INIT_MAXSIZE; + if (s) { + if ((l + 1) > max) + max = l + 1; + } + str->str = (char *) DohMalloc(max); + str->maxsize = max; + if (s) { + strcpy(str->str, s); + str->len = l; + str->sp = l; + } else { + str->str[0] = 0; + str->len = 0; + } + return DohObjMalloc(&DohStringType, str); +} + + +/* ----------------------------------------------------------------------------- + * NewStringEmpty() - Create a new string + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewStringEmpty(void) { + int max = INIT_MAXSIZE; + String *str = (String *) DohMalloc(sizeof(String)); + str->hashkey = 0; + str->sp = 0; + str->line = 0; + str->file = 0; + str->str = (char *) DohMalloc(max); + str->maxsize = max; + str->str[0] = 0; + str->len = 0; + return DohObjMalloc(&DohStringType, str); +} + +/* ----------------------------------------------------------------------------- + * NewStringWithSize() - Create a new string + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewStringWithSize(const DOHString_or_char *so, int len) { + int l = 0, max; + String *str; + char *s; + if (DohCheck(so)) { + s = (char *) String_data((String *) so); + } else { + s = (char *) so; + } + + str = (String *) DohMalloc(sizeof(String)); + str->hashkey = -1; + str->sp = 0; + str->line = 0; + str->file = 0; + max = INIT_MAXSIZE; + if (s) { + l = (int) len; + if ((l + 1) > max) + max = l + 1; + } + str->str = (char *) DohMalloc(max); + str->maxsize = max; + if (s) { + memcpy(str->str, s, len); + str->str[l] = 0; + str->len = l; + str->sp = l; + } else { + str->str[0] = 0; + str->len = 0; + } + return DohObjMalloc(&DohStringType, str); +} + +/* ----------------------------------------------------------------------------- + * NewStringf() + * + * Create a new string from a list of objects. + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewStringf(const DOHString_or_char *fmt, ...) { + va_list ap; + DOH *r; + va_start(ap, fmt); + r = NewStringEmpty(); + DohvPrintf(r, Char(fmt), ap); + va_end(ap); + return (DOHString *) r; +} + +/* ----------------------------------------------------------------------------- + * Strcmp() + * Strncmp() + * Strstr() + * Strchr() + * + * Some utility functions. + * ----------------------------------------------------------------------------- */ + +int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2) { + const char *c1 = Char(s1); + const char *c2 = Char(s2); + return strcmp(c1, c2); +} + +int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n) { + return strncmp(Char(s1), Char(s2), n); +} + +char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2) { + char *p1 = Char(s1); + char *p2 = Char(s2); + return p1 == 0 || p2 == 0 || *p2 == '\0' ? p1 : strstr(p1, p2); +} + +char *DohStrchr(const DOHString_or_char *s1, int ch) { + return strchr(Char(s1), ch); +} |