|
|
1.1 root 1: #include "sam.h"
2: #include "parse.h"
3:
4: int nl_cmd(), a_cmd(), b_cmd(), c_cmd(), cd_cmd(), d_cmd(), D_cmd(), e_cmd();
5: int f_cmd(), g_cmd(), i_cmd(), k_cmd(), m_cmd(), n_cmd(), p_cmd(), q_cmd();
6: int s_cmd(), u_cmd(), w_cmd(), x_cmd(), X_cmd(), unix_cmd(), eq_cmd();
7:
8: static char linex[]="\n";
9: static char wordx[]=" \t\n";
10: struct cmdtab cmdtab[]={
11: /* cmdc text regexp addr defcmd defaddr count token fn */
12: '\n', 0, 0, 0, 0, aDot, 0, 0, nl_cmd,
13: 'a', 1, 0, 0, 0, aDot, 0, 0, a_cmd,
14: 'b', 0, 0, 0, 0, aNo, 0, linex, b_cmd,
15: 'B', 0, 0, 0, 0, aNo, 0, linex, b_cmd,
16: 'c', 1, 0, 0, 0, aDot, 0, 0, c_cmd,
17: 'd', 0, 0, 0, 0, aDot, 0, 0, d_cmd,
18: 'D', 0, 0, 0, 0, aNo, 0, linex, D_cmd,
19: 'e', 0, 0, 0, 0, aNo, 0, wordx, e_cmd,
20: 'f', 0, 0, 0, 0, aNo, 0, wordx, f_cmd,
21: 'g', 0, 1, 0, 'p', aDot, 0, 0, g_cmd,
22: 'i', 1, 0, 0, 0, aDot, 0, 0, i_cmd,
23: 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd,
24: 'm', 0, 0, 1, 0, aDot, 0, 0, m_cmd,
25: 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd,
26: 'p', 0, 0, 0, 0, aDot, 0, 0, p_cmd,
27: 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd,
28: 'r', 0, 0, 0, 0, aDot, 0, wordx, e_cmd,
29: 's', 0, 1, 0, 0, aDot, 1, 0, s_cmd,
30: 't', 0, 0, 1, 0, aDot, 0, 0, m_cmd,
31: 'u', 0, 0, 0, 0, aNo, 1, 0, u_cmd,
32: 'v', 0, 1, 0, 'p', aDot, 0, 0, g_cmd,
33: 'w', 0, 0, 0, 0, aAll, 0, wordx, w_cmd,
34: 'x', 0, 1, 0, 'p', aDot, 0, 0, x_cmd,
35: 'y', 0, 1, 0, 'p', aDot, 0, 0, x_cmd,
36: 'X', 0, 1, 0, 'f', aNo, 0, 0, X_cmd,
37: 'Y', 0, 1, 0, 'f', aNo, 0, 0, X_cmd,
38: '!', 0, 0, 0, 0, aNo, 0, linex, unix_cmd,
39: '>', 0, 0, 0, 0, aDot, 0, linex, unix_cmd,
40: '<', 0, 0, 0, 0, aDot, 0, linex, unix_cmd,
41: '|', 0, 0, 0, 0, aDot, 0, linex, unix_cmd,
42: '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd,
43: 'c'|0x100,0, 0, 0, 0, aNo, 0, wordx, cd_cmd,
44: 0, 0, 0, 0, 0, 0, 0, 0,
45: };
46: Cmd *parsecmd();
47: Addr *compoundaddr();
48: Addr *simpleaddr();
49: uchar line[BLOCKSIZE];
50: uchar termline[BLOCKSIZE];
51: uchar *linep=line;
52: uchar *terminp=termline;
53: uchar *termoutp=termline;
54: List cmdlist;
55: List addrlist;
56: List relist;
57: List stringlist;
58: int eof;
59:
60: resetcmd(){
61: linep=line;
62: *linep=0;
63: terminp=termoutp=termline;
64: freecmd();
65: }
66: getc(){
67: if(eof)
68: return -1;
69: if(*linep==0 && inputline()<0){
70: eof=TRUE;
71: return -1;
72: }
73: return *linep++;
74: }
75: nextc(){
76: if(*linep==0)
77: return -1;
78: return *linep;
79: }
80: ungetc(){
81: if(--linep<line)
82: panic("ungetc");
83: }
84: inputline(){
85: register i, c;
86: linep=line;
87: i=0;
88: do{
89: if((c=inputc())<=0)
90: return -1;
91: if(i==(sizeof line)-1)
92: error(Etoolong);
93: }while((line[i++]=c)!='\n');
94: line[i]=0;
95: return 1;
96: }
97: termcommand()
98: {
99: register Posn p;
100: dounlock=TRUE;
101: Fgetcset(cmd, cmdpt);
102: for(p=cmdpt; p<cmd->nbytes; p++)
103: *terminp++=Fgetc(cmd);
104: cmdpt=cmd->nbytes;
105: }
106: inputc()
107: {
108: register c, n;
109: uchar cc;
110: Again:
111: if(downloaded){
112: while(termoutp==terminp){
113: if(cmd && cmd->mod!=0){
114: Fupdate(cmd, FALSE, downloaded);
115: cmd->dot.r.p1=cmd->dot.r.p2=cmd->nbytes;
116: telldot(cmd);
117: }
118: if(dounlock){
119: outT0(Hunlock);
120: dounlock=FALSE;
121: }
122: if(patset)
123: tellpat();
124: if(rcv()==0)
125: return -1;
126: }
127: c= *termoutp++;
128: if(termoutp==terminp)
129: terminp=termoutp=termline;
130: n=1;
131: }else{
132: n=read(0, (char *)&cc, 1);
133: c=cc;
134: }
135: if(n<=0)
136: return -1;
137: if(c==0 || (c&HIGHBIT)){
138: warn(Wnonascii);
139: goto Again;
140: }
141: return c;
142: }
143: cmdloop(){
144: Cmd *cmdp;
145: File *ocurfile;
146: int loaded;
147: for(;;){
148: if(!downloaded && curfile && curfile->state==Unread)
149: load(curfile);
150: if((cmdp=parsecmd(0))==0)
151: break;
152: ocurfile=curfile;
153: loaded=curfile && curfile->state!=Unread;
154: if(cmdexec(curfile, cmdp)==0)
155: break;
156: freecmd();
157: update();
158: if(downloaded && curfile &&
159: (ocurfile!=curfile || (!loaded && curfile->state!=Unread)))
160: outTs(Hcurrent, curfile->tag);
161: }
162: }
163: Cmd *
164: newcmd(){
165: register Cmd *p;
166: p=new(Cmd, 1);
167: inslist(&cmdlist, cmdlist.nused, (long)p);
168: return p;
169: }
170: Addr *
171: newaddr(){
172: register Addr *p;
173: p=new(Addr, 1);
174: inslist(&addrlist, addrlist.nused, (long)p);
175: return p;
176: }
177: Regexp *
178: newre(){
179: register Regexp *p;
180: p=new(Regexp, 1);
181: inslist(&relist, relist.nused, (long)p);
182: strinit(&p->text);
183: return p;
184: }
185: String *
186: newstring(){
187: register String *p;
188: p=new(String, 1);
189: inslist(&stringlist, stringlist.nused, (long)p);
190: strinit(p);
191: return p;
192: }
193: freecmd()
194: {
195: register i;
196: while(cmdlist.nused>0)
197: free((uchar *)cmdlist.ptr[--cmdlist.nused]);
198: while(addrlist.nused>0)
199: free((uchar *)addrlist.ptr[--addrlist.nused]);
200: while(relist.nused>0){
201: i= --relist.nused;
202: strclose(&((Regexp *)relist.ptr[i])->text);
203: free((uchar *)relist.ptr[i]); /* WARNING!! */
204: }
205: while(stringlist.nused>0){
206: i= --stringlist.nused;
207: strclose((String *)stringlist.ptr[i]);
208: free((uchar *)stringlist.ptr[i]);
209: }
210: }
211: lookup(c)
212: register c;
213: {
214: register i;
215: for(i=0; cmdtab[i].cmdc; i++)
216: if(cmdtab[i].cmdc==c)
217: return i;
218: return -1;
219: }
220: okdelim(c){
221: if(c=='\\' || ('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
222: error_c(Edelim, c);
223: }
224: atnl(){
225: skipbl();
226: if(getc()!='\n')
227: error(Enewline);
228: }
229: getrhs(s, delim, cmd)
230: register String *s;
231: register delim;
232: {
233: register c;
234: while((c=getc())>0 && c!=delim && c!='\n'){
235: if(c=='\\'){
236: if((c=getc())<=0)
237: error(Ebadrhs);
238: if(c=='\n'){
239: ungetc();
240: c='\\';
241: }else if(c=='n')
242: c='\n';
243: else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */
244: straddc(s, '\\');
245: }
246: straddc(s, c);
247: }
248: ungetc(); /* let client read whether delimeter, '\n' or whatever */
249: }
250: String *
251: collecttoken(end)
252: register char *end;
253: {
254: register String *s=newstring();
255: register c, i;
256: i=0;
257: while((c=nextc())==' ' || c=='\t')
258: i++, straddc(s, getc()); /* blanks significant for getname() */
259: while((c=getc())>0 && strchr(end, c)==0)
260: i++, straddc(s, c);
261: straddc(s, 0);
262: if(c!='\n')
263: atnl();
264: return s;
265: }
266: String *
267: collecttext(){
268: register String *s=newstring();
269: register begline, i;
270: register c, delim;
271: if(skipbl()=='\n'){
272: getc();
273: i=0;
274: do{
275: begline=i;
276: while((c=getc())>0 && c!='\n')
277: i++, straddc(s, c);
278: i++, straddc(s, '\n');
279: if(c<0)
280: goto Return;
281: }while(s->s[begline]!='.' || s->s[begline+1]!='\n');
282: strdelete(s, (long)s->n-2, (long)s->n);
283: }else{
284: okdelim(delim=getc());
285: getrhs(s, delim, 'a');
286: if(nextc()==delim)
287: getc();
288: atnl();
289: }
290: Return:
291: straddc(s, 0); /* JUST FOR CMDPRINT() */
292: return s;
293: }
294: Cmd *
295: parsecmd(nest)
296: {
297: register i, c;
298: register struct cmdtab *ct;
299: register Cmd *cp, *ncp;
300: Cmd cmd;
301: cmd.next=cmd.ccmd=0;
302: cmd.re=0;
303: cmd.flag=cmd.num=0;
304: cmd.addr=compoundaddr();
305: if(skipbl()==-1)
306: return 0;
307: if((c=getc())==-1)
308: return 0;
309: cmd.cmdc=c;
310: if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */
311: getc(); /* the 'd' */
312: cmd.cmdc='c'|0x100;
313: }
314: i=lookup(cmd.cmdc);
315: if(i>=0){
316: if(cmd.cmdc=='\n')
317: goto Return; /* let nl_cmd work it all out */
318: ct= &cmdtab[i];
319: if(ct->defaddr==aNo && cmd.addr)
320: error(Enoaddr);
321: if(ct->count)
322: cmd.num=getnum();
323: if(ct->regexp){
324: /* x without pattern -> .*\n, indicated by cmd.re==0 */
325: /* X without pattern is all files */
326: if((ct->cmdc!='x' && ct->cmdc!='X') ||
327: ((c=nextc())!=' ' && c!='\t' && c!='\n')){
328: skipbl();
329: if((c=getc())=='\n' || c<0)
330: error(Enopattern);
331: cmd.re=getregexp(c);
332: if(ct->cmdc=='s'){
333: cmd.ctext=newstring();
334: getrhs(cmd.ctext, c, 's');
335: if(nextc()==c){
336: getc();
337: if(nextc()=='g')
338: cmd.flag=getc();
339: }
340:
341: }
342: }
343: }
344: if(ct->addr && (cmd.caddr=simpleaddr())==0)
345: error(Eaddress);
346: if(ct->defcmd){
347: if(skipbl()=='\n'){
348: getc();
349: cmd.ccmd=newcmd();
350: cmd.ccmd->cmdc=ct->defcmd;
351: }else if((cmd.ccmd=parsecmd(nest))==0)
352: panic("defcmd");
353: }else if(ct->text)
354: cmd.ctext=collecttext();
355: else if(ct->token)
356: cmd.ctext=collecttoken(ct->token);
357: else
358: atnl();
359: }else
360: switch(cmd.cmdc){
361: case '{':
362: cp=0;
363: do{
364: if(skipbl()=='\n')
365: getc();
366: ncp=parsecmd(nest+1);
367: if(cp)
368: cp->next=ncp;
369: else
370: cmd.ccmd=ncp;
371: }while(cp=ncp);
372: break;
373: case '}':
374: atnl();
375: if(nest==0)
376: error(Enolbrace);
377: return 0;
378: default:
379: error_c(Eunk, cmd.cmdc);
380: }
381: Return:
382: cp=newcmd();
383: *cp=cmd;
384: return cp;
385: }
386: Regexp * /* BUGGERED */
387: getregexp(delim)
388: register delim;
389: {
390: register Regexp *r=newre();
391: register c;
392: for(strzero(&genstr); ; straddc(&genstr, c))
393: if((c=getc())=='\\'){
394: if(nextc()==delim)
395: c=getc();
396: else if(nextc()=='\\'){
397: straddc(&genstr, c);
398: c=getc();
399: }
400: }else if(c==delim || c=='\n')
401: break;
402: if(c!=delim && c)
403: ungetc();
404: if(genstr.n>0){
405: patset=TRUE;
406: strdupstr(&lastpat, &genstr);
407: straddc(&lastpat, '\0');
408: }
409: if(lastpat.n<=1)
410: error(Epattern);
411: strdupstr(&r->text, &lastpat);
412: return r;
413: }
414: Addr *
415: compoundaddr(){
416: Addr addr;
417: register Addr *ap;
418: addr.aprev=simpleaddr();
419: if((addr.type=skipbl())!=',' && addr.type!=';')
420: return addr.aprev;
421: getc();
422: addr.next=compoundaddr();
423: if(addr.next && addr.next->aprev==0)
424: error(Eaddress);
425: ap=newaddr();
426: *ap=addr;
427: return ap;
428: }
429: Addr *
430: simpleaddr()
431: {
432: Addr addr;
433: register Addr *ap, *nap;
434: addr.next=0;
435: switch(skipbl()){
436: case '#':
437: addr.type=getc();
438: addr.num=getnum();
439: break;
440: case '0': case '1': case '2': case '3': case '4':
441: case '5': case '6': case '7': case '8': case '9':
442: addr.num=getnum();
443: addr.type='l';
444: break;
445: case '/': case '?': case '"':
446: addr.are=getregexp(addr.type=getc());
447: break;
448: case '.':
449: case '$':
450: case '+':
451: case '-':
452: case '\'':
453: addr.type=getc();
454: break;
455: default:
456: return 0;
457: }
458: if(addr.next=simpleaddr())
459: switch(addr.next->type){
460: case '.':
461: case '$':
462: case '\'':
463: if(addr.type!='"')
464: case '"':
465: error(Eaddress);
466: break;
467: case 'l':
468: case '#':
469: if(addr.type=='"')
470: break;
471: /* fall through */
472: case '/':
473: case '?':
474: if(addr.type!='+' && addr.type!='-'){
475: /* insert the missing '+' */
476: nap=newaddr();
477: nap->type='+';
478: nap->next=addr.next;
479: addr.next=nap;
480: }
481: break;
482: case '+':
483: case '-':
484: break;
485: default:
486: panic("simpleaddr");
487: }
488: ap=newaddr();
489: *ap=addr;
490: return ap;
491: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.