|
|
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 <ctype.h> ! 8: #include "config.h" ! 9: #include "vi.h" ! 10: #include "regexp.h" ! 11: ! 12: static char *previous; /* a copy of the text from the previous substitution */ ! 13: ! 14: /* perform substitutions after a regexp match */ ! 15: void regsub(re, src, dst) ! 16: regexp *re; ! 17: REG char *src; ! 18: REG char *dst; ! 19: { ! 20: REG char *cpy; ! 21: REG char *end; ! 22: REG char c; ! 23: char *start; ! 24: #ifndef CRUNCH ! 25: int mod; ! 26: ! 27: mod = 0; ! 28: #endif ! 29: ! 30: start = src; ! 31: while ((c = *src++) != '\0') ! 32: { ! 33: #ifndef NO_MAGIC ! 34: /* recognize any meta characters */ ! 35: if (c == '&' && *o_magic) ! 36: { ! 37: cpy = re->startp[0]; ! 38: end = re->endp[0]; ! 39: } ! 40: else if (c == '~' && *o_magic) ! 41: { ! 42: cpy = previous; ! 43: if (cpy) ! 44: end = cpy + strlen(cpy); ! 45: } ! 46: else ! 47: #endif /* not NO_MAGIC */ ! 48: if (c == '\\') ! 49: { ! 50: c = *src++; ! 51: switch (c) ! 52: { ! 53: #ifndef NO_MAGIC ! 54: case '0': ! 55: case '1': ! 56: case '2': ! 57: case '3': ! 58: case '4': ! 59: case '5': ! 60: case '6': ! 61: case '7': ! 62: case '8': ! 63: case '9': ! 64: /* \0 thru \9 mean "copy subexpression" */ ! 65: c -= '0'; ! 66: cpy = re->startp[c]; ! 67: end = re->endp[c]; ! 68: break; ! 69: # ifndef CRUNCH ! 70: case 'U': ! 71: case 'u': ! 72: case 'L': ! 73: case 'l': ! 74: /* \U and \L mean "convert to upper/lowercase" */ ! 75: mod = c; ! 76: continue; ! 77: ! 78: case 'E': ! 79: case 'e': ! 80: /* \E ends the \U or \L */ ! 81: mod = 0; ! 82: continue; ! 83: # endif /* not CRUNCH */ ! 84: case '&': ! 85: /* "\&" means "original text" */ ! 86: if (*o_magic) ! 87: { ! 88: *dst++ = c; ! 89: continue; ! 90: } ! 91: cpy = re->startp[0]; ! 92: end = re->endp[0]; ! 93: break; ! 94: ! 95: case '~': ! 96: /* "\~" means "previous text, if any" */ ! 97: if (*o_magic) ! 98: { ! 99: *dst++ = c; ! 100: continue; ! 101: } ! 102: cpy = previous; ! 103: if (cpy) ! 104: end = cpy + strlen(cpy); ! 105: break; ! 106: #else /* NO_MAGIC */ ! 107: case '&': ! 108: /* "\&" means "original text" */ ! 109: cpy = re->startp[0]; ! 110: end = re->endp[0]; ! 111: break; ! 112: ! 113: case '~': ! 114: /* "\~" means "previous text, if any" */ ! 115: cpy = previous; ! 116: if (cpy) ! 117: end = cpy + strlen(cpy); ! 118: break; ! 119: #endif /* NO_MAGIC */ ! 120: default: ! 121: /* ordinary char preceded by backslash */ ! 122: *dst++ = c; ! 123: continue; ! 124: } ! 125: } ! 126: else ! 127: { ! 128: /* ordinary character, so just copy it */ ! 129: *dst++ = c; ! 130: continue; ! 131: } ! 132: ! 133: /* Note: to reach this point in the code, we must have evaded ! 134: * all "continue" statements. To do that, we must have hit ! 135: * a metacharacter that involves copying. ! 136: */ ! 137: ! 138: /* if there is nothing to copy, loop */ ! 139: if (!cpy) ! 140: continue; ! 141: ! 142: /* copy over a portion of the original */ ! 143: while (cpy < end) ! 144: { ! 145: #ifndef NO_MAGIC ! 146: # ifndef CRUNCH ! 147: switch (mod) ! 148: { ! 149: case 'U': ! 150: case 'u': ! 151: /* convert to uppercase */ ! 152: if (isascii(*cpy) && islower(*cpy)) ! 153: { ! 154: *dst++ = toupper(*cpy); ! 155: cpy++; ! 156: } ! 157: else ! 158: { ! 159: *dst++ = *cpy++; ! 160: } ! 161: break; ! 162: ! 163: case 'L': ! 164: case 'l': ! 165: /* convert to lowercase */ ! 166: if (isascii(*cpy) && isupper(*cpy)) ! 167: { ! 168: *dst++ = tolower(*cpy); ! 169: cpy++; ! 170: } ! 171: else ! 172: { ! 173: *dst++ = *cpy++; ! 174: } ! 175: break; ! 176: ! 177: default: ! 178: /* copy without any conversion */ ! 179: *dst++ = *cpy++; ! 180: } ! 181: ! 182: /* \u and \l end automatically after the first char */ ! 183: if (mod && (mod == 'u' || mod == 'l')) ! 184: { ! 185: mod = 0; ! 186: } ! 187: # else /* CRUNCH */ ! 188: *dst++ = *cpy++; ! 189: # endif /* CRUNCH */ ! 190: #else /* NO_MAGIC */ ! 191: *dst++ = *cpy++; ! 192: #endif /* NO_MAGIC */ ! 193: } ! 194: } ! 195: *dst = '\0'; ! 196: ! 197: /* remember what text we inserted this time */ ! 198: if (previous) ! 199: free(previous); ! 200: previous = (char *)malloc((unsigned)(strlen(start) + 1)); ! 201: if (previous) ! 202: strcpy(previous, start); ! 203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.