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 cbeb0b26 2006-04-01 devnull /* ocurfile = curfile; */
86 cbeb0b26 2006-04-01 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 334cb1e9 2004-12-27 devnull chansetname(editerrc, "editerrc");
182 b3994ec5 2003-12-11 devnull lastpat = allocstring(0);
183 b3994ec5 2003-12-11 devnull }
184 b3994ec5 2003-12-11 devnull threadcreate(editthread, nil, STACK);
185 b3994ec5 2003-12-11 devnull err = recvp(editerrc);
186 b3994ec5 2003-12-11 devnull editing = Inactive;
187 b3994ec5 2003-12-11 devnull if(err != nil){
188 b3994ec5 2003-12-11 devnull if(err[0] != '\0')
189 b3994ec5 2003-12-11 devnull warning(nil, "Edit: %s\n", err);
190 b3994ec5 2003-12-11 devnull free(err);
191 b3994ec5 2003-12-11 devnull }
192 b3994ec5 2003-12-11 devnull
193 b3994ec5 2003-12-11 devnull /* update everyone whose edit log has data */
194 b3994ec5 2003-12-11 devnull allwindows(allupdate, nil);
195 b3994ec5 2003-12-11 devnull }
196 b3994ec5 2003-12-11 devnull
197 b3994ec5 2003-12-11 devnull int
198 b3994ec5 2003-12-11 devnull getch(void)
199 b3994ec5 2003-12-11 devnull {
200 b3994ec5 2003-12-11 devnull if(*cmdp == *cmdendp)
201 b3994ec5 2003-12-11 devnull return -1;
202 b3994ec5 2003-12-11 devnull return *cmdp++;
203 b3994ec5 2003-12-11 devnull }
204 b3994ec5 2003-12-11 devnull
205 b3994ec5 2003-12-11 devnull int
206 b3994ec5 2003-12-11 devnull nextc(void)
207 b3994ec5 2003-12-11 devnull {
208 b3994ec5 2003-12-11 devnull if(*cmdp == *cmdendp)
209 b3994ec5 2003-12-11 devnull return -1;
210 b3994ec5 2003-12-11 devnull return *cmdp;
211 b3994ec5 2003-12-11 devnull }
212 b3994ec5 2003-12-11 devnull
213 b3994ec5 2003-12-11 devnull void
214 b3994ec5 2003-12-11 devnull ungetch(void)
215 b3994ec5 2003-12-11 devnull {
216 b3994ec5 2003-12-11 devnull if(--cmdp < cmdstartp)
217 b3994ec5 2003-12-11 devnull error("ungetch");
218 b3994ec5 2003-12-11 devnull }
219 b3994ec5 2003-12-11 devnull
220 b3994ec5 2003-12-11 devnull long
221 b3994ec5 2003-12-11 devnull getnum(int signok)
222 b3994ec5 2003-12-11 devnull {
223 b3994ec5 2003-12-11 devnull long n;
224 b3994ec5 2003-12-11 devnull int c, sign;
225 b3994ec5 2003-12-11 devnull
226 b3994ec5 2003-12-11 devnull n = 0;
227 b3994ec5 2003-12-11 devnull sign = 1;
228 b3994ec5 2003-12-11 devnull if(signok>1 && nextc()=='-'){
229 b3994ec5 2003-12-11 devnull sign = -1;
230 b3994ec5 2003-12-11 devnull getch();
231 b3994ec5 2003-12-11 devnull }
232 b3994ec5 2003-12-11 devnull if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */
233 b3994ec5 2003-12-11 devnull return sign;
234 b3994ec5 2003-12-11 devnull while('0'<=(c=getch()) && c<='9')
235 b3994ec5 2003-12-11 devnull n = n*10 + (c-'0');
236 b3994ec5 2003-12-11 devnull ungetch();
237 b3994ec5 2003-12-11 devnull return sign*n;
238 b3994ec5 2003-12-11 devnull }
239 b3994ec5 2003-12-11 devnull
240 b3994ec5 2003-12-11 devnull int
241 b3994ec5 2003-12-11 devnull cmdskipbl(void)
242 b3994ec5 2003-12-11 devnull {
243 b3994ec5 2003-12-11 devnull int c;
244 b3994ec5 2003-12-11 devnull do
245 b3994ec5 2003-12-11 devnull c = getch();
246 b3994ec5 2003-12-11 devnull while(c==' ' || c=='\t');
247 b3994ec5 2003-12-11 devnull if(c >= 0)
248 b3994ec5 2003-12-11 devnull ungetch();
249 b3994ec5 2003-12-11 devnull return c;
250 b3994ec5 2003-12-11 devnull }
251 b3994ec5 2003-12-11 devnull
252 b3994ec5 2003-12-11 devnull /*
253 b3994ec5 2003-12-11 devnull * Check that list has room for one more element.
254 b3994ec5 2003-12-11 devnull */
255 b3994ec5 2003-12-11 devnull void
256 b3994ec5 2003-12-11 devnull growlist(List *l)
257 b3994ec5 2003-12-11 devnull {
258 b3994ec5 2003-12-11 devnull if(l->u.listptr==0 || l->nalloc==0){
259 b3994ec5 2003-12-11 devnull l->nalloc = INCR;
260 b3994ec5 2003-12-11 devnull l->u.listptr = emalloc(INCR*sizeof(long));
261 b3994ec5 2003-12-11 devnull l->nused = 0;
262 b3994ec5 2003-12-11 devnull }else if(l->nused == l->nalloc){
263 b3994ec5 2003-12-11 devnull l->u.listptr = erealloc(l->u.listptr, (l->nalloc+INCR)*sizeof(long));
264 b3994ec5 2003-12-11 devnull memset((void*)(l->u.longptr+l->nalloc), 0, INCR*sizeof(long));
265 b3994ec5 2003-12-11 devnull l->nalloc += INCR;
266 b3994ec5 2003-12-11 devnull }
267 b3994ec5 2003-12-11 devnull }
268 b3994ec5 2003-12-11 devnull
269 b3994ec5 2003-12-11 devnull /*
270 b3994ec5 2003-12-11 devnull * Remove the ith element from the list
271 b3994ec5 2003-12-11 devnull */
272 b3994ec5 2003-12-11 devnull void
273 b3994ec5 2003-12-11 devnull dellist(List *l, int i)
274 b3994ec5 2003-12-11 devnull {
275 b3994ec5 2003-12-11 devnull memmove(&l->u.longptr[i], &l->u.longptr[i+1], (l->nused-(i+1))*sizeof(long));
276 b3994ec5 2003-12-11 devnull l->nused--;
277 b3994ec5 2003-12-11 devnull }
278 b3994ec5 2003-12-11 devnull
279 b3994ec5 2003-12-11 devnull /*
280 b3994ec5 2003-12-11 devnull * Add a new element, whose position is i, to the list
281 b3994ec5 2003-12-11 devnull */
282 b3994ec5 2003-12-11 devnull void
283 b3994ec5 2003-12-11 devnull inslist(List *l, int i, long val)
284 b3994ec5 2003-12-11 devnull {
285 b3994ec5 2003-12-11 devnull growlist(l);
286 b3994ec5 2003-12-11 devnull memmove(&l->u.longptr[i+1], &l->u.longptr[i], (l->nused-i)*sizeof(long));
287 b3994ec5 2003-12-11 devnull l->u.longptr[i] = val;
288 b3994ec5 2003-12-11 devnull l->nused++;
289 b3994ec5 2003-12-11 devnull }
290 b3994ec5 2003-12-11 devnull
291 b3994ec5 2003-12-11 devnull void
292 b3994ec5 2003-12-11 devnull listfree(List *l)
293 b3994ec5 2003-12-11 devnull {
294 b3994ec5 2003-12-11 devnull free(l->u.listptr);
295 b3994ec5 2003-12-11 devnull free(l);
296 b3994ec5 2003-12-11 devnull }
297 b3994ec5 2003-12-11 devnull
298 b3994ec5 2003-12-11 devnull String*
299 b3994ec5 2003-12-11 devnull allocstring(int n)
300 b3994ec5 2003-12-11 devnull {
301 b3994ec5 2003-12-11 devnull String *s;
302 b3994ec5 2003-12-11 devnull
303 b3994ec5 2003-12-11 devnull s = emalloc(sizeof(String));
304 b3994ec5 2003-12-11 devnull s->n = n;
305 b3994ec5 2003-12-11 devnull s->nalloc = n+10;
306 b3994ec5 2003-12-11 devnull s->r = emalloc(s->nalloc*sizeof(Rune));
307 b3994ec5 2003-12-11 devnull s->r[n] = '\0';
308 b3994ec5 2003-12-11 devnull return s;
309 b3994ec5 2003-12-11 devnull }
310 b3994ec5 2003-12-11 devnull
311 b3994ec5 2003-12-11 devnull void
312 b3994ec5 2003-12-11 devnull freestring(String *s)
313 b3994ec5 2003-12-11 devnull {
314 b3994ec5 2003-12-11 devnull free(s->r);
315 b3994ec5 2003-12-11 devnull free(s);
316 b3994ec5 2003-12-11 devnull }
317 b3994ec5 2003-12-11 devnull
318 b3994ec5 2003-12-11 devnull Cmd*
319 b3994ec5 2003-12-11 devnull newcmd(void){
320 b3994ec5 2003-12-11 devnull Cmd *p;
321 b3994ec5 2003-12-11 devnull
322 b3994ec5 2003-12-11 devnull p = emalloc(sizeof(Cmd));
323 b3994ec5 2003-12-11 devnull inslist(&cmdlist, cmdlist.nused, (long)p);
324 b3994ec5 2003-12-11 devnull return p;
325 b3994ec5 2003-12-11 devnull }
326 b3994ec5 2003-12-11 devnull
327 b3994ec5 2003-12-11 devnull String*
328 b3994ec5 2003-12-11 devnull newstring(int n)
329 b3994ec5 2003-12-11 devnull {
330 b3994ec5 2003-12-11 devnull String *p;
331 b3994ec5 2003-12-11 devnull
332 b3994ec5 2003-12-11 devnull p = allocstring(n);
333 b3994ec5 2003-12-11 devnull inslist(&stringlist, stringlist.nused, (long)p);
334 b3994ec5 2003-12-11 devnull return p;
335 b3994ec5 2003-12-11 devnull }
336 b3994ec5 2003-12-11 devnull
337 b3994ec5 2003-12-11 devnull Addr*
338 b3994ec5 2003-12-11 devnull newaddr(void)
339 b3994ec5 2003-12-11 devnull {
340 b3994ec5 2003-12-11 devnull Addr *p;
341 b3994ec5 2003-12-11 devnull
342 b3994ec5 2003-12-11 devnull p = emalloc(sizeof(Addr));
343 b3994ec5 2003-12-11 devnull inslist(&addrlist, addrlist.nused, (long)p);
344 b3994ec5 2003-12-11 devnull return p;
345 b3994ec5 2003-12-11 devnull }
346 b3994ec5 2003-12-11 devnull
347 b3994ec5 2003-12-11 devnull void
348 b3994ec5 2003-12-11 devnull freecmd(void)
349 b3994ec5 2003-12-11 devnull {
350 b3994ec5 2003-12-11 devnull int i;
351 b3994ec5 2003-12-11 devnull
352 b3994ec5 2003-12-11 devnull while(cmdlist.nused > 0)
353 b3994ec5 2003-12-11 devnull free(cmdlist.u.ucharptr[--cmdlist.nused]);
354 b3994ec5 2003-12-11 devnull while(addrlist.nused > 0)
355 b3994ec5 2003-12-11 devnull free(addrlist.u.ucharptr[--addrlist.nused]);
356 b3994ec5 2003-12-11 devnull while(stringlist.nused>0){
357 b3994ec5 2003-12-11 devnull i = --stringlist.nused;
358 b3994ec5 2003-12-11 devnull freestring(stringlist.u.stringptr[i]);
359 b3994ec5 2003-12-11 devnull }
360 b3994ec5 2003-12-11 devnull }
361 b3994ec5 2003-12-11 devnull
362 b3994ec5 2003-12-11 devnull void
363 b3994ec5 2003-12-11 devnull okdelim(int c)
364 b3994ec5 2003-12-11 devnull {
365 b3994ec5 2003-12-11 devnull if(c=='\\' || ('a'<=c && c<='z')
366 b3994ec5 2003-12-11 devnull || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
367 b3994ec5 2003-12-11 devnull editerror("bad delimiter %c\n", c);
368 b3994ec5 2003-12-11 devnull }
369 b3994ec5 2003-12-11 devnull
370 b3994ec5 2003-12-11 devnull void
371 b3994ec5 2003-12-11 devnull atnl(void)
372 b3994ec5 2003-12-11 devnull {
373 b3994ec5 2003-12-11 devnull int c;
374 b3994ec5 2003-12-11 devnull
375 b3994ec5 2003-12-11 devnull cmdskipbl();
376 b3994ec5 2003-12-11 devnull c = getch();
377 b3994ec5 2003-12-11 devnull if(c != '\n')
378 b3994ec5 2003-12-11 devnull editerror("newline expected (saw %C)", c);
379 b3994ec5 2003-12-11 devnull }
380 b3994ec5 2003-12-11 devnull
381 b3994ec5 2003-12-11 devnull void
382 b3994ec5 2003-12-11 devnull Straddc(String *s, int c)
383 b3994ec5 2003-12-11 devnull {
384 b3994ec5 2003-12-11 devnull if(s->n+1 >= s->nalloc){
385 b3994ec5 2003-12-11 devnull s->nalloc += 10;
386 b3994ec5 2003-12-11 devnull s->r = erealloc(s->r, s->nalloc*sizeof(Rune));
387 b3994ec5 2003-12-11 devnull }
388 b3994ec5 2003-12-11 devnull s->r[s->n++] = c;
389 b3994ec5 2003-12-11 devnull s->r[s->n] = '\0';
390 b3994ec5 2003-12-11 devnull }
391 b3994ec5 2003-12-11 devnull
392 b3994ec5 2003-12-11 devnull void
393 b3994ec5 2003-12-11 devnull getrhs(String *s, int delim, int cmd)
394 b3994ec5 2003-12-11 devnull {
395 b3994ec5 2003-12-11 devnull int c;
396 b3994ec5 2003-12-11 devnull
397 b3994ec5 2003-12-11 devnull while((c = getch())>0 && c!=delim && c!='\n'){
398 b3994ec5 2003-12-11 devnull if(c == '\\'){
399 b3994ec5 2003-12-11 devnull if((c=getch()) <= 0)
400 b3994ec5 2003-12-11 devnull error("bad right hand side");
401 b3994ec5 2003-12-11 devnull if(c == '\n'){
402 b3994ec5 2003-12-11 devnull ungetch();
403 b3994ec5 2003-12-11 devnull c='\\';
404 b3994ec5 2003-12-11 devnull }else if(c == 'n')
405 b3994ec5 2003-12-11 devnull c='\n';
406 b3994ec5 2003-12-11 devnull else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */
407 b3994ec5 2003-12-11 devnull Straddc(s, '\\');
408 b3994ec5 2003-12-11 devnull }
409 b3994ec5 2003-12-11 devnull Straddc(s, c);
410 b3994ec5 2003-12-11 devnull }
411 b3994ec5 2003-12-11 devnull ungetch(); /* let client read whether delimiter, '\n' or whatever */
412 b3994ec5 2003-12-11 devnull }
413 b3994ec5 2003-12-11 devnull
414 b3994ec5 2003-12-11 devnull String *
415 b3994ec5 2003-12-11 devnull collecttoken(char *end)
416 b3994ec5 2003-12-11 devnull {
417 b3994ec5 2003-12-11 devnull String *s = newstring(0);
418 b3994ec5 2003-12-11 devnull int c;
419 b3994ec5 2003-12-11 devnull
420 b3994ec5 2003-12-11 devnull while((c=nextc())==' ' || c=='\t')
421 b3994ec5 2003-12-11 devnull Straddc(s, getch()); /* blanks significant for getname() */
422 b3994ec5 2003-12-11 devnull while((c=getch())>0 && utfrune(end, c)==0)
423 b3994ec5 2003-12-11 devnull Straddc(s, c);
424 b3994ec5 2003-12-11 devnull if(c != '\n')
425 b3994ec5 2003-12-11 devnull atnl();
426 b3994ec5 2003-12-11 devnull return s;
427 b3994ec5 2003-12-11 devnull }
428 b3994ec5 2003-12-11 devnull
429 b3994ec5 2003-12-11 devnull String *
430 b3994ec5 2003-12-11 devnull collecttext(void)
431 b3994ec5 2003-12-11 devnull {
432 b3994ec5 2003-12-11 devnull String *s;
433 b3994ec5 2003-12-11 devnull int begline, i, c, delim;
434 b3994ec5 2003-12-11 devnull
435 b3994ec5 2003-12-11 devnull s = newstring(0);
436 b3994ec5 2003-12-11 devnull if(cmdskipbl()=='\n'){
437 b3994ec5 2003-12-11 devnull getch();
438 b3994ec5 2003-12-11 devnull i = 0;
439 b3994ec5 2003-12-11 devnull do{
440 b3994ec5 2003-12-11 devnull begline = i;
441 b3994ec5 2003-12-11 devnull while((c = getch())>0 && c!='\n')
442 b3994ec5 2003-12-11 devnull i++, Straddc(s, c);
443 b3994ec5 2003-12-11 devnull i++, Straddc(s, '\n');
444 b3994ec5 2003-12-11 devnull if(c < 0)
445 b3994ec5 2003-12-11 devnull goto Return;
446 b3994ec5 2003-12-11 devnull }while(s->r[begline]!='.' || s->r[begline+1]!='\n');
447 b3994ec5 2003-12-11 devnull s->r[s->n-2] = '\0';
448 6d7fdb24 2004-12-27 devnull s->n -= 2;
449 b3994ec5 2003-12-11 devnull }else{
450 b3994ec5 2003-12-11 devnull okdelim(delim = getch());
451 b3994ec5 2003-12-11 devnull getrhs(s, delim, 'a');
452 b3994ec5 2003-12-11 devnull if(nextc()==delim)
453 b3994ec5 2003-12-11 devnull getch();
454 b3994ec5 2003-12-11 devnull atnl();
455 b3994ec5 2003-12-11 devnull }
456 b3994ec5 2003-12-11 devnull Return:
457 b3994ec5 2003-12-11 devnull return s;
458 b3994ec5 2003-12-11 devnull }
459 b3994ec5 2003-12-11 devnull
460 b3994ec5 2003-12-11 devnull int
461 b3994ec5 2003-12-11 devnull cmdlookup(int c)
462 b3994ec5 2003-12-11 devnull {
463 b3994ec5 2003-12-11 devnull int i;
464 b3994ec5 2003-12-11 devnull
465 b3994ec5 2003-12-11 devnull for(i=0; cmdtab[i].cmdc; i++)
466 b3994ec5 2003-12-11 devnull if(cmdtab[i].cmdc == c)
467 b3994ec5 2003-12-11 devnull return i;
468 b3994ec5 2003-12-11 devnull return -1;
469 b3994ec5 2003-12-11 devnull }
470 b3994ec5 2003-12-11 devnull
471 b3994ec5 2003-12-11 devnull Cmd*
472 b3994ec5 2003-12-11 devnull parsecmd(int nest)
473 b3994ec5 2003-12-11 devnull {
474 b3994ec5 2003-12-11 devnull int i, c;
475 b3994ec5 2003-12-11 devnull struct cmdtab *ct;
476 b3994ec5 2003-12-11 devnull Cmd *cp, *ncp;
477 b3994ec5 2003-12-11 devnull Cmd cmd;
478 b3994ec5 2003-12-11 devnull
479 b3994ec5 2003-12-11 devnull cmd.next = cmd.u.cmd = 0;
480 b3994ec5 2003-12-11 devnull cmd.re = 0;
481 b3994ec5 2003-12-11 devnull cmd.flag = cmd.num = 0;
482 b3994ec5 2003-12-11 devnull cmd.addr = compoundaddr();
483 b3994ec5 2003-12-11 devnull if(cmdskipbl() == -1)
484 b3994ec5 2003-12-11 devnull return 0;
485 b3994ec5 2003-12-11 devnull if((c=getch())==-1)
486 b3994ec5 2003-12-11 devnull return 0;
487 b3994ec5 2003-12-11 devnull cmd.cmdc = c;
488 b3994ec5 2003-12-11 devnull if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */
489 b3994ec5 2003-12-11 devnull getch(); /* the 'd' */
490 b3994ec5 2003-12-11 devnull cmd.cmdc='c'|0x100;
491 b3994ec5 2003-12-11 devnull }
492 b3994ec5 2003-12-11 devnull i = cmdlookup(cmd.cmdc);
493 b3994ec5 2003-12-11 devnull if(i >= 0){
494 b3994ec5 2003-12-11 devnull if(cmd.cmdc == '\n')
495 b3994ec5 2003-12-11 devnull goto Return; /* let nl_cmd work it all out */
496 b3994ec5 2003-12-11 devnull ct = &cmdtab[i];
497 b3994ec5 2003-12-11 devnull if(ct->defaddr==aNo && cmd.addr)
498 b3994ec5 2003-12-11 devnull editerror("command takes no address");
499 b3994ec5 2003-12-11 devnull if(ct->count)
500 b3994ec5 2003-12-11 devnull cmd.num = getnum(ct->count);
501 b3994ec5 2003-12-11 devnull if(ct->regexp){
502 b3994ec5 2003-12-11 devnull /* x without pattern -> .*\n, indicated by cmd.re==0 */
503 b3994ec5 2003-12-11 devnull /* X without pattern is all files */
504 b3994ec5 2003-12-11 devnull if((ct->cmdc!='x' && ct->cmdc!='X') ||
505 b3994ec5 2003-12-11 devnull ((c = nextc())!=' ' && c!='\t' && c!='\n')){
506 b3994ec5 2003-12-11 devnull cmdskipbl();
507 b3994ec5 2003-12-11 devnull if((c = getch())=='\n' || c<0)
508 b3994ec5 2003-12-11 devnull editerror("no address");
509 b3994ec5 2003-12-11 devnull okdelim(c);
510 b3994ec5 2003-12-11 devnull cmd.re = getregexp(c);
511 b3994ec5 2003-12-11 devnull if(ct->cmdc == 's'){
512 b3994ec5 2003-12-11 devnull cmd.u.text = newstring(0);
513 b3994ec5 2003-12-11 devnull getrhs(cmd.u.text, c, 's');
514 b3994ec5 2003-12-11 devnull if(nextc() == c){
515 b3994ec5 2003-12-11 devnull getch();
516 b3994ec5 2003-12-11 devnull if(nextc() == 'g')
517 b3994ec5 2003-12-11 devnull cmd.flag = getch();
518 b3994ec5 2003-12-11 devnull }
519 b3994ec5 2003-12-11 devnull
520 b3994ec5 2003-12-11 devnull }
521 b3994ec5 2003-12-11 devnull }
522 b3994ec5 2003-12-11 devnull }
523 b3994ec5 2003-12-11 devnull if(ct->addr && (cmd.u.mtaddr=simpleaddr())==0)
524 b3994ec5 2003-12-11 devnull editerror("bad address");
525 b3994ec5 2003-12-11 devnull if(ct->defcmd){
526 b3994ec5 2003-12-11 devnull if(cmdskipbl() == '\n'){
527 b3994ec5 2003-12-11 devnull getch();
528 b3994ec5 2003-12-11 devnull cmd.u.cmd = newcmd();
529 b3994ec5 2003-12-11 devnull cmd.u.cmd->cmdc = ct->defcmd;
530 b3994ec5 2003-12-11 devnull }else if((cmd.u.cmd = parsecmd(nest))==0)
531 b3994ec5 2003-12-11 devnull error("defcmd");
532 b3994ec5 2003-12-11 devnull }else if(ct->text)
533 b3994ec5 2003-12-11 devnull cmd.u.text = collecttext();
534 b3994ec5 2003-12-11 devnull else if(ct->token)
535 b3994ec5 2003-12-11 devnull cmd.u.text = collecttoken(ct->token);
536 b3994ec5 2003-12-11 devnull else
537 b3994ec5 2003-12-11 devnull atnl();
538 b3994ec5 2003-12-11 devnull }else
539 b3994ec5 2003-12-11 devnull switch(cmd.cmdc){
540 b3994ec5 2003-12-11 devnull case '{':
541 b3994ec5 2003-12-11 devnull cp = 0;
542 b3994ec5 2003-12-11 devnull do{
543 b3994ec5 2003-12-11 devnull if(cmdskipbl()=='\n')
544 b3994ec5 2003-12-11 devnull getch();
545 b3994ec5 2003-12-11 devnull ncp = parsecmd(nest+1);
546 b3994ec5 2003-12-11 devnull if(cp)
547 b3994ec5 2003-12-11 devnull cp->next = ncp;
548 b3994ec5 2003-12-11 devnull else
549 b3994ec5 2003-12-11 devnull cmd.u.cmd = ncp;
550 b3994ec5 2003-12-11 devnull }while(cp = ncp);
551 b3994ec5 2003-12-11 devnull break;
552 b3994ec5 2003-12-11 devnull case '}':
553 b3994ec5 2003-12-11 devnull atnl();
554 b3994ec5 2003-12-11 devnull if(nest==0)
555 b3994ec5 2003-12-11 devnull editerror("right brace with no left brace");
556 b3994ec5 2003-12-11 devnull return 0;
557 b3994ec5 2003-12-11 devnull default:
558 b3994ec5 2003-12-11 devnull editerror("unknown command %c", cmd.cmdc);
559 b3994ec5 2003-12-11 devnull }
560 b3994ec5 2003-12-11 devnull Return:
561 b3994ec5 2003-12-11 devnull cp = newcmd();
562 b3994ec5 2003-12-11 devnull *cp = cmd;
563 b3994ec5 2003-12-11 devnull return cp;
564 b3994ec5 2003-12-11 devnull }
565 b3994ec5 2003-12-11 devnull
566 b3994ec5 2003-12-11 devnull String*
567 b3994ec5 2003-12-11 devnull getregexp(int delim)
568 b3994ec5 2003-12-11 devnull {
569 b3994ec5 2003-12-11 devnull String *buf, *r;
570 b3994ec5 2003-12-11 devnull int i, c;
571 b3994ec5 2003-12-11 devnull
572 b3994ec5 2003-12-11 devnull buf = allocstring(0);
573 b3994ec5 2003-12-11 devnull for(i=0; ; i++){
574 b3994ec5 2003-12-11 devnull if((c = getch())=='\\'){
575 b3994ec5 2003-12-11 devnull if(nextc()==delim)
576 b3994ec5 2003-12-11 devnull c = getch();
577 b3994ec5 2003-12-11 devnull else if(nextc()=='\\'){
578 b3994ec5 2003-12-11 devnull Straddc(buf, c);
579 b3994ec5 2003-12-11 devnull c = getch();
580 b3994ec5 2003-12-11 devnull }
581 b3994ec5 2003-12-11 devnull }else if(c==delim || c=='\n')
582 b3994ec5 2003-12-11 devnull break;
583 b3994ec5 2003-12-11 devnull if(i >= RBUFSIZE)
584 b3994ec5 2003-12-11 devnull editerror("regular expression too long");
585 b3994ec5 2003-12-11 devnull Straddc(buf, c);
586 b3994ec5 2003-12-11 devnull }
587 b3994ec5 2003-12-11 devnull if(c!=delim && c)
588 b3994ec5 2003-12-11 devnull ungetch();
589 b3994ec5 2003-12-11 devnull if(buf->n > 0){
590 b3994ec5 2003-12-11 devnull patset = TRUE;
591 b3994ec5 2003-12-11 devnull freestring(lastpat);
592 b3994ec5 2003-12-11 devnull lastpat = buf;
593 b3994ec5 2003-12-11 devnull }else
594 b3994ec5 2003-12-11 devnull freestring(buf);
595 b3994ec5 2003-12-11 devnull if(lastpat->n == 0)
596 b3994ec5 2003-12-11 devnull editerror("no regular expression defined");
597 b3994ec5 2003-12-11 devnull r = newstring(lastpat->n);
598 b3994ec5 2003-12-11 devnull runemove(r->r, lastpat->r, lastpat->n); /* newstring put \0 at end */
599 b3994ec5 2003-12-11 devnull return r;
600 b3994ec5 2003-12-11 devnull }
601 b3994ec5 2003-12-11 devnull
602 b3994ec5 2003-12-11 devnull Addr *
603 b3994ec5 2003-12-11 devnull simpleaddr(void)
604 b3994ec5 2003-12-11 devnull {
605 b3994ec5 2003-12-11 devnull Addr addr;
606 b3994ec5 2003-12-11 devnull Addr *ap, *nap;
607 b3994ec5 2003-12-11 devnull
608 a8ec4910 2005-07-13 devnull addr.num = 0;
609 b3994ec5 2003-12-11 devnull addr.next = 0;
610 b3994ec5 2003-12-11 devnull addr.u.left = 0;
611 b3994ec5 2003-12-11 devnull switch(cmdskipbl()){
612 b3994ec5 2003-12-11 devnull case '#':
613 b3994ec5 2003-12-11 devnull addr.type = getch();
614 b3994ec5 2003-12-11 devnull addr.num = getnum(1);
615 b3994ec5 2003-12-11 devnull break;
616 b3994ec5 2003-12-11 devnull case '0': case '1': case '2': case '3': case '4':
617 b3994ec5 2003-12-11 devnull case '5': case '6': case '7': case '8': case '9':
618 b3994ec5 2003-12-11 devnull addr.num = getnum(1);
619 b3994ec5 2003-12-11 devnull addr.type='l';
620 b3994ec5 2003-12-11 devnull break;
621 b3994ec5 2003-12-11 devnull case '/': case '?': case '"':
622 b3994ec5 2003-12-11 devnull addr.u.re = getregexp(addr.type = getch());
623 b3994ec5 2003-12-11 devnull break;
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 case '\'':
629 b3994ec5 2003-12-11 devnull addr.type = getch();
630 b3994ec5 2003-12-11 devnull break;
631 b3994ec5 2003-12-11 devnull default:
632 b3994ec5 2003-12-11 devnull return 0;
633 b3994ec5 2003-12-11 devnull }
634 b3994ec5 2003-12-11 devnull if(addr.next = simpleaddr())
635 b3994ec5 2003-12-11 devnull switch(addr.next->type){
636 b3994ec5 2003-12-11 devnull case '.':
637 b3994ec5 2003-12-11 devnull case '$':
638 b3994ec5 2003-12-11 devnull case '\'':
639 b3994ec5 2003-12-11 devnull if(addr.type!='"')
640 b3994ec5 2003-12-11 devnull case '"':
641 b3994ec5 2003-12-11 devnull editerror("bad address syntax");
642 b3994ec5 2003-12-11 devnull break;
643 b3994ec5 2003-12-11 devnull case 'l':
644 b3994ec5 2003-12-11 devnull case '#':
645 b3994ec5 2003-12-11 devnull if(addr.type=='"')
646 b3994ec5 2003-12-11 devnull break;
647 b3994ec5 2003-12-11 devnull /* fall through */
648 b3994ec5 2003-12-11 devnull case '/':
649 b3994ec5 2003-12-11 devnull case '?':
650 b3994ec5 2003-12-11 devnull if(addr.type!='+' && addr.type!='-'){
651 b3994ec5 2003-12-11 devnull /* insert the missing '+' */
652 b3994ec5 2003-12-11 devnull nap = newaddr();
653 b3994ec5 2003-12-11 devnull nap->type='+';
654 b3994ec5 2003-12-11 devnull nap->next = addr.next;
655 b3994ec5 2003-12-11 devnull addr.next = nap;
656 b3994ec5 2003-12-11 devnull }
657 b3994ec5 2003-12-11 devnull break;
658 b3994ec5 2003-12-11 devnull case '+':
659 b3994ec5 2003-12-11 devnull case '-':
660 b3994ec5 2003-12-11 devnull break;
661 b3994ec5 2003-12-11 devnull default:
662 b3994ec5 2003-12-11 devnull error("simpleaddr");
663 b3994ec5 2003-12-11 devnull }
664 b3994ec5 2003-12-11 devnull ap = newaddr();
665 b3994ec5 2003-12-11 devnull *ap = addr;
666 b3994ec5 2003-12-11 devnull return ap;
667 b3994ec5 2003-12-11 devnull }
668 b3994ec5 2003-12-11 devnull
669 b3994ec5 2003-12-11 devnull Addr *
670 b3994ec5 2003-12-11 devnull compoundaddr(void)
671 b3994ec5 2003-12-11 devnull {
672 b3994ec5 2003-12-11 devnull Addr addr;
673 b3994ec5 2003-12-11 devnull Addr *ap, *next;
674 b3994ec5 2003-12-11 devnull
675 b3994ec5 2003-12-11 devnull addr.u.left = simpleaddr();
676 b3994ec5 2003-12-11 devnull if((addr.type = cmdskipbl())!=',' && addr.type!=';')
677 b3994ec5 2003-12-11 devnull return addr.u.left;
678 b3994ec5 2003-12-11 devnull getch();
679 b3994ec5 2003-12-11 devnull next = addr.next = compoundaddr();
680 b3994ec5 2003-12-11 devnull if(next && (next->type==',' || next->type==';') && next->u.left==0)
681 b3994ec5 2003-12-11 devnull editerror("bad address syntax");
682 b3994ec5 2003-12-11 devnull ap = newaddr();
683 b3994ec5 2003-12-11 devnull *ap = addr;
684 b3994ec5 2003-12-11 devnull return ap;
685 b3994ec5 2003-12-11 devnull }