13e12c5d1SDavid du Colombier #include "sam.h" 23e12c5d1SDavid du Colombier #include "parse.h" 33e12c5d1SDavid du Colombier 43e12c5d1SDavid du Colombier static char linex[]="\n"; 53e12c5d1SDavid du Colombier static char wordx[]=" \t\n"; 65e91980fSDavid du Colombier Cmdtab cmdtab[]={ 73e12c5d1SDavid du Colombier /* cmdc text regexp addr defcmd defaddr count token fn */ 83e12c5d1SDavid du Colombier '\n', 0, 0, 0, 0, aDot, 0, 0, nl_cmd, 93e12c5d1SDavid du Colombier 'a', 1, 0, 0, 0, aDot, 0, 0, a_cmd, 103e12c5d1SDavid du Colombier 'b', 0, 0, 0, 0, aNo, 0, linex, b_cmd, 113e12c5d1SDavid du Colombier 'B', 0, 0, 0, 0, aNo, 0, linex, b_cmd, 123e12c5d1SDavid du Colombier 'c', 1, 0, 0, 0, aDot, 0, 0, c_cmd, 133e12c5d1SDavid du Colombier 'd', 0, 0, 0, 0, aDot, 0, 0, d_cmd, 143e12c5d1SDavid du Colombier 'D', 0, 0, 0, 0, aNo, 0, linex, D_cmd, 153e12c5d1SDavid du Colombier 'e', 0, 0, 0, 0, aNo, 0, wordx, e_cmd, 163e12c5d1SDavid du Colombier 'f', 0, 0, 0, 0, aNo, 0, wordx, f_cmd, 173e12c5d1SDavid du Colombier 'g', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, 183e12c5d1SDavid du Colombier 'i', 1, 0, 0, 0, aDot, 0, 0, i_cmd, 193e12c5d1SDavid du Colombier 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd, 203e12c5d1SDavid du Colombier 'm', 0, 0, 1, 0, aDot, 0, 0, m_cmd, 213e12c5d1SDavid du Colombier 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd, 223e12c5d1SDavid du Colombier 'p', 0, 0, 0, 0, aDot, 0, 0, p_cmd, 233e12c5d1SDavid du Colombier 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd, 243e12c5d1SDavid du Colombier 'r', 0, 0, 0, 0, aDot, 0, wordx, e_cmd, 253e12c5d1SDavid du Colombier 's', 0, 1, 0, 0, aDot, 1, 0, s_cmd, 263e12c5d1SDavid du Colombier 't', 0, 0, 1, 0, aDot, 0, 0, m_cmd, 277dd7cddfSDavid du Colombier 'u', 0, 0, 0, 0, aNo, 2, 0, u_cmd, 283e12c5d1SDavid du Colombier 'v', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, 293e12c5d1SDavid du Colombier 'w', 0, 0, 0, 0, aAll, 0, wordx, w_cmd, 303e12c5d1SDavid du Colombier 'x', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, 313e12c5d1SDavid du Colombier 'y', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, 323e12c5d1SDavid du Colombier 'X', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, 333e12c5d1SDavid du Colombier 'Y', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, 343e12c5d1SDavid du Colombier '!', 0, 0, 0, 0, aNo, 0, linex, plan9_cmd, 353e12c5d1SDavid du Colombier '>', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, 363e12c5d1SDavid du Colombier '<', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, 373e12c5d1SDavid du Colombier '|', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, 383e12c5d1SDavid du Colombier '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd, 393e12c5d1SDavid du Colombier 'c'|0x100,0, 0, 0, 0, aNo, 0, wordx, cd_cmd, 403e12c5d1SDavid du Colombier 0, 0, 0, 0, 0, 0, 0, 0, 413e12c5d1SDavid du Colombier }; 423e12c5d1SDavid du Colombier Cmd *parsecmd(int); 433e12c5d1SDavid du Colombier Addr *compoundaddr(void); 443e12c5d1SDavid du Colombier Addr *simpleaddr(void); 453e12c5d1SDavid du Colombier void freecmd(void); 463e12c5d1SDavid du Colombier void okdelim(int); 473e12c5d1SDavid du Colombier 483e12c5d1SDavid du Colombier Rune line[BLOCKSIZE]; 493e12c5d1SDavid du Colombier Rune termline[BLOCKSIZE]; 503e12c5d1SDavid du Colombier Rune *linep = line; 513e12c5d1SDavid du Colombier Rune *terminp = termline; 523e12c5d1SDavid du Colombier Rune *termoutp = termline; 5373e742d7SDavid du Colombier 5473e742d7SDavid du Colombier List cmdlist = { 'p' }; 5573e742d7SDavid du Colombier List addrlist = { 'p' }; 5673e742d7SDavid du Colombier List relist = { 'p' }; 5773e742d7SDavid du Colombier List stringlist = { 'p' }; 5873e742d7SDavid du Colombier 593e12c5d1SDavid du Colombier int eof; 603e12c5d1SDavid du Colombier 613e12c5d1SDavid du Colombier void 623e12c5d1SDavid du Colombier resetcmd(void) 633e12c5d1SDavid du Colombier { 643e12c5d1SDavid du Colombier linep = line; 653e12c5d1SDavid du Colombier *linep = 0; 663e12c5d1SDavid du Colombier terminp = termoutp = termline; 673e12c5d1SDavid du Colombier freecmd(); 683e12c5d1SDavid du Colombier } 693e12c5d1SDavid du Colombier 703e12c5d1SDavid du Colombier int 713e12c5d1SDavid du Colombier inputc(void) 723e12c5d1SDavid du Colombier { 733e12c5d1SDavid du Colombier int n, nbuf; 74*82726826SDavid du Colombier char buf[UTFmax]; 753e12c5d1SDavid du Colombier Rune r; 763e12c5d1SDavid du Colombier 773e12c5d1SDavid du Colombier Again: 783e12c5d1SDavid du Colombier nbuf = 0; 793e12c5d1SDavid du Colombier if(downloaded){ 803e12c5d1SDavid du Colombier while(termoutp == terminp){ 813e12c5d1SDavid du Colombier cmdupdate(); 823e12c5d1SDavid du Colombier if(patset) 833e12c5d1SDavid du Colombier tellpat(); 843e12c5d1SDavid du Colombier while(termlocked > 0){ 853e12c5d1SDavid du Colombier outT0(Hunlock); 863e12c5d1SDavid du Colombier termlocked--; 873e12c5d1SDavid du Colombier } 883e12c5d1SDavid du Colombier if(rcv() == 0) 893e12c5d1SDavid du Colombier return -1; 903e12c5d1SDavid du Colombier } 913e12c5d1SDavid du Colombier r = *termoutp++; 923e12c5d1SDavid du Colombier if(termoutp == terminp) 933e12c5d1SDavid du Colombier terminp = termoutp = termline; 943e12c5d1SDavid du Colombier }else{ 953e12c5d1SDavid du Colombier do{ 963e12c5d1SDavid du Colombier n = read(0, buf+nbuf, 1); 973e12c5d1SDavid du Colombier if(n <= 0) 983e12c5d1SDavid du Colombier return -1; 993e12c5d1SDavid du Colombier nbuf += n; 1003e12c5d1SDavid du Colombier }while(!fullrune(buf, nbuf)); 1013e12c5d1SDavid du Colombier chartorune(&r, buf); 1023e12c5d1SDavid du Colombier } 1033e12c5d1SDavid du Colombier if(r == 0){ 1043e12c5d1SDavid du Colombier warn(Wnulls); 1053e12c5d1SDavid du Colombier goto Again; 1063e12c5d1SDavid du Colombier } 1073e12c5d1SDavid du Colombier return r; 1083e12c5d1SDavid du Colombier } 1093e12c5d1SDavid du Colombier 1103e12c5d1SDavid du Colombier int 1113e12c5d1SDavid du Colombier inputline(void) 1123e12c5d1SDavid du Colombier { 1135e91980fSDavid du Colombier int i, c, start; 1143e12c5d1SDavid du Colombier 1155e91980fSDavid du Colombier /* 1165e91980fSDavid du Colombier * Could set linep = line and i = 0 here and just 1175e91980fSDavid du Colombier * error(Etoolong) below, but this way we keep 1185e91980fSDavid du Colombier * old input buffer history around for a while. 1195e91980fSDavid du Colombier * This is useful only for debugging. 1205e91980fSDavid du Colombier */ 1215e91980fSDavid du Colombier i = linep - line; 1223e12c5d1SDavid du Colombier do{ 1233e12c5d1SDavid du Colombier if((c = inputc())<=0) 1243e12c5d1SDavid du Colombier return -1; 1255e91980fSDavid du Colombier if(i == nelem(line)-1){ 1265e91980fSDavid du Colombier if(linep == line) 1273e12c5d1SDavid du Colombier error(Etoolong); 1285e91980fSDavid du Colombier start = linep - line; 1295e91980fSDavid du Colombier runemove(line, linep, i-start); 1305e91980fSDavid du Colombier i -= start; 1315e91980fSDavid du Colombier linep = line; 1325e91980fSDavid du Colombier } 1333e12c5d1SDavid du Colombier }while((line[i++]=c) != '\n'); 1343e12c5d1SDavid du Colombier line[i] = 0; 1353e12c5d1SDavid du Colombier return 1; 1363e12c5d1SDavid du Colombier } 1373e12c5d1SDavid du Colombier 1383e12c5d1SDavid du Colombier int 1393e12c5d1SDavid du Colombier getch(void) 1403e12c5d1SDavid du Colombier { 1413e12c5d1SDavid du Colombier if(eof) 1423e12c5d1SDavid du Colombier return -1; 1433e12c5d1SDavid du Colombier if(*linep==0 && inputline()<0){ 1443e12c5d1SDavid du Colombier eof = TRUE; 1453e12c5d1SDavid du Colombier return -1; 1463e12c5d1SDavid du Colombier } 1473e12c5d1SDavid du Colombier return *linep++; 1483e12c5d1SDavid du Colombier } 1493e12c5d1SDavid du Colombier 1503e12c5d1SDavid du Colombier int 1513e12c5d1SDavid du Colombier nextc(void) 1523e12c5d1SDavid du Colombier { 1533e12c5d1SDavid du Colombier if(*linep == 0) 1543e12c5d1SDavid du Colombier return -1; 1553e12c5d1SDavid du Colombier return *linep; 1563e12c5d1SDavid du Colombier } 1573e12c5d1SDavid du Colombier 1583e12c5d1SDavid du Colombier void 1593e12c5d1SDavid du Colombier ungetch(void) 1603e12c5d1SDavid du Colombier { 1613e12c5d1SDavid du Colombier if(--linep < line) 1623e12c5d1SDavid du Colombier panic("ungetch"); 1633e12c5d1SDavid du Colombier } 1643e12c5d1SDavid du Colombier 1653e12c5d1SDavid du Colombier Posn 1667dd7cddfSDavid du Colombier getnum(int signok) 1673e12c5d1SDavid du Colombier { 1683e12c5d1SDavid du Colombier Posn n=0; 1697dd7cddfSDavid du Colombier int c, sign; 1703e12c5d1SDavid du Colombier 1717dd7cddfSDavid du Colombier sign = 1; 1727dd7cddfSDavid du Colombier if(signok>1 && nextc()=='-'){ 1737dd7cddfSDavid du Colombier sign = -1; 1747dd7cddfSDavid du Colombier getch(); 1757dd7cddfSDavid du Colombier } 1763e12c5d1SDavid du Colombier if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */ 1777dd7cddfSDavid du Colombier return sign; 1783e12c5d1SDavid du Colombier while('0'<=(c=getch()) && c<='9') 1793e12c5d1SDavid du Colombier n = n*10 + (c-'0'); 1803e12c5d1SDavid du Colombier ungetch(); 1817dd7cddfSDavid du Colombier return sign*n; 1823e12c5d1SDavid du Colombier } 1833e12c5d1SDavid du Colombier 1843e12c5d1SDavid du Colombier int 1853e12c5d1SDavid du Colombier skipbl(void) 1863e12c5d1SDavid du Colombier { 1873e12c5d1SDavid du Colombier int c; 1883e12c5d1SDavid du Colombier do 1893e12c5d1SDavid du Colombier c = getch(); 1903e12c5d1SDavid du Colombier while(c==' ' || c=='\t'); 1913e12c5d1SDavid du Colombier if(c >= 0) 1923e12c5d1SDavid du Colombier ungetch(); 1933e12c5d1SDavid du Colombier return c; 1943e12c5d1SDavid du Colombier } 1953e12c5d1SDavid du Colombier 1963e12c5d1SDavid du Colombier void 1973e12c5d1SDavid du Colombier termcommand(void) 1983e12c5d1SDavid du Colombier { 1993e12c5d1SDavid du Colombier Posn p; 2003e12c5d1SDavid du Colombier 2017dd7cddfSDavid du Colombier for(p=cmdpt; p<cmd->nc; p++){ 2025e91980fSDavid du Colombier if(terminp >= termline+nelem(termline)){ 2037dd7cddfSDavid du Colombier cmdpt = cmd->nc; 2043e12c5d1SDavid du Colombier error(Etoolong); 2053e12c5d1SDavid du Colombier } 2067dd7cddfSDavid du Colombier *terminp++ = filereadc(cmd, p); 2073e12c5d1SDavid du Colombier } 2087dd7cddfSDavid du Colombier cmdpt = cmd->nc; 2093e12c5d1SDavid du Colombier } 2103e12c5d1SDavid du Colombier 2113e12c5d1SDavid du Colombier void 2123e12c5d1SDavid du Colombier cmdloop(void) 2133e12c5d1SDavid du Colombier { 2143e12c5d1SDavid du Colombier Cmd *cmdp; 2153e12c5d1SDavid du Colombier File *ocurfile; 2163e12c5d1SDavid du Colombier int loaded; 2173e12c5d1SDavid du Colombier 2183e12c5d1SDavid du Colombier for(;;){ 2197dd7cddfSDavid du Colombier if(!downloaded && curfile && curfile->unread) 2203e12c5d1SDavid du Colombier load(curfile); 2213e12c5d1SDavid du Colombier if((cmdp = parsecmd(0))==0){ 2223e12c5d1SDavid du Colombier if(downloaded){ 2233e12c5d1SDavid du Colombier rescue(); 2243e12c5d1SDavid du Colombier exits("eof"); 2253e12c5d1SDavid du Colombier } 2263e12c5d1SDavid du Colombier break; 2273e12c5d1SDavid du Colombier } 2283e12c5d1SDavid du Colombier ocurfile = curfile; 2297dd7cddfSDavid du Colombier loaded = curfile && !curfile->unread; 2303e12c5d1SDavid du Colombier if(cmdexec(curfile, cmdp) == 0) 2313e12c5d1SDavid du Colombier break; 2323e12c5d1SDavid du Colombier freecmd(); 2333e12c5d1SDavid du Colombier cmdupdate(); 2343e12c5d1SDavid du Colombier update(); 2353e12c5d1SDavid du Colombier if(downloaded && curfile && 2367dd7cddfSDavid du Colombier (ocurfile!=curfile || (!loaded && !curfile->unread))) 2373e12c5d1SDavid du Colombier outTs(Hcurrent, curfile->tag); 2387dd7cddfSDavid du Colombier /* don't allow type ahead on files that aren't bound */ 2397dd7cddfSDavid du Colombier if(downloaded && curfile && curfile->rasp == 0) 2407dd7cddfSDavid du Colombier terminp = termoutp; 2413e12c5d1SDavid du Colombier } 2423e12c5d1SDavid du Colombier } 2433e12c5d1SDavid du Colombier 2443e12c5d1SDavid du Colombier Cmd * 2453e12c5d1SDavid du Colombier newcmd(void){ 2463e12c5d1SDavid du Colombier Cmd *p; 2473e12c5d1SDavid du Colombier 2483e12c5d1SDavid du Colombier p = emalloc(sizeof(Cmd)); 24973e742d7SDavid du Colombier inslist(&cmdlist, cmdlist.nused, p); 2503e12c5d1SDavid du Colombier return p; 2513e12c5d1SDavid du Colombier } 2523e12c5d1SDavid du Colombier 2533e12c5d1SDavid du Colombier Addr* 2543e12c5d1SDavid du Colombier newaddr(void) 2553e12c5d1SDavid du Colombier { 2563e12c5d1SDavid du Colombier Addr *p; 2573e12c5d1SDavid du Colombier 2583e12c5d1SDavid du Colombier p = emalloc(sizeof(Addr)); 25973e742d7SDavid du Colombier inslist(&addrlist, addrlist.nused, p); 2603e12c5d1SDavid du Colombier return p; 2613e12c5d1SDavid du Colombier } 2623e12c5d1SDavid du Colombier 2633e12c5d1SDavid du Colombier String* 2643e12c5d1SDavid du Colombier newre(void) 2653e12c5d1SDavid du Colombier { 2663e12c5d1SDavid du Colombier String *p; 2673e12c5d1SDavid du Colombier 2683e12c5d1SDavid du Colombier p = emalloc(sizeof(String)); 26973e742d7SDavid du Colombier inslist(&relist, relist.nused, p); 2703e12c5d1SDavid du Colombier Strinit(p); 2713e12c5d1SDavid du Colombier return p; 2723e12c5d1SDavid du Colombier } 2733e12c5d1SDavid du Colombier 2743e12c5d1SDavid du Colombier String* 2753e12c5d1SDavid du Colombier newstring(void) 2763e12c5d1SDavid du Colombier { 2773e12c5d1SDavid du Colombier String *p; 2783e12c5d1SDavid du Colombier 2793e12c5d1SDavid du Colombier p = emalloc(sizeof(String)); 28073e742d7SDavid du Colombier inslist(&stringlist, stringlist.nused, p); 2813e12c5d1SDavid du Colombier Strinit(p); 2823e12c5d1SDavid du Colombier return p; 2833e12c5d1SDavid du Colombier } 2843e12c5d1SDavid du Colombier 2853e12c5d1SDavid du Colombier void 2863e12c5d1SDavid du Colombier freecmd(void) 2873e12c5d1SDavid du Colombier { 2883e12c5d1SDavid du Colombier int i; 2893e12c5d1SDavid du Colombier 2903e12c5d1SDavid du Colombier while(cmdlist.nused > 0) 29173e742d7SDavid du Colombier free(cmdlist.voidpptr[--cmdlist.nused]); 2923e12c5d1SDavid du Colombier while(addrlist.nused > 0) 29373e742d7SDavid du Colombier free(addrlist.voidpptr[--addrlist.nused]); 2943e12c5d1SDavid du Colombier while(relist.nused > 0){ 2953e12c5d1SDavid du Colombier i = --relist.nused; 2963e12c5d1SDavid du Colombier Strclose(relist.stringpptr[i]); 2973e12c5d1SDavid du Colombier free(relist.stringpptr[i]); 2983e12c5d1SDavid du Colombier } 2993e12c5d1SDavid du Colombier while(stringlist.nused>0){ 3003e12c5d1SDavid du Colombier i = --stringlist.nused; 3013e12c5d1SDavid du Colombier Strclose(stringlist.stringpptr[i]); 3023e12c5d1SDavid du Colombier free(stringlist.stringpptr[i]); 3033e12c5d1SDavid du Colombier } 3043e12c5d1SDavid du Colombier } 3053e12c5d1SDavid du Colombier 3063e12c5d1SDavid du Colombier int 3073e12c5d1SDavid du Colombier lookup(int c) 3083e12c5d1SDavid du Colombier { 3093e12c5d1SDavid du Colombier int i; 3103e12c5d1SDavid du Colombier 3113e12c5d1SDavid du Colombier for(i=0; cmdtab[i].cmdc; i++) 3123e12c5d1SDavid du Colombier if(cmdtab[i].cmdc == c) 3133e12c5d1SDavid du Colombier return i; 3143e12c5d1SDavid du Colombier return -1; 3153e12c5d1SDavid du Colombier } 3163e12c5d1SDavid du Colombier 3173e12c5d1SDavid du Colombier void 3183e12c5d1SDavid du Colombier okdelim(int c) 3193e12c5d1SDavid du Colombier { 3203e12c5d1SDavid du Colombier if(c=='\\' || ('a'<=c && c<='z') 3213e12c5d1SDavid du Colombier || ('A'<=c && c<='Z') || ('0'<=c && c<='9')) 3223e12c5d1SDavid du Colombier error_c(Edelim, c); 3233e12c5d1SDavid du Colombier } 3243e12c5d1SDavid du Colombier 3253e12c5d1SDavid du Colombier void 3263e12c5d1SDavid du Colombier atnl(void) 3273e12c5d1SDavid du Colombier { 3283e12c5d1SDavid du Colombier skipbl(); 3293e12c5d1SDavid du Colombier if(getch() != '\n') 3303e12c5d1SDavid du Colombier error(Enewline); 3313e12c5d1SDavid du Colombier } 3323e12c5d1SDavid du Colombier 3333e12c5d1SDavid du Colombier void 3343e12c5d1SDavid du Colombier getrhs(String *s, int delim, int cmd) 3353e12c5d1SDavid du Colombier { 3363e12c5d1SDavid du Colombier int c; 3373e12c5d1SDavid du Colombier 3383e12c5d1SDavid du Colombier while((c = getch())>0 && c!=delim && c!='\n'){ 3393e12c5d1SDavid du Colombier if(c == '\\'){ 3403e12c5d1SDavid du Colombier if((c=getch()) <= 0) 3413e12c5d1SDavid du Colombier error(Ebadrhs); 3423e12c5d1SDavid du Colombier if(c == '\n'){ 3433e12c5d1SDavid du Colombier ungetch(); 3443e12c5d1SDavid du Colombier c='\\'; 3453e12c5d1SDavid du Colombier }else if(c == 'n') 3463e12c5d1SDavid du Colombier c='\n'; 3473e12c5d1SDavid du Colombier else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */ 3483e12c5d1SDavid du Colombier Straddc(s, '\\'); 3493e12c5d1SDavid du Colombier } 3503e12c5d1SDavid du Colombier Straddc(s, c); 3513e12c5d1SDavid du Colombier } 3523e12c5d1SDavid du Colombier ungetch(); /* let client read whether delimeter, '\n' or whatever */ 3533e12c5d1SDavid du Colombier } 3543e12c5d1SDavid du Colombier 3553e12c5d1SDavid du Colombier String * 3563e12c5d1SDavid du Colombier collecttoken(char *end) 3573e12c5d1SDavid du Colombier { 3583e12c5d1SDavid du Colombier String *s = newstring(); 3593e12c5d1SDavid du Colombier int c; 3603e12c5d1SDavid du Colombier 3613e12c5d1SDavid du Colombier while((c=nextc())==' ' || c=='\t') 3623e12c5d1SDavid du Colombier Straddc(s, getch()); /* blanks significant for getname() */ 3633e12c5d1SDavid du Colombier while((c=getch())>0 && utfrune(end, c)==0) 3643e12c5d1SDavid du Colombier Straddc(s, c); 3653e12c5d1SDavid du Colombier Straddc(s, 0); 3663e12c5d1SDavid du Colombier if(c != '\n') 3673e12c5d1SDavid du Colombier atnl(); 3683e12c5d1SDavid du Colombier return s; 3693e12c5d1SDavid du Colombier } 3703e12c5d1SDavid du Colombier 3713e12c5d1SDavid du Colombier String * 3723e12c5d1SDavid du Colombier collecttext(void) 3733e12c5d1SDavid du Colombier { 3743e12c5d1SDavid du Colombier String *s = newstring(); 3753e12c5d1SDavid du Colombier int begline, i, c, delim; 3763e12c5d1SDavid du Colombier 3773e12c5d1SDavid du Colombier if(skipbl()=='\n'){ 3783e12c5d1SDavid du Colombier getch(); 3793e12c5d1SDavid du Colombier i = 0; 3803e12c5d1SDavid du Colombier do{ 3813e12c5d1SDavid du Colombier begline = i; 3823e12c5d1SDavid du Colombier while((c = getch())>0 && c!='\n') 3833e12c5d1SDavid du Colombier i++, Straddc(s, c); 3843e12c5d1SDavid du Colombier i++, Straddc(s, '\n'); 3853e12c5d1SDavid du Colombier if(c < 0) 3863e12c5d1SDavid du Colombier goto Return; 3873e12c5d1SDavid du Colombier }while(s->s[begline]!='.' || s->s[begline+1]!='\n'); 3883e12c5d1SDavid du Colombier Strdelete(s, s->n-2, s->n); 3893e12c5d1SDavid du Colombier }else{ 3903e12c5d1SDavid du Colombier okdelim(delim = getch()); 3913e12c5d1SDavid du Colombier getrhs(s, delim, 'a'); 3923e12c5d1SDavid du Colombier if(nextc()==delim) 3933e12c5d1SDavid du Colombier getch(); 3943e12c5d1SDavid du Colombier atnl(); 3953e12c5d1SDavid du Colombier } 3963e12c5d1SDavid du Colombier Return: 3973e12c5d1SDavid du Colombier Straddc(s, 0); /* JUST FOR CMDPRINT() */ 3983e12c5d1SDavid du Colombier return s; 3993e12c5d1SDavid du Colombier } 4003e12c5d1SDavid du Colombier 4013e12c5d1SDavid du Colombier Cmd * 4023e12c5d1SDavid du Colombier parsecmd(int nest) 4033e12c5d1SDavid du Colombier { 4043e12c5d1SDavid du Colombier int i, c; 4055e91980fSDavid du Colombier Cmdtab *ct; 4063e12c5d1SDavid du Colombier Cmd *cp, *ncp; 4073e12c5d1SDavid du Colombier Cmd cmd; 4083e12c5d1SDavid du Colombier 4093e12c5d1SDavid du Colombier cmd.next = cmd.ccmd = 0; 4103e12c5d1SDavid du Colombier cmd.re = 0; 4113e12c5d1SDavid du Colombier cmd.flag = cmd.num = 0; 4123e12c5d1SDavid du Colombier cmd.addr = compoundaddr(); 4133e12c5d1SDavid du Colombier if(skipbl() == -1) 4143e12c5d1SDavid du Colombier return 0; 4153e12c5d1SDavid du Colombier if((c=getch())==-1) 4163e12c5d1SDavid du Colombier return 0; 4173e12c5d1SDavid du Colombier cmd.cmdc = c; 4183e12c5d1SDavid du Colombier if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */ 4193e12c5d1SDavid du Colombier getch(); /* the 'd' */ 4203e12c5d1SDavid du Colombier cmd.cmdc='c'|0x100; 4213e12c5d1SDavid du Colombier } 4223e12c5d1SDavid du Colombier i = lookup(cmd.cmdc); 4233e12c5d1SDavid du Colombier if(i >= 0){ 4243e12c5d1SDavid du Colombier if(cmd.cmdc == '\n') 4253e12c5d1SDavid du Colombier goto Return; /* let nl_cmd work it all out */ 4263e12c5d1SDavid du Colombier ct = &cmdtab[i]; 4273e12c5d1SDavid du Colombier if(ct->defaddr==aNo && cmd.addr) 4283e12c5d1SDavid du Colombier error(Enoaddr); 4293e12c5d1SDavid du Colombier if(ct->count) 4307dd7cddfSDavid du Colombier cmd.num = getnum(ct->count); 4313e12c5d1SDavid du Colombier if(ct->regexp){ 4323e12c5d1SDavid du Colombier /* x without pattern -> .*\n, indicated by cmd.re==0 */ 4333e12c5d1SDavid du Colombier /* X without pattern is all files */ 4343e12c5d1SDavid du Colombier if((ct->cmdc!='x' && ct->cmdc!='X') || 4353e12c5d1SDavid du Colombier ((c = nextc())!=' ' && c!='\t' && c!='\n')){ 4363e12c5d1SDavid du Colombier skipbl(); 4373e12c5d1SDavid du Colombier if((c = getch())=='\n' || c<0) 4383e12c5d1SDavid du Colombier error(Enopattern); 4393e12c5d1SDavid du Colombier okdelim(c); 4403e12c5d1SDavid du Colombier cmd.re = getregexp(c); 4413e12c5d1SDavid du Colombier if(ct->cmdc == 's'){ 4423e12c5d1SDavid du Colombier cmd.ctext = newstring(); 4433e12c5d1SDavid du Colombier getrhs(cmd.ctext, c, 's'); 4443e12c5d1SDavid du Colombier if(nextc() == c){ 4453e12c5d1SDavid du Colombier getch(); 4463e12c5d1SDavid du Colombier if(nextc() == 'g') 4473e12c5d1SDavid du Colombier cmd.flag = getch(); 4483e12c5d1SDavid du Colombier } 4493e12c5d1SDavid du Colombier 4503e12c5d1SDavid du Colombier } 4513e12c5d1SDavid du Colombier } 4523e12c5d1SDavid du Colombier } 4533e12c5d1SDavid du Colombier if(ct->addr && (cmd.caddr=simpleaddr())==0) 4543e12c5d1SDavid du Colombier error(Eaddress); 4553e12c5d1SDavid du Colombier if(ct->defcmd){ 4563e12c5d1SDavid du Colombier if(skipbl() == '\n'){ 4573e12c5d1SDavid du Colombier getch(); 4583e12c5d1SDavid du Colombier cmd.ccmd = newcmd(); 4593e12c5d1SDavid du Colombier cmd.ccmd->cmdc = ct->defcmd; 4603e12c5d1SDavid du Colombier }else if((cmd.ccmd = parsecmd(nest))==0) 4613e12c5d1SDavid du Colombier panic("defcmd"); 4623e12c5d1SDavid du Colombier }else if(ct->text) 4633e12c5d1SDavid du Colombier cmd.ctext = collecttext(); 4643e12c5d1SDavid du Colombier else if(ct->token) 4653e12c5d1SDavid du Colombier cmd.ctext = collecttoken(ct->token); 4663e12c5d1SDavid du Colombier else 4673e12c5d1SDavid du Colombier atnl(); 4683e12c5d1SDavid du Colombier }else 4693e12c5d1SDavid du Colombier switch(cmd.cmdc){ 4703e12c5d1SDavid du Colombier case '{': 4713e12c5d1SDavid du Colombier cp = 0; 4723e12c5d1SDavid du Colombier do{ 4733e12c5d1SDavid du Colombier if(skipbl()=='\n') 4743e12c5d1SDavid du Colombier getch(); 4753e12c5d1SDavid du Colombier ncp = parsecmd(nest+1); 4763e12c5d1SDavid du Colombier if(cp) 4773e12c5d1SDavid du Colombier cp->next = ncp; 4783e12c5d1SDavid du Colombier else 4793e12c5d1SDavid du Colombier cmd.ccmd = ncp; 4803e12c5d1SDavid du Colombier }while(cp = ncp); 4813e12c5d1SDavid du Colombier break; 4823e12c5d1SDavid du Colombier case '}': 4833e12c5d1SDavid du Colombier atnl(); 4843e12c5d1SDavid du Colombier if(nest==0) 4853e12c5d1SDavid du Colombier error(Enolbrace); 4863e12c5d1SDavid du Colombier return 0; 4873e12c5d1SDavid du Colombier default: 4883e12c5d1SDavid du Colombier error_c(Eunk, cmd.cmdc); 4893e12c5d1SDavid du Colombier } 4903e12c5d1SDavid du Colombier Return: 4913e12c5d1SDavid du Colombier cp = newcmd(); 4923e12c5d1SDavid du Colombier *cp = cmd; 4933e12c5d1SDavid du Colombier return cp; 4943e12c5d1SDavid du Colombier } 4953e12c5d1SDavid du Colombier 4963e12c5d1SDavid du Colombier String* /* BUGGERED */ 4973e12c5d1SDavid du Colombier getregexp(int delim) 4983e12c5d1SDavid du Colombier { 4993e12c5d1SDavid du Colombier String *r = newre(); 5003e12c5d1SDavid du Colombier int c; 5013e12c5d1SDavid du Colombier 5023e12c5d1SDavid du Colombier for(Strzero(&genstr); ; Straddc(&genstr, c)) 5033e12c5d1SDavid du Colombier if((c = getch())=='\\'){ 5043e12c5d1SDavid du Colombier if(nextc()==delim) 5053e12c5d1SDavid du Colombier c = getch(); 5063e12c5d1SDavid du Colombier else if(nextc()=='\\'){ 5073e12c5d1SDavid du Colombier Straddc(&genstr, c); 5083e12c5d1SDavid du Colombier c = getch(); 5093e12c5d1SDavid du Colombier } 5103e12c5d1SDavid du Colombier }else if(c==delim || c=='\n') 5113e12c5d1SDavid du Colombier break; 5123e12c5d1SDavid du Colombier if(c!=delim && c) 5133e12c5d1SDavid du Colombier ungetch(); 5143e12c5d1SDavid du Colombier if(genstr.n > 0){ 5153e12c5d1SDavid du Colombier patset = TRUE; 5163e12c5d1SDavid du Colombier Strduplstr(&lastpat, &genstr); 5173e12c5d1SDavid du Colombier Straddc(&lastpat, '\0'); 5183e12c5d1SDavid du Colombier } 5193e12c5d1SDavid du Colombier if(lastpat.n <= 1) 5203e12c5d1SDavid du Colombier error(Epattern); 5213e12c5d1SDavid du Colombier Strduplstr(r, &lastpat); 5223e12c5d1SDavid du Colombier return r; 5233e12c5d1SDavid du Colombier } 5243e12c5d1SDavid du Colombier 5253e12c5d1SDavid du Colombier Addr * 5263e12c5d1SDavid du Colombier simpleaddr(void) 5273e12c5d1SDavid du Colombier { 5283e12c5d1SDavid du Colombier Addr addr; 5293e12c5d1SDavid du Colombier Addr *ap, *nap; 5303e12c5d1SDavid du Colombier 5313e12c5d1SDavid du Colombier addr.next = 0; 5323e12c5d1SDavid du Colombier addr.left = 0; 5333e12c5d1SDavid du Colombier switch(skipbl()){ 5343e12c5d1SDavid du Colombier case '#': 5353e12c5d1SDavid du Colombier addr.type = getch(); 5367dd7cddfSDavid du Colombier addr.num = getnum(1); 5373e12c5d1SDavid du Colombier break; 5383e12c5d1SDavid du Colombier case '0': case '1': case '2': case '3': case '4': 5393e12c5d1SDavid du Colombier case '5': case '6': case '7': case '8': case '9': 5407dd7cddfSDavid du Colombier addr.num = getnum(1); 5413e12c5d1SDavid du Colombier addr.type='l'; 5423e12c5d1SDavid du Colombier break; 5433e12c5d1SDavid du Colombier case '/': case '?': case '"': 5443e12c5d1SDavid du Colombier addr.are = getregexp(addr.type = getch()); 5453e12c5d1SDavid du Colombier break; 5463e12c5d1SDavid du Colombier case '.': 5473e12c5d1SDavid du Colombier case '$': 5483e12c5d1SDavid du Colombier case '+': 5493e12c5d1SDavid du Colombier case '-': 5503e12c5d1SDavid du Colombier case '\'': 5513e12c5d1SDavid du Colombier addr.type = getch(); 5523e12c5d1SDavid du Colombier break; 5533e12c5d1SDavid du Colombier default: 5543e12c5d1SDavid du Colombier return 0; 5553e12c5d1SDavid du Colombier } 5563e12c5d1SDavid du Colombier if(addr.next = simpleaddr()) 5573e12c5d1SDavid du Colombier switch(addr.next->type){ 5583e12c5d1SDavid du Colombier case '.': 5593e12c5d1SDavid du Colombier case '$': 5603e12c5d1SDavid du Colombier case '\'': 5613e12c5d1SDavid du Colombier if(addr.type!='"') 5623e12c5d1SDavid du Colombier case '"': 5633e12c5d1SDavid du Colombier error(Eaddress); 5643e12c5d1SDavid du Colombier break; 5653e12c5d1SDavid du Colombier case 'l': 5663e12c5d1SDavid du Colombier case '#': 5673e12c5d1SDavid du Colombier if(addr.type=='"') 5683e12c5d1SDavid du Colombier break; 5693e12c5d1SDavid du Colombier /* fall through */ 5703e12c5d1SDavid du Colombier case '/': 5713e12c5d1SDavid du Colombier case '?': 5723e12c5d1SDavid du Colombier if(addr.type!='+' && addr.type!='-'){ 5733e12c5d1SDavid du Colombier /* insert the missing '+' */ 5743e12c5d1SDavid du Colombier nap = newaddr(); 5753e12c5d1SDavid du Colombier nap->type='+'; 5763e12c5d1SDavid du Colombier nap->next = addr.next; 5773e12c5d1SDavid du Colombier addr.next = nap; 5783e12c5d1SDavid du Colombier } 5793e12c5d1SDavid du Colombier break; 5803e12c5d1SDavid du Colombier case '+': 5813e12c5d1SDavid du Colombier case '-': 5823e12c5d1SDavid du Colombier break; 5833e12c5d1SDavid du Colombier default: 5843e12c5d1SDavid du Colombier panic("simpleaddr"); 5853e12c5d1SDavid du Colombier } 5863e12c5d1SDavid du Colombier ap = newaddr(); 5873e12c5d1SDavid du Colombier *ap = addr; 5883e12c5d1SDavid du Colombier return ap; 5893e12c5d1SDavid du Colombier } 5903e12c5d1SDavid du Colombier 5913e12c5d1SDavid du Colombier Addr * 5923e12c5d1SDavid du Colombier compoundaddr(void) 5933e12c5d1SDavid du Colombier { 5943e12c5d1SDavid du Colombier Addr addr; 5953e12c5d1SDavid du Colombier Addr *ap, *next; 5963e12c5d1SDavid du Colombier 5973e12c5d1SDavid du Colombier addr.left = simpleaddr(); 5983e12c5d1SDavid du Colombier if((addr.type = skipbl())!=',' && addr.type!=';') 5993e12c5d1SDavid du Colombier return addr.left; 6003e12c5d1SDavid du Colombier getch(); 6013e12c5d1SDavid du Colombier next = addr.next = compoundaddr(); 6023e12c5d1SDavid du Colombier if(next && (next->type==',' || next->type==';') && next->left==0) 6033e12c5d1SDavid du Colombier error(Eaddress); 6043e12c5d1SDavid du Colombier ap = newaddr(); 6053e12c5d1SDavid du Colombier *ap = addr; 6063e12c5d1SDavid du Colombier return ap; 6073e12c5d1SDavid du Colombier } 608