source: trunk/minix/commands/elvis/regsub.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 4.7 KB
Line 
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 */
14void 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 start = cpy = (char *)malloc((unsigned)(len + 1));
60 if (!cpy)
61 {
62 regerror("Not enough memory for ~ expansion");
63 return;
64 }
65
66 /* copy src into start, replacing the ~s by the previous text */
67 while (*src)
68 {
69# ifndef NO_MAGIC
70 if (*o_magic && *src == '~')
71 {
72 strcpy(cpy, prev);
73 cpy += strlen(prev);
74 src++;
75 }
76 else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
77# else /* NO_MAGIC */
78 if (*src == '\\' && *(src + 1) == '~')
79# endif /* NO_MAGIC */
80 {
81 strcpy(cpy, prev);
82 cpy += strlen(prev);
83 src += 2;
84 }
85 else
86 {
87 *cpy++ = *src++;
88 }
89 }
90 *cpy = '\0';
91#ifdef DEBUG
92 if ((int)(cpy - start) != len)
93 {
94 msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
95 }
96#endif
97
98 /* remember this as the "previous" for next time */
99 if (prev)
100 free(prev);
101 prev = src = start;
102
103#endif /* undef CRUNCH */
104
105 start = src;
106 while ((c = *src++) != '\0')
107 {
108#ifndef NO_MAGIC
109 /* recognize any meta characters */
110 if (c == '&' && *o_magic)
111 {
112 cpy = re->startp[0];
113 end = re->endp[0];
114 }
115 else
116#endif /* not NO_MAGIC */
117 if (c == '\\')
118 {
119 c = *src++;
120 switch (c)
121 {
122#ifndef NO_MAGIC
123 case '0':
124 case '1':
125 case '2':
126 case '3':
127 case '4':
128 case '5':
129 case '6':
130 case '7':
131 case '8':
132 case '9':
133 /* \0 thru \9 mean "copy subexpression" */
134 c -= '0';
135 cpy = re->startp[c];
136 end = re->endp[c];
137 break;
138# ifndef CRUNCH
139 case 'U':
140 case 'u':
141 case 'L':
142 case 'l':
143 /* \U and \L mean "convert to upper/lowercase" */
144 mod = c;
145 continue;
146
147 case 'E':
148 case 'e':
149 /* \E ends the \U or \L */
150 mod = 0;
151 continue;
152# endif /* not CRUNCH */
153 case '&':
154 /* "\&" means "original text" */
155 if (*o_magic)
156 {
157 *dst++ = c;
158 continue;
159 }
160 cpy = re->startp[0];
161 end = re->endp[0];
162 break;
163
164#else /* NO_MAGIC */
165 case '&':
166 /* "\&" means "original text" */
167 cpy = re->startp[0];
168 end = re->endp[0];
169 break;
170#endif /* NO_MAGIC */
171 default:
172 /* ordinary char preceded by backslash */
173 *dst++ = c;
174 continue;
175 }
176 }
177#ifndef CRUNCH
178# if OSK
179 else if (c == '\l')
180# else
181 else if (c == '\r')
182# endif
183 {
184 /* transliterate ^M into newline */
185 *dst++ = '\n';
186 continue;
187 }
188#endif /* !CRUNCH */
189 else
190 {
191 /* ordinary character, so just copy it */
192 *dst++ = c;
193 continue;
194 }
195
196 /* Note: to reach this point in the code, we must have evaded
197 * all "continue" statements. To do that, we must have hit
198 * a metacharacter that involves copying.
199 */
200
201 /* if there is nothing to copy, loop */
202 if (!cpy)
203 continue;
204
205 /* copy over a portion of the original */
206 while (cpy < end)
207 {
208#ifndef NO_MAGIC
209# ifndef CRUNCH
210 switch (mod)
211 {
212 case 'U':
213 case 'u':
214 /* convert to uppercase */
215 *dst++ = toupper(*cpy++);
216 break;
217
218 case 'L':
219 case 'l':
220 /* convert to lowercase */
221 *dst++ = tolower(*cpy++);
222 break;
223
224 default:
225 /* copy without any conversion */
226 *dst++ = *cpy++;
227 }
228
229 /* \u and \l end automatically after the first char */
230 if (mod && (mod == 'u' || mod == 'l'))
231 {
232 mod = 0;
233 }
234# else /* CRUNCH */
235 *dst++ = *cpy++;
236# endif /* CRUNCH */
237#else /* NO_MAGIC */
238 *dst++ = *cpy++;
239#endif /* NO_MAGIC */
240 }
241 }
242 *dst = '\0';
243}
Note: See TracBrowser for help on using the repository browser.