--- src/interpret.c Fri Nov 12 02:05:32 1999 +++ src-stick/interpret.c Fri Nov 12 17:25:20 1999 @@ -16552,6 +16552,142 @@ } #endif /* F_SET_LIGHT */ +#ifdef F_SUBSTITUTE_STRING + /* Added to support StickLib: */ + CASE(F_SUBSTITUTE_STRING); + { +#define MAX_REC_DEPTH 8 +#define STR_BUF_LENGTH 4096 +#define MY_ALNUM(x) (isalnum(x) || x == '_') + + static char *rec_stack[MAX_REC_DEPTH]; + static char strbuf[STR_BUF_LENGTH + 1]; + svalue_t *arg; + char *ret, *src; + vector_t *aliases, *repl_strings; + int min_len, max_len; + int a_size; + int rec_count = 0, replaced = 0; + char *dest = strbuf; + char *end = &strbuf[STR_BUF_LENGTH - 1]; + char *a, *b, *tmp; + char x; + int i, str_len, low, high, curr, bingo; + + arg = sp - 4; + if (arg[0].type != T_STRING) + goto bad_arg_1; + if (arg[1].type != T_POINTER) + goto bad_arg_2; + if (arg[2].type != T_POINTER) + goto bad_arg_3; + if (arg[3].type != T_NUMBER) + goto bad_arg_4; + if (arg[4].type != T_NUMBER) + goto bad_arg_4; + /* Hmmh, last is incorrect of course but I don't want to + * add a new label to the other place. :-) + */ + + src = arg[0].u.string; + aliases = arg[1].u.vec; + repl_strings = arg[2].u.vec; + min_len = arg[3].u.number; + max_len = arg[4].u.number; + a_size = VEC_SIZE(aliases); + + /* The core substitute_string() code: */ + + do { /* Main substitute_string loop... */ + + /* First we'll skip through the separators (non-letters) */ + while ((x = *src) && !(MY_ALNUM(x))) { + /* Let's skip all non-letters */ + *dest = x; + if (++dest >= end) { + ret = replaced ? (*dest = '\0', strbuf) : NULL; + goto subst_string_done; + } + src++; + } + + /* If we ran to the end of the string we'll 'return from + * recursions', or, if at the top level, end substitution: + */ + if (!x) { + if (!rec_count) { + ret = replaced ? (*dest = '\0', strbuf) : NULL; + goto subst_string_done; + } + src = rec_stack[--rec_count]; + continue; + } + tmp = src; + while ((x = *tmp) && MY_ALNUM(x)) + tmp++; /* Let's search last char of the word. */ + str_len = tmp - src; + if (str_len >= min_len && str_len <= max_len && + rec_count < MAX_REC_DEPTH) { + bingo = low = -1; + high = a_size; + while ((curr = (low + high) / 2) > low) { + a = src; + b = aliases -> item[curr].u.string; + i = 1; + while ((x = *b) && !(i = *a - x)) { + a++; + b++; + } + if (!i && a == tmp) { + bingo = curr; + break; + } + if (i < 0) { + if (!curr) break; + high = curr; + } else { + low = curr; + } + } + if (bingo >= 0) { + rec_stack[rec_count++] = tmp; + src = repl_strings -> item[bingo].u.string; + replaced++; + continue; + } + } + if (str_len > (end - dest + 1)) { + while (dest < end) { + *dest = *src; + dest++; + src++; + } + ret = replaced ? (*dest = '\0', strbuf) : NULL; + goto subst_string_done; + } + do { + *dest = *src; + dest++; + } while (++src < tmp); + } while (1); + + subst_string_done: + +/*********/ + + if (!ret) { + pop_n_elems(4); + } else { + pop_n_elems(5); +fprintf(stderr, "Result = %s.\n", ret); + push_string_malloced(ret); + } + break; + } + + /* ... end of StickLib-extra-func */ +#endif + /* --- XEfun and XCodes --- */ CASE(F_ESCAPE); /* --- escape <instr> ... --- */