|
|
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.