summaryrefslogtreecommitdiffstats
path: root/contrib/tools/swig/Source/DOH/string.c
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2025-08-28 14:27:58 +0300
committerrobot-piglet <[email protected]>2025-08-28 14:57:06 +0300
commit81d828c32c8d5477cb2f0ce5da06a1a8d9392ca3 (patch)
tree3081d566f0d5158d76e9093261344f6406fd09f7 /contrib/tools/swig/Source/DOH/string.c
parent77ea11423f959e51795cc3ef36a48d808b4ffb98 (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.c1287
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);
+}