4 static char linex[]="\n";
5 static char wordx[]=" \t\n";
7 /* cmdc text regexp addr defcmd defaddr count token fn */
8 '\n', 0, 0, 0, 0, aDot, 0, 0, nl_cmd,
9 'a', 1, 0, 0, 0, aDot, 0, 0, a_cmd,
10 'b', 0, 0, 0, 0, aNo, 0, linex, b_cmd,
11 'B', 0, 0, 0, 0, aNo, 0, linex, b_cmd,
12 'c', 1, 0, 0, 0, aDot, 0, 0, c_cmd,
13 'd', 0, 0, 0, 0, aDot, 0, 0, d_cmd,
14 'D', 0, 0, 0, 0, aNo, 0, linex, D_cmd,
15 'e', 0, 0, 0, 0, aNo, 0, wordx, e_cmd,
16 'f', 0, 0, 0, 0, aNo, 0, wordx, f_cmd,
17 'g', 0, 1, 0, 'p', aDot, 0, 0, g_cmd,
18 'i', 1, 0, 0, 0, aDot, 0, 0, i_cmd,
19 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd,
20 'm', 0, 0, 1, 0, aDot, 0, 0, m_cmd,
21 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd,
22 'p', 0, 0, 0, 0, aDot, 0, 0, p_cmd,
23 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd,
24 'r', 0, 0, 0, 0, aDot, 0, wordx, e_cmd,
25 's', 0, 1, 0, 0, aDot, 1, 0, s_cmd,
26 't', 0, 0, 1, 0, aDot, 0, 0, m_cmd,
27 'u', 0, 0, 0, 0, aNo, 2, 0, u_cmd,
28 'v', 0, 1, 0, 'p', aDot, 0, 0, g_cmd,
29 'w', 0, 0, 0, 0, aAll, 0, wordx, w_cmd,
30 'x', 0, 1, 0, 'p', aDot, 0, 0, x_cmd,
31 'y', 0, 1, 0, 'p', aDot, 0, 0, x_cmd,
32 'X', 0, 1, 0, 'f', aNo, 0, 0, X_cmd,
33 'Y', 0, 1, 0, 'f', aNo, 0, 0, X_cmd,
34 '!', 0, 0, 0, 0, aNo, 0, linex, plan9_cmd,
35 '>', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd,
36 '<', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd,
37 '|', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd,
38 '^', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd,
39 '_', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd,
40 '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd,
41 'c'|0x100,0, 0, 0, 0, aNo, 0, wordx, cd_cmd,
42 0, 0, 0, 0, 0, 0, 0, 0,
45 Addr *compoundaddr(void);
46 Addr *simpleaddr(void);
51 Rune termline[BLOCKSIZE];
53 Rune *terminp = termline;
54 Rune *termoutp = termline;
56 List cmdlist = { 'p' };
57 List addrlist = { 'p' };
58 List relist = { 'p' };
59 List stringlist = { 'p' };
68 terminp = termoutp = termline;
81 if(cmdbufpos > cmdbuf.nc && cmdbuf.nc > 0){
85 if(cmdbufpos < cmdbuf.nc && cmdbuf.nc > 0)
86 bufread(&cmdbuf, cmdbufpos++, &r, 1);
88 while(termoutp == terminp){
92 while(termlocked > 0){
100 if(termoutp == terminp)
101 terminp = termoutp = termline;
104 n = read(0, buf+nbuf, 1);
108 }while(!fullrune(buf, nbuf));
124 * Could set linep = line and i = 0 here and just
125 * error(Etoolong) below, but this way we keep
126 * old input buffer history around for a while.
127 * This is useful only for debugging.
131 if((c = inputc())<=0)
133 if(i == nelem(line)-1){
136 start = linep - line;
137 runemove(line, linep, i-start);
141 }while((line[i++]=c) != '\n');
151 if(*linep==0 && inputline()<0){
180 if(signok>1 && nextc()=='-'){
184 if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */
186 while('0'<=(c=getch()) && c<='9')
198 while(c==' ' || c=='\t');
209 for(p=cmdpt; p<cmd->nc; p++){
210 if(terminp >= termline+nelem(termline)){
214 *terminp++ = filereadc(cmd, p);
227 if(!downloaded && curfile && curfile->unread)
229 if((cmdp = parsecmd(0))==0){
237 loaded = curfile && !curfile->unread;
238 if(cmdexec(curfile, cmdp) == 0)
243 if(downloaded && curfile &&
244 (ocurfile!=curfile || (!loaded && !curfile->unread)))
245 outTs(Hcurrent, curfile->tag);
246 /* don't allow type ahead on files that aren't bound */
247 if(downloaded && curfile && curfile->rasp == 0)
256 p = emalloc(sizeof(Cmd));
257 inslist(&cmdlist, cmdlist.nused, p);
266 p = emalloc(sizeof(Addr));
267 inslist(&addrlist, addrlist.nused, p);
276 p = emalloc(sizeof(String));
277 inslist(&relist, relist.nused, p);
287 p = emalloc(sizeof(String));
288 inslist(&stringlist, stringlist.nused, p);
298 while(cmdlist.nused > 0)
299 free(cmdlist.voidpptr[--cmdlist.nused]);
300 while(addrlist.nused > 0)
301 free(addrlist.voidpptr[--addrlist.nused]);
302 while(relist.nused > 0){
304 Strclose(relist.stringpptr[i]);
305 free(relist.stringpptr[i]);
307 while(stringlist.nused>0){
308 i = --stringlist.nused;
309 Strclose(stringlist.stringpptr[i]);
310 free(stringlist.stringpptr[i]);
319 for(i=0; cmdtab[i].cmdc; i++)
320 if(cmdtab[i].cmdc == c)
328 if(c=='\\' || ('a'<=c && c<='z')
329 || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
342 getrhs(String *s, int delim, int cmd)
346 while((c = getch())>0 && c!=delim && c!='\n'){
355 else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */
360 ungetch(); /* let client read whether delimeter, '\n' or whatever */
364 collecttoken(char *end)
366 String *s = newstring();
369 while((c=nextc())==' ' || c=='\t')
370 Straddc(s, getch()); /* blanks significant for getname() */
371 while((c=getch())>0 && utfrune(end, c)==0)
382 String *s = newstring();
383 int begline, i, c, delim;
390 while((c = getch())>0 && c!='\n')
392 i++, Straddc(s, '\n');
395 }while(s->s[begline]!='.' || s->s[begline+1]!='\n');
396 Strdelete(s, s->n-2, s->n);
398 okdelim(delim = getch());
399 getrhs(s, delim, 'a');
405 Straddc(s, 0); /* JUST FOR CMDPRINT() */
417 cmd.next = cmd.ccmd = 0;
419 cmd.flag = cmd.num = 0;
420 cmd.addr = compoundaddr();
426 if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */
427 getch(); /* the 'd' */
430 i = lookup(cmd.cmdc);
433 goto Return; /* let nl_cmd work it all out */
435 if(ct->defaddr==aNo && cmd.addr)
438 cmd.num = getnum(ct->count);
440 /* x without pattern -> .*\n, indicated by cmd.re==0 */
441 /* X without pattern is all files */
442 if((ct->cmdc!='x' && ct->cmdc!='X') ||
443 ((c = nextc())!=' ' && c!='\t' && c!='\n')){
445 if((c = getch())=='\n' || c<0)
448 cmd.re = getregexp(c);
450 cmd.ctext = newstring();
451 getrhs(cmd.ctext, c, 's');
461 if(ct->addr && (cmd.caddr=simpleaddr())==0)
464 if(skipbl() == '\n'){
467 cmd.ccmd->cmdc = ct->defcmd;
468 }else if((cmd.ccmd = parsecmd(nest))==0)
471 cmd.ctext = collecttext();
473 cmd.ctext = collecttoken(ct->token);
483 ncp = parsecmd(nest+1);
496 error_c(Eunk, cmd.cmdc);
504 String* /* BUGGERED */
510 for(Strzero(&genstr); ; Straddc(&genstr, c))
511 if((c = getch())=='\\'){
514 else if(nextc()=='\\'){
518 }else if(c==delim || c=='\n')
524 Strduplstr(&lastpat, &genstr);
525 Straddc(&lastpat, '\0');
529 Strduplstr(r, &lastpat);
544 addr.num = getnum(1);
546 case '0': case '1': case '2': case '3': case '4':
547 case '5': case '6': case '7': case '8': case '9':
548 addr.num = getnum(1);
551 case '/': case '?': case '"':
552 addr.are = getregexp(addr.type = getch());
564 if(addr.next = simpleaddr())
565 switch(addr.next->type){
580 if(addr.type!='+' && addr.type!='-'){
581 /* insert the missing '+' */
584 nap->next = addr.next;
605 addr.left = simpleaddr();
606 if((addr.type = skipbl())!=',' && addr.type!=';')
609 next = addr.next = compoundaddr();
610 if(next && (next->type==',' || next->type==';') && next->left==0)