Blame


1 b3994ec5 2003-12-11 devnull #include <u.h>
2 b3994ec5 2003-12-11 devnull #include <libc.h>
3 b3994ec5 2003-12-11 devnull #include <draw.h>
4 b3994ec5 2003-12-11 devnull #include <thread.h>
5 b3994ec5 2003-12-11 devnull #include <cursor.h>
6 b3994ec5 2003-12-11 devnull #include <mouse.h>
7 b3994ec5 2003-12-11 devnull #include <keyboard.h>
8 b3994ec5 2003-12-11 devnull #include <frame.h>
9 b3994ec5 2003-12-11 devnull #include <fcall.h>
10 b3994ec5 2003-12-11 devnull #include <plumb.h>
11 67dbeee5 2017-10-10 rsc #include <libsec.h>
12 b3994ec5 2003-12-11 devnull #include "dat.h"
13 b3994ec5 2003-12-11 devnull #include "edit.h"
14 b3994ec5 2003-12-11 devnull #include "fns.h"
15 b3994ec5 2003-12-11 devnull
16 b3994ec5 2003-12-11 devnull static char linex[]="\n";
17 b3994ec5 2003-12-11 devnull static char wordx[]=" \t\n";
18 b3994ec5 2003-12-11 devnull struct cmdtab cmdtab[]={
19 b3994ec5 2003-12-11 devnull /* cmdc text regexp addr defcmd defaddr count token fn */
20 b3994ec5 2003-12-11 devnull '\n', 0, 0, 0, 0, aDot, 0, 0, nl_cmd,
21 b3994ec5 2003-12-11 devnull 'a', 1, 0, 0, 0, aDot, 0, 0, a_cmd,
22 b3994ec5 2003-12-11 devnull 'b', 0, 0, 0, 0, aNo, 0, linex, b_cmd,
23 b3994ec5 2003-12-11 devnull 'c', 1, 0, 0, 0, aDot, 0, 0, c_cmd,
24 b3994ec5 2003-12-11 devnull 'd', 0, 0, 0, 0, aDot, 0, 0, d_cmd,
25 b3994ec5 2003-12-11 devnull 'e', 0, 0, 0, 0, aNo, 0, wordx, e_cmd,
26 b3994ec5 2003-12-11 devnull 'f', 0, 0, 0, 0, aNo, 0, wordx, f_cmd,
27 b3994ec5 2003-12-11 devnull 'g', 0, 1, 0, 'p', aDot, 0, 0, g_cmd,
28 b3994ec5 2003-12-11 devnull 'i', 1, 0, 0, 0, aDot, 0, 0, i_cmd,
29 b3994ec5 2003-12-11 devnull 'm', 0, 0, 1, 0, aDot, 0, 0, m_cmd,
30 b3994ec5 2003-12-11 devnull 'p', 0, 0, 0, 0, aDot, 0, 0, p_cmd,
31 b3994ec5 2003-12-11 devnull 'r', 0, 0, 0, 0, aDot, 0, wordx, e_cmd,
32 b3994ec5 2003-12-11 devnull 's', 0, 1, 0, 0, aDot, 1, 0, s_cmd,
33 b3994ec5 2003-12-11 devnull 't', 0, 0, 1, 0, aDot, 0, 0, m_cmd,
34 b3994ec5 2003-12-11 devnull 'u', 0, 0, 0, 0, aNo, 2, 0, u_cmd,
35 b3994ec5 2003-12-11 devnull 'v', 0, 1, 0, 'p', aDot, 0, 0, g_cmd,
36 b3994ec5 2003-12-11 devnull 'w', 0, 0, 0, 0, aAll, 0, wordx, w_cmd,
37 b3994ec5 2003-12-11 devnull 'x', 0, 1, 0, 'p', aDot, 0, 0, x_cmd,
38 b3994ec5 2003-12-11 devnull 'y', 0, 1, 0, 'p', aDot, 0, 0, x_cmd,
39 b3994ec5 2003-12-11 devnull '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd,
40 b3994ec5 2003-12-11 devnull 'B', 0, 0, 0, 0, aNo, 0, linex, B_cmd,
41 b3994ec5 2003-12-11 devnull 'D', 0, 0, 0, 0, aNo, 0, linex, D_cmd,
42 b3994ec5 2003-12-11 devnull 'X', 0, 1, 0, 'f', aNo, 0, 0, X_cmd,
43 b3994ec5 2003-12-11 devnull 'Y', 0, 1, 0, 'f', aNo, 0, 0, X_cmd,
44 b3994ec5 2003-12-11 devnull '<', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd,
45 b3994ec5 2003-12-11 devnull '|', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd,
46 b3994ec5 2003-12-11 devnull '>', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd,
47 b3994ec5 2003-12-11 devnull /* deliberately unimplemented:
48 b3994ec5 2003-12-11 devnull 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd,
49 b3994ec5 2003-12-11 devnull 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd,
50 b3994ec5 2003-12-11 devnull 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd,
51 b3994ec5 2003-12-11 devnull '!', 0, 0, 0, 0, aNo, 0, linex, plan9_cmd,
52 b3994ec5 2003-12-11 devnull */
53 cbeb0b26 2006-04-01 devnull 0, 0, 0, 0, 0, 0, 0, 0
54 b3994ec5 2003-12-11 devnull };
55 b3994ec5 2003-12-11 devnull
56 b3994ec5 2003-12-11 devnull Cmd *parsecmd(int);
57 b3994ec5 2003-12-11 devnull Addr *compoundaddr(void);
58 b3994ec5 2003-12-11 devnull Addr *simpleaddr(void);
59 b3994ec5 2003-12-11 devnull void freecmd(void);
60 b3994ec5 2003-12-11 devnull void okdelim(int);
61 b3994ec5 2003-12-11 devnull
62 b3994ec5 2003-12-11 devnull Rune *cmdstartp;
63 b3994ec5 2003-12-11 devnull Rune *cmdendp;
64 b3994ec5 2003-12-11 devnull Rune *cmdp;
65 b3994ec5 2003-12-11 devnull Channel *editerrc;
66 b3994ec5 2003-12-11 devnull
67 b3994ec5 2003-12-11 devnull String *lastpat;
68 b3994ec5 2003-12-11 devnull int patset;
69 b3994ec5 2003-12-11 devnull
70 b3994ec5 2003-12-11 devnull List cmdlist;
71 b3994ec5 2003-12-11 devnull List addrlist;
72 b3994ec5 2003-12-11 devnull List stringlist;
73 b3994ec5 2003-12-11 devnull Text *curtext;
74 b3994ec5 2003-12-11 devnull int editing = Inactive;
75 b3994ec5 2003-12-11 devnull
76 b3994ec5 2003-12-11 devnull String* newstring(int);
77 b3994ec5 2003-12-11 devnull
78 b3994ec5 2003-12-11 devnull void
79 b3994ec5 2003-12-11 devnull editthread(void *v)
80 b3994ec5 2003-12-11 devnull {
81 b3994ec5 2003-12-11 devnull Cmd *cmdp;
82 b3994ec5 2003-12-11 devnull
83 b3994ec5 2003-12-11 devnull USED(v);
84 b3994ec5 2003-12-11 devnull threadsetname("editthread");
85 b3994ec5 2003-12-11 devnull while((cmdp=parsecmd(0)) != 0){
86 b3994ec5 2003-12-11 devnull if(cmdexec(curtext, cmdp) == 0)
87 b3994ec5 2003-12-11 devnull break;
88 b3994ec5 2003-12-11 devnull freecmd();
89 b3994ec5 2003-12-11 devnull }
90 b3994ec5 2003-12-11 devnull sendp(editerrc, nil);
91 b3994ec5 2003-12-11 devnull }
92 b3994ec5 2003-12-11 devnull
93 b3994ec5 2003-12-11 devnull void
94 b3994ec5 2003-12-11 devnull allelogterm(Window *w, void *x)
95 b3994ec5 2003-12-11 devnull {
96 b3994ec5 2003-12-11 devnull USED(x);
97 b3994ec5 2003-12-11 devnull elogterm(w->body.file);
98 b3994ec5 2003-12-11 devnull }
99 b3994ec5 2003-12-11 devnull
100 b3994ec5 2003-12-11 devnull void
101 b3994ec5 2003-12-11 devnull alleditinit(Window *w, void *x)
102 b3994ec5 2003-12-11 devnull {
103 b3994ec5 2003-12-11 devnull USED(x);
104 b3994ec5 2003-12-11 devnull textcommit(&w->tag, TRUE);
105 b3994ec5 2003-12-11 devnull textcommit(&w->body, TRUE);
106 b3994ec5 2003-12-11 devnull w->body.file->editclean = FALSE;
107 b3994ec5 2003-12-11 devnull }
108 b3994ec5 2003-12-11 devnull
109 b3994ec5 2003-12-11 devnull void
110 b3994ec5 2003-12-11 devnull allupdate(Window *w, void *x)
111 b3994ec5 2003-12-11 devnull {
112 b3994ec5 2003-12-11 devnull Text *t;
113 b3994ec5 2003-12-11 devnull int i;
114 b3994ec5 2003-12-11 devnull File *f;
115 b3994ec5 2003-12-11 devnull
116 b3994ec5 2003-12-11 devnull USED(x);
117 b3994ec5 2003-12-11 devnull t = &w->body;
118 b3994ec5 2003-12-11 devnull f = t->file;
119 b3994ec5 2003-12-11 devnull if(f->curtext != t) /* do curtext only */
120 b3994ec5 2003-12-11 devnull return;
121 b3994ec5 2003-12-11 devnull if(f->elog.type == Null)
122 b3994ec5 2003-12-11 devnull elogterm(f);
123 b3994ec5 2003-12-11 devnull else if(f->elog.type != Empty){
124 b3994ec5 2003-12-11 devnull elogapply(f);
125 b3994ec5 2003-12-11 devnull if(f->editclean){
126 b3994ec5 2003-12-11 devnull f->mod = FALSE;
127 b3994ec5 2003-12-11 devnull for(i=0; i<f->ntext; i++)
128 b3994ec5 2003-12-11 devnull f->text[i]->w->dirty = FALSE;
129 b3994ec5 2003-12-11 devnull }
130 b3994ec5 2003-12-11 devnull }
131 b3994ec5 2003-12-11 devnull textsetselect(t, t->q0, t->q1);
132 b3994ec5 2003-12-11 devnull textscrdraw(t);
133 b3994ec5 2003-12-11 devnull winsettag(w);
134 b3994ec5 2003-12-11 devnull }
135 b3994ec5 2003-12-11 devnull
136 b3994ec5 2003-12-11 devnull void
137 b3994ec5 2003-12-11 devnull editerror(char *fmt, ...)
138 b3994ec5 2003-12-11 devnull {
139 b3994ec5 2003-12-11 devnull va_list arg;
140 b3994ec5 2003-12-11 devnull char *s;
141 b3994ec5 2003-12-11 devnull
142 b3994ec5 2003-12-11 devnull va_start(arg, fmt);
143 b3994ec5 2003-12-11 devnull s = vsmprint(fmt, arg);
144 b3994ec5 2003-12-11 devnull va_end(arg);
145 b3994ec5 2003-12-11 devnull freecmd();
146 b3994ec5 2003-12-11 devnull allwindows(allelogterm, nil); /* truncate the edit logs */
147 b3994ec5 2003-12-11 devnull sendp(editerrc, s);
148 b3994ec5 2003-12-11 devnull threadexits(nil);
149 b3994ec5 2003-12-11 devnull }
150 b3994ec5 2003-12-11 devnull
151 b3994ec5 2003-12-11 devnull void
152 b3994ec5 2003-12-11 devnull editcmd(Text *ct, Rune *r, uint n)
153 b3994ec5 2003-12-11 devnull {
154 b3994ec5 2003-12-11 devnull char *err;
155 b3994ec5 2003-12-11 devnull
156 b3994ec5 2003-12-11 devnull if(n == 0)
157 b3994ec5 2003-12-11 devnull return;
158 b3994ec5 2003-12-11 devnull if(2*n > RBUFSIZE){
159 b3994ec5 2003-12-11 devnull warning(nil, "string too long\n");
160 b3994ec5 2003-12-11 devnull return;
161 b3994ec5 2003-12-11 devnull }
162 b3994ec5 2003-12-11 devnull
163 b3994ec5 2003-12-11 devnull allwindows(alleditinit, nil);
164 b3994ec5 2003-12-11 devnull if(cmdstartp)
165 b3994ec5 2003-12-11 devnull free(cmdstartp);
166 b3994ec5 2003-12-11 devnull cmdstartp = runemalloc(n+2);
167 b3994ec5 2003-12-11 devnull runemove(cmdstartp, r, n);
168 75a851e9 2010-07-14 rsc if(r[n-1] != '\n')
169 b3994ec5 2003-12-11 devnull cmdstartp[n++] = '\n';
170 b3994ec5 2003-12-11 devnull cmdstartp[n] = '\0';
171 b3994ec5 2003-12-11 devnull cmdendp = cmdstartp+n;
172 b3994ec5 2003-12-11 devnull cmdp = cmdstartp;
173 b3994ec5 2003-12-11 devnull if(ct->w == nil)
174 b3994ec5 2003-12-11 devnull curtext = nil;
175 b3994ec5 2003-12-11 devnull else
176 b3994ec5 2003-12-11 devnull curtext = &ct->w->body;
177 b3994ec5 2003-12-11 devnull resetxec();
178 b3994ec5 2003-12-11 devnull if(editerrc == nil){
179 b3994ec5 2003-12-11 devnull editerrc = chancreate(sizeof(char*), 0);
180 334cb1e9 2004-12-27 devnull chansetname(editerrc, "editerrc");
181 b3994ec5 2003-12-11 devnull lastpat = allocstring(0);
182 b3994ec5 2003-12-11 devnull }
183 b3994ec5 2003-12-11 devnull threadcreate(editthread, nil, STACK);
184 b3994ec5 2003-12-11 devnull err = recvp(editerrc);
185 b3994ec5 2003-12-11 devnull editing = Inactive;
186 b3994ec5 2003-12-11 devnull if(err != nil){
187 b3994ec5 2003-12-11 devnull if(err[0] != '\0')
188 b3994ec5 2003-12-11 devnull warning(nil, "Edit: %s\n", err);
189 b3994ec5 2003-12-11 devnull free(err);
190 b3994ec5 2003-12-11 devnull }
191 b3994ec5 2003-12-11 devnull
192 b3994ec5 2003-12-11 devnull /* update everyone whose edit log has data */
193 b3994ec5 2003-12-11 devnull allwindows(allupdate, nil);
194 b3994ec5 2003-12-11 devnull }
195 b3994ec5 2003-12-11 devnull
196 b3994ec5 2003-12-11 devnull int
197 b3994ec5 2003-12-11 devnull getch(void)
198 b3994ec5 2003-12-11 devnull {
199 75a851e9 2010-07-14 rsc if(cmdp == cmdendp)
200 b3994ec5 2003-12-11 devnull return -1;
201 b3994ec5 2003-12-11 devnull return *cmdp++;
202 b3994ec5 2003-12-11 devnull }
203 b3994ec5 2003-12-11 devnull
204 b3994ec5 2003-12-11 devnull int
205 b3994ec5 2003-12-11 devnull nextc(void)
206 b3994ec5 2003-12-11 devnull {
207 75a851e9 2010-07-14 rsc if(cmdp == cmdendp)
208 b3994ec5 2003-12-11 devnull return -1;
209 b3994ec5 2003-12-11 devnull return *cmdp;
210 b3994ec5 2003-12-11 devnull }
211 b3994ec5 2003-12-11 devnull
212 b3994ec5 2003-12-11 devnull void
213 b3994ec5 2003-12-11 devnull ungetch(void)
214 b3994ec5 2003-12-11 devnull {
215 b3994ec5 2003-12-11 devnull if(--cmdp < cmdstartp)
216 b3994ec5 2003-12-11 devnull error("ungetch");
217 b3994ec5 2003-12-11 devnull }
218 b3994ec5 2003-12-11 devnull
219 b3994ec5 2003-12-11 devnull long
220 b3994ec5 2003-12-11 devnull getnum(int signok)
221 b3994ec5 2003-12-11 devnull {
222 b3994ec5 2003-12-11 devnull long n;
223 b3994ec5 2003-12-11 devnull int c, sign;
224 b3994ec5 2003-12-11 devnull
225 b3994ec5 2003-12-11 devnull n = 0;
226 b3994ec5 2003-12-11 devnull sign = 1;
227 b3994ec5 2003-12-11 devnull if(signok>1 && nextc()=='-'){
228 b3994ec5 2003-12-11 devnull sign = -1;
229 b3994ec5 2003-12-11 devnull getch();
230 b3994ec5 2003-12-11 devnull }
231 b3994ec5 2003-12-11 devnull if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */
232 b3994ec5 2003-12-11 devnull return sign;
233 b3994ec5 2003-12-11 devnull while('0'<=(c=getch()) && c<='9')
234 b3994ec5 2003-12-11 devnull n = n*10 + (c-'0');
235 b3994ec5 2003-12-11 devnull ungetch();
236 b3994ec5 2003-12-11 devnull return sign*n;
237 b3994ec5 2003-12-11 devnull }
238 b3994ec5 2003-12-11 devnull
239 b3994ec5 2003-12-11 devnull int
240 b3994ec5 2003-12-11 devnull cmdskipbl(void)
241 b3994ec5 2003-12-11 devnull {
242 b3994ec5 2003-12-11 devnull int c;
243 b3994ec5 2003-12-11 devnull do
244 b3994ec5 2003-12-11 devnull c = getch();
245 b3994ec5 2003-12-11 devnull while(c==' ' || c=='\t');
246 b3994ec5 2003-12-11 devnull if(c >= 0)
247 b3994ec5 2003-12-11 devnull ungetch();
248 b3994ec5 2003-12-11 devnull return c;
249 b3994ec5 2003-12-11 devnull }
250 b3994ec5 2003-12-11 devnull
251 b3994ec5 2003-12-11 devnull /*
252 b3994ec5 2003-12-11 devnull * Check that list has room for one more element.
253 b3994ec5 2003-12-11 devnull */
254 b3994ec5 2003-12-11 devnull void
255 b3994ec5 2003-12-11 devnull growlist(List *l)
256 b3994ec5 2003-12-11 devnull {
257 b3994ec5 2003-12-11 devnull if(l->u.listptr==0 || l->nalloc==0){
258 b3994ec5 2003-12-11 devnull l->nalloc = INCR;
259 734a96bd 2008-03-07 rsc l->u.listptr = emalloc(INCR*sizeof(void*));
260 b3994ec5 2003-12-11 devnull l->nused = 0;
261 b3994ec5 2003-12-11 devnull }else if(l->nused == l->nalloc){
262 734a96bd 2008-03-07 rsc l->u.listptr = erealloc(l->u.listptr, (l->nalloc+INCR)*sizeof(void*));
263 734a96bd 2008-03-07 rsc memset(l->u.ptr+l->nalloc, 0, INCR*sizeof(void*));
264 b3994ec5 2003-12-11 devnull l->nalloc += INCR;
265 b3994ec5 2003-12-11 devnull }
266 b3994ec5 2003-12-11 devnull }
267 b3994ec5 2003-12-11 devnull
268 b3994ec5 2003-12-11 devnull /*
269 b3994ec5 2003-12-11 devnull * Remove the ith element from the list
270 b3994ec5 2003-12-11 devnull */
271 b3994ec5 2003-12-11 devnull void
272 b3994ec5 2003-12-11 devnull dellist(List *l, int i)
273 b3994ec5 2003-12-11 devnull {
274 734a96bd 2008-03-07 rsc memmove(&l->u.ptr[i], &l->u.ptr[i+1], (l->nused-(i+1))*sizeof(void*));
275 b3994ec5 2003-12-11 devnull l->nused--;
276 b3994ec5 2003-12-11 devnull }
277 b3994ec5 2003-12-11 devnull
278 b3994ec5 2003-12-11 devnull /*
279 b3994ec5 2003-12-11 devnull * Add a new element, whose position is i, to the list
280 b3994ec5 2003-12-11 devnull */
281 b3994ec5 2003-12-11 devnull void
282 734a96bd 2008-03-07 rsc inslist(List *l, int i, void *v)
283 b3994ec5 2003-12-11 devnull {
284 b3994ec5 2003-12-11 devnull growlist(l);
285 734a96bd 2008-03-07 rsc memmove(&l->u.ptr[i+1], &l->u.ptr[i], (l->nused-i)*sizeof(void*));
286 734a96bd 2008-03-07 rsc l->u.ptr[i] = v;
287 b3994ec5 2003-12-11 devnull l->nused++;
288 b3994ec5 2003-12-11 devnull }
289 b3994ec5 2003-12-11 devnull
290 b3994ec5 2003-12-11 devnull void
291 b3994ec5 2003-12-11 devnull listfree(List *l)
292 b3994ec5 2003-12-11 devnull {
293 b3994ec5 2003-12-11 devnull free(l->u.listptr);
294 b3994ec5 2003-12-11 devnull free(l);
295 b3994ec5 2003-12-11 devnull }
296 b3994ec5 2003-12-11 devnull
297 b3994ec5 2003-12-11 devnull String*
298 b3994ec5 2003-12-11 devnull allocstring(int n)
299 b3994ec5 2003-12-11 devnull {
300 b3994ec5 2003-12-11 devnull String *s;
301 b3994ec5 2003-12-11 devnull
302 b3994ec5 2003-12-11 devnull s = emalloc(sizeof(String));
303 b3994ec5 2003-12-11 devnull s->n = n;
304 b3994ec5 2003-12-11 devnull s->nalloc = n+10;
305 b3994ec5 2003-12-11 devnull s->r = emalloc(s->nalloc*sizeof(Rune));
306 b3994ec5 2003-12-11 devnull s->r[n] = '\0';
307 b3994ec5 2003-12-11 devnull return s;
308 b3994ec5 2003-12-11 devnull }
309 b3994ec5 2003-12-11 devnull
310 b3994ec5 2003-12-11 devnull void
311 b3994ec5 2003-12-11 devnull freestring(String *s)
312 b3994ec5 2003-12-11 devnull {
313 b3994ec5 2003-12-11 devnull free(s->r);
314 b3994ec5 2003-12-11 devnull free(s);
315 b3994ec5 2003-12-11 devnull }
316 b3994ec5 2003-12-11 devnull
317 b3994ec5 2003-12-11 devnull Cmd*
318 b3994ec5 2003-12-11 devnull newcmd(void){
319 b3994ec5 2003-12-11 devnull Cmd *p;
320 b3994ec5 2003-12-11 devnull
321 b3994ec5 2003-12-11 devnull p = emalloc(sizeof(Cmd));
322 734a96bd 2008-03-07 rsc inslist(&cmdlist, cmdlist.nused, p);
323 b3994ec5 2003-12-11 devnull return p;
324 b3994ec5 2003-12-11 devnull }
325 b3994ec5 2003-12-11 devnull
326 b3994ec5 2003-12-11 devnull String*
327 b3994ec5 2003-12-11 devnull newstring(int n)
328 b3994ec5 2003-12-11 devnull {
329 b3994ec5 2003-12-11 devnull String *p;
330 b3994ec5 2003-12-11 devnull
331 b3994ec5 2003-12-11 devnull p = allocstring(n);
332 734a96bd 2008-03-07 rsc inslist(&stringlist, stringlist.nused, p);
333 b3994ec5 2003-12-11 devnull return p;
334 b3994ec5 2003-12-11 devnull }
335 b3994ec5 2003-12-11 devnull
336 b3994ec5 2003-12-11 devnull Addr*
337 b3994ec5 2003-12-11 devnull newaddr(void)
338 b3994ec5 2003-12-11 devnull {
339 b3994ec5 2003-12-11 devnull Addr *p;
340 b3994ec5 2003-12-11 devnull
341 b3994ec5 2003-12-11 devnull p = emalloc(sizeof(Addr));
342 734a96bd 2008-03-07 rsc inslist(&addrlist, addrlist.nused, p);
343 b3994ec5 2003-12-11 devnull return p;
344 b3994ec5 2003-12-11 devnull }
345 b3994ec5 2003-12-11 devnull
346 b3994ec5 2003-12-11 devnull void
347 b3994ec5 2003-12-11 devnull freecmd(void)
348 b3994ec5 2003-12-11 devnull {
349 b3994ec5 2003-12-11 devnull int i;
350 b3994ec5 2003-12-11 devnull
351 b3994ec5 2003-12-11 devnull while(cmdlist.nused > 0)
352 b3994ec5 2003-12-11 devnull free(cmdlist.u.ucharptr[--cmdlist.nused]);
353 b3994ec5 2003-12-11 devnull while(addrlist.nused > 0)
354 b3994ec5 2003-12-11 devnull free(addrlist.u.ucharptr[--addrlist.nused]);
355 b3994ec5 2003-12-11 devnull while(stringlist.nused>0){
356 b3994ec5 2003-12-11 devnull i = --stringlist.nused;
357 b3994ec5 2003-12-11 devnull freestring(stringlist.u.stringptr[i]);
358 b3994ec5 2003-12-11 devnull }
359 b3994ec5 2003-12-11 devnull }
360 b3994ec5 2003-12-11 devnull
361 b3994ec5 2003-12-11 devnull void
362 b3994ec5 2003-12-11 devnull okdelim(int c)
363 b3994ec5 2003-12-11 devnull {
364 b3994ec5 2003-12-11 devnull if(c=='\\' || ('a'<=c && c<='z')
365 b3994ec5 2003-12-11 devnull || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
366 b3994ec5 2003-12-11 devnull editerror("bad delimiter %c\n", c);
367 b3994ec5 2003-12-11 devnull }
368 b3994ec5 2003-12-11 devnull
369 b3994ec5 2003-12-11 devnull void
370 b3994ec5 2003-12-11 devnull atnl(void)
371 b3994ec5 2003-12-11 devnull {
372 b3994ec5 2003-12-11 devnull int c;
373 b3994ec5 2003-12-11 devnull
374 b3994ec5 2003-12-11 devnull cmdskipbl();
375 b3994ec5 2003-12-11 devnull c = getch();
376 b3994ec5 2003-12-11 devnull if(c != '\n')
377 b3994ec5 2003-12-11 devnull editerror("newline expected (saw %C)", c);
378 b3994ec5 2003-12-11 devnull }
379 b3994ec5 2003-12-11 devnull
380 b3994ec5 2003-12-11 devnull void
381 b3994ec5 2003-12-11 devnull Straddc(String *s, int c)
382 b3994ec5 2003-12-11 devnull {
383 b3994ec5 2003-12-11 devnull if(s->n+1 >= s->nalloc){
384 b3994ec5 2003-12-11 devnull s->nalloc += 10;
385 b3994ec5 2003-12-11 devnull s->r = erealloc(s->r, s->nalloc*sizeof(Rune));
386 b3994ec5 2003-12-11 devnull }
387 b3994ec5 2003-12-11 devnull s->r[s->n++] = c;
388 b3994ec5 2003-12-11 devnull s->r[s->n] = '\0';
389 b3994ec5 2003-12-11 devnull }
390 b3994ec5 2003-12-11 devnull
391 b3994ec5 2003-12-11 devnull void
392 b3994ec5 2003-12-11 devnull getrhs(String *s, int delim, int cmd)
393 b3994ec5 2003-12-11 devnull {
394 b3994ec5 2003-12-11 devnull int c;
395 b3994ec5 2003-12-11 devnull
396 b3994ec5 2003-12-11 devnull while((c = getch())>0 && c!=delim && c!='\n'){
397 b3994ec5 2003-12-11 devnull if(c == '\\'){
398 b3994ec5 2003-12-11 devnull if((c=getch()) <= 0)
399 b3994ec5 2003-12-11 devnull error("bad right hand side");
400 b3994ec5 2003-12-11 devnull if(c == '\n'){
401 b3994ec5 2003-12-11 devnull ungetch();
402 b3994ec5 2003-12-11 devnull c='\\';
403 b3994ec5 2003-12-11 devnull }else if(c == 'n')
404 b3994ec5 2003-12-11 devnull c='\n';
405 b3994ec5 2003-12-11 devnull else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */
406 b3994ec5 2003-12-11 devnull Straddc(s, '\\');
407 b3994ec5 2003-12-11 devnull }
408 b3994ec5 2003-12-11 devnull Straddc(s, c);
409 b3994ec5 2003-12-11 devnull }
410 b3994ec5 2003-12-11 devnull ungetch(); /* let client read whether delimiter, '\n' or whatever */
411 b3994ec5 2003-12-11 devnull }
412 b3994ec5 2003-12-11 devnull
413 b3994ec5 2003-12-11 devnull String *
414 b3994ec5 2003-12-11 devnull collecttoken(char *end)
415 b3994ec5 2003-12-11 devnull {
416 b3994ec5 2003-12-11 devnull String *s = newstring(0);
417 b3994ec5 2003-12-11 devnull int c;
418 b3994ec5 2003-12-11 devnull
419 b3994ec5 2003-12-11 devnull while((c=nextc())==' ' || c=='\t')
420 b3994ec5 2003-12-11 devnull Straddc(s, getch()); /* blanks significant for getname() */
421 b3994ec5 2003-12-11 devnull while((c=getch())>0 && utfrune(end, c)==0)
422 b3994ec5 2003-12-11 devnull Straddc(s, c);
423 b3994ec5 2003-12-11 devnull if(c != '\n')
424 b3994ec5 2003-12-11 devnull atnl();
425 b3994ec5 2003-12-11 devnull return s;
426 b3994ec5 2003-12-11 devnull }
427 b3994ec5 2003-12-11 devnull
428 b3994ec5 2003-12-11 devnull String *
429 b3994ec5 2003-12-11 devnull collecttext(void)
430 b3994ec5 2003-12-11 devnull {
431 b3994ec5 2003-12-11 devnull String *s;
432 b3994ec5 2003-12-11 devnull int begline, i, c, delim;
433 b3994ec5 2003-12-11 devnull
434 b3994ec5 2003-12-11 devnull s = newstring(0);
435 b3994ec5 2003-12-11 devnull if(cmdskipbl()=='\n'){
436 b3994ec5 2003-12-11 devnull getch();
437 b3994ec5 2003-12-11 devnull i = 0;
438 b3994ec5 2003-12-11 devnull do{
439 b3994ec5 2003-12-11 devnull begline = i;
440 b3994ec5 2003-12-11 devnull while((c = getch())>0 && c!='\n')
441 b3994ec5 2003-12-11 devnull i++, Straddc(s, c);
442 b3994ec5 2003-12-11 devnull i++, Straddc(s, '\n');
443 b3994ec5 2003-12-11 devnull if(c < 0)
444 b3994ec5 2003-12-11 devnull goto Return;
445 b3994ec5 2003-12-11 devnull }while(s->r[begline]!='.' || s->r[begline+1]!='\n');
446 b3994ec5 2003-12-11 devnull s->r[s->n-2] = '\0';
447 6d7fdb24 2004-12-27 devnull s->n -= 2;
448 b3994ec5 2003-12-11 devnull }else{
449 b3994ec5 2003-12-11 devnull okdelim(delim = getch());
450 b3994ec5 2003-12-11 devnull getrhs(s, delim, 'a');
451 b3994ec5 2003-12-11 devnull if(nextc()==delim)
452 b3994ec5 2003-12-11 devnull getch();
453 b3994ec5 2003-12-11 devnull atnl();
454 b3994ec5 2003-12-11 devnull }
455 b3994ec5 2003-12-11 devnull Return:
456 b3994ec5 2003-12-11 devnull return s;
457 b3994ec5 2003-12-11 devnull }
458 b3994ec5 2003-12-11 devnull
459 b3994ec5 2003-12-11 devnull int
460 b3994ec5 2003-12-11 devnull cmdlookup(int c)
461 b3994ec5 2003-12-11 devnull {
462 b3994ec5 2003-12-11 devnull int i;
463 b3994ec5 2003-12-11 devnull
464 b3994ec5 2003-12-11 devnull for(i=0; cmdtab[i].cmdc; i++)
465 b3994ec5 2003-12-11 devnull if(cmdtab[i].cmdc == c)
466 b3994ec5 2003-12-11 devnull return i;
467 b3994ec5 2003-12-11 devnull return -1;
468 b3994ec5 2003-12-11 devnull }
469 b3994ec5 2003-12-11 devnull
470 b3994ec5 2003-12-11 devnull Cmd*
471 b3994ec5 2003-12-11 devnull parsecmd(int nest)
472 b3994ec5 2003-12-11 devnull {
473 b3994ec5 2003-12-11 devnull int i, c;
474 b3994ec5 2003-12-11 devnull struct cmdtab *ct;
475 b3994ec5 2003-12-11 devnull Cmd *cp, *ncp;
476 b3994ec5 2003-12-11 devnull Cmd cmd;
477 b3994ec5 2003-12-11 devnull
478 b3994ec5 2003-12-11 devnull cmd.next = cmd.u.cmd = 0;
479 b3994ec5 2003-12-11 devnull cmd.re = 0;
480 b3994ec5 2003-12-11 devnull cmd.flag = cmd.num = 0;
481 b3994ec5 2003-12-11 devnull cmd.addr = compoundaddr();
482 b3994ec5 2003-12-11 devnull if(cmdskipbl() == -1)
483 b3994ec5 2003-12-11 devnull return 0;
484 b3994ec5 2003-12-11 devnull if((c=getch())==-1)
485 b3994ec5 2003-12-11 devnull return 0;
486 b3994ec5 2003-12-11 devnull cmd.cmdc = c;
487 b3994ec5 2003-12-11 devnull if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */
488 b3994ec5 2003-12-11 devnull getch(); /* the 'd' */
489 b3994ec5 2003-12-11 devnull cmd.cmdc='c'|0x100;
490 b3994ec5 2003-12-11 devnull }
491 b3994ec5 2003-12-11 devnull i = cmdlookup(cmd.cmdc);
492 b3994ec5 2003-12-11 devnull if(i >= 0){
493 b3994ec5 2003-12-11 devnull if(cmd.cmdc == '\n')
494 b3994ec5 2003-12-11 devnull goto Return; /* let nl_cmd work it all out */
495 b3994ec5 2003-12-11 devnull ct = &cmdtab[i];
496 b3994ec5 2003-12-11 devnull if(ct->defaddr==aNo && cmd.addr)
497 b3994ec5 2003-12-11 devnull editerror("command takes no address");
498 b3994ec5 2003-12-11 devnull if(ct->count)
499 b3994ec5 2003-12-11 devnull cmd.num = getnum(ct->count);
500 b3994ec5 2003-12-11 devnull if(ct->regexp){
501 b3994ec5 2003-12-11 devnull /* x without pattern -> .*\n, indicated by cmd.re==0 */
502 b3994ec5 2003-12-11 devnull /* X without pattern is all files */
503 b3994ec5 2003-12-11 devnull if((ct->cmdc!='x' && ct->cmdc!='X') ||
504 b3994ec5 2003-12-11 devnull ((c = nextc())!=' ' && c!='\t' && c!='\n')){
505 b3994ec5 2003-12-11 devnull cmdskipbl();
506 b3994ec5 2003-12-11 devnull if((c = getch())=='\n' || c<0)
507 b3994ec5 2003-12-11 devnull editerror("no address");
508 b3994ec5 2003-12-11 devnull okdelim(c);
509 b3994ec5 2003-12-11 devnull cmd.re = getregexp(c);
510 b3994ec5 2003-12-11 devnull if(ct->cmdc == 's'){
511 b3994ec5 2003-12-11 devnull cmd.u.text = newstring(0);
512 b3994ec5 2003-12-11 devnull getrhs(cmd.u.text, c, 's');
513 b3994ec5 2003-12-11 devnull if(nextc() == c){
514 b3994ec5 2003-12-11 devnull getch();
515 b3994ec5 2003-12-11 devnull if(nextc() == 'g')
516 b3994ec5 2003-12-11 devnull cmd.flag = getch();
517 b3994ec5 2003-12-11 devnull }
518 fa325e9b 2020-01-10 cross
519 b3994ec5 2003-12-11 devnull }
520 b3994ec5 2003-12-11 devnull }
521 b3994ec5 2003-12-11 devnull }
522 b3994ec5 2003-12-11 devnull if(ct->addr && (cmd.u.mtaddr=simpleaddr())==0)
523 b3994ec5 2003-12-11 devnull editerror("bad address");
524 b3994ec5 2003-12-11 devnull if(ct->defcmd){
525 b3994ec5 2003-12-11 devnull if(cmdskipbl() == '\n'){
526 b3994ec5 2003-12-11 devnull getch();
527 b3994ec5 2003-12-11 devnull cmd.u.cmd = newcmd();
528 b3994ec5 2003-12-11 devnull cmd.u.cmd->cmdc = ct->defcmd;
529 b3994ec5 2003-12-11 devnull }else if((cmd.u.cmd = parsecmd(nest))==0)
530 b3994ec5 2003-12-11 devnull error("defcmd");
531 b3994ec5 2003-12-11 devnull }else if(ct->text)
532 b3994ec5 2003-12-11 devnull cmd.u.text = collecttext();
533 b3994ec5 2003-12-11 devnull else if(ct->token)
534 b3994ec5 2003-12-11 devnull cmd.u.text = collecttoken(ct->token);
535 b3994ec5 2003-12-11 devnull else
536 b3994ec5 2003-12-11 devnull atnl();
537 b3994ec5 2003-12-11 devnull }else
538 b3994ec5 2003-12-11 devnull switch(cmd.cmdc){
539 b3994ec5 2003-12-11 devnull case '{':
540 b3994ec5 2003-12-11 devnull cp = 0;
541 b3994ec5 2003-12-11 devnull do{
542 b3994ec5 2003-12-11 devnull if(cmdskipbl()=='\n')
543 b3994ec5 2003-12-11 devnull getch();
544 b3994ec5 2003-12-11 devnull ncp = parsecmd(nest+1);
545 b3994ec5 2003-12-11 devnull if(cp)
546 b3994ec5 2003-12-11 devnull cp->next = ncp;
547 b3994ec5 2003-12-11 devnull else
548 b3994ec5 2003-12-11 devnull cmd.u.cmd = ncp;
549 b3994ec5 2003-12-11 devnull }while(cp = ncp);
550 b3994ec5 2003-12-11 devnull break;
551 b3994ec5 2003-12-11 devnull case '}':
552 b3994ec5 2003-12-11 devnull atnl();
553 b3994ec5 2003-12-11 devnull if(nest==0)
554 b3994ec5 2003-12-11 devnull editerror("right brace with no left brace");
555 b3994ec5 2003-12-11 devnull return 0;
556 b3994ec5 2003-12-11 devnull default:
557 b3994ec5 2003-12-11 devnull editerror("unknown command %c", cmd.cmdc);
558 b3994ec5 2003-12-11 devnull }
559 b3994ec5 2003-12-11 devnull Return:
560 b3994ec5 2003-12-11 devnull cp = newcmd();
561 b3994ec5 2003-12-11 devnull *cp = cmd;
562 b3994ec5 2003-12-11 devnull return cp;
563 b3994ec5 2003-12-11 devnull }
564 b3994ec5 2003-12-11 devnull
565 b3994ec5 2003-12-11 devnull String*
566 b3994ec5 2003-12-11 devnull getregexp(int delim)
567 b3994ec5 2003-12-11 devnull {
568 b3994ec5 2003-12-11 devnull String *buf, *r;
569 b3994ec5 2003-12-11 devnull int i, c;
570 b3994ec5 2003-12-11 devnull
571 b3994ec5 2003-12-11 devnull buf = allocstring(0);
572 b3994ec5 2003-12-11 devnull for(i=0; ; i++){
573 b3994ec5 2003-12-11 devnull if((c = getch())=='\\'){
574 b3994ec5 2003-12-11 devnull if(nextc()==delim)
575 b3994ec5 2003-12-11 devnull c = getch();
576 b3994ec5 2003-12-11 devnull else if(nextc()=='\\'){
577 b3994ec5 2003-12-11 devnull Straddc(buf, c);
578 b3994ec5 2003-12-11 devnull c = getch();
579 b3994ec5 2003-12-11 devnull }
580 b3994ec5 2003-12-11 devnull }else if(c==delim || c=='\n')
581 b3994ec5 2003-12-11 devnull break;
582 b3994ec5 2003-12-11 devnull if(i >= RBUFSIZE)
583 b3994ec5 2003-12-11 devnull editerror("regular expression too long");
584 b3994ec5 2003-12-11 devnull Straddc(buf, c);
585 b3994ec5 2003-12-11 devnull }
586 b3994ec5 2003-12-11 devnull if(c!=delim && c)
587 b3994ec5 2003-12-11 devnull ungetch();
588 b3994ec5 2003-12-11 devnull if(buf->n > 0){
589 b3994ec5 2003-12-11 devnull patset = TRUE;
590 b3994ec5 2003-12-11 devnull freestring(lastpat);
591 b3994ec5 2003-12-11 devnull lastpat = buf;
592 b3994ec5 2003-12-11 devnull }else
593 b3994ec5 2003-12-11 devnull freestring(buf);
594 b3994ec5 2003-12-11 devnull if(lastpat->n == 0)
595 b3994ec5 2003-12-11 devnull editerror("no regular expression defined");
596 b3994ec5 2003-12-11 devnull r = newstring(lastpat->n);
597 b3994ec5 2003-12-11 devnull runemove(r->r, lastpat->r, lastpat->n); /* newstring put \0 at end */
598 b3994ec5 2003-12-11 devnull return r;
599 b3994ec5 2003-12-11 devnull }
600 b3994ec5 2003-12-11 devnull
601 b3994ec5 2003-12-11 devnull Addr *
602 b3994ec5 2003-12-11 devnull simpleaddr(void)
603 b3994ec5 2003-12-11 devnull {
604 b3994ec5 2003-12-11 devnull Addr addr;
605 b3994ec5 2003-12-11 devnull Addr *ap, *nap;
606 b3994ec5 2003-12-11 devnull
607 a8ec4910 2005-07-13 devnull addr.num = 0;
608 b3994ec5 2003-12-11 devnull addr.next = 0;
609 b3994ec5 2003-12-11 devnull addr.u.left = 0;
610 b3994ec5 2003-12-11 devnull switch(cmdskipbl()){
611 b3994ec5 2003-12-11 devnull case '#':
612 b3994ec5 2003-12-11 devnull addr.type = getch();
613 b3994ec5 2003-12-11 devnull addr.num = getnum(1);
614 b3994ec5 2003-12-11 devnull break;
615 b3994ec5 2003-12-11 devnull case '0': case '1': case '2': case '3': case '4':
616 fa325e9b 2020-01-10 cross case '5': case '6': case '7': case '8': case '9':
617 b3994ec5 2003-12-11 devnull addr.num = getnum(1);
618 b3994ec5 2003-12-11 devnull addr.type='l';
619 b3994ec5 2003-12-11 devnull break;
620 b3994ec5 2003-12-11 devnull case '/': case '?': case '"':
621 b3994ec5 2003-12-11 devnull addr.u.re = getregexp(addr.type = getch());
622 b3994ec5 2003-12-11 devnull break;
623 b3994ec5 2003-12-11 devnull case '.':
624 b3994ec5 2003-12-11 devnull case '$':
625 b3994ec5 2003-12-11 devnull case '+':
626 b3994ec5 2003-12-11 devnull case '-':
627 b3994ec5 2003-12-11 devnull case '\'':
628 b3994ec5 2003-12-11 devnull addr.type = getch();
629 b3994ec5 2003-12-11 devnull break;
630 b3994ec5 2003-12-11 devnull default:
631 b3994ec5 2003-12-11 devnull return 0;
632 b3994ec5 2003-12-11 devnull }
633 b3994ec5 2003-12-11 devnull if(addr.next = simpleaddr())
634 b3994ec5 2003-12-11 devnull switch(addr.next->type){
635 b3994ec5 2003-12-11 devnull case '.':
636 b3994ec5 2003-12-11 devnull case '$':
637 b3994ec5 2003-12-11 devnull case '\'':
638 1c845e0b 2021-01-06 rsc if(addr.type=='"')
639 1c845e0b 2021-01-06 rsc break;
640 1c845e0b 2021-01-06 rsc /* fall through */
641 b3994ec5 2003-12-11 devnull case '"':
642 1c845e0b 2021-01-06 rsc editerror("bad address syntax");
643 b3994ec5 2003-12-11 devnull break;
644 b3994ec5 2003-12-11 devnull case 'l':
645 b3994ec5 2003-12-11 devnull case '#':
646 b3994ec5 2003-12-11 devnull if(addr.type=='"')
647 b3994ec5 2003-12-11 devnull break;
648 b3994ec5 2003-12-11 devnull /* fall through */
649 b3994ec5 2003-12-11 devnull case '/':
650 b3994ec5 2003-12-11 devnull case '?':
651 b3994ec5 2003-12-11 devnull if(addr.type!='+' && addr.type!='-'){
652 b3994ec5 2003-12-11 devnull /* insert the missing '+' */
653 b3994ec5 2003-12-11 devnull nap = newaddr();
654 b3994ec5 2003-12-11 devnull nap->type='+';
655 b3994ec5 2003-12-11 devnull nap->next = addr.next;
656 b3994ec5 2003-12-11 devnull addr.next = nap;
657 b3994ec5 2003-12-11 devnull }
658 b3994ec5 2003-12-11 devnull break;
659 b3994ec5 2003-12-11 devnull case '+':
660 b3994ec5 2003-12-11 devnull case '-':
661 b3994ec5 2003-12-11 devnull break;
662 b3994ec5 2003-12-11 devnull default:
663 b3994ec5 2003-12-11 devnull error("simpleaddr");
664 b3994ec5 2003-12-11 devnull }
665 b3994ec5 2003-12-11 devnull ap = newaddr();
666 b3994ec5 2003-12-11 devnull *ap = addr;
667 b3994ec5 2003-12-11 devnull return ap;
668 b3994ec5 2003-12-11 devnull }
669 b3994ec5 2003-12-11 devnull
670 b3994ec5 2003-12-11 devnull Addr *
671 b3994ec5 2003-12-11 devnull compoundaddr(void)
672 b3994ec5 2003-12-11 devnull {
673 b3994ec5 2003-12-11 devnull Addr addr;
674 b3994ec5 2003-12-11 devnull Addr *ap, *next;
675 b3994ec5 2003-12-11 devnull
676 b3994ec5 2003-12-11 devnull addr.u.left = simpleaddr();
677 b3994ec5 2003-12-11 devnull if((addr.type = cmdskipbl())!=',' && addr.type!=';')
678 b3994ec5 2003-12-11 devnull return addr.u.left;
679 b3994ec5 2003-12-11 devnull getch();
680 b3994ec5 2003-12-11 devnull next = addr.next = compoundaddr();
681 b3994ec5 2003-12-11 devnull if(next && (next->type==',' || next->type==';') && next->u.left==0)
682 b3994ec5 2003-12-11 devnull editerror("bad address syntax");
683 b3994ec5 2003-12-11 devnull ap = newaddr();
684 b3994ec5 2003-12-11 devnull *ap = addr;
685 b3994ec5 2003-12-11 devnull return ap;
686 b3994ec5 2003-12-11 devnull }