Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 250 lines (229 sloc) 4.861 kB
6335386 @mbert Import Elvis 1.8 (written by Steve Kirkendall)
authored
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 if (*src == '\\')
89 {
90 *cpy++ = *src++;
91 }
92 *cpy++ = *src++;
93 }
94 }
95 *cpy = '\0';
96 #ifdef DEBUG
97 if ((int)(cpy - start) != len)
98 {
99 msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
100 }
101 #endif
102 checkmem();
103
104 /* remember this as the "previous" for next time */
105 if (prev)
106 _free_(prev);
107 prev = src = start;
108
109 #endif /* undef CRUNCH */
110
111 start = src;
112 while ((c = *src++) != '\0')
113 {
114 #ifndef NO_MAGIC
115 /* recognize any meta characters */
116 if (c == '&' && *o_magic)
117 {
118 cpy = re->startp[0];
119 end = re->endp[0];
120 }
121 else
122 #endif /* not NO_MAGIC */
123 if (c == '\\')
124 {
125 c = *src++;
126 switch (c)
127 {
128 #ifndef NO_MAGIC
129 case '0':
130 case '1':
131 case '2':
132 case '3':
133 case '4':
134 case '5':
135 case '6':
136 case '7':
137 case '8':
138 case '9':
139 /* \0 thru \9 mean "copy subexpression" */
140 c -= '0';
141 cpy = re->startp[c];
142 end = re->endp[c];
143 break;
144 # ifndef CRUNCH
145 case 'U':
146 case 'u':
147 case 'L':
148 case 'l':
149 /* \U and \L mean "convert to upper/lowercase" */
150 mod = c;
151 continue;
152
153 case 'E':
154 case 'e':
155 /* \E ends the \U or \L */
156 mod = 0;
157 continue;
158 # endif /* not CRUNCH */
159 case '&':
160 /* "\&" means "original text" */
161 if (*o_magic)
162 {
163 *dst++ = c;
164 continue;
165 }
166 cpy = re->startp[0];
167 end = re->endp[0];
168 break;
169
170 #else /* NO_MAGIC */
171 case '&':
172 /* "\&" means "original text" */
173 cpy = re->startp[0];
174 end = re->endp[0];
175 break;
176 #endif /* NO_MAGIC */
177 default:
178 /* ordinary char preceded by backslash */
179 *dst++ = c;
180 continue;
181 }
182 }
183 #ifndef CRUNCH
184 # if OSK
185 else if (c == '\l')
186 # else
187 else if (c == '\r')
188 # endif
189 {
190 /* transliterate ^M into newline */
191 *dst++ = '\n';
192 continue;
193 }
194 #endif /* !CRUNCH */
195 else
196 {
197 /* ordinary character, so just copy it */
198 *dst++ = c;
199 continue;
200 }
201
202 /* Note: to reach this point in the code, we must have evaded
203 * all "continue" statements. To do that, we must have hit
204 * a metacharacter that involves copying.
205 */
206
207 /* if there is nothing to copy, loop */
208 if (!cpy)
209 continue;
210
211 /* copy over a portion of the original */
212 while (cpy < end)
213 {
214 #ifndef NO_MAGIC
215 # ifndef CRUNCH
216 switch (mod)
217 {
218 case 'U':
219 case 'u':
220 /* convert to uppercase */
221 *dst++ = toupper(*cpy++);
222 break;
223
224 case 'L':
225 case 'l':
226 /* convert to lowercase */
227 *dst++ = tolower(*cpy++);
228 break;
229
230 default:
231 /* copy without any conversion */
232 *dst++ = *cpy++;
233 }
234
235 /* \u and \l end automatically after the first char */
236 if (mod && (mod == 'u' || mod == 'l'))
237 {
238 mod = 0;
239 }
240 # else /* CRUNCH */
241 *dst++ = *cpy++;
242 # endif /* CRUNCH */
243 #else /* NO_MAGIC */
244 *dst++ = *cpy++;
245 #endif /* NO_MAGIC */
246 }
247 }
248 *dst = '\0';
249 }
Something went wrong with that request. Please try again.