/* * stringutil.c -- string utilities */ /* * $Id: stringutil.c,v 1.2 2005/08/08 09:43:07 murrayma Exp $ */ #include "copyright.h" #include "config.h" #include "mudconf.h" #include "config.h" #include "externs.h" #include "alloc.h" #include "ansi.h" #ifdef __linux__ char *___strtok; #endif /* Convert raw character sequences into MUX substitutions (type = 1) * or strips them (type = 0). */ char *translate_string(str, type) const char *str; int type; { char old[LBUF_SIZE]; static char new[LBUF_SIZE]; char *j, *c, *bp; int i; bp = new; StringCopy(old, str); for (j = old; *j != '\0'; j++) { switch (*j) { case ESC_CHAR: c = strchr(j, 'm'); if (c) { if (!type) { j = c; break; } *c = '\0'; i = atoi(j + 2); switch (i) { case 0: safe_str("%cn", new, &bp); break; case 1: safe_str("%ch", new, &bp); break; case 5: safe_str("%cf", new, &bp); break; case 7: safe_str("%ci", new, &bp); break; case 30: safe_str("%cx", new, &bp); break; case 31: safe_str("%cr", new, &bp); break; case 32: safe_str("%cg", new, &bp); break; case 33: safe_str("%cy", new, &bp); break; case 34: safe_str("%cb", new, &bp); break; case 35: safe_str("%cm", new, &bp); break; case 36: safe_str("%cc", new, &bp); break; case 37: safe_str("%cw", new, &bp); break; case 40: safe_str("%cX", new, &bp); break; case 41: safe_str("%cR", new, &bp); break; case 42: safe_str("%cG", new, &bp); break; case 43: safe_str("%cY", new, &bp); break; case 44: safe_str("%cB", new, &bp); break; case 45: safe_str("%cM", new, &bp); break; case 46: safe_str("%cC", new, &bp); break; case 47: safe_str("%cW", new, &bp); break; } j = c; } else { safe_chr(*j, new, &bp); } break; case ' ': if ((*(j + 1) == ' ') && type) safe_str("%b", new, &bp); else safe_chr(' ', new, &bp); break; case '\\': if (type) safe_str("\\", new, &bp); else safe_chr('\\', new, &bp); break; case '%': if (type) safe_str("%%", new, &bp); else safe_chr('%', new, &bp); break; case '[': if (type) safe_str("%[", new, &bp); else safe_chr('[', new, &bp); break; case ']': if (type) safe_str("%]", new, &bp); else safe_chr(']', new, &bp); break; case '{': if (type) safe_str("%{", new, &bp); else safe_chr('{', new, &bp); break; case '}': if (type) safe_str("%}", new, &bp); else safe_chr('}', new, &bp); break; case '(': if (type) safe_str("%(", new, &bp); else safe_chr('(', new, &bp); break; case ')': if (type) safe_str("%)", new, &bp); else safe_chr(')', new, &bp); break; case '\r': break; case '\n': if (type) safe_str("%r", new, &bp); else safe_chr(' ', new, &bp); break; default: safe_chr(*j, new, &bp); } } *bp = '\0'; return new; } /* * capitalizes an entire string */ char *upcasestr(s) char *s; { char *p; for (p = s; p && *p; p++) *p = ToUpper(*p); return s; } /* * returns a pointer to the non-space character in s, or a NULL if s == NULL * or *s == NULL or s has only spaces. */ char *skip_space(s) const char *s; { char *cp; cp = (char *) s; while (cp && *cp && isspace(*cp)) cp++; return (cp); } /* * returns a pointer to the next character in s matching c, or a pointer to * the \0 at the end of s. Yes, this is a lot like index, but not exactly. */ char *seek_char(s, c) const char *s; char c; { char *cp; cp = (char *) s; while (cp && *cp && (*cp != c)) cp++; return (cp); } /* * --------------------------------------------------------------------------- * * munge_space: Compress multiple spaces to one space, also remove leading and * * trailing spaces. */ char *munge_space(string) char *string; { char *buffer, *p, *q; buffer = alloc_lbuf("munge_space"); p = string; q = buffer; while (p && *p && isspace(*p)) p++; /* * remove inital spaces */ while (p && *p) { while (*p && !isspace(*p)) *q++ = *p++; while (*p && isspace(*++p)); if (*p) *q++ = ' '; } *q = '\0'; /* * remove terminal spaces and terminate * * * * * * string */ return (buffer); } /* * --------------------------------------------------------------------------- * * trim_spaces: Remove leading and trailing spaces. */ char *trim_spaces(string) char *string; { char *buffer, *p, *q; buffer = alloc_lbuf("trim_spaces"); p = string; q = buffer; while (p && *p && isspace(*p)) /* * remove inital spaces */ p++; while (p && *p) { while (*p && !isspace(*p)) /* * copy nonspace chars */ *q++ = *p++; while (*p && isspace(*p)) /* * compress spaces */ p++; if (*p) *q++ = ' '; /* * leave one space */ } *q = '\0'; /* * terminate string */ return (buffer); } /* * --------------------------------------------------------------------------- * * grabto: Return portion of a string up to the indicated character. Also * * returns a modified pointer to the string ready for another call. */ char *grabto(str, targ) char **str, targ; { char *savec, *cp; if (!str || !*str || !**str) return NULL; savec = cp = *str; while (*cp && *cp != targ) cp++; if (*cp) *cp++ = '\0'; *str = cp; return savec; } int string_compare(s1, s2) const char *s1, *s2; { #ifndef STANDALONE if (!mudconf.space_compress) { while (*s1 && *s2 && ToLower(*s1) == ToLower(*s2)) s1++, s2++; return (ToLower(*s1) - ToLower(*s2)); } else { #endif while (isspace(*s1)) s1++; while (isspace(*s2)) s2++; while (*s1 && *s2 && ((ToLower(*s1) == ToLower(*s2)) || (isspace(*s1) && isspace(*s2)))) { if (isspace(*s1) && isspace(*s2)) { /* * skip all * * * * * * * other * * * * spaces */ while (isspace(*s1)) s1++; while (isspace(*s2)) s2++; } else { s1++; s2++; } } if ((*s1) && (*s2)) return (1); if (isspace(*s1)) { while (isspace(*s1)) s1++; return (*s1); } if (isspace(*s2)) { while (isspace(*s2)) s2++; return (*s2); } if ((*s1) || (*s2)) return (1); return (0); #ifndef STANDALONE } #endif } int string_prefix(string, prefix) const char *string, *prefix; { int count = 0; while (*string && *prefix && ToLower(*string) == ToLower(*prefix)) string++, prefix++, count++; if (*prefix == '\0') /* * Matched all of prefix */ return (count); else return (0); } /* * accepts only nonempty matches starting at the beginning of a word */ const char *string_match(src, sub) const char *src, *sub; { if ((*sub != '\0') && (src)) { while (*src) { if (string_prefix(src, sub)) return src; /* * else scan to beginning of next word */ while (*src && isalnum(*src)) src++; while (*src && !isalnum(*src)) src++; } } return 0; } /* * --------------------------------------------------------------------------- * * replace_string: Returns an lbuf containing string STRING with all occurances * * of OLD replaced by NEW. OLD and NEW may be different lengths. * * (mitch 1 feb 91) */ char *replace_string(old, new, string) const char *old, *new, *string; { char *result, *r, *s; int olen; if (string == NULL) return NULL; s = (char *) string; olen = strlen(old); r = result = alloc_lbuf("replace_string"); while (*s) { /* * Copy up to the next occurrence of the first char of OLD */ while (*s && *s != *old) { safe_chr(*s, result, &r); s++; } /* * If we are really at an OLD, append NEW to the result and * * * * * * * * bump the input string past the occurrence of * OLD. * * * * Otherwise, copy the char and try again. */ if (*s) { if (!strncmp(old, s, olen)) { safe_str((char *) new, result, &r); s += olen; } else { safe_chr(*s, result, &r); s++; } } } *r = '\0'; return result; } /* * Returns string STRING with all occurances * of OLD replaced by NEW. OLD * and NEW may be different lengths. Modifies string, so: Note - STRING must * already be allocated large enough to handle the new size. (mitch 1 feb 91) */ char *replace_string_inplace(old, new, string) const char *old, *new; char *string; { char *s; s = replace_string(old, new, string); StringCopy(string, s); free_lbuf(s); return string; } /* * Counts occurances of C in STR. - mnp 7 feb 91 */ int count_chars(str, c) const char *str, c; { int out = 0; const char *p = str; if (p) while (*p != '\0') if (*p++ == c) out++; return out; } /* * returns the number of identical characters in the two strings */ int prefix_match(s1, s2) const char *s1, *s2; { int count = 0; while (*s1 && *s2 && (ToLower(*s1) == ToLower(*s2))) s1++, s2++, count++; /* * If the whole string matched, count the null. (Yes really.) */ if (!*s1 && !*s2) count++; return count; } int minmatch(str, target, min) char *str, *target; int min; { while (*str && *target && (ToLower(*str) == ToLower(*target))) { str++; target++; min--; } if (*str) return 0; if (!*target) return 1; return ((min <= 0) ? 1 : 0); } char *strsave(s) const char *s; { char *p; p = (char *) XMALLOC(sizeof(char) * (strlen(s) + 1), "strsave"); if (p) StringCopy(p, s); return p; } /* * --------------------------------------------------------------------------- * * safe_copy_str, safe_copy_chr - Copy buffers, watching for overflows. */ int safe_copy_str(char *src, char *buff, char **bufp, int max) { char *tp; tp = *bufp; if (src == NULL) return 0; while (*src && ((tp - buff) < max)) *tp++ = *src++; *bufp = tp; return strlen(src); } int safe_copy_chr(src, buff, bufp, max) char src, *buff, **bufp; int max; { char *tp; int retval; tp = *bufp; retval = 0; if ((tp - buff) < max) { *tp++ = src; } else { retval = 1; } *bufp = tp; return retval; } int matches_exit_from_list(str, pattern) char *str, *pattern; { char *s; while (*pattern) { for (s = str; /* * check out this one */ (*s && (ToLower(*s) == ToLower(*pattern)) && *pattern && (*pattern != EXIT_DELIMITER)); s++, pattern++); /* * Did we match it all? */ if (*s == '\0') { /* * Make sure nothing afterwards */ while (*pattern && isspace(*pattern)) pattern++; /* * Did we get it? */ if (!*pattern || (*pattern == EXIT_DELIMITER)) return 1; } /* * We didn't get it, find next string to test */ while (*pattern && *pattern++ != EXIT_DELIMITER); while (isspace(*pattern)) pattern++; } return 0; }