static int compsub(int ch) { register int seof, c; int gsubf; gsubf = 0; xflag = 0; switch (ch) { case 's': ignore(skipwh()); seof = ex_getchar(); if (endcmd(seof)) error("Substitute needs re|Missing regular expression for substitute"); seof = compile(seof, 1); savere(subre); comprhs(seof); break; case '&': if (subre.Expbuf[0] == 0) error("No previous substitute re|No previous substitute to repeat"); resre(subre); break; case '~': if (re.Expbuf[0] == 0) error("No previous re|No previous regular expression"); savere(subre); break; } for (;;) { c = ex_getchar(); switch (c) { case 'g': gsubf++; continue; case 'c': xflag++; continue; default: ungetchar(c); setcount(); ex_newline(); return (gsubf); } } }
/* * Parse an address. * Just about any sequence of address characters is legal. * * If you are tricky you can use this routine and the = command * to do simple addition and subtraction of cardinals less * than the number of lines in the file. */ line * address(char *inputline) { register line *addr; register int offset, c; short lastsign; bigmove = 0; lastsign = 0; offset = 0; addr = 0; for (;;) { if (isdigit(peekcd())) { if (addr == 0) { addr = zero; bigmove = 1; } loc1 = 0; addr += offset; offset = getnum(); if (lastsign >= 0) addr += offset; else addr -= offset; lastsign = 0; offset = 0; } switch (c = getcd()) { case '?': case '/': case '$': case '\'': case '\\': bigmove++; case '.': if (addr || offset) error("Badly formed address"); } offset += lastsign; lastsign = 0; switch (c) { case ' ': case '\t': continue; case '+': lastsign = 1; if (addr == 0) addr = dot; continue; case '^': case '-': lastsign = -1; if (addr == 0) addr = dot; continue; case '\\': case '?': case '/': c = compile(c, 1); notempty(); savere(scanre); addr = dot; if (inputline && execute(0, dot)) { if (c == '/') { while (loc1 <= inputline) { if (loc1 == loc2) loc2++; if (!execute(1, NULL)) goto nope; } break; } else if (loc1 < inputline) { char *last; doques: do { last = loc1; if (loc1 == loc2) loc2++; if (!execute(1, NULL)) break; } while (loc1 < inputline); loc1 = last; break; } } nope: for (;;) { if (c == '/') { addr++; if (addr > dol) { if (value(WRAPSCAN) == 0) error("No match to BOTTOM|Address search hit BOTTOM without matching pattern"); addr = zero; } } else { addr--; if (addr < zero) { if (value(WRAPSCAN) == 0) error("No match to TOP|Address search hit TOP without matching pattern"); addr = dol; } } if (execute(0, addr)) { if (inputline && c == '?') { inputline = &linebuf[LBSIZE]; goto doques; } break; } if (addr == dot) error("Fail|Pattern not found"); } continue; case '$': addr = dol; continue; case '.': addr = dot; continue; case '\'': c = markreg(ex_getchar()); if (c == 0) error("Marks are ' and a-z"); addr = getmark(c); if (addr == 0) error("Undefined mark@referenced"); break; default: ungetchar(c); if (offset) { if (addr == 0) addr = dot; addr += offset; loc1 = 0; } if (addr == 0) { bigmove = 0; return (0); } if (addr != zero) notempty(); addr += lastsign; if (addr < zero) error("Negative address@- first buffer line is 1"); if (addr > dol) error("Not that many lines@in buffer"); return (addr); } } }
oop() { register char *ic; #ifndef u370 char atube[TUBESIZE + LBSIZE]; #endif ttymode f; /* mjm: was register */ int resize; if (resize = setjmp(venv)) { setsize(); initev = (char *)0; inopen = 0; addr1 = addr2 = dot; } (void)signal(SIGWINCH, winch); ovbeg(); if (peekchar() == '/') { ignore(compile(getchar(), 1)); savere(scanre); if (execute(0, dot) == 0) error("Fail|Pattern not found on addressed line"); ic = loc1; if (ic > linebuf && *ic == 0) ic--; } else { getDOT(); ic = vskipwh(linebuf); } newline(); /* * If overstrike then have to HARDOPEN * else if can move cursor up off current line can use CRTOPEN (~~vi1) * otherwise (ugh) have to use ONEOPEN (like adm3) */ if (OS && !EO) bastate = HARDOPEN; else if (CA || UP) bastate = CRTOPEN; else bastate = ONEOPEN; setwind(); /* * To avoid bombing on glass-crt's when the line is too long * pretend that such terminals are 160 columns wide. * If a line is too wide for display, we will dynamically * switch to hardcopy open mode. */ if (state != CRTOPEN) WCOLS = TUBECOLS; if (!inglobal) savevis(); vok(atube); if (state != CRTOPEN) COLUMNS = WCOLS; Outchar = vputchar; f = ostart(); if (state == CRTOPEN) { if (outcol == UKCOL) outcol = 0; vmoveitup(1, 1); } else outline = destline = WBOT; vshow(dot, NOLINE); vnline(ic); vmain(); if (state != CRTOPEN) vclean(); Command = "open"; ovend(f); (void)signal(SIGWINCH, SIG_DFL); }
void global(bool k) { register char *gp; register int c; register line *a1; char globuf[GBSIZE], *Cwas; int lines = lineDOL(); char *oglobp = globp; Cwas = Command; if (inglobal) error("Global within global@not allowed"); markDOT(); setall(); nonzero(); if (skipend()) error("Global needs re|Missing regular expression for global"); c = ex_getchar(); ignore(compile(c, 0)); savere(scanre); gp = globuf; while ((c = ex_getchar()) != '\n') { switch (c) { case EOF: c = '\n'; goto brkwh; case '\\': c = ex_getchar(); switch (c) { case '\\': ungetchar(c); break; case '\n': break; default: *gp++ = '\\'; break; } break; } *gp++ = c; if (gp >= &globuf[GBSIZE - 2]) error("Global command too long"); } brkwh: ungetchar(c); ex_newline(); *gp++ = c; *gp++ = 0; inglobal = 1; for (a1 = one; a1 <= dol; a1++) { *a1 &= ~01; if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k) *a1 |= 01; } /* should use gdelete from ed to avoid n**2 here on g/.../d */ saveall(); if (inopen) inopen = -1; for (a1 = one; a1 <= dol; a1++) { if (*a1 & 01) { *a1 &= ~01; dot = a1; globp = globuf; commands(1, 1); a1 = zero; } } globp = oglobp; inglobal = 0; endline = 1; Command = Cwas; netchHAD(lines); setlastchar(EOF); if (inopen) { ungetchar(EOF); inopen = 1; } }