/*% cc -c -O % */ #include "vars.h" char *next_new; char *next_old; int new_line; int old_line; char rhsbuf[RHSIZE]; substitute(inglob, reg) { register int n, m; register char *p; char *q; int *a1; int gsubf; extern int getsub(); int t, count, autop=0; count=0; t = FALSE; n=getnum(); gsubf = compsub(TRUE, &autop); if(reg!= -1){ /* Substitution in a register */ cpstr(string[reg].str, linebuf); loc2=0; /* signal execute to take line from linebuf */ a1=0; goto Do_it; } for (a1 = addr1; a1 <= addr2 && reg==-1; a1++) { Do_it: if (execute(a1)) { next_old=linebuf; next_new=genbuf; m=n; do { if (--m <= 0) { dosub(); t = TRUE; count++; if (!gsubf) break; } /* can't find something at EOL twice */ if (*loc2=='\0') break; /* can't match same location twice */ if (loc1==loc2) loc2++; } while (execute((int *)0)); if (m<=0) { inglob |= TRUE; p=next_old; do ; while (*p++); place(next_old,p,0); if(reg==-1){ p=linebuf; q=genbuf; do ; while (*p++ = *q++); replace(a1,putline()); m=append(getsub,a1); a1 += m; addr2 += m; }else{ startstring(); copystring(genbuf); setstring(reg); } } } } if (!inglob) error('s'); settruth(t); setcount(count); if(autop) if(reg>=0) puts(string[reg].str); else{ addr1=addr2=dot; display('p'); } } compsub(subbing, autop) int subbing; int *autop; { register int seof, c; char *rhsmagic; register char *p; int getsvc(); *autop=FALSE; seof = getchar(); if(subbing) { compile(seof); rhsmagic = "/&^\n\\123456789"; } else rhsmagic = "/\\\n"; rhsmagic[0] = seof; p = rhsbuf; startstring(); for (;;) { c = getquote(rhsmagic, getsvc); if (c=='\n' || c==EOF){ *autop=TRUE; ungetchar('\n'); break; } if (c==seof) break; *p++ = c; if (p >= &rhsbuf[RHSIZE]) error('l'); } *p = 0; dropstring(); setstring(SAVRHS); if (subbing && nextchar() == 'g') { getchar(); /* clear 'g' */ return(1); } return(0); } int getsub() { register char *p1, *p2; p1 = linebuf; if ((p2 = linebp) == 0) return(EOF); do ; while (*p1++ = (*p2++ & 0177)); linebp = 0; return(0); } dosub() { register int c; register char *p; place(next_old,loc1,0); next_old=loc2; p=rhsbuf; while (c = *p++) { if (c=='&' || (c == '^' && uflag)) place(loc1,loc2,c=='^'); else if ((c&0200) && (c &= 0177)>='1' && c<'1'+nbra) place(braslist[c-'1'],braelist[c-'1'], 0); else { *next_new++ = c; if (next_new >= genbuf+LBSIZE) error('l'); } } } place(l1, l2, ucase) register char *l1; char *l2; { register char *sp; register c; sp = next_new; while (l1 < l2) { *sp++ = (*l1++ & 0177); if (sp >= &genbuf[LBSIZE]) error('l'); } if(ucase){ for(l1 = next_new;l1 < sp;){ c = (*l1 & 0177); if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){ switch(uflag){ case 's': *l1++ ^= 040; break; case 'u': *l1++ &= ~040; break; case 'l': *l1++ |= 040; break; default: l1++; } }else{ l1++; } } } next_new = sp; } undo() { register int *l; for (l=zero+1; l<=dol && (*l|01)!=new_line; l++) ; if (l>dol) error('u'); replace(l,old_line); dot=l; } replace(line,ptr) register int *line; register int ptr; { register int *p; *line |= 01; for (p=names; p<names+NBUFS; p++) if (*p == *line) *p = ptr|01; old_line = *line; *line = ptr; new_line = ptr | 01; } join() { register int *l; register char *p, *q; int rep; int autop=FALSE; rep=FALSE; if(nextchar() == '/'){ compsub(FALSE, &autop); rep=TRUE; } p = genbuf; for (l=addr1; ;) { q = getline(*l++, linebuf); while (*q) { *p++ = *q++; if (p >= genbuf + sizeof genbuf) error('l'); } if(l > addr2) break; if(rep) { q = string[SAVRHS].str; while (*q) { *p++ = *q++; if (p >= genbuf + sizeof genbuf) error('l'); } } } *p = '\0'; linebp=p=linebuf; q=genbuf; do ; while (*p++ = *q++); getsub(); *(l=addr1++)=putline(); /* if you want marks preserved for join, change the above line to /* the one commented out here. /* problem: undo then undoes the join, but gets it wrong. Your choice. replace(l=addr1++, putline()); */ if(l != addr2) delete(); append(getsub, l); if(autop){ addr1=addr2=dot; display('p'); } } int next_col(col,cp,input) register int col; register char *cp; int input; { register c; c = *cp; if (c=='\t') col |= 07; else if (c<' ' || c=='\177') error('t'); /* invalid character in x data */ else if (input && (c==ttybuf.sg_erase || c==ttybuf.sg_kill)) col++; /* One column for the backslash */ return (++col); } xform() { register char *i, *m, *o; int *line, insert, change, ic, mc, c; char *tf, *tl; if(getchar() != '\n') error('x'); for (line=addr1; line<=addr2; line++) { getline(*line, linebuf); change=FALSE; dot=line; for(;;){ puts(linebuf); pushinp(XTTY, 0, FALSE); m=rhsbuf; while ((c = getchar())!='\n') { if (c == EOF) error('t'); /* unexpected EOF */ *m++ = c; if (m==rhsbuf+RHSIZE-1) error('l'); /* out of space */ } *m='\0'; if (m==rhsbuf) break; change++; i=linebuf; o=genbuf; do ; while (*o++ = *i++); if (i+(m-rhsbuf) > linebuf+LBSIZE) error('l'); /* out of space */ i=genbuf; o=linebuf; m=rhsbuf; insert=FALSE; ic=0; mc=0; while (*i && *m && !insert) { if(*i=='\t' && *m!='#' && *m!='^' && *m!='$') { ic=next_col(ic,i,FALSE); tf=m; tl=m; do { if (*m!=' ' && *m!='\t') { if(*m=='%') *m=' '; tl=m+1; } mc=next_col(mc,m++,TRUE); } while (ic>mc && *m && *m!='#' && *m!='^' && *m!='$'); if (ic>mc) { ic=mc; if (*m) tl=m; } else { if (tl==m) i++; else ic--; } while (tf!=tl) *o++ = *tf++; } else { mc=next_col(mc,m,TRUE); *o = *m; switch (*m++) { case ' ': case '\t': break; case '^': mc=ic; insert++; break; case '$': i=""; break; case '#': ic=next_col(ic,i++,FALSE); while(*m=='#' && ic>mc) mc=next_col(mc,m++,TRUE); if (ic!=mc) error('t'); break; case '%': *o = ' '; /* fall through */ default: o++; ic=next_col(ic,i++,FALSE); } /* switch */ } /* else */ for (;;) { if (ic>mc && *m) { if (*m!=' ' && *m!='\t') error('t'); mc=next_col(mc,m++,TRUE); } else if (mc>ic && *i) { ic=next_col(ic,i,FALSE); *o++ = *i++; } else break; } } /* while */ if (mc>ic && m[-1]=='\t') *o++ = '\t'; if (insert && (*o++ = *m++) == '\0') { replace(line,putline()); linebp=i; append(getsub,line); line++; addr2++; change = FALSE; } else { while (*m) *o++ = *m++; do ; while (*o++ = *i++); } } if (change) replace(line,putline()); } /* for */ }