1 /* @(#)substcmds.c 1.23 09/07/09 Copyright 1986-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)substcmds.c 1.23 09/07/09 Copyright 1986-2009 J. Schilling";
6 #endif
7 /*
8 * Substitution commands called from ECS : command line
9 *
10 * Copyright (c) 1986-2009 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include "ved.h"
27
28 #define OLDSIZE 4096
29
30 #define iswhite(c) ((c) == ' ' || (c) == '\t')
31
32 LOCAL BOOL subverbose;
33
34 EXPORT void subst __PR((ewin_t *wp, Uchar* cmd, int cmdlen));
35 LOCAL void substitute __PR((ewin_t *wp, Uchar* from, long fromlen, Uchar* to, long tolen));
36 LOCAL BOOL simpleto __PR((Uchar* s, long len));
37 LOCAL void catsub __PR((ewin_t *wp, Uchar* old, long oldlen, Uchar* to, long tolen));
38
39 /*
40 * This is the external callable subsitution command routine.
41 * It parses the command line and then calls the 'real' substitution command.
42 * Syntax is: ESC: sub /old/new/v
43 */
44 EXPORT void
subst(wp,cmd,cmdlen)45 subst(wp, cmd, cmdlen)
46 ewin_t *wp;
47 Uchar *cmd;
48 int cmdlen;
49 {
50 register Uchar *from;
51 register Uchar *to;
52 register Uchar *cp;
53 register Uchar *endp;
54 register Uchar c = '/';
55 register Uchar dc;
56 long fromlen;
57 long tolen;
58
59 from = cmd;
60 endp = &cmd[cmdlen];
61
62 while (from < endp) {
63 c = *from;
64 if (iswhite(c))
65 from++;
66 else
67 break;
68 }
69 dc = c;
70 to = ++from;
71 while (to < endp) {
72 c = *to;
73 if (c != dc)
74 to++;
75 else
76 break;
77 }
78 fromlen = to-from;
79 *to++ = '\0';
80 cp = to;
81 while (cp < endp) {
82 c = *cp;
83 if (c != dc)
84 cp++;
85 else
86 break;
87 }
88 tolen = cp-to;
89 *cp = '\0';
90 subverbose = FALSE;
91 if (++cp < endp && *cp == 'v')
92 subverbose = TRUE;
93
94 if (subverbose) {
95 writeerr(wp, "'%s'%s'(%ld,%ld)", from, to, fromlen, tolen);
96 sleep(1);
97 }
98 substitute(wp, from, fromlen, to, tolen);
99 }
100
101 /*
102 * This is the 'real' sunstitution routine.
103 * It gets called with pre-parsed strings.
104 */
105 LOCAL void
substitute(wp,from,fromlen,to,tolen)106 substitute(wp, from, fromlen, to, tolen)
107 ewin_t *wp;
108 Uchar *from;
109 long fromlen;
110 Uchar *to;
111 long tolen;
112 {
113 /* epos_t savedot = dot;*/
114 epos_t newdot;
115 epos_t omark = wp->mark;
116 int omarkvalid = wp->markvalid;
117 ecnt_t n = wp->curnum;
118 Uchar old[NAMESIZE+1];
119 long oldlen = 0;
120 BOOL tosimple;
121
122 if (fromlen == 0)
123 return;
124 tosimple = simpleto(to, tolen);
125
126 while (n--) {
127 /*
128 * Search the next occurence of the 'from' string.
129 * Use a temporary mark to tell whre the found pattern starts.
130 */
131 if ((newdot = search(wp, wp->dot, from, fromlen, 1)) > wp->eof) {
132 if (newdot == (wp->eof+2))
133 not_found(wp);
134 break;
135 } else {
136 wp->dot = newdot;
137 }
138
139 if (!tosimple) {
140 /*
141 * We need to remember the old 'from' string before.
142 */
143 oldlen = wp->dot-wp->mark > NAMESIZE ?
144 NAMESIZE : (long)wp->dot-wp->mark;
145 oldlen = extract(wp, wp->mark, old, (int)oldlen);
146 if (subverbose) {
147 writeerr(wp, "%ld'%s'", oldlen, old);
148 sleep(1);
149 }
150 }
151 /*
152 * Now delete the old string in the buffer
153 * and insert substitution
154 */
155 rubchars(wp, wp->dot-wp->mark); /* Mark is before dot */
156 if (tosimple)
157 insert(wp, to, tolen);
158 else
159 catsub(wp, old, oldlen, to, tolen);
160 dispup(wp, wp->dot, wp->mark);
161 }
162
163 /*
164 * Re-set mark to remembered place
165 */
166 resetmark(wp);
167 if (omarkvalid)
168 setmark(wp, omark);
169 }
170
171 /*
172 * Check is this is a 'simple' 'to'-substitution string
173 * that does not require to be expanded via 'catsub()'.
174 */
175 LOCAL BOOL
simpleto(s,len)176 simpleto(s, len)
177 register Uchar *s;
178 register long len;
179 {
180 register Uchar c;
181
182 if (len <= 0)
183 return (TRUE);
184 while (--len >= 0) {
185 c = *s++;
186 if (c == '\\' || c == '&')
187 return (FALSE);
188 }
189 return (TRUE);
190 }
191
192 /*
193 * Insert the substitution string.
194 * The '&' character in the to string is substituted with the old from string.
195 */
196 LOCAL void
catsub(wp,old,oldlen,to,tolen)197 catsub(wp, old, oldlen, to, tolen)
198 ewin_t *wp;
199 register Uchar *old;
200 register long oldlen;
201 register Uchar *to;
202 register long tolen;
203 {
204 if (tolen <= 0)
205 return;
206
207 while (--tolen >= 0) {
208 if (*to == '\\') {
209 if (--tolen >= 0)
210 insert(wp, ++to, 1L);
211 } else if (*to == '&') {
212 insert(wp, old, oldlen);
213 } else {
214 insert(wp, to, 1L);
215 }
216 to++;
217 }
218 }
219