Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 250 lines (229 sloc) 4.861 kb
6335386 Martin Dietze 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.