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