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 b3994ec5 2003-12-11 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 // ocurfile = curfile;
86 b3994ec5 2003-12-11 devnull // loaded = curfile && !curfile->unread;
87 b3994ec5 2003-12-11 devnull if(cmdexec(curtext, cmdp) == 0)
88 b3994ec5 2003-12-11 devnull break;
89 b3994ec5 2003-12-11 devnull freecmd();
90 b3994ec5 2003-12-11 devnull }
91 b3994ec5 2003-12-11 devnull sendp(editerrc, nil);
92 b3994ec5 2003-12-11 devnull }
93 b3994ec5 2003-12-11 devnull
94 b3994ec5 2003-12-11 devnull void
95 b3994ec5 2003-12-11 devnull allelogterm(Window *w, void *x)
96 b3994ec5 2003-12-11 devnull {
97 b3994ec5 2003-12-11 devnull USED(x);
98 b3994ec5 2003-12-11 devnull elogterm(w->body.file);
99 b3994ec5 2003-12-11 devnull }
100 b3994ec5 2003-12-11 devnull
101 b3994ec5 2003-12-11 devnull void
102 b3994ec5 2003-12-11 devnull alleditinit(Window *w, void *x)
103 b3994ec5 2003-12-11 devnull {
104 b3994ec5 2003-12-11 devnull USED(x);
105 b3994ec5 2003-12-11 devnull textcommit(&w->tag, TRUE);
106 b3994ec5 2003-12-11 devnull textcommit(&w->body, TRUE);
107 b3994ec5 2003-12-11 devnull w->body.file->editclean = FALSE;
108 b3994ec5 2003-12-11 devnull }
109 b3994ec5 2003-12-11 devnull
110 b3994ec5 2003-12-11 devnull void
111 b3994ec5 2003-12-11 devnull allupdate(Window *w, void *x)
112 b3994ec5 2003-12-11 devnull {
113 b3994ec5 2003-12-11 devnull Text *t;
114 b3994ec5 2003-12-11 devnull int i;
115 b3994ec5 2003-12-11 devnull File *f;
116 b3994ec5 2003-12-11 devnull
117 b3994ec5 2003-12-11 devnull USED(x);
118 b3994ec5 2003-12-11 devnull t = &w->body;
119 b3994ec5 2003-12-11 devnull f = t->file;
120 b3994ec5 2003-12-11 devnull if(f->curtext != t) /* do curtext only */
121 b3994ec5 2003-12-11 devnull return;
122 b3994ec5 2003-12-11 devnull if(f->elog.type == Null)
123 b3994ec5 2003-12-11 devnull elogterm(f);
124 b3994ec5 2003-12-11 devnull else if(f->elog.type != Empty){
125 b3994ec5 2003-12-11 devnull elogapply(f);
126 b3994ec5 2003-12-11 devnull if(f->editclean){
127 b3994ec5 2003-12-11 devnull f->mod = FALSE;
128 b3994ec5 2003-12-11 devnull for(i=0; i<f->ntext; i++)
129 b3994ec5 2003-12-11 devnull f->text[i]->w->dirty = FALSE;
130 b3994ec5 2003-12-11 devnull }
131 b3994ec5 2003-12-11 devnull }
132 b3994ec5 2003-12-11 devnull textsetselect(t, t->q0, t->q1);
133 b3994ec5 2003-12-11 devnull textscrdraw(t);
134 b3994ec5 2003-12-11 devnull winsettag(w);
135 b3994ec5 2003-12-11 devnull }
136 b3994ec5 2003-12-11 devnull
137 b3994ec5 2003-12-11 devnull void
138 b3994ec5 2003-12-11 devnull editerror(char *fmt, ...)
139 b3994ec5 2003-12-11 devnull {
140 b3994ec5 2003-12-11 devnull va_list arg;
141 b3994ec5 2003-12-11 devnull char *s;
142 b3994ec5 2003-12-11 devnull
143 b3994ec5 2003-12-11 devnull va_start(arg, fmt);
144 b3994ec5 2003-12-11 devnull s = vsmprint(fmt, arg);
145 b3994ec5 2003-12-11 devnull va_end(arg);
146 b3994ec5 2003-12-11 devnull freecmd();
147 b3994ec5 2003-12-11 devnull allwindows(allelogterm, nil); /* truncate the edit logs */
148 b3994ec5 2003-12-11 devnull sendp(editerrc, s);
149 b3994ec5 2003-12-11 devnull threadexits(nil);
150 b3994ec5 2003-12-11 devnull }
151 b3994ec5 2003-12-11 devnull
152 b3994ec5 2003-12-11 devnull void
153 b3994ec5 2003-12-11 devnull editcmd(Text *ct, Rune *r, uint n)
154 b3994ec5 2003-12-11 devnull {
155 b3994ec5 2003-12-11 devnull char *err;
156 b3994ec5 2003-12-11 devnull
157 b3994ec5 2003-12-11 devnull if(n == 0)
158 b3994ec5 2003-12-11 devnull return;
159 b3994ec5 2003-12-11 devnull if(2*n > RBUFSIZE){
160 b3994ec5 2003-12-11 devnull warning(nil, "string too long\n");
161 b3994ec5 2003-12-11 devnull return;
162 b3994ec5 2003-12-11 devnull }
163 b3994ec5 2003-12-11 devnull
164 b3994ec5 2003-12-11 devnull allwindows(alleditinit, nil);
165 b3994ec5 2003-12-11 devnull if(cmdstartp)
166 b3994ec5 2003-12-11 devnull free(cmdstartp);
167 b3994ec5 2003-12-11 devnull cmdstartp = runemalloc(n+2);
168 b3994ec5 2003-12-11 devnull runemove(cmdstartp, r, n);
169 b3994ec5 2003-12-11 devnull if(r[n] != '\n')
170 b3994ec5 2003-12-11 devnull cmdstartp[n++] = '\n';
171 b3994ec5 2003-12-11 devnull cmdstartp[n] = '\0';
172 b3994ec5 2003-12-11 devnull cmdendp = cmdstartp+n;
173 b3994ec5 2003-12-11 devnull cmdp = cmdstartp;
174 b3994ec5 2003-12-11 devnull if(ct->w == nil)
175 b3994ec5 2003-12-11 devnull curtext = nil;
176 b3994ec5 2003-12-11 devnull else
177 b3994ec5 2003-12-11 devnull curtext = &ct->w->body;
178 b3994ec5 2003-12-11 devnull resetxec();
179 b3994ec5 2003-12-11 devnull if(editerrc == nil){
180 b3994ec5 2003-12-11 devnull editerrc = chancreate(sizeof(char*), 0);
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 b3994ec5 2003-12-11 devnull 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 b3994ec5 2003-12-11 devnull 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 b3994ec5 2003-12-11 devnull l->u.listptr = emalloc(INCR*sizeof(long));
260 b3994ec5 2003-12-11 devnull l->nused = 0;
261 b3994ec5 2003-12-11 devnull }else if(l->nused == l->nalloc){
262 b3994ec5 2003-12-11 devnull l->u.listptr = erealloc(l->u.listptr, (l->nalloc+INCR)*sizeof(long));
263 b3994ec5 2003-12-11 devnull memset((void*)(l->u.longptr+l->nalloc), 0, INCR*sizeof(long));
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 b3994ec5 2003-12-11 devnull memmove(&l->u.longptr[i], &l->u.longptr[i+1], (l->nused-(i+1))*sizeof(long));
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 b3994ec5 2003-12-11 devnull inslist(List *l, int i, long val)
283 b3994ec5 2003-12-11 devnull {
284 b3994ec5 2003-12-11 devnull growlist(l);
285 b3994ec5 2003-12-11 devnull memmove(&l->u.longptr[i+1], &l->u.longptr[i], (l->nused-i)*sizeof(long));
286 b3994ec5 2003-12-11 devnull l->u.longptr[i] = val;
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 b3994ec5 2003-12-11 devnull inslist(&cmdlist, cmdlist.nused, (long)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 b3994ec5 2003-12-11 devnull inslist(&stringlist, stringlist.nused, (long)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 b3994ec5 2003-12-11 devnull inslist(&addrlist, addrlist.nused, (long)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 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 b3994ec5 2003-12-11 devnull addr.next = 0;
607 b3994ec5 2003-12-11 devnull addr.u.left = 0;
608 b3994ec5 2003-12-11 devnull switch(cmdskipbl()){
609 b3994ec5 2003-12-11 devnull case '#':
610 b3994ec5 2003-12-11 devnull addr.type = getch();
611 b3994ec5 2003-12-11 devnull addr.num = getnum(1);
612 b3994ec5 2003-12-11 devnull break;
613 b3994ec5 2003-12-11 devnull case '0': case '1': case '2': case '3': case '4':
614 b3994ec5 2003-12-11 devnull case '5': case '6': case '7': case '8': case '9':
615 b3994ec5 2003-12-11 devnull addr.num = getnum(1);
616 b3994ec5 2003-12-11 devnull addr.type='l';
617 b3994ec5 2003-12-11 devnull break;
618 b3994ec5 2003-12-11 devnull case '/': case '?': case '"':
619 b3994ec5 2003-12-11 devnull addr.u.re = getregexp(addr.type = getch());
620 b3994ec5 2003-12-11 devnull break;
621 b3994ec5 2003-12-11 devnull case '.':
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 addr.type = getch();
627 b3994ec5 2003-12-11 devnull break;
628 b3994ec5 2003-12-11 devnull default:
629 b3994ec5 2003-12-11 devnull return 0;
630 b3994ec5 2003-12-11 devnull }
631 b3994ec5 2003-12-11 devnull if(addr.next = simpleaddr())
632 b3994ec5 2003-12-11 devnull switch(addr.next->type){
633 b3994ec5 2003-12-11 devnull case '.':
634 b3994ec5 2003-12-11 devnull case '$':
635 b3994ec5 2003-12-11 devnull case '\'':
636 b3994ec5 2003-12-11 devnull if(addr.type!='"')
637 b3994ec5 2003-12-11 devnull case '"':
638 b3994ec5 2003-12-11 devnull editerror("bad address syntax");
639 b3994ec5 2003-12-11 devnull break;
640 b3994ec5 2003-12-11 devnull case 'l':
641 b3994ec5 2003-12-11 devnull case '#':
642 b3994ec5 2003-12-11 devnull if(addr.type=='"')
643 b3994ec5 2003-12-11 devnull break;
644 b3994ec5 2003-12-11 devnull /* fall through */
645 b3994ec5 2003-12-11 devnull case '/':
646 b3994ec5 2003-12-11 devnull case '?':
647 b3994ec5 2003-12-11 devnull if(addr.type!='+' && addr.type!='-'){
648 b3994ec5 2003-12-11 devnull /* insert the missing '+' */
649 b3994ec5 2003-12-11 devnull nap = newaddr();
650 b3994ec5 2003-12-11 devnull nap->type='+';
651 b3994ec5 2003-12-11 devnull nap->next = addr.next;
652 b3994ec5 2003-12-11 devnull addr.next = nap;
653 b3994ec5 2003-12-11 devnull }
654 b3994ec5 2003-12-11 devnull break;
655 b3994ec5 2003-12-11 devnull case '+':
656 b3994ec5 2003-12-11 devnull case '-':
657 b3994ec5 2003-12-11 devnull break;
658 b3994ec5 2003-12-11 devnull default:
659 b3994ec5 2003-12-11 devnull error("simpleaddr");
660 b3994ec5 2003-12-11 devnull }
661 b3994ec5 2003-12-11 devnull ap = newaddr();
662 b3994ec5 2003-12-11 devnull *ap = addr;
663 b3994ec5 2003-12-11 devnull return ap;
664 b3994ec5 2003-12-11 devnull }
665 b3994ec5 2003-12-11 devnull
666 b3994ec5 2003-12-11 devnull Addr *
667 b3994ec5 2003-12-11 devnull compoundaddr(void)
668 b3994ec5 2003-12-11 devnull {
669 b3994ec5 2003-12-11 devnull Addr addr;
670 b3994ec5 2003-12-11 devnull Addr *ap, *next;
671 b3994ec5 2003-12-11 devnull
672 b3994ec5 2003-12-11 devnull addr.u.left = simpleaddr();
673 b3994ec5 2003-12-11 devnull if((addr.type = cmdskipbl())!=',' && addr.type!=';')
674 b3994ec5 2003-12-11 devnull return addr.u.left;
675 b3994ec5 2003-12-11 devnull getch();
676 b3994ec5 2003-12-11 devnull next = addr.next = compoundaddr();
677 b3994ec5 2003-12-11 devnull if(next && (next->type==',' || next->type==';') && next->u.left==0)
678 b3994ec5 2003-12-11 devnull editerror("bad address syntax");
679 b3994ec5 2003-12-11 devnull ap = newaddr();
680 b3994ec5 2003-12-11 devnull *ap = addr;
681 b3994ec5 2003-12-11 devnull return ap;
682 b3994ec5 2003-12-11 devnull }