|
|
1.1 ! root 1: /* regsub.c */ ! 2: ! 3: /* This file contains the regsub() function, which performs substitutions ! 4: * after a regexp match has been found. ! 5: */ ! 6: ! 7: #include "config.h" ! 8: #include "ctype.h" ! 9: #include "vi.h" ! 10: #include "regexp.h" ! 11: ! 12: ! 13: /* perform substitutions after a regexp match */ ! 14: void regsub(re, src, dst) ! 15: regexp *re; /* the regexp with pointers into matched text */ ! 16: REG char *src; /* the replacement string */ ! 17: REG char *dst; /* where to put the result of the subst */ ! 18: { ! 19: REG char *cpy; /* pointer to start of text to copy */ ! 20: REG char *end; /* pointer to end of text to copy */ ! 21: REG char c; ! 22: char *start; ! 23: #ifndef CRUNCH ! 24: int mod = 0;/* used to track \U, \L, \u, \l, and \E */ ! 25: int len; /* used to calculate length of subst string */ ! 26: static char *prev; /* a copy of the text from the previous subst */ ! 27: ! 28: /* replace \~ (or maybe ~) by previous substitution text */ ! 29: ! 30: /* step 1: calculate the length of the new substitution text */ ! 31: for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++) ! 32: { ! 33: # ifdef NO_MAGIC ! 34: if (c == '\\' && *cpy == '~') ! 35: # else ! 36: if (c == (*o_magic ? '\0' : '\\') && *cpy == '~') ! 37: # endif ! 38: { ! 39: if (!prev) ! 40: { ! 41: regerror("No prev text to substitute for ~"); ! 42: return; ! 43: } ! 44: len += strlen(prev) - 1; ! 45: # ifndef NO_MAGIC ! 46: if (!*o_magic) ! 47: # endif ! 48: len -= 1; /* because we lose the \ too */ ! 49: } ! 50: ! 51: /* watch backslash quoting */ ! 52: if (c != '\\' && *cpy == '\\') ! 53: c = '\\'; ! 54: else ! 55: c = '\0'; ! 56: } ! 57: ! 58: /* allocate memory for the ~ed version of src */ ! 59: checkmem(); ! 60: start = cpy = (char *)malloc((unsigned)(len + 1)); ! 61: if (!cpy) ! 62: { ! 63: regerror("Not enough memory for ~ expansion"); ! 64: return; ! 65: } ! 66: ! 67: /* copy src into start, replacing the ~s by the previous text */ ! 68: while (*src) ! 69: { ! 70: # ifndef NO_MAGIC ! 71: if (*o_magic && *src == '~') ! 72: { ! 73: strcpy(cpy, prev); ! 74: cpy += strlen(prev); ! 75: src++; ! 76: } ! 77: else if (!*o_magic && *src == '\\' && *(src + 1) == '~') ! 78: # else /* NO_MAGIC */ ! 79: if (*src == '\\' && *(src + 1) == '~') ! 80: # endif /* NO_MAGIC */ ! 81: { ! 82: strcpy(cpy, prev); ! 83: cpy += strlen(prev); ! 84: src += 2; ! 85: } ! 86: else ! 87: { ! 88: *cpy++ = *src++; ! 89: } ! 90: } ! 91: *cpy = '\0'; ! 92: #ifdef DEBUG ! 93: if ((int)(cpy - start) != len) ! 94: { ! 95: msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start)); ! 96: } ! 97: #endif ! 98: checkmem(); ! 99: ! 100: /* remember this as the "previous" for next time */ ! 101: if (prev) ! 102: _free_(prev); ! 103: prev = src = start; ! 104: ! 105: #endif /* undef CRUNCH */ ! 106: ! 107: start = src; ! 108: while ((c = *src++) != '\0') ! 109: { ! 110: #ifndef NO_MAGIC ! 111: /* recognize any meta characters */ ! 112: if (c == '&' && *o_magic) ! 113: { ! 114: cpy = re->startp[0]; ! 115: end = re->endp[0]; ! 116: } ! 117: else ! 118: #endif /* not NO_MAGIC */ ! 119: if (c == '\\') ! 120: { ! 121: c = *src++; ! 122: switch (c) ! 123: { ! 124: #ifndef NO_MAGIC ! 125: case '0': ! 126: case '1': ! 127: case '2': ! 128: case '3': ! 129: case '4': ! 130: case '5': ! 131: case '6': ! 132: case '7': ! 133: case '8': ! 134: case '9': ! 135: /* \0 thru \9 mean "copy subexpression" */ ! 136: c -= '0'; ! 137: cpy = re->startp[c]; ! 138: end = re->endp[c]; ! 139: break; ! 140: # ifndef CRUNCH ! 141: case 'U': ! 142: case 'u': ! 143: case 'L': ! 144: case 'l': ! 145: /* \U and \L mean "convert to upper/lowercase" */ ! 146: mod = c; ! 147: continue; ! 148: ! 149: case 'E': ! 150: case 'e': ! 151: /* \E ends the \U or \L */ ! 152: mod = 0; ! 153: continue; ! 154: # endif /* not CRUNCH */ ! 155: case '&': ! 156: /* "\&" means "original text" */ ! 157: if (*o_magic) ! 158: { ! 159: *dst++ = c; ! 160: continue; ! 161: } ! 162: cpy = re->startp[0]; ! 163: end = re->endp[0]; ! 164: break; ! 165: ! 166: #else /* NO_MAGIC */ ! 167: case '&': ! 168: /* "\&" means "original text" */ ! 169: cpy = re->startp[0]; ! 170: end = re->endp[0]; ! 171: break; ! 172: #endif /* NO_MAGIC */ ! 173: default: ! 174: /* ordinary char preceded by backslash */ ! 175: *dst++ = c; ! 176: continue; ! 177: } ! 178: } ! 179: #ifndef CRUNCH ! 180: # if OSK ! 181: else if (c == '\l') ! 182: # else ! 183: else if (c == '\r') ! 184: # endif ! 185: { ! 186: /* transliterate ^M into newline */ ! 187: *dst++ = '\n'; ! 188: continue; ! 189: } ! 190: #endif /* !CRUNCH */ ! 191: else ! 192: { ! 193: /* ordinary character, so just copy it */ ! 194: *dst++ = c; ! 195: continue; ! 196: } ! 197: ! 198: /* Note: to reach this point in the code, we must have evaded ! 199: * all "continue" statements. To do that, we must have hit ! 200: * a metacharacter that involves copying. ! 201: */ ! 202: ! 203: /* if there is nothing to copy, loop */ ! 204: if (!cpy) ! 205: continue; ! 206: ! 207: /* copy over a portion of the original */ ! 208: while (cpy < end) ! 209: { ! 210: #ifndef NO_MAGIC ! 211: # ifndef CRUNCH ! 212: switch (mod) ! 213: { ! 214: case 'U': ! 215: case 'u': ! 216: /* convert to uppercase */ ! 217: *dst++ = toupper(*cpy++); ! 218: break; ! 219: ! 220: case 'L': ! 221: case 'l': ! 222: /* convert to lowercase */ ! 223: *dst++ = tolower(*cpy++); ! 224: break; ! 225: ! 226: default: ! 227: /* copy without any conversion */ ! 228: *dst++ = *cpy++; ! 229: } ! 230: ! 231: /* \u and \l end automatically after the first char */ ! 232: if (mod && (mod == 'u' || mod == 'l')) ! 233: { ! 234: mod = 0; ! 235: } ! 236: # else /* CRUNCH */ ! 237: *dst++ = *cpy++; ! 238: # endif /* CRUNCH */ ! 239: #else /* NO_MAGIC */ ! 240: *dst++ = *cpy++; ! 241: #endif /* NO_MAGIC */ ! 242: } ! 243: } ! 244: *dst = '\0'; ! 245: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.