/* Copyright (c) 1979 Regents of the University of California */
* Global, substitute and regular expressions.
* Very similar to ed, with some re extensions and
char globuf
[GBSIZE
], *Cwas
;
int oinglobal
= inglobal
;
* 0: ordinary - not in a global command.
* 1: text coming from some buffer, not tty.
* 2: like 1, but the source of the buffer is a global command.
* Hence you're only in a global command if inglobal==2. This
* strange sounding convention is historically derived from
* everybody simulating a global command.
error("Global within global@not allowed");
error("Global needs re|Missing regular expression for global");
while ((c
= getchar()) != '\n') {
if (gp
>= &globuf
[GBSIZE
- 2])
error("Global command too long");
for (a1
= one
; a1
<= dol
; a1
++) {
if (a1
>= addr1
&& a1
<= addr2
&& execute(0, a1
) == k
)
/* should use gdelete from ed to avoid n**2 here on g/.../d */
for (a1
= one
; a1
<= dol
; a1
++) {
int scount
, slines
, stotal
;
save12(), undkind
= UNDCHANGE
;
for (addr
= addr1
; addr
<= addr2
; addr
++) {
if (dosubcon(0, addr
) == 0)
* should check but loc2 is already munged.
* This needs a fancier check later.
error("substitution loop");
if (dosubcon(1, addr
) == 0)
n
= append(getsub
, addr
);
if (stotal
== 0 && !inglobal
&& !xflag
)
error("Fail|Substitute pattern match failed");
register int seof
, c
, uselastre
;
if (!value(EDCOMPATIBLE
))
if (endcmd(seof
) || any(seof
, "gcr")) {
if (isalpha(seof
) || isdigit(seof
))
error("Substitute needs re|Missing regular expression for substitute");
error("No previous re|No previous regular expression");
char orhsbuf
[LBSIZE
/ 2];
* When "magic", \& turns into a plain &,
* and all other chars work fine quoted.
for (orp
= orhsbuf
; *orp
; *rp
++ = *orp
++)
if (rp
>= &rhsbuf
[LBSIZE
/ 2 + 1])
if (rp
>= &rhsbuf
[LBSIZE
/ 2 - 1])
error("Replacement pattern too long@- limit 256 characters");
ugo(c
- 1 + (inopen
? 1 : 0), ' ');
ugo(column(loc2
- 1) - c
, '^');
if (c
!= '\n' && c
!= EOF
) {
register char *lp
, *sp
, *rp
;
sp
= place(sp
, loc1
, loc2
);
if (c
< 0 && (c
&= TRIM
) >= '1' && c
< nbra
+ '1') {
sp
= place(sp
, braslist
[c
- '1'], braelist
[c
- '1']);
*sp
++ = fixcase(c
& TRIM
);
if (sp
>= &genbuf
[LBSIZE
])
error("Line overflow@in substitute");
loc2
= sp
+ (linebuf
- genbuf
);
if (sp
>= &genbuf
[LBSIZE
])
register char *sp
, *l1
, *l2
;
if (sp
>= &genbuf
[LBSIZE
])
register int total
, lines
;
printf(mesg("%d subs|%d substitutions"), total
);
if (lines
!= 1 && lines
!= total
)
printf(" on %d lines", lines
);
char bracket
[NBRA
], *bracketp
, *rhsp
;
if (isalpha(eof
) || isdigit(eof
))
error("Regular expressions cannot be delimited by letters or digits");
if (scanre
.Expbuf
[0] == 0)
error("No previous scan re|No previous scanning regular expression");
if (subre
.Expbuf
[0] == 0)
error("No previous substitute re|No previous substitute regular expression");
error("Badly formed re|Regular expression \\ must be followed by / or ?");
if (c
== eof
|| c
== '\n' || c
== EOF
) {
error("No previous re|No previous regular expression");
if (c
== '\n' && oknl
== 0)
error("Missing closing delimiter@for regular expression");
if (ep
>= &expbuf
[ESIZE
- 2])
cerror("Re too complex|Regular expression too complicated");
if (c
== eof
|| c
== EOF
) {
cerror("Unmatched \\(|More \\('s than \\)'s in regular expression");
if (c
!= '*' || ep
== expbuf
)
if (c
!= '\\' || peekchar() != '*' || ep
== expbuf
)
cerror("Awash in \\('s!|Too many \\('d subexressions in a regular expression");
cerror("Extra \\)|More \\)'s than \\('s in regular expression");
error("Replacement pattern contains &@- cannot use in re");
if (c
>= '1' && c
<= '9')
error("Replacement pattern contains \\d@- cannot use in re");
if (ep
>= &expbuf
[ESIZE
-2])
if (*lastep
== CBRA
|| *lastep
== CKET
)
cerror("Illegal *|Can't * a \\( ... \\) in regular expression");
if (*lastep
== CCHR
&& (lastep
[1] & QUOTE
))
cerror("Illegal *|Can't * a \\n in regular expression");
cerror("Bad character class|Empty character class '[]' or '[^]' cannot match");
if (c
== '\\' && any(peekchar(), "]-^\\"))
if (c
== '\n' || c
== EOF
)
if (ep
>= &expbuf
[ESIZE
])
cerror("No newlines in re's|Can't escape newlines into regular expressions");
if (c < '1' || c > NBRA + '1') {
cerror("Bad \\n|\\n in regular expression with n greater than the number of \\('s");
cerror("Badly formed re|Missing closing delimiter for regular expression");
if (peekchar() == eof
|| peekchar() == EOF
|| oknl
&& peekchar() == '\n') {
return (a
== b
|| value(IGNORECASE
) &&
((islower(a
) && toupper(a
) == b
) || (islower(b
) && toupper(b
) == a
)));
return (advance(p1
, p2
));
/* fast check for first character */
if (c
!= *p1
&& (!value(IGNORECASE
) ||
!((islower(c
) && toupper(c
) == *p1
) ||
(islower(*p1
) && toupper(*p1
) == c
))))
#define uletter(c) (isalpha(c) || c == '_')
for (;;) switch (*ep
++) {
if (cclass(ep
, *lp
++, 1)) {
if (cclass(ep
, *lp
++, 0)) {
while (cclass(ep
, *lp
++, ep
[-1] == (CCL
|STAR
)))
if ((isdigit(*lp
) || uletter(*lp
)) && !uletter(lp
[-1]) && !isdigit(lp
[-1]))
if (!uletter(*lp
) && !isdigit(*lp
))
error("Re internal error");
if (value(IGNORECASE
) && isupper(c
))
if (n
> 2 && set
[1] == '-') {
if (c
>= (set
[0] & TRIM
) && c
<= (set
[2] & TRIM
))
if ((*set
++ & TRIM
) == c
)