17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*23a1cceaSRoger A. Faulkner * Common Development and Distribution License (the "License").
6*23a1cceaSRoger A. Faulkner * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21*23a1cceaSRoger A. Faulkner
22f6db9f27Scf46844 /*
23*23a1cceaSRoger A. Faulkner * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24f6db9f27Scf46844 */
25f6db9f27Scf46844
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
277c478bd9Sstevel@tonic-gate /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include "ex.h"
337c478bd9Sstevel@tonic-gate #include "ex_re.h"
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate /* from libgen */
367c478bd9Sstevel@tonic-gate char *_compile(const char *, char *, char *, int);
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate * The compiled-regular-expression storage areas (re, scanre, and subre)
407c478bd9Sstevel@tonic-gate * have been changed into dynamically allocated memory areas, in both the
417c478bd9Sstevel@tonic-gate * Solaris and XPG4 versions.
427c478bd9Sstevel@tonic-gate *
437c478bd9Sstevel@tonic-gate * In the Solaris version, which uses the original libgen(3g) compile()
447c478bd9Sstevel@tonic-gate * and step() calls, these areas are allocated once, and then data are
457c478bd9Sstevel@tonic-gate * copied between them subsequently, as they were in the original
467c478bd9Sstevel@tonic-gate * implementation. This is possible because the compiled information is
477c478bd9Sstevel@tonic-gate * a self-contained block of bits.
487c478bd9Sstevel@tonic-gate *
497c478bd9Sstevel@tonic-gate * In the XPG4 version, the expr:compile.o object is linked in as a
507c478bd9Sstevel@tonic-gate * simulation of these functions using the new regcomp() and regexec()
517c478bd9Sstevel@tonic-gate * functions. The problem here is that the resulting
527c478bd9Sstevel@tonic-gate * compiled-regular-expression data contain pointers to other data, which
537c478bd9Sstevel@tonic-gate * need to be freed, but only when we are quite sure that we are done
547c478bd9Sstevel@tonic-gate * with them - and certainly not before. There was an earlier attempt to
557c478bd9Sstevel@tonic-gate * handle these differences, but that effort was flawed.
567c478bd9Sstevel@tonic-gate */
577c478bd9Sstevel@tonic-gate
58f6db9f27Scf46844 extern int getchar();
597c478bd9Sstevel@tonic-gate #ifdef XPG4
607c478bd9Sstevel@tonic-gate void regex_comp_free(void *);
617c478bd9Sstevel@tonic-gate extern size_t regexc_size; /* compile.c: size of regex_comp structure */
627c478bd9Sstevel@tonic-gate #endif /* XPG4 */
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate * Global, substitute and regular expressions.
667c478bd9Sstevel@tonic-gate * Very similar to ed, with some re extensions and
677c478bd9Sstevel@tonic-gate * confirmed substitute.
687c478bd9Sstevel@tonic-gate */
69f6db9f27Scf46844 void
global(k)707c478bd9Sstevel@tonic-gate global(k)
717c478bd9Sstevel@tonic-gate bool k;
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate unsigned char *gp;
747c478bd9Sstevel@tonic-gate int c;
757c478bd9Sstevel@tonic-gate line *a1;
767c478bd9Sstevel@tonic-gate unsigned char globuf[GBSIZE], *Cwas;
777c478bd9Sstevel@tonic-gate int nlines = lineDOL();
787c478bd9Sstevel@tonic-gate int oinglobal = inglobal;
797c478bd9Sstevel@tonic-gate unsigned char *oglobp = globp;
807c478bd9Sstevel@tonic-gate char multi[MB_LEN_MAX + 1];
817c478bd9Sstevel@tonic-gate wchar_t wc;
827c478bd9Sstevel@tonic-gate int len;
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate Cwas = Command;
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate * States of inglobal:
887c478bd9Sstevel@tonic-gate * 0: ordinary - not in a global command.
897c478bd9Sstevel@tonic-gate * 1: text coming from some buffer, not tty.
907c478bd9Sstevel@tonic-gate * 2: like 1, but the source of the buffer is a global command.
917c478bd9Sstevel@tonic-gate * Hence you're only in a global command if inglobal==2. This
927c478bd9Sstevel@tonic-gate * strange sounding convention is historically derived from
937c478bd9Sstevel@tonic-gate * everybody simulating a global command.
947c478bd9Sstevel@tonic-gate */
957c478bd9Sstevel@tonic-gate if (inglobal==2)
967c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Global within global") :
977c478bd9Sstevel@tonic-gate gettext("Global within global not allowed"));
987c478bd9Sstevel@tonic-gate markDOT();
997c478bd9Sstevel@tonic-gate setall();
1007c478bd9Sstevel@tonic-gate nonzero();
1017c478bd9Sstevel@tonic-gate if (skipend())
1027c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Global needs re") :
1037c478bd9Sstevel@tonic-gate gettext("Missing regular expression for global"));
1047c478bd9Sstevel@tonic-gate c = getchar();
1057c478bd9Sstevel@tonic-gate (void)vi_compile(c, 1);
1067c478bd9Sstevel@tonic-gate savere(&scanre);
1077c478bd9Sstevel@tonic-gate gp = globuf;
1087c478bd9Sstevel@tonic-gate while ((c = peekchar()) != '\n') {
1097c478bd9Sstevel@tonic-gate if (!isascii(c)) {
1107c478bd9Sstevel@tonic-gate if (c == EOF) {
1117c478bd9Sstevel@tonic-gate c = '\n';
1127c478bd9Sstevel@tonic-gate ungetchar(c);
1137c478bd9Sstevel@tonic-gate goto out;
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate mb_copy:
1177c478bd9Sstevel@tonic-gate if ((len = _mbftowc(multi, &wc, getchar, &peekc)) > 0) {
1187c478bd9Sstevel@tonic-gate if ((gp + len) >= &globuf[GBSIZE - 2])
1197c478bd9Sstevel@tonic-gate error(gettext("Global command too long"));
1207c478bd9Sstevel@tonic-gate strncpy(gp, multi, len);
1217c478bd9Sstevel@tonic-gate gp += len;
1227c478bd9Sstevel@tonic-gate continue;
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate (void) getchar();
1277c478bd9Sstevel@tonic-gate switch (c) {
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate case EOF:
1307c478bd9Sstevel@tonic-gate c = '\n';
1317c478bd9Sstevel@tonic-gate ungetchar(c);
1327c478bd9Sstevel@tonic-gate goto out;
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate case '\\':
1357c478bd9Sstevel@tonic-gate c = peekchar();
1367c478bd9Sstevel@tonic-gate if (!isascii(c)) {
1377c478bd9Sstevel@tonic-gate *gp++ = '\\';
1387c478bd9Sstevel@tonic-gate goto mb_copy;
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate (void) getchar();
1427c478bd9Sstevel@tonic-gate switch (c) {
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate case '\\':
1457c478bd9Sstevel@tonic-gate ungetchar(c);
1467c478bd9Sstevel@tonic-gate break;
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate case '\n':
1497c478bd9Sstevel@tonic-gate break;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate default:
1527c478bd9Sstevel@tonic-gate *gp++ = '\\';
1537c478bd9Sstevel@tonic-gate break;
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate break;
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate *gp++ = c;
1587c478bd9Sstevel@tonic-gate if (gp >= &globuf[GBSIZE - 2])
1597c478bd9Sstevel@tonic-gate error(gettext("Global command too long"));
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate out:
1637c478bd9Sstevel@tonic-gate donewline();
1647c478bd9Sstevel@tonic-gate *gp++ = c;
1657c478bd9Sstevel@tonic-gate *gp++ = 0;
1667c478bd9Sstevel@tonic-gate saveall();
1677c478bd9Sstevel@tonic-gate inglobal = 2;
1687c478bd9Sstevel@tonic-gate for (a1 = one; a1 <= dol; a1++) {
1697c478bd9Sstevel@tonic-gate *a1 &= ~01;
1707c478bd9Sstevel@tonic-gate if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k)
1717c478bd9Sstevel@tonic-gate *a1 |= 01;
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate #ifdef notdef
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate * This code is commented out for now. The problem is that we don't
1767c478bd9Sstevel@tonic-gate * fix up the undo area the way we should. Basically, I think what has
1777c478bd9Sstevel@tonic-gate * to be done is to copy the undo area down (since we shrunk everything)
1787c478bd9Sstevel@tonic-gate * and move the various pointers into it down too. I will do this later
1797c478bd9Sstevel@tonic-gate * when I have time. (Mark, 10-20-80)
1807c478bd9Sstevel@tonic-gate */
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate * Special case: g/.../d (avoid n^2 algorithm)
1837c478bd9Sstevel@tonic-gate */
1847c478bd9Sstevel@tonic-gate if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') {
1857c478bd9Sstevel@tonic-gate gdelete();
1867c478bd9Sstevel@tonic-gate return;
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate #endif
1897c478bd9Sstevel@tonic-gate if (inopen)
1907c478bd9Sstevel@tonic-gate inopen = -1;
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate * Now for each marked line, set dot there and do the commands.
1937c478bd9Sstevel@tonic-gate * Note the n^2 behavior here for lots of lines matching.
1947c478bd9Sstevel@tonic-gate * This is really needed: in some cases you could delete lines,
1957c478bd9Sstevel@tonic-gate * causing a marked line to be moved before a1 and missed if
1967c478bd9Sstevel@tonic-gate * we didn't restart at zero each time.
1977c478bd9Sstevel@tonic-gate */
1987c478bd9Sstevel@tonic-gate for (a1 = one; a1 <= dol; a1++) {
1997c478bd9Sstevel@tonic-gate if (*a1 & 01) {
2007c478bd9Sstevel@tonic-gate *a1 &= ~01;
2017c478bd9Sstevel@tonic-gate dot = a1;
2027c478bd9Sstevel@tonic-gate globp = globuf;
2037c478bd9Sstevel@tonic-gate commands(1, 1);
2047c478bd9Sstevel@tonic-gate a1 = zero;
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate globp = oglobp;
2087c478bd9Sstevel@tonic-gate inglobal = oinglobal;
2097c478bd9Sstevel@tonic-gate endline = 1;
2107c478bd9Sstevel@tonic-gate Command = Cwas;
2117c478bd9Sstevel@tonic-gate netchHAD(nlines);
2127c478bd9Sstevel@tonic-gate setlastchar(EOF);
2137c478bd9Sstevel@tonic-gate if (inopen) {
2147c478bd9Sstevel@tonic-gate ungetchar(EOF);
2157c478bd9Sstevel@tonic-gate inopen = 1;
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate * gdelete: delete inside a global command. Handles the
2217c478bd9Sstevel@tonic-gate * special case g/r.e./d. All lines to be deleted have
2227c478bd9Sstevel@tonic-gate * already been marked. Squeeze the remaining lines together.
2237c478bd9Sstevel@tonic-gate * Note that other cases such as g/r.e./p, g/r.e./s/r.e.2/rhs/,
2247c478bd9Sstevel@tonic-gate * and g/r.e./.,/r.e.2/d are not treated specially. There is no
2257c478bd9Sstevel@tonic-gate * good reason for this except the question: where to you draw the line?
2267c478bd9Sstevel@tonic-gate */
227f6db9f27Scf46844 void
gdelete(void)228f6db9f27Scf46844 gdelete(void)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate line *a1, *a2, *a3;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate a3 = dol;
2337c478bd9Sstevel@tonic-gate /* find first marked line. can skip all before it */
2347c478bd9Sstevel@tonic-gate for (a1=zero; (*a1&01)==0; a1++)
2357c478bd9Sstevel@tonic-gate if (a1>=a3)
2367c478bd9Sstevel@tonic-gate return;
2377c478bd9Sstevel@tonic-gate /* copy down unmarked lines, compacting as we go. */
2387c478bd9Sstevel@tonic-gate for (a2=a1+1; a2<=a3;) {
2397c478bd9Sstevel@tonic-gate if (*a2&01) {
2407c478bd9Sstevel@tonic-gate a2++; /* line is marked, skip it */
2417c478bd9Sstevel@tonic-gate dot = a1; /* dot left after line deletion */
2427c478bd9Sstevel@tonic-gate } else
2437c478bd9Sstevel@tonic-gate *a1++ = *a2++; /* unmarked, copy it */
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate dol = a1-1;
2467c478bd9Sstevel@tonic-gate if (dot>dol)
2477c478bd9Sstevel@tonic-gate dot = dol;
2487c478bd9Sstevel@tonic-gate change();
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate bool cflag;
2527c478bd9Sstevel@tonic-gate int scount, slines, stotal;
2537c478bd9Sstevel@tonic-gate
254f6db9f27Scf46844 int
substitute(int c)255f6db9f27Scf46844 substitute(int c)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate line *addr;
2587c478bd9Sstevel@tonic-gate int n;
2597c478bd9Sstevel@tonic-gate int gsubf, hopcount;
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate gsubf = compsub(c);
2627c478bd9Sstevel@tonic-gate if(FIXUNDO)
2637c478bd9Sstevel@tonic-gate save12(), undkind = UNDCHANGE;
2647c478bd9Sstevel@tonic-gate stotal = 0;
2657c478bd9Sstevel@tonic-gate slines = 0;
2667c478bd9Sstevel@tonic-gate for (addr = addr1; addr <= addr2; addr++) {
2677c478bd9Sstevel@tonic-gate scount = hopcount = 0;
2687c478bd9Sstevel@tonic-gate if (dosubcon(0, addr) == 0)
2697c478bd9Sstevel@tonic-gate continue;
2707c478bd9Sstevel@tonic-gate if (gsubf) {
2717c478bd9Sstevel@tonic-gate /*
2727c478bd9Sstevel@tonic-gate * The loop can happen from s/\</&/g
2737c478bd9Sstevel@tonic-gate * but we don't want to break other, reasonable cases.
2747c478bd9Sstevel@tonic-gate */
2757c478bd9Sstevel@tonic-gate hopcount = 0;
2767c478bd9Sstevel@tonic-gate while (*loc2) {
2777c478bd9Sstevel@tonic-gate if (++hopcount > sizeof linebuf)
2787c478bd9Sstevel@tonic-gate error(gettext("substitution loop"));
2797c478bd9Sstevel@tonic-gate if (dosubcon(1, addr) == 0)
2807c478bd9Sstevel@tonic-gate break;
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate if (scount) {
2847c478bd9Sstevel@tonic-gate stotal += scount;
2857c478bd9Sstevel@tonic-gate slines++;
2867c478bd9Sstevel@tonic-gate putmark(addr);
2877c478bd9Sstevel@tonic-gate n = append(getsub, addr);
2887c478bd9Sstevel@tonic-gate addr += n;
2897c478bd9Sstevel@tonic-gate addr2 += n;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate if (stotal == 0 && !inglobal && !cflag)
2937c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Fail") :
2947c478bd9Sstevel@tonic-gate gettext("Substitute pattern match failed"));
2957c478bd9Sstevel@tonic-gate snote(stotal, slines);
2967c478bd9Sstevel@tonic-gate return (stotal);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate
299f6db9f27Scf46844 int
compsub(int ch)300f6db9f27Scf46844 compsub(int ch)
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate int seof, c, uselastre;
3037c478bd9Sstevel@tonic-gate static int gsubf;
3047c478bd9Sstevel@tonic-gate static unsigned char remem[RHSSIZE];
3057c478bd9Sstevel@tonic-gate static int remflg = -1;
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate if (!value(vi_EDCOMPATIBLE))
3087c478bd9Sstevel@tonic-gate gsubf = cflag = 0;
3097c478bd9Sstevel@tonic-gate uselastre = 0;
3107c478bd9Sstevel@tonic-gate switch (ch) {
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate case 's':
3137c478bd9Sstevel@tonic-gate (void)skipwh();
3147c478bd9Sstevel@tonic-gate seof = getchar();
3157c478bd9Sstevel@tonic-gate if (endcmd(seof) || any(seof, "gcr")) {
3167c478bd9Sstevel@tonic-gate ungetchar(seof);
3177c478bd9Sstevel@tonic-gate goto redo;
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate if (isalpha(seof) || isdigit(seof))
3207c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Substitute needs re") :
3217c478bd9Sstevel@tonic-gate gettext("Missing regular expression for substitute"));
3227c478bd9Sstevel@tonic-gate seof = vi_compile(seof, 1);
3237c478bd9Sstevel@tonic-gate uselastre = 1;
3247c478bd9Sstevel@tonic-gate comprhs(seof);
3257c478bd9Sstevel@tonic-gate gsubf = cflag = 0;
3267c478bd9Sstevel@tonic-gate break;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate case '~':
3297c478bd9Sstevel@tonic-gate uselastre = 1;
3307c478bd9Sstevel@tonic-gate /* fall into ... */
3317c478bd9Sstevel@tonic-gate case '&':
3327c478bd9Sstevel@tonic-gate redo:
3337c478bd9Sstevel@tonic-gate if (re == NULL || re->Expbuf[1] == 0)
3347c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("No previous re") :
3357c478bd9Sstevel@tonic-gate gettext("No previous regular expression"));
3367c478bd9Sstevel@tonic-gate if (subre == NULL || subre->Expbuf[1] == 0)
3377c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("No previous substitute re") :
3387c478bd9Sstevel@tonic-gate gettext("No previous substitute to repeat"));
3397c478bd9Sstevel@tonic-gate break;
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate for (;;) {
3427c478bd9Sstevel@tonic-gate c = getchar();
3437c478bd9Sstevel@tonic-gate switch (c) {
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate case 'g':
3467c478bd9Sstevel@tonic-gate gsubf = !gsubf;
3477c478bd9Sstevel@tonic-gate continue;
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate case 'c':
3507c478bd9Sstevel@tonic-gate cflag = !cflag;
3517c478bd9Sstevel@tonic-gate continue;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate case 'r':
3547c478bd9Sstevel@tonic-gate uselastre = 1;
3557c478bd9Sstevel@tonic-gate continue;
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate default:
3587c478bd9Sstevel@tonic-gate ungetchar(c);
3597c478bd9Sstevel@tonic-gate setcount();
3607c478bd9Sstevel@tonic-gate donewline();
3617c478bd9Sstevel@tonic-gate if (uselastre)
3627c478bd9Sstevel@tonic-gate savere(&subre);
3637c478bd9Sstevel@tonic-gate else
3647c478bd9Sstevel@tonic-gate resre(subre);
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate * The % by itself on the right hand side means
3687c478bd9Sstevel@tonic-gate * that the previous value of the right hand side
3697c478bd9Sstevel@tonic-gate * should be used. A -1 is used to indicate no
3707c478bd9Sstevel@tonic-gate * previously remembered search string.
3717c478bd9Sstevel@tonic-gate */
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate if (rhsbuf[0] == '%' && rhsbuf[1] == 0)
3747c478bd9Sstevel@tonic-gate if (remflg == -1)
3757c478bd9Sstevel@tonic-gate error(gettext("No previously remembered string"));
3767c478bd9Sstevel@tonic-gate else
3777c478bd9Sstevel@tonic-gate strcpy(rhsbuf, remem);
3787c478bd9Sstevel@tonic-gate else {
3797c478bd9Sstevel@tonic-gate strcpy(remem, rhsbuf);
3807c478bd9Sstevel@tonic-gate remflg = 1;
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate return (gsubf);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate
387f6db9f27Scf46844 void
comprhs(int seof)388f6db9f27Scf46844 comprhs(int seof)
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate unsigned char *rp, *orp;
3917c478bd9Sstevel@tonic-gate int c;
3927c478bd9Sstevel@tonic-gate unsigned char orhsbuf[RHSSIZE];
3937c478bd9Sstevel@tonic-gate char multi[MB_LEN_MAX + 1];
3947c478bd9Sstevel@tonic-gate int len;
3957c478bd9Sstevel@tonic-gate wchar_t wc;
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate rp = rhsbuf;
3987c478bd9Sstevel@tonic-gate CP(orhsbuf, rp);
3997c478bd9Sstevel@tonic-gate for (;;) {
4007c478bd9Sstevel@tonic-gate c = peekchar();
4017c478bd9Sstevel@tonic-gate if (c == seof) {
4027c478bd9Sstevel@tonic-gate (void) getchar();
4037c478bd9Sstevel@tonic-gate break;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate if (!isascii(c) && c != EOF) {
4077c478bd9Sstevel@tonic-gate if ((len = _mbftowc(multi, &wc, getchar, &peekc)) > 0) {
4087c478bd9Sstevel@tonic-gate if ((rp + len) >= &rhsbuf[RHSSIZE - 1])
4097c478bd9Sstevel@tonic-gate goto toobig;
4107c478bd9Sstevel@tonic-gate strncpy(rp, multi, len);
4117c478bd9Sstevel@tonic-gate rp += len;
4127c478bd9Sstevel@tonic-gate continue;
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate (void) getchar();
4177c478bd9Sstevel@tonic-gate switch (c) {
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate case '\\':
4207c478bd9Sstevel@tonic-gate c = peekchar();
4217c478bd9Sstevel@tonic-gate if (c == EOF) {
4227c478bd9Sstevel@tonic-gate (void) getchar();
4237c478bd9Sstevel@tonic-gate error(gettext("Replacement string ends with \\"));
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate if (!isascii(c)) {
4277c478bd9Sstevel@tonic-gate *rp++ = '\\';
4287c478bd9Sstevel@tonic-gate if ((len = _mbftowc(multi, &wc, getchar, &peekc)) > 0) {
4297c478bd9Sstevel@tonic-gate if ((rp + len) >= &rhsbuf[RHSSIZE - 1])
4307c478bd9Sstevel@tonic-gate goto over_flow;
4317c478bd9Sstevel@tonic-gate strncpy(rp, multi, len);
4327c478bd9Sstevel@tonic-gate rp += len;
4337c478bd9Sstevel@tonic-gate continue;
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate (void) getchar();
4387c478bd9Sstevel@tonic-gate if (value(vi_MAGIC)) {
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate * When "magic", \& turns into a plain &,
4417c478bd9Sstevel@tonic-gate * and all other chars work fine quoted.
4427c478bd9Sstevel@tonic-gate */
4437c478bd9Sstevel@tonic-gate if (c != '&') {
4447c478bd9Sstevel@tonic-gate if(rp >= &rhsbuf[RHSSIZE - 1]) {
4457c478bd9Sstevel@tonic-gate *rp=0;
4467c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ?
4477c478bd9Sstevel@tonic-gate gettext("Replacement pattern too long") :
4487c478bd9Sstevel@tonic-gate gettext("Replacement pattern too long - limit 256 characters"));
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate *rp++ = '\\';
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate break;
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate magic:
4557c478bd9Sstevel@tonic-gate if (c == '~') {
4567c478bd9Sstevel@tonic-gate for (orp = orhsbuf; *orp; *rp++ = *orp++)
4577c478bd9Sstevel@tonic-gate if (rp >= &rhsbuf[RHSSIZE - 1])
4587c478bd9Sstevel@tonic-gate goto toobig;
4597c478bd9Sstevel@tonic-gate continue;
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate if(rp >= &rhsbuf[RHSSIZE - 1]) {
4627c478bd9Sstevel@tonic-gate over_flow:
4637c478bd9Sstevel@tonic-gate *rp=0;
4647c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ?
4657c478bd9Sstevel@tonic-gate gettext("Replacement pattern too long") :
4667c478bd9Sstevel@tonic-gate gettext("Replacement pattern too long - limit 256 characters"));
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate *rp++ = '\\';
4697c478bd9Sstevel@tonic-gate break;
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate case '\n':
4727c478bd9Sstevel@tonic-gate case EOF:
4737c478bd9Sstevel@tonic-gate if (!(globp && globp[0])) {
4747c478bd9Sstevel@tonic-gate ungetchar(c);
4757c478bd9Sstevel@tonic-gate goto endrhs;
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate case '~':
4797c478bd9Sstevel@tonic-gate case '&':
4807c478bd9Sstevel@tonic-gate if (value(vi_MAGIC))
4817c478bd9Sstevel@tonic-gate goto magic;
4827c478bd9Sstevel@tonic-gate break;
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate if (rp >= &rhsbuf[RHSSIZE - 1]) {
4857c478bd9Sstevel@tonic-gate toobig:
4867c478bd9Sstevel@tonic-gate *rp = 0;
4877c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ?
4887c478bd9Sstevel@tonic-gate gettext("Replacement pattern too long") :
4897c478bd9Sstevel@tonic-gate gettext("Replacement pattern too long - limit 256 characters"));
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate *rp++ = c;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate endrhs:
4947c478bd9Sstevel@tonic-gate *rp++ = 0;
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate
497f6db9f27Scf46844 int
getsub(void)498f6db9f27Scf46844 getsub(void)
4997c478bd9Sstevel@tonic-gate {
5007c478bd9Sstevel@tonic-gate unsigned char *p;
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate if ((p = linebp) == 0)
5037c478bd9Sstevel@tonic-gate return (EOF);
5047c478bd9Sstevel@tonic-gate strcLIN(p);
5057c478bd9Sstevel@tonic-gate linebp = 0;
5067c478bd9Sstevel@tonic-gate return (0);
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate
509f6db9f27Scf46844 int
dosubcon(bool f,line * a)510f6db9f27Scf46844 dosubcon(bool f, line *a)
5117c478bd9Sstevel@tonic-gate {
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate if (execute(f, a) == 0)
5147c478bd9Sstevel@tonic-gate return (0);
5157c478bd9Sstevel@tonic-gate if (confirmed(a)) {
5167c478bd9Sstevel@tonic-gate dosub();
5177c478bd9Sstevel@tonic-gate scount++;
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate return (1);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate
522f6db9f27Scf46844 int
confirmed(line * a)523f6db9f27Scf46844 confirmed(line *a)
5247c478bd9Sstevel@tonic-gate {
5257c478bd9Sstevel@tonic-gate int c, cnt, ch;
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate if (cflag == 0)
5287c478bd9Sstevel@tonic-gate return (1);
5297c478bd9Sstevel@tonic-gate pofix();
5307c478bd9Sstevel@tonic-gate pline(lineno(a));
5317c478bd9Sstevel@tonic-gate if (inopen)
5327c478bd9Sstevel@tonic-gate putchar('\n' | QUOTE);
5337c478bd9Sstevel@tonic-gate c = lcolumn(loc1);
5347c478bd9Sstevel@tonic-gate ugo(c, ' ');
5357c478bd9Sstevel@tonic-gate ugo(lcolumn(loc2) - c, '^');
5367c478bd9Sstevel@tonic-gate flush();
5377c478bd9Sstevel@tonic-gate cnt = 0;
5387c478bd9Sstevel@tonic-gate bkup:
5397c478bd9Sstevel@tonic-gate ch = c = getkey();
5407c478bd9Sstevel@tonic-gate again:
5417c478bd9Sstevel@tonic-gate if (c == '\b') {
5427c478bd9Sstevel@tonic-gate if ((inopen)
5437c478bd9Sstevel@tonic-gate && (cnt > 0)) {
5447c478bd9Sstevel@tonic-gate putchar('\b' | QUOTE);
5457c478bd9Sstevel@tonic-gate putchar(' ');
5467c478bd9Sstevel@tonic-gate putchar('\b' | QUOTE), flush();
5477c478bd9Sstevel@tonic-gate cnt --;
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate goto bkup;
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate if (c == '\r')
5527c478bd9Sstevel@tonic-gate c = '\n';
5537c478bd9Sstevel@tonic-gate if (inopen && MB_CUR_MAX == 1 || c < 0200) {
5547c478bd9Sstevel@tonic-gate putchar(c);
5557c478bd9Sstevel@tonic-gate flush();
5567c478bd9Sstevel@tonic-gate cnt++;
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate if (c != '\n' && c != EOF) {
5597c478bd9Sstevel@tonic-gate c = getkey();
5607c478bd9Sstevel@tonic-gate goto again;
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate noteinp();
5637c478bd9Sstevel@tonic-gate return (ch == 'y');
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate
566f6db9f27Scf46844 void
ugo(int cnt,int with)567f6db9f27Scf46844 ugo(int cnt, int with)
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate if (cnt > 0)
5717c478bd9Sstevel@tonic-gate do
5727c478bd9Sstevel@tonic-gate putchar(with);
5737c478bd9Sstevel@tonic-gate while (--cnt > 0);
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate int casecnt;
5777c478bd9Sstevel@tonic-gate bool destuc;
5787c478bd9Sstevel@tonic-gate
579f6db9f27Scf46844 void
dosub(void)580f6db9f27Scf46844 dosub(void)
5817c478bd9Sstevel@tonic-gate {
5827c478bd9Sstevel@tonic-gate unsigned char *lp, *sp, *rp;
5837c478bd9Sstevel@tonic-gate int c;
5847c478bd9Sstevel@tonic-gate int len;
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate lp = linebuf;
5877c478bd9Sstevel@tonic-gate sp = genbuf;
5887c478bd9Sstevel@tonic-gate rp = rhsbuf;
5897c478bd9Sstevel@tonic-gate while (lp < (unsigned char *)loc1)
5907c478bd9Sstevel@tonic-gate *sp++ = *lp++;
5917c478bd9Sstevel@tonic-gate casecnt = 0;
5927c478bd9Sstevel@tonic-gate /*
5937c478bd9Sstevel@tonic-gate * Caution: depending on the hardware, c will be either sign
5947c478bd9Sstevel@tonic-gate * extended or not if C"E is set. Thus, on a VAX, c will
5957c478bd9Sstevel@tonic-gate * be < 0, but on a 3B, c will be >= 128.
5967c478bd9Sstevel@tonic-gate */
5977c478bd9Sstevel@tonic-gate while (c = *rp) {
5987c478bd9Sstevel@tonic-gate if ((len = mblen((char *)rp, MB_CUR_MAX)) <= 0)
5997c478bd9Sstevel@tonic-gate len = 1;
6007c478bd9Sstevel@tonic-gate /* ^V <return> from vi to split lines */
6017c478bd9Sstevel@tonic-gate if (c == '\r')
6027c478bd9Sstevel@tonic-gate c = '\n';
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate if (c == '\\') {
6057c478bd9Sstevel@tonic-gate rp++;
6067c478bd9Sstevel@tonic-gate if ((len = mblen((char *)rp, MB_CUR_MAX)) <= 0)
6077c478bd9Sstevel@tonic-gate len = 1;
6087c478bd9Sstevel@tonic-gate switch (c = *rp++) {
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate case '&':
6117c478bd9Sstevel@tonic-gate sp = place(sp, loc1, loc2);
6127c478bd9Sstevel@tonic-gate if (sp == 0)
6137c478bd9Sstevel@tonic-gate goto ovflo;
6147c478bd9Sstevel@tonic-gate continue;
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate case 'l':
6177c478bd9Sstevel@tonic-gate casecnt = 1;
6187c478bd9Sstevel@tonic-gate destuc = 0;
6197c478bd9Sstevel@tonic-gate continue;
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate case 'L':
6227c478bd9Sstevel@tonic-gate casecnt = LBSIZE;
6237c478bd9Sstevel@tonic-gate destuc = 0;
6247c478bd9Sstevel@tonic-gate continue;
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate case 'u':
6277c478bd9Sstevel@tonic-gate casecnt = 1;
6287c478bd9Sstevel@tonic-gate destuc = 1;
6297c478bd9Sstevel@tonic-gate continue;
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate case 'U':
6327c478bd9Sstevel@tonic-gate casecnt = LBSIZE;
6337c478bd9Sstevel@tonic-gate destuc = 1;
6347c478bd9Sstevel@tonic-gate continue;
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate case 'E':
6377c478bd9Sstevel@tonic-gate case 'e':
6387c478bd9Sstevel@tonic-gate casecnt = 0;
6397c478bd9Sstevel@tonic-gate continue;
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate if(re != NULL && c >= '1' && c < re->Nbra + '1') {
6427c478bd9Sstevel@tonic-gate sp = place(sp, braslist[c - '1'] , braelist[c - '1']);
6437c478bd9Sstevel@tonic-gate if (sp == 0)
6447c478bd9Sstevel@tonic-gate goto ovflo;
6457c478bd9Sstevel@tonic-gate continue;
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate rp--;
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate if (len > 1) {
6507c478bd9Sstevel@tonic-gate if ((sp + len) >= &genbuf[LBSIZE])
6517c478bd9Sstevel@tonic-gate goto ovflo;
6527c478bd9Sstevel@tonic-gate strncpy(sp, rp, len);
6537c478bd9Sstevel@tonic-gate } else {
6547c478bd9Sstevel@tonic-gate if (casecnt)
6557c478bd9Sstevel@tonic-gate *sp = fixcase(c);
6567c478bd9Sstevel@tonic-gate else
6577c478bd9Sstevel@tonic-gate *sp = c;
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate sp += len; rp += len;
6607c478bd9Sstevel@tonic-gate if (sp >= &genbuf[LBSIZE])
6617c478bd9Sstevel@tonic-gate ovflo:
6627c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Line overflow") :
6637c478bd9Sstevel@tonic-gate gettext("Line overflow in substitute"));
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate lp = (unsigned char *)loc2;
6667c478bd9Sstevel@tonic-gate loc2 = (char *)(linebuf + (sp - genbuf));
6677c478bd9Sstevel@tonic-gate while (*sp++ = *lp++)
6687c478bd9Sstevel@tonic-gate if (sp >= &genbuf[LBSIZE])
6697c478bd9Sstevel@tonic-gate goto ovflo;
6707c478bd9Sstevel@tonic-gate strcLIN(genbuf);
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate
673f6db9f27Scf46844 int
fixcase(int c)674f6db9f27Scf46844 fixcase(int c)
6757c478bd9Sstevel@tonic-gate {
6767c478bd9Sstevel@tonic-gate
6777c478bd9Sstevel@tonic-gate if (casecnt == 0)
6787c478bd9Sstevel@tonic-gate return (c);
6797c478bd9Sstevel@tonic-gate casecnt--;
6807c478bd9Sstevel@tonic-gate if (destuc) {
6817c478bd9Sstevel@tonic-gate if (islower(c))
6827c478bd9Sstevel@tonic-gate c = toupper(c);
6837c478bd9Sstevel@tonic-gate } else
6847c478bd9Sstevel@tonic-gate if (isupper(c))
6857c478bd9Sstevel@tonic-gate c = tolower(c);
6867c478bd9Sstevel@tonic-gate return (c);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate unsigned char *
place(sp,l1,l2)6907c478bd9Sstevel@tonic-gate place(sp, l1, l2)
6917c478bd9Sstevel@tonic-gate unsigned char *sp, *l1, *l2;
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate while (l1 < l2) {
6957c478bd9Sstevel@tonic-gate *sp++ = fixcase(*l1++);
6967c478bd9Sstevel@tonic-gate if (sp >= &genbuf[LBSIZE])
6977c478bd9Sstevel@tonic-gate return (0);
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate return (sp);
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate
702f6db9f27Scf46844 void
snote(int total,int nlines)703f6db9f27Scf46844 snote(int total, int nlines)
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate if (!notable(total))
7077c478bd9Sstevel@tonic-gate return;
7087c478bd9Sstevel@tonic-gate if (nlines != 1 && nlines != total)
709f6db9f27Scf46844 viprintf(mesg(value(vi_TERSE) ?
7107c478bd9Sstevel@tonic-gate /*
7117c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE
7127c478bd9Sstevel@tonic-gate * Reference order of arguments must not
7137c478bd9Sstevel@tonic-gate * be changed using '%digit$', since vi's
714f6db9f27Scf46844 * viprintf() does not support it.
7157c478bd9Sstevel@tonic-gate */
7167c478bd9Sstevel@tonic-gate gettext("%d subs on %d lines") :
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE
7197c478bd9Sstevel@tonic-gate * Reference order of arguments must not
7207c478bd9Sstevel@tonic-gate * be changed using '%digit$', since vi's
721f6db9f27Scf46844 * viprintf() does not support it.
7227c478bd9Sstevel@tonic-gate */
7237c478bd9Sstevel@tonic-gate gettext("%d substitutions on %d lines")),
7247c478bd9Sstevel@tonic-gate total, nlines);
7257c478bd9Sstevel@tonic-gate else
726f6db9f27Scf46844 viprintf(mesg(value(vi_TERSE) ?
7277c478bd9Sstevel@tonic-gate gettext("%d subs") :
7287c478bd9Sstevel@tonic-gate gettext("%d substitutions")),
7297c478bd9Sstevel@tonic-gate total);
7307c478bd9Sstevel@tonic-gate noonl();
7317c478bd9Sstevel@tonic-gate flush();
7327c478bd9Sstevel@tonic-gate }
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate #ifdef XPG4
7357c478bd9Sstevel@tonic-gate #include <regex.h>
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate extern int regcomp_flags; /* use to specify cflags for regcomp() */
7387c478bd9Sstevel@tonic-gate #endif /* XPG4 */
7397c478bd9Sstevel@tonic-gate
740f6db9f27Scf46844 int
vi_compile(int eof,int oknl)741f6db9f27Scf46844 vi_compile(int eof, int oknl)
7427c478bd9Sstevel@tonic-gate {
7437c478bd9Sstevel@tonic-gate int c;
7447c478bd9Sstevel@tonic-gate unsigned char *gp, *p1;
7457c478bd9Sstevel@tonic-gate unsigned char *rhsp;
7467c478bd9Sstevel@tonic-gate unsigned char rebuf[LBSIZE];
7477c478bd9Sstevel@tonic-gate char multi[MB_LEN_MAX + 1];
7487c478bd9Sstevel@tonic-gate int len;
7497c478bd9Sstevel@tonic-gate wchar_t wc;
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate #ifdef XPG4
7527c478bd9Sstevel@tonic-gate /*
7537c478bd9Sstevel@tonic-gate * reset cflags to plain BRE
7547c478bd9Sstevel@tonic-gate * if \< and/or \> is specified, REG_WORDS is set.
7557c478bd9Sstevel@tonic-gate */
7567c478bd9Sstevel@tonic-gate regcomp_flags = 0;
7577c478bd9Sstevel@tonic-gate #endif /* XPG4 */
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate gp = genbuf;
7607c478bd9Sstevel@tonic-gate if (isalpha(eof) || isdigit(eof))
7617c478bd9Sstevel@tonic-gate error(gettext("Regular expressions cannot be delimited by letters or digits"));
7627c478bd9Sstevel@tonic-gate if(eof >= 0200 && MB_CUR_MAX > 1)
7637c478bd9Sstevel@tonic-gate error(gettext("Regular expressions cannot be delimited by multibyte characters"));
7647c478bd9Sstevel@tonic-gate c = getchar();
7657c478bd9Sstevel@tonic-gate if (eof == '\\')
7667c478bd9Sstevel@tonic-gate switch (c) {
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate case '/':
7697c478bd9Sstevel@tonic-gate case '?':
7707c478bd9Sstevel@tonic-gate if (scanre == NULL || scanre->Expbuf[1] == 0)
7717c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("No previous scan re") :
7727c478bd9Sstevel@tonic-gate gettext("No previous scanning regular expression"));
7737c478bd9Sstevel@tonic-gate resre(scanre);
7747c478bd9Sstevel@tonic-gate return (c);
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate case '&':
7777c478bd9Sstevel@tonic-gate if (subre == NULL || subre->Expbuf[1] == 0)
7787c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("No previous substitute re") :
7797c478bd9Sstevel@tonic-gate gettext("No previous substitute regular expression"));
7807c478bd9Sstevel@tonic-gate resre(subre);
7817c478bd9Sstevel@tonic-gate return (c);
7827c478bd9Sstevel@tonic-gate
7837c478bd9Sstevel@tonic-gate default:
7847c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Badly formed re") :
7857c478bd9Sstevel@tonic-gate gettext("Regular expression \\ must be followed by / or ?"));
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate if (c == eof || c == '\n' || c == EOF) {
7887c478bd9Sstevel@tonic-gate if (re == NULL || re->Expbuf[1] == 0)
7897c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("No previous re") :
7907c478bd9Sstevel@tonic-gate gettext("No previous regular expression"));
7917c478bd9Sstevel@tonic-gate if (c == '\n' && oknl == 0)
7927c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Missing closing delimiter") :
7937c478bd9Sstevel@tonic-gate gettext("Missing closing delimiter for regular expression"));
7947c478bd9Sstevel@tonic-gate if (c != eof)
7957c478bd9Sstevel@tonic-gate ungetchar(c);
7967c478bd9Sstevel@tonic-gate return (eof);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate gp = genbuf;
7997c478bd9Sstevel@tonic-gate if (c == '^') {
8007c478bd9Sstevel@tonic-gate *gp++ = c;
8017c478bd9Sstevel@tonic-gate c = getchar();
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate ungetchar(c);
8047c478bd9Sstevel@tonic-gate for (;;) {
8057c478bd9Sstevel@tonic-gate c = getchar();
8067c478bd9Sstevel@tonic-gate if (c == eof || c == EOF) {
8077c478bd9Sstevel@tonic-gate if (c == EOF)
8087c478bd9Sstevel@tonic-gate ungetchar(c);
8097c478bd9Sstevel@tonic-gate goto out;
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate if (gp >= &genbuf[LBSIZE - 3])
8127c478bd9Sstevel@tonic-gate complex:
813f6db9f27Scf46844 cerror(value(vi_TERSE) ?
814f6db9f27Scf46844 (unsigned char *)gettext("Re too complex") :
815f6db9f27Scf46844 (unsigned char *)
8167c478bd9Sstevel@tonic-gate gettext("Regular expression too complicated"));
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate if (!(isascii(c) || MB_CUR_MAX == 1)) {
8197c478bd9Sstevel@tonic-gate ungetchar(c);
8207c478bd9Sstevel@tonic-gate if ((len = _mbftowc(multi, &wc, getchar, &peekc)) >= 1) {
8217c478bd9Sstevel@tonic-gate if ((gp + len) >= &genbuf[LBSIZE - 3])
8227c478bd9Sstevel@tonic-gate goto complex;
8237c478bd9Sstevel@tonic-gate strncpy(gp, multi, len);
8247c478bd9Sstevel@tonic-gate gp += len;
8257c478bd9Sstevel@tonic-gate continue;
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate (void) getchar();
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate switch (c) {
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate case '\\':
8337c478bd9Sstevel@tonic-gate c = getchar();
8347c478bd9Sstevel@tonic-gate if (!isascii(c)) {
8357c478bd9Sstevel@tonic-gate ungetchar(c);
8367c478bd9Sstevel@tonic-gate if ((len = _mbftowc(multi, &wc, getchar, &peekc)) >= 1) {
8377c478bd9Sstevel@tonic-gate if ((gp + len) >= &genbuf[LBSIZE - 3])
8387c478bd9Sstevel@tonic-gate goto complex;
8397c478bd9Sstevel@tonic-gate *gp++ = '\\';
8407c478bd9Sstevel@tonic-gate strncpy(gp, multi, len);
8417c478bd9Sstevel@tonic-gate gp += len;
8427c478bd9Sstevel@tonic-gate continue;
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate (void) getchar();
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate switch (c) {
8487c478bd9Sstevel@tonic-gate
8497c478bd9Sstevel@tonic-gate case '<':
8507c478bd9Sstevel@tonic-gate case '>':
8517c478bd9Sstevel@tonic-gate #ifdef XPG4
8527c478bd9Sstevel@tonic-gate regcomp_flags = REG_WORDS;
8537c478bd9Sstevel@tonic-gate /*FALLTHRU*/
8547c478bd9Sstevel@tonic-gate #endif /* XPG4 */
8557c478bd9Sstevel@tonic-gate case '(':
8567c478bd9Sstevel@tonic-gate case ')':
8577c478bd9Sstevel@tonic-gate case '{':
8587c478bd9Sstevel@tonic-gate case '}':
8597c478bd9Sstevel@tonic-gate case '$':
8607c478bd9Sstevel@tonic-gate case '^':
8617c478bd9Sstevel@tonic-gate case '\\':
8627c478bd9Sstevel@tonic-gate *gp++ = '\\';
8637c478bd9Sstevel@tonic-gate *gp++ = c;
8647c478bd9Sstevel@tonic-gate continue;
8657c478bd9Sstevel@tonic-gate
8667c478bd9Sstevel@tonic-gate case 'n':
8677c478bd9Sstevel@tonic-gate *gp++ = c;
8687c478bd9Sstevel@tonic-gate continue;
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate if(c >= '0' && c <= '9') {
8717c478bd9Sstevel@tonic-gate *gp++ = '\\';
8727c478bd9Sstevel@tonic-gate *gp++ = c;
8737c478bd9Sstevel@tonic-gate continue;
8747c478bd9Sstevel@tonic-gate }
8757c478bd9Sstevel@tonic-gate if (value(vi_MAGIC) == 0)
8767c478bd9Sstevel@tonic-gate magic:
8777c478bd9Sstevel@tonic-gate switch (c) {
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate case '.':
8807c478bd9Sstevel@tonic-gate *gp++ = '.';
8817c478bd9Sstevel@tonic-gate continue;
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate case '~':
8847c478bd9Sstevel@tonic-gate rhsp = rhsbuf;
8857c478bd9Sstevel@tonic-gate while (*rhsp) {
8867c478bd9Sstevel@tonic-gate if (!isascii(*rhsp)) {
8877c478bd9Sstevel@tonic-gate if ((len = mbtowc((wchar_t *)0, (char *)rhsp, MB_CUR_MAX)) > 1) {
8887c478bd9Sstevel@tonic-gate if ((gp + len) >= &genbuf[LBSIZE-2])
8897c478bd9Sstevel@tonic-gate goto complex;
8907c478bd9Sstevel@tonic-gate strncpy(gp, rhsp, len);
8917c478bd9Sstevel@tonic-gate rhsp += len; gp += len;
8927c478bd9Sstevel@tonic-gate continue;
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate len = 1;
8967c478bd9Sstevel@tonic-gate if (*rhsp == '\\') {
8977c478bd9Sstevel@tonic-gate c = *++rhsp;
8987c478bd9Sstevel@tonic-gate if (c == '&')
899f6db9f27Scf46844 cerror(value(vi_TERSE) ? (unsigned char *)
900f6db9f27Scf46844 gettext("Replacement pattern contains &") :
901f6db9f27Scf46844 (unsigned char *)gettext("Replacement pattern contains & - cannot use in re"));
9027c478bd9Sstevel@tonic-gate if (c >= '1' && c <= '9')
903f6db9f27Scf46844 cerror(value(vi_TERSE) ? (unsigned char *)
904f6db9f27Scf46844 gettext("Replacement pattern contains \\d") :
905f6db9f27Scf46844 (unsigned char *)
9067c478bd9Sstevel@tonic-gate gettext("Replacement pattern contains \\d - cannot use in re"));
9077c478bd9Sstevel@tonic-gate if ((len = mbtowc((wchar_t *)0, (char *)rhsp, MB_CUR_MAX)) <= 1) {
9087c478bd9Sstevel@tonic-gate len = 1;
9097c478bd9Sstevel@tonic-gate if(any(c, ".\\*[$"))
9107c478bd9Sstevel@tonic-gate *gp++ = '\\';
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate if ((gp + len) >= &genbuf[LBSIZE-2])
9157c478bd9Sstevel@tonic-gate goto complex;
9167c478bd9Sstevel@tonic-gate if (len == 1) {
9177c478bd9Sstevel@tonic-gate c = *rhsp++;
9187c478bd9Sstevel@tonic-gate *gp++ = (value(vi_IGNORECASE) ? tolower(c) : c);
9197c478bd9Sstevel@tonic-gate } else {
9207c478bd9Sstevel@tonic-gate strncpy(gp, rhsp, len);
9217c478bd9Sstevel@tonic-gate gp += len; rhsp += len;
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate continue;
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate case '*':
9277c478bd9Sstevel@tonic-gate *gp++ = '*';
9287c478bd9Sstevel@tonic-gate continue;
9297c478bd9Sstevel@tonic-gate
9307c478bd9Sstevel@tonic-gate case '[':
9317c478bd9Sstevel@tonic-gate *gp++ = '[';
9327c478bd9Sstevel@tonic-gate c = getchar();
9337c478bd9Sstevel@tonic-gate if (c == '^') {
9347c478bd9Sstevel@tonic-gate *gp++ = '^';
9357c478bd9Sstevel@tonic-gate c = getchar();
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate
9387c478bd9Sstevel@tonic-gate do {
9397c478bd9Sstevel@tonic-gate if (!isascii(c) && c != EOF) {
9407c478bd9Sstevel@tonic-gate ungetchar(c);
9417c478bd9Sstevel@tonic-gate if ((len = _mbftowc(multi, &wc, getchar, &peekc)) >= 1) {
9427c478bd9Sstevel@tonic-gate if ((gp + len)>= &genbuf[LBSIZE-4])
9437c478bd9Sstevel@tonic-gate goto complex;
9447c478bd9Sstevel@tonic-gate strncpy(gp, multi, len);
9457c478bd9Sstevel@tonic-gate gp += len;
9467c478bd9Sstevel@tonic-gate c = getchar();
9477c478bd9Sstevel@tonic-gate continue;
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate (void) getchar();
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate if (gp >= &genbuf[LBSIZE-4])
9537c478bd9Sstevel@tonic-gate goto complex;
9547c478bd9Sstevel@tonic-gate if(c == '\\' && peekchar() == ']') {
9557c478bd9Sstevel@tonic-gate (void)getchar();
9567c478bd9Sstevel@tonic-gate *gp++ = '\\';
9577c478bd9Sstevel@tonic-gate *gp++ = ']';
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate else if (c == '\n' || c == EOF)
960f6db9f27Scf46844 cerror((unsigned char *)
961f6db9f27Scf46844 gettext("Missing ]"));
9627c478bd9Sstevel@tonic-gate else
9637c478bd9Sstevel@tonic-gate *gp++ = (value(vi_IGNORECASE) ? tolower(c) : c);
9647c478bd9Sstevel@tonic-gate c = getchar();
9657c478bd9Sstevel@tonic-gate } while(c != ']');
9667c478bd9Sstevel@tonic-gate *gp++ = ']';
9677c478bd9Sstevel@tonic-gate continue;
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate if (c == EOF) {
9707c478bd9Sstevel@tonic-gate ungetchar(EOF);
9717c478bd9Sstevel@tonic-gate *gp++ = '\\';
9727c478bd9Sstevel@tonic-gate *gp++ = '\\';
9737c478bd9Sstevel@tonic-gate continue;
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate if (c == '\n')
976f6db9f27Scf46844 cerror(value(vi_TERSE) ? (unsigned char *)gettext("No newlines in re's") :
977f6db9f27Scf46844 (unsigned char *)gettext("Can't escape newlines into regular expressions"));
9787c478bd9Sstevel@tonic-gate *gp++ = '\\';
9797c478bd9Sstevel@tonic-gate *gp++ = (value(vi_IGNORECASE) ? tolower(c) : c);
9807c478bd9Sstevel@tonic-gate continue;
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate case '\n':
9837c478bd9Sstevel@tonic-gate if (oknl) {
9847c478bd9Sstevel@tonic-gate ungetchar(c);
9857c478bd9Sstevel@tonic-gate goto out;
9867c478bd9Sstevel@tonic-gate }
987f6db9f27Scf46844 cerror(value(vi_TERSE) ? (unsigned char *)gettext("Badly formed re") :
988f6db9f27Scf46844 (unsigned char *)gettext("Missing closing delimiter for regular expression"));
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate case '.':
9917c478bd9Sstevel@tonic-gate case '~':
9927c478bd9Sstevel@tonic-gate case '*':
9937c478bd9Sstevel@tonic-gate case '[':
9947c478bd9Sstevel@tonic-gate if (value(vi_MAGIC))
9957c478bd9Sstevel@tonic-gate goto magic;
9967c478bd9Sstevel@tonic-gate if(c != '~')
9977c478bd9Sstevel@tonic-gate *gp++ = '\\';
9987c478bd9Sstevel@tonic-gate defchar:
9997c478bd9Sstevel@tonic-gate default:
10007c478bd9Sstevel@tonic-gate *gp++ = (value(vi_IGNORECASE) ? tolower(c) : c);
10017c478bd9Sstevel@tonic-gate continue;
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate out:
10057c478bd9Sstevel@tonic-gate *gp++ = '\0';
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate #ifdef XPG4
10087c478bd9Sstevel@tonic-gate /* see if our compiled RE's will fit in the re structure: */
10097c478bd9Sstevel@tonic-gate if (regexc_size > EXPSIZ) {
10107c478bd9Sstevel@tonic-gate /*
10117c478bd9Sstevel@tonic-gate * this should never happen. but it's critical that we
10127c478bd9Sstevel@tonic-gate * check here, otherwise .bss would get overwritten.
10137c478bd9Sstevel@tonic-gate */
1014f6db9f27Scf46844 cerror(value(vi_TERSE) ? (unsigned char *)
1015f6db9f27Scf46844 gettext("RE's can't fit") :
1016f6db9f27Scf46844 (unsigned char *)gettext("Regular expressions can't fit"));
10177c478bd9Sstevel@tonic-gate return(eof);
10187c478bd9Sstevel@tonic-gate }
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate /*
10217c478bd9Sstevel@tonic-gate * We create re each time we need it.
10227c478bd9Sstevel@tonic-gate */
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate if (re == NULL || re == scanre || re == subre) {
10257c478bd9Sstevel@tonic-gate if ((re = calloc(1, sizeof(struct regexp))) == NULL) {
10267c478bd9Sstevel@tonic-gate error(gettext("out of memory"));
10277c478bd9Sstevel@tonic-gate exit(errcnt);
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate } else {
10307c478bd9Sstevel@tonic-gate regex_comp_free(&re->Expbuf);
10317c478bd9Sstevel@tonic-gate memset(re, 0, sizeof(struct regexp));
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate compile((char *) genbuf, (char *) re->Expbuf, (char *) re->Expbuf
10357c478bd9Sstevel@tonic-gate + regexc_size);
10367c478bd9Sstevel@tonic-gate #else /* !XPG4 */
10377c478bd9Sstevel@tonic-gate (void) _compile((const char *)genbuf, (char *)re->Expbuf,
10387c478bd9Sstevel@tonic-gate (char *)(re->Expbuf + sizeof (re->Expbuf)), 1);
10397c478bd9Sstevel@tonic-gate #endif /* XPG4 */
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate if(regerrno)
10427c478bd9Sstevel@tonic-gate switch(regerrno) {
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate case 42:
1045f6db9f27Scf46844 cerror((unsigned char *)gettext("\\( \\) Imbalance"));
10467c478bd9Sstevel@tonic-gate case 43:
1047f6db9f27Scf46844 cerror(value(vi_TERSE) ? (unsigned char *)gettext("Awash in \\('s!") :
1048f6db9f27Scf46844 (unsigned char *)
10497c478bd9Sstevel@tonic-gate gettext("Too many \\('d subexpressions in a regular expression"));
10507c478bd9Sstevel@tonic-gate case 50:
10517c478bd9Sstevel@tonic-gate goto complex;
10527c478bd9Sstevel@tonic-gate case 67:
1053f6db9f27Scf46844 cerror(value(vi_TERSE) ? (unsigned char *)gettext("Illegal byte sequence") :
1054f6db9f27Scf46844 (unsigned char *)gettext("Regular expression has illegal byte sequence"));
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate re->Nbra = nbra;
10577c478bd9Sstevel@tonic-gate return(eof);
10587c478bd9Sstevel@tonic-gate }
10597c478bd9Sstevel@tonic-gate
1060f6db9f27Scf46844 void
cerror(unsigned char * s)1061f6db9f27Scf46844 cerror(unsigned char *s)
10627c478bd9Sstevel@tonic-gate {
10637c478bd9Sstevel@tonic-gate if (re) {
10647c478bd9Sstevel@tonic-gate re->Expbuf[0] = re->Expbuf[1] = 0;
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate error(s);
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate
1069f6db9f27Scf46844 int
execute(int gf,line * addr)1070f6db9f27Scf46844 execute(int gf, line *addr)
10717c478bd9Sstevel@tonic-gate {
10727c478bd9Sstevel@tonic-gate unsigned char *p1, *p2;
10737c478bd9Sstevel@tonic-gate char *start;
10747c478bd9Sstevel@tonic-gate int c, i;
10757c478bd9Sstevel@tonic-gate int ret;
10767c478bd9Sstevel@tonic-gate int len;
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate if (gf) {
10797c478bd9Sstevel@tonic-gate if (re == NULL || re->Expbuf[0])
10807c478bd9Sstevel@tonic-gate return (0);
10817c478bd9Sstevel@tonic-gate if(value(vi_IGNORECASE)) {
10827c478bd9Sstevel@tonic-gate p1 = genbuf;
10837c478bd9Sstevel@tonic-gate p2 = (unsigned char *)loc2;
10847c478bd9Sstevel@tonic-gate while(c = *p2) {
10857c478bd9Sstevel@tonic-gate if ((len = mblen((char *)p2, MB_CUR_MAX)) <= 0)
10867c478bd9Sstevel@tonic-gate len = 1;
10877c478bd9Sstevel@tonic-gate if (len == 1) {
10887c478bd9Sstevel@tonic-gate *p1++ = tolower(c);
10897c478bd9Sstevel@tonic-gate p2++;
10907c478bd9Sstevel@tonic-gate continue;
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate strncpy(p1, p2, len);
10937c478bd9Sstevel@tonic-gate p1 += len; p2 += len;
10947c478bd9Sstevel@tonic-gate }
10957c478bd9Sstevel@tonic-gate *p1 = '\0';
10967c478bd9Sstevel@tonic-gate locs = (char *)genbuf;
10977c478bd9Sstevel@tonic-gate p1 = genbuf;
10987c478bd9Sstevel@tonic-gate start = loc2;
10997c478bd9Sstevel@tonic-gate } else {
11007c478bd9Sstevel@tonic-gate p1 = (unsigned char *)loc2;
11017c478bd9Sstevel@tonic-gate locs = loc2;
11027c478bd9Sstevel@tonic-gate }
11037c478bd9Sstevel@tonic-gate } else {
11047c478bd9Sstevel@tonic-gate if (addr == zero)
11057c478bd9Sstevel@tonic-gate return (0);
11067c478bd9Sstevel@tonic-gate p1 = linebuf;
1107*23a1cceaSRoger A. Faulkner getaline(*addr);
11087c478bd9Sstevel@tonic-gate if(value(vi_IGNORECASE)) {
11097c478bd9Sstevel@tonic-gate p1 = genbuf;
11107c478bd9Sstevel@tonic-gate p2 = linebuf;
11117c478bd9Sstevel@tonic-gate while(c = *p2) {
11127c478bd9Sstevel@tonic-gate if ((len = mblen((char *)p2, MB_CUR_MAX)) <= 0)
11137c478bd9Sstevel@tonic-gate len = 1;
11147c478bd9Sstevel@tonic-gate if (len == 1) {
11157c478bd9Sstevel@tonic-gate *p1++ = tolower(c);
11167c478bd9Sstevel@tonic-gate p2++;
11177c478bd9Sstevel@tonic-gate continue;
11187c478bd9Sstevel@tonic-gate }
11197c478bd9Sstevel@tonic-gate strncpy(p1, p2, len);
11207c478bd9Sstevel@tonic-gate p1 += len; p2 += len;
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate *p1 = '\0';
11237c478bd9Sstevel@tonic-gate p1 = genbuf;
11247c478bd9Sstevel@tonic-gate start = (char *)linebuf;
11257c478bd9Sstevel@tonic-gate }
11267c478bd9Sstevel@tonic-gate locs = (char *)0;
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate
11297c478bd9Sstevel@tonic-gate ret = step((char *)p1, (char *)re->Expbuf);
11307c478bd9Sstevel@tonic-gate
11317c478bd9Sstevel@tonic-gate if(value(vi_IGNORECASE) && ret) {
11327c478bd9Sstevel@tonic-gate loc1 = start + (loc1 - (char *)genbuf);
11337c478bd9Sstevel@tonic-gate loc2 = start + (loc2 - (char *)genbuf);
11347c478bd9Sstevel@tonic-gate for(i = 0; i < NBRA; i++) {
11357c478bd9Sstevel@tonic-gate braslist[i] = start + (braslist[i] - (char *)genbuf);
11367c478bd9Sstevel@tonic-gate braelist[i] = start + (braelist[i] - (char *)genbuf);
11377c478bd9Sstevel@tonic-gate }
11387c478bd9Sstevel@tonic-gate }
11397c478bd9Sstevel@tonic-gate return ret;
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate /*
11437c478bd9Sstevel@tonic-gate * Initialize the compiled regular-expression storage areas (called from
11447c478bd9Sstevel@tonic-gate * main()).
11457c478bd9Sstevel@tonic-gate */
11467c478bd9Sstevel@tonic-gate
init_re(void)11477c478bd9Sstevel@tonic-gate void init_re (void)
11487c478bd9Sstevel@tonic-gate {
11497c478bd9Sstevel@tonic-gate #ifdef XPG4
11507c478bd9Sstevel@tonic-gate re = scanre = subre = NULL;
11517c478bd9Sstevel@tonic-gate #else /* !XPG4 */
11527c478bd9Sstevel@tonic-gate if ((re = calloc(1, sizeof(struct regexp))) == NULL) {
11537c478bd9Sstevel@tonic-gate error(gettext("out of memory"));
11547c478bd9Sstevel@tonic-gate exit(errcnt);
11557c478bd9Sstevel@tonic-gate }
11567c478bd9Sstevel@tonic-gate
11577c478bd9Sstevel@tonic-gate if ((scanre = calloc(1, sizeof(struct regexp))) == NULL) {
11587c478bd9Sstevel@tonic-gate error(gettext("out of memory"));
11597c478bd9Sstevel@tonic-gate exit(errcnt);
11607c478bd9Sstevel@tonic-gate }
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate if ((subre = calloc(1, sizeof(struct regexp))) == NULL) {
11637c478bd9Sstevel@tonic-gate error(gettext("out of memory"));
11647c478bd9Sstevel@tonic-gate exit(errcnt);
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate #endif /* XPG4 */
11677c478bd9Sstevel@tonic-gate }
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate /*
11707c478bd9Sstevel@tonic-gate * Save what is in the special place re to the named alternate
11717c478bd9Sstevel@tonic-gate * location. This means freeing up what's currently in this target
11727c478bd9Sstevel@tonic-gate * location, if necessary.
11737c478bd9Sstevel@tonic-gate */
11747c478bd9Sstevel@tonic-gate
savere(struct regexp ** a)11757c478bd9Sstevel@tonic-gate void savere(struct regexp ** a)
11767c478bd9Sstevel@tonic-gate {
11777c478bd9Sstevel@tonic-gate #ifdef XPG4
11787c478bd9Sstevel@tonic-gate if (a == NULL || re == NULL) {
11797c478bd9Sstevel@tonic-gate return;
11807c478bd9Sstevel@tonic-gate }
11817c478bd9Sstevel@tonic-gate
11827c478bd9Sstevel@tonic-gate if (*a == NULL) {
11837c478bd9Sstevel@tonic-gate *a = re;
11847c478bd9Sstevel@tonic-gate return;
11857c478bd9Sstevel@tonic-gate }
11867c478bd9Sstevel@tonic-gate
11877c478bd9Sstevel@tonic-gate if (*a != re) {
11887c478bd9Sstevel@tonic-gate if (scanre != subre) {
11897c478bd9Sstevel@tonic-gate regex_comp_free(&((*a)->Expbuf));
11907c478bd9Sstevel@tonic-gate free(*a);
11917c478bd9Sstevel@tonic-gate }
11927c478bd9Sstevel@tonic-gate *a = re;
11937c478bd9Sstevel@tonic-gate }
11947c478bd9Sstevel@tonic-gate #else /* !XPG4 */
11957c478bd9Sstevel@tonic-gate memcpy(*a, re, sizeof(struct regexp));
11967c478bd9Sstevel@tonic-gate #endif /* XPG4 */
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate /*
12017c478bd9Sstevel@tonic-gate * Restore what is in the named alternate location to the special place
12027c478bd9Sstevel@tonic-gate * re. This means first freeing up what's currently in re, if necessary.
12037c478bd9Sstevel@tonic-gate */
12047c478bd9Sstevel@tonic-gate
resre(struct regexp * a)12057c478bd9Sstevel@tonic-gate void resre(struct regexp * a)
12067c478bd9Sstevel@tonic-gate {
12077c478bd9Sstevel@tonic-gate #ifdef XPG4
12087c478bd9Sstevel@tonic-gate if (a == NULL) {
12097c478bd9Sstevel@tonic-gate return;
12107c478bd9Sstevel@tonic-gate }
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate if (re == NULL) {
12137c478bd9Sstevel@tonic-gate re = a;
12147c478bd9Sstevel@tonic-gate return;
12157c478bd9Sstevel@tonic-gate }
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate if (a != re) {
12187c478bd9Sstevel@tonic-gate if ((re != scanre) && (re != subre)) {
12197c478bd9Sstevel@tonic-gate regex_comp_free(&re->Expbuf);
12207c478bd9Sstevel@tonic-gate free(re);
12217c478bd9Sstevel@tonic-gate }
12227c478bd9Sstevel@tonic-gate
12237c478bd9Sstevel@tonic-gate re = a;
12247c478bd9Sstevel@tonic-gate }
12257c478bd9Sstevel@tonic-gate #else /* !XPG4 */
12267c478bd9Sstevel@tonic-gate memcpy(re, a, sizeof(struct regexp));
12277c478bd9Sstevel@tonic-gate #endif /* XPG4 */
12287c478bd9Sstevel@tonic-gate }
1229