String * collecttext(void) { String *s = newstring(); int begline, i, c, delim; if(skipbl()=='\n'){ getch(); i = 0; do{ begline = i; while((c = getch())>0 && c!='\n') i++, Straddc(s, c); i++, Straddc(s, '\n'); if(c < 0) goto Return; }while(s->s[begline]!='.' || s->s[begline+1]!='\n'); Strdelete(s, s->n-2, s->n); }else{ okdelim(delim = getch()); getrhs(s, delim, 'a'); if(nextc()==delim) getch(); atnl(); } Return: Straddc(s, 0); /* JUST FOR CMDPRINT() */ return s; }
String * collecttext(void) { String *s; int begline, i, c, delim; s = newstring(0); if(cmdskipbl()=='\n'){ getch(); i = 0; do{ begline = i; while((c = getch())>0 && c!='\n') i++, Straddc(s, c); i++, Straddc(s, '\n'); if(c < 0) goto Return; }while(s->r[begline]!='.' || s->r[begline+1]!='\n'); s->r[s->n-2] = '\0'; s->n -= 2; }else{ okdelim(delim = getch()); getrhs(s, delim, 'a'); if(nextc()==delim) getch(); atnl(); } Return: return s; }
Cmd * parsecmd(int nest) { int i, c; Cmdtab *ct; Cmd *cp, *ncp; Cmd cmd; cmd.next = cmd.ccmd = 0; cmd.re = 0; cmd.flag = cmd.num = 0; cmd.addr = compoundaddr(); if(skipbl() == -1) return 0; if((c=getch())==-1) return 0; cmd.cmdc = c; if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */ getch(); /* the 'd' */ cmd.cmdc='c'|0x100; } i = lookup(cmd.cmdc); if(i >= 0){ if(cmd.cmdc == '\n') goto Return; /* let nl_cmd work it all out */ ct = &cmdtab[i]; if(ct->defaddr==aNo && cmd.addr) error(Enoaddr); if(ct->count) cmd.num = getnum(ct->count); if(ct->regexp){ /* x without pattern -> .*\n, indicated by cmd.re==0 */ /* X without pattern is all files */ if((ct->cmdc!='x' && ct->cmdc!='X') || ((c = nextc())!=' ' && c!='\t' && c!='\n')){ skipbl(); if((c = getch())=='\n' || c<0) error(Enopattern); okdelim(c); cmd.re = getregexp(c); if(ct->cmdc == 's'){ cmd.ctext = newstring(); getrhs(cmd.ctext, c, 's'); if(nextc() == c){ getch(); if(nextc() == 'g') cmd.flag = getch(); } } } } if(ct->addr && (cmd.caddr=simpleaddr())==0) error(Eaddress); if(ct->defcmd){ if(skipbl() == '\n'){ getch(); cmd.ccmd = newcmd(); cmd.ccmd->cmdc = ct->defcmd; }else if((cmd.ccmd = parsecmd(nest))==0) panic("defcmd"); }else if(ct->text) cmd.ctext = collecttext(); else if(ct->token) cmd.ctext = collecttoken(ct->token); else atnl(); }else switch(cmd.cmdc){ case '{': cp = 0; do{ if(skipbl()=='\n') getch(); ncp = parsecmd(nest+1); if(cp) cp->next = ncp; else cmd.ccmd = ncp; }while(cp = ncp); break; case '}': atnl(); if(nest==0) error(Enolbrace); return 0; default: error_c(Eunk, cmd.cmdc); } Return: cp = newcmd(); *cp = cmd; return cp; }