|
|
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.