4 static char linex[]="\n";
5 static char wordx[]=" \t\n";
6 struct cmdtab cmdtab[]={
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, eq_cmd,
39 'c'|0x100,0, 0, 0, 0, aNo, 0, wordx, cd_cmd,
40 0, 0, 0, 0, 0, 0, 0, 0
43 Addr *compoundaddr(void);
44 Addr *simpleaddr(void);
49 Rune termline[BLOCKSIZE];
51 Rune *terminp = termline;
52 Rune *termoutp = termline;
54 List cmdlist = { 'p' };
55 List addrlist = { 'p' };
56 List relist = { 'p' };
57 List stringlist = { 'p' };
66 terminp = termoutp = termline;
80 while(termoutp == terminp){
84 while(termlocked > 0){
92 if(termoutp == terminp)
93 terminp = termoutp = termline;
96 n = read(0, buf+nbuf, 1);
100 }while(!fullrune(buf, nbuf));
116 * Could set linep = line and i = 0 here and just
117 * error(Etoolong) below, but this way we keep
118 * old input buffer history around for a while.
119 * This is useful only for debugging.
123 if((c = inputc())<=0)
125 if(i == nelem(line)-1){
128 start = linep - line;
129 runemove(line, linep, i-start);
133 }while((line[i++]=c) != '\n');
143 if(*linep==0 && inputline()<0){
172 if(signok>1 && nextc()=='-'){
176 if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */
178 while('0'<=(c=getch()) && c<='9')
190 while(c==' ' || c=='\t');
201 for(p=cmdpt; p<cmd->b.nc; p++){
202 if(terminp >= &termline[BLOCKSIZE]){
206 *terminp++ = filereadc(cmd, p);
219 if(!downloaded && curfile && curfile->unread)
221 if((cmdp = parsecmd(0))==0){
229 loaded = curfile && !curfile->unread;
230 if(cmdexec(curfile, cmdp) == 0)
235 if(downloaded && curfile &&
236 (ocurfile!=curfile || (!loaded && !curfile->unread)))
237 outTs(Hcurrent, curfile->tag);
238 /* don't allow type ahead on files that aren't bound */
239 if(downloaded && curfile && curfile->rasp == 0)
248 p = emalloc(sizeof(Cmd));
249 inslist(&cmdlist, cmdlist.nused, (long)p);
258 p = emalloc(sizeof(Addr));
259 inslist(&addrlist, addrlist.nused, (long)p);
268 p = emalloc(sizeof(String));
269 inslist(&relist, relist.nused, (long)p);
279 p = emalloc(sizeof(String));
280 inslist(&stringlist, stringlist.nused, (long)p);
290 while(cmdlist.nused > 0)
291 free(cmdlist.voidpptr[--cmdlist.nused]);
292 while(addrlist.nused > 0)
293 free(addrlist.voidpptr[--addrlist.nused]);
294 while(relist.nused > 0){
296 Strclose(relist.stringpptr[i]);
297 free(relist.stringpptr[i]);
299 while(stringlist.nused>0){
300 i = --stringlist.nused;
301 Strclose(stringlist.stringpptr[i]);
302 free(stringlist.stringpptr[i]);
311 for(i=0; cmdtab[i].cmdc; i++)
312 if(cmdtab[i].cmdc == c)
320 if(c=='\\' || ('a'<=c && c<='z')
321 || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
334 getrhs(String *s, int delim, int cmd)
338 while((c = getch())>0 && c!=delim && c!='\n'){
347 else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */
352 ungetch(); /* let client read whether delimeter, '\n' or whatever */
356 collecttoken(char *end)
358 String *s = newstring();
361 while((c=nextc())==' ' || c=='\t')
362 Straddc(s, getch()); /* blanks significant for getname() */
363 while((c=getch())>0 && utfrune(end, c)==0)
374 String *s = newstring();
375 int begline, i, c, delim;
382 while((c = getch())>0 && c!='\n')
384 i++, Straddc(s, '\n');
387 }while(s->s[begline]!='.' || s->s[begline+1]!='\n');
388 Strdelete(s, s->n-2, s->n);
390 okdelim(delim = getch());
391 getrhs(s, delim, 'a');
397 Straddc(s, 0); /* JUST FOR CMDPRINT() */
409 cmd.next = cmd.ccmd = 0;
411 cmd.flag = cmd.num = 0;
412 cmd.addr = compoundaddr();
418 if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */
419 getch(); /* the 'd' */
422 i = lookup(cmd.cmdc);
425 goto Return; /* let nl_cmd work it all out */
427 if(ct->defaddr==aNo && cmd.addr)
430 cmd.num = getnum(ct->count);
432 /* x without pattern -> .*\n, indicated by cmd.re==0 */
433 /* X without pattern is all files */
434 if((ct->cmdc!='x' && ct->cmdc!='X') ||
435 ((c = nextc())!=' ' && c!='\t' && c!='\n')){
437 if((c = getch())=='\n' || c<0)
440 cmd.re = getregexp(c);
442 cmd.ctext = newstring();
443 getrhs(cmd.ctext, c, 's');
453 if(ct->addr && (cmd.caddr=simpleaddr())==0)
456 if(skipbl() == '\n'){
459 cmd.ccmd->cmdc = ct->defcmd;
460 }else if((cmd.ccmd = parsecmd(nest))==0)
463 cmd.ctext = collecttext();
465 cmd.ctext = collecttoken(ct->token);
475 ncp = parsecmd(nest+1);
488 error_c(Eunk, cmd.cmdc);
496 String* /* BUGGERED */
502 for(Strzero(&genstr); ; Straddc(&genstr, c))
503 if((c = getch())=='\\'){
506 else if(nextc()=='\\'){
510 }else if(c==delim || c=='\n')
516 Strduplstr(&lastpat, &genstr);
517 Straddc(&lastpat, '\0');
521 Strduplstr(r, &lastpat);
537 addr.num = getnum(1);
539 case '0': case '1': case '2': case '3': case '4':
540 case '5': case '6': case '7': case '8': case '9':
541 addr.num = getnum(1);
544 case '/': case '?': case '"':
545 addr.are = getregexp(addr.type = getch());
557 if(addr.next = simpleaddr())
558 switch(addr.next->type){
573 if(addr.type!='+' && addr.type!='-'){
574 /* insert the missing '+' */
577 nap->next = addr.next;
598 addr.left = simpleaddr();
599 if((addr.type = skipbl())!=',' && addr.type!=';')
602 next = addr.next = compoundaddr();
603 if(next && (next->type==',' || next->type==';') && next->left==0)