version 1.4, 2000/02/29 16:00:23 |
version 1.5, 2000/04/13 06:12:16 |
|
|
/* |
/* |
* regular expression search commands for |
* regular expression search commands for Mg |
* MicroGnuEmacs |
|
* |
* |
* This file contains functions to implement several of gnuemacs' |
* This file contains functions to implement several of gnuemacs' |
* regular expression functions for MicroGnuEmacs. Several of |
* regular expression functions for Mg. Several of the routines |
* the routines below are just minor rearrangements of the MicroGnuEmacs |
* below are just minor rearrangements of the Mg non-regular |
* non-regular expression search functions. Hence some of them date back |
* expression search functions. Hence some of them date back in |
* in essential structure to the original MicroEMACS; others are modifications |
* essential structure to the original MicroEMACS; others are modifications |
* of Rich Ellison's code. I, Peter Newton, wrote about half from scratch. |
* of Rich Ellison's code. I, Peter Newton, wrote about half from scratch. |
*/ |
*/ |
|
|
|
|
#include "def.h" |
#include "def.h" |
#include "macro.h" |
#include "macro.h" |
|
|
#define SRCH_BEGIN (0) /* Search sub-codes. */ |
#define SRCH_BEGIN (0) /* Search sub-codes. */ |
#define SRCH_FORW (-1) |
#define SRCH_FORW (-1) |
#define SRCH_BACK (-2) |
#define SRCH_BACK (-2) |
#define SRCH_NOPR (-3) |
#define SRCH_NOPR (-3) |
#define SRCH_ACCM (-4) |
#define SRCH_ACCM (-4) |
#define SRCH_MARK (-5) |
#define SRCH_MARK (-5) |
|
|
#define RE_NMATCH 10 /* max number of matches */ |
#define RE_NMATCH 10 /* max number of matches */ |
|
|
char re_pat[NPAT]; /* Regex pattern */ |
char re_pat[NPAT]; /* Regex pattern */ |
int re_srch_lastdir = SRCH_NOPR; /* Last search flags. */ |
int re_srch_lastdir = SRCH_NOPR; /* Last search flags. */ |
int casefoldsearch = TRUE; /* Does search ignore case ? */ |
int casefoldsearch = TRUE; /* Does search ignore case ? */ |
|
|
/* Indexed by a character, gives the upper case equivalent of the character */ |
/* Indexed by a character, gives the upper case equivalent of the character */ |
|
|
static char upcase[0400] = |
static char upcase[0400] = |
{ 000, 001, 002, 003, 004, 005, 006, 007, |
{000, 001, 002, 003, 004, 005, 006, 007, |
010, 011, 012, 013, 014, 015, 016, 017, |
010, 011, 012, 013, 014, 015, 016, 017, |
020, 021, 022, 023, 024, 025, 026, 027, |
020, 021, 022, 023, 024, 025, 026, 027, |
030, 031, 032, 033, 034, 035, 036, 037, |
030, 031, 032, 033, 034, 035, 036, 037, |
040, 041, 042, 043, 044, 045, 046, 047, |
040, 041, 042, 043, 044, 045, 046, 047, |
050, 051, 052, 053, 054, 055, 056, 057, |
050, 051, 052, 053, 054, 055, 056, 057, |
060, 061, 062, 063, 064, 065, 066, 067, |
060, 061, 062, 063, 064, 065, 066, 067, |
070, 071, 072, 073, 074, 075, 076, 077, |
070, 071, 072, 073, 074, 075, 076, 077, |
0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, |
0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, |
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, |
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, |
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, |
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, |
0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, |
0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, |
0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, |
0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, |
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, |
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, |
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, |
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, |
0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, |
0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, |
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, |
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, |
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, |
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, |
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, |
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, |
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, |
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, |
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, |
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, |
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, |
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, |
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, |
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, |
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, |
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, |
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, |
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, |
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, |
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, |
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, |
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, |
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, |
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, |
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, |
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, |
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, |
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, |
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, |
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, |
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 |
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 |
}; |
}; |
|
|
/* |
/* |
* Search forward. |
* Search forward. |
|
|
* matched characters, and display does all the hard stuff. |
* matched characters, and display does all the hard stuff. |
* If not found, it just prints a message. |
* If not found, it just prints a message. |
*/ |
*/ |
/*ARGSUSED*/ |
/* ARGSUSED */ |
re_forwsearch(f, n) { |
re_forwsearch(f, n) |
register int s; |
{ |
|
register int s; |
|
|
if ((s=re_readpattern("RE Search")) != TRUE) |
if ((s = re_readpattern("RE Search")) != TRUE) |
return (s); |
return (s); |
if (re_forwsrch() == FALSE) { |
if (re_forwsrch() == FALSE) { |
ewprintf("Search failed: \"%s\"", re_pat); |
ewprintf("Search failed: \"%s\"", re_pat); |
|
|
* pointing at the first character of the pattern [the last character that |
* pointing at the first character of the pattern [the last character that |
* was matched]. |
* was matched]. |
*/ |
*/ |
/*ARGSUSED*/ |
/* ARGSUSED */ |
re_backsearch(f, n) { |
re_backsearch(f, n) |
register int s; |
{ |
|
register int s; |
|
|
if ((s=re_readpattern("RE Search backward")) != TRUE) |
if ((s = re_readpattern("RE Search backward")) != TRUE) |
return (s); |
return (s); |
if (re_backsrch() == FALSE) { |
if (re_backsrch() == FALSE) { |
ewprintf("Search failed: \"%s\"", re_pat); |
ewprintf("Search failed: \"%s\"", re_pat); |
|
|
* has been saved in "srch_lastdir", so you know which way |
* has been saved in "srch_lastdir", so you know which way |
* to go. |
* to go. |
*/ |
*/ |
/*ARGSUSED*/ |
/* ARGSUSED */ |
/* This code has problems-- some incompatibility(?) with |
/* |
extend.c causes match to fail when it should not. |
* This code has problems-- some incompatibility(?) with extend.c causes |
|
* match to fail when it should not. |
*/ |
*/ |
re_searchagain(f, n) { |
re_searchagain(f, n) |
|
{ |
|
|
if (re_srch_lastdir == SRCH_NOPR) { |
if (re_srch_lastdir == SRCH_NOPR) { |
ewprintf("No last search"); |
ewprintf("No last search"); |
return (FALSE); |
return (FALSE); |
} |
} |
|
if (re_srch_lastdir == SRCH_FORW) { |
if (re_srch_lastdir == SRCH_FORW) { |
if (re_forwsrch() == FALSE) { |
if (re_forwsrch() == FALSE) { |
ewprintf("Search failed: \"%s\"", re_pat); |
ewprintf("Search failed: \"%s\"", re_pat); |
return (FALSE); |
return (FALSE); |
} |
} |
return (TRUE); |
return (TRUE); |
} |
} |
if (re_srch_lastdir == SRCH_BACK) { |
if (re_srch_lastdir == SRCH_BACK) { |
if (re_backsrch() == FALSE) { |
if (re_backsrch() == FALSE) { |
ewprintf("Search failed: \"%s\"", re_pat); |
ewprintf("Search failed: \"%s\"", re_pat); |
return (FALSE); |
return (FALSE); |
} |
} |
return (TRUE); |
return (TRUE); |
} |
} |
|
} |
} |
|
|
|
|
/* Compiled regex goes here-- changed only when new pattern read */ |
/* Compiled regex goes here-- changed only when new pattern read */ |
static regex_t re_buff; |
static regex_t re_buff; |
static regmatch_t re_match[RE_NMATCH]; |
static regmatch_t re_match[RE_NMATCH]; |
|
|
/* |
/* |
* Re-Query Replace. |
* Re-Query Replace. |
* Replace strings selectively. Does a search and replace operation. |
* Replace strings selectively. Does a search and replace operation. |
*/ |
*/ |
/*ARGSUSED*/ |
/* ARGSUSED */ |
re_queryrepl(f, n) { |
re_queryrepl(f, n) |
register int s; |
{ |
register int rcnt = 0; /* Replacements made so far */ |
register int s; |
register int plen; /* length of found string */ |
register int rcnt = 0; /* Replacements made so far */ |
char news[NPAT]; /* replacement string */ |
register int plen; /* length of found string */ |
|
char news[NPAT]; /* replacement string */ |
|
|
/* Casefold check */ |
/* Casefold check */ |
if (!casefoldsearch) f = TRUE; |
if (!casefoldsearch) |
|
f = TRUE; |
|
|
if ((s=re_readpattern("RE Query replace")) != TRUE) |
if ((s = re_readpattern("RE Query replace")) != TRUE) |
return (s); |
return (s); |
if ((s=ereply("Query replace %s with: ",news, NPAT, re_pat)) == ABORT) |
if ((s = ereply("Query replace %s with: ", news, NPAT, re_pat)) == ABORT) |
return (s); |
return (s); |
if (s == FALSE) |
if (s == FALSE) |
news[0] = '\0'; |
news[0] = '\0'; |
|
|
*/ |
*/ |
|
|
while (re_forwsrch() == TRUE) { |
while (re_forwsrch() == TRUE) { |
retry: |
retry: |
update(); |
update(); |
switch (getkey(FALSE)) { |
switch (getkey(FALSE)) { |
case ' ': |
case ' ': |
|
|
rcnt++; |
rcnt++; |
goto stopsearch; |
goto stopsearch; |
|
|
case CCHR('G'): /* ^G */ |
case CCHR('G'):/* ^G */ |
(VOID) ctrlg(FFRAND, 0); |
(VOID) ctrlg(FFRAND, 0); |
case CCHR('['): /* ESC */ |
case CCHR('['):/* ESC */ |
case '`': |
case '`': |
goto stopsearch; |
goto stopsearch; |
|
|
|
|
} while (re_forwsrch() == TRUE); |
} while (re_forwsrch() == TRUE); |
goto stopsearch; |
goto stopsearch; |
|
|
case CCHR('?'): /* To not replace */ |
case CCHR('?'):/* To not replace */ |
break; |
break; |
|
|
default: |
default: |
ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit"); |
ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit"); |
goto retry; |
goto retry; |
} |
} |
} |
} |
|
|
|
|
|
|
|
|
/* Routine re_doreplace calls lreplace to make replacements needed by |
/* |
* re_query replace. Its reason for existence is to deal with \1, |
* Routine re_doreplace calls lreplace to make replacements needed by |
* \2. etc. |
* re_query replace. Its reason for existence is to deal with \1, \2. etc. |
*/ |
*/ |
|
|
/* Maximum length of replacement string */ |
/* Maximum length of replacement string */ |
#define REPLEN 256 |
#define REPLEN 256 |
|
|
re_doreplace(plen, st, f) |
re_doreplace(plen, st, f) |
register RSIZE plen; /* length to remove */ |
register RSIZE plen; /* length to remove */ |
char *st; /* replacement string */ |
char *st; /* replacement string */ |
int f; /* case hack disable */ |
int f; /* case hack disable */ |
{ |
{ |
int s; |
int s; |
int num, k; |
int num, k; |
register int j; |
register int j; |
int more, state; |
int more, state; |
LINE *clp; |
LINE *clp; |
char repstr[REPLEN]; |
char repstr[REPLEN]; |
|
|
clp = curwp->w_dotp; |
clp = curwp->w_dotp; |
more = TRUE; |
more = TRUE; |
j = 0; |
j = 0; |
state = 0; |
state = 0; |
|
|
/* The following FSA parses the replacement string */ |
/* The following FSA parses the replacement string */ |
while (more) { |
while (more) { |
switch (state) { |
switch (state) { |
|
|
case 0: if (*st == '\\') { |
case 0: |
st++; |
if (*st == '\\') { |
state = 1; |
st++; |
} |
state = 1; |
else if (*st == '\0') |
} else if (*st == '\0') |
more = FALSE; |
more = FALSE; |
else { |
else { |
repstr[j] = *st; |
repstr[j] = *st; |
j++; if (j >= REPLEN) return(FALSE); |
j++; |
st++; |
if (j >= REPLEN) |
} |
return (FALSE); |
break; |
st++; |
case 1: if (*st >= '0' && *st <= '9') { |
} |
num = *st - '0'; |
break; |
st++; |
case 1: |
state = 2; |
if (*st >= '0' && *st <= '9') { |
} |
num = *st - '0'; |
else if (*st == '\0') |
st++; |
more = FALSE; |
state = 2; |
else { |
} else if (*st == '\0') |
repstr[j] = *st; |
more = FALSE; |
j++; if (j >= REPLEN) return(FALSE); |
else { |
st++; |
repstr[j] = *st; |
state = 0; |
j++; |
} |
if (j >= REPLEN) |
break; |
return (FALSE); |
case 2: if (*st >= '0' && *st <= '9') { |
st++; |
num = 10*num + *st - '0'; |
state = 0; |
st++; |
} |
} |
break; |
else { |
case 2: |
if (num >= RE_NMATCH) return(FALSE); |
if (*st >= '0' && *st <= '9') { |
k = re_match[num].rm_eo - re_match[num].rm_so; |
num = 10 * num + *st - '0'; |
if (j+k >= REPLEN) return(FALSE); |
st++; |
bcopy(&(clp->l_text[re_match[num].rm_so]), &repstr[j], k); |
} else { |
j += k; |
if (num >= RE_NMATCH) |
if (*st == '\0') |
return (FALSE); |
more = FALSE; |
k = re_match[num].rm_eo - re_match[num].rm_so; |
if (*st == '\\') { |
if (j + k >= REPLEN) |
st++; |
return (FALSE); |
state = 1; |
bcopy(&(clp->l_text[re_match[num].rm_so]), &repstr[j], k); |
} |
j += k; |
else { |
if (*st == '\0') |
repstr[j] = *st; |
more = FALSE; |
j++; if (j >= REPLEN) return(FALSE); |
if (*st == '\\') { |
st++; |
st++; |
state = 0; |
state = 1; |
} |
} else { |
} |
repstr[j] = *st; |
break; |
j++; |
} /* end case */ |
if (j >= REPLEN) |
} /* end while */ |
return (FALSE); |
|
st++; |
|
state = 0; |
|
} |
|
} |
|
break; |
|
} /* end case */ |
|
} /* end while */ |
|
|
repstr[j] = '\0'; |
repstr[j] = '\0'; |
|
|
s = lreplace(plen, repstr, f); |
s = lreplace(plen, repstr, f); |
|
|
return(s); |
return (s); |
} |
} |
|
|
|
|
|
|
* is notified of the change, and TRUE is returned. If the |
* is notified of the change, and TRUE is returned. If the |
* string isn't found, FALSE is returned. |
* string isn't found, FALSE is returned. |
*/ |
*/ |
re_forwsrch() { |
re_forwsrch() |
|
{ |
|
|
register LINE *clp; |
register LINE *clp; |
register int tbo; |
register int tbo; |
int error, plen; |
int error, plen; |
|
|
clp = curwp->w_dotp; |
clp = curwp->w_dotp; |
tbo = curwp->w_doto; |
tbo = curwp->w_doto; |
|
|
if (tbo == clp->l_used) |
if (tbo == clp->l_used) |
/* Don't start matching off end of line-- must |
/* |
* move to beginning of next line, unless at end |
* Don't start matching off end of line-- must move to |
*/ |
* beginning of next line, unless at end |
if (clp != curbp->b_linep) { |
*/ |
clp = lforw(clp); |
if (clp != curbp->b_linep) { |
tbo = 0; |
clp = lforw(clp); |
} |
tbo = 0; |
|
} |
|
/* |
|
* Note this loop does not process the last line, but this editor |
|
* always makes the last line empty so this is good. |
|
*/ |
|
|
|
while (clp != (curbp->b_linep)) { |
|
|
/* Note this loop does not process the last line, but this editor |
re_match[0].rm_so = tbo; |
always makes the last line empty so this is good. |
re_match[0].rm_eo = llength(clp); |
*/ |
error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND); |
|
|
while (clp != (curbp->b_linep)) { |
if (error) { |
|
clp = lforw(clp); |
|
tbo = 0; |
|
} else { |
|
curwp->w_doto = re_match[0].rm_eo; |
|
curwp->w_dotp = clp; |
|
curwp->w_flag |= WFMOVE; |
|
return (TRUE); |
|
} |
|
|
re_match[0].rm_so = tbo; |
} |
re_match[0].rm_eo = llength(clp); |
|
error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND); |
|
|
|
if (error) { |
return (FALSE); |
clp = lforw(clp); |
|
tbo = 0; |
|
} else { |
|
curwp->w_doto = re_match[0].rm_eo; |
|
curwp->w_dotp = clp; |
|
curwp->w_flag |= WFMOVE; |
|
return (TRUE); |
|
} |
|
|
|
} |
|
|
|
return(FALSE); |
|
|
|
} |
} |
|
|
|
|
|
|
* is notified of the change, and TRUE is returned. If the |
* is notified of the change, and TRUE is returned. If the |
* string isn't found, FALSE is returned. |
* string isn't found, FALSE is returned. |
*/ |
*/ |
re_backsrch() { |
re_backsrch() |
|
{ |
|
|
register LINE *clp; |
register LINE *clp; |
register int tbo; |
register int tbo; |
regmatch_t lastmatch; |
regmatch_t lastmatch; |
char m[1]; |
char m[1]; |
|
|
clp = curwp->w_dotp; |
clp = curwp->w_dotp; |
tbo = curwp->w_doto; |
tbo = curwp->w_doto; |
|
|
/* Start search one position to the left of dot */ |
/* Start search one position to the left of dot */ |
tbo = tbo - 1; |
tbo = tbo - 1; |
if (tbo < 0) { |
if (tbo < 0) { |
/* must move up one line */ |
/* must move up one line */ |
clp = lback(clp); |
clp = lback(clp); |
tbo = llength(clp); |
tbo = llength(clp); |
} |
} |
|
/* |
|
* Note this loop does not process the last line, but this editor |
|
* always makes the last line empty so this is good. |
|
*/ |
|
|
/* Note this loop does not process the last line, but this editor |
while (clp != (curbp->b_linep)) { |
always makes the last line empty so this is good. |
|
*/ |
|
|
|
while (clp != (curbp->b_linep)) { |
re_match[0].rm_so = 0; |
|
re_match[0].rm_eo = llength(clp); |
|
lastmatch.rm_so = -1; |
|
/* |
|
* Keep searching until we don't match any longer. Assumes a |
|
* non-match does not modify the re_match array. We have to |
|
* do this character-by-character after the first match since |
|
* POSIX regexps don't give you a way to do reverse matches. |
|
*/ |
|
while (!regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, |
|
REG_STARTEND) && re_match[0].rm_so < tbo) { |
|
memcpy(&lastmatch, &re_match[0], sizeof(regmatch_t)); |
|
re_match[0].rm_so++; |
|
re_match[0].rm_eo = llength(clp); |
|
} |
|
|
re_match[0].rm_so = 0; |
if (lastmatch.rm_so == -1) { |
re_match[0].rm_eo = llength(clp); |
clp = lback(clp); |
lastmatch.rm_so = -1; |
tbo = llength(clp); |
/* Keep searching until we don't match any longer. Assumes a non-match |
} else { |
does not modify the re_match array. We have to do this |
memcpy(&re_match[0], &lastmatch, sizeof(regmatch_t)); |
character-by-character after the first match since POSIX regexps don't |
curwp->w_doto = re_match[0].rm_so; |
give you a way to do reverse matches. |
curwp->w_dotp = clp; |
*/ |
curwp->w_flag |= WFMOVE; |
while (!regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND) && |
return (TRUE); |
re_match[0].rm_so < tbo) { |
} |
memcpy(&lastmatch, &re_match[0], sizeof(regmatch_t)); |
|
re_match[0].rm_so++; |
|
re_match[0].rm_eo = llength(clp); |
|
} |
|
|
|
if (lastmatch.rm_so == -1) { |
} |
clp = lback(clp); |
|
tbo = llength(clp); |
|
} else { |
|
memcpy(&re_match[0], &lastmatch, sizeof(regmatch_t)); |
|
curwp->w_doto = re_match[0].rm_so; |
|
curwp->w_dotp = clp; |
|
curwp->w_flag |= WFMOVE; |
|
return (TRUE); |
|
} |
|
|
|
} |
return (FALSE); |
|
|
return(FALSE); |
|
|
|
} |
} |
|
|
|
|
|
|
* Display the old pattern, in the style of Jeff Lomicka. There is |
* Display the old pattern, in the style of Jeff Lomicka. There is |
* some do-it-yourself control expansion. |
* some do-it-yourself control expansion. |
*/ |
*/ |
re_readpattern(prompt) char *prompt; { |
re_readpattern(prompt) |
int s; |
char *prompt; |
int flags; |
{ |
int error; |
int s; |
char tpat[NPAT]; |
int flags; |
static int dofree = 0; |
int error; |
|
char tpat[NPAT]; |
|
static int dofree = 0; |
|
|
if (re_pat[0] == '\0') s = ereply("%s: ", tpat, NPAT, prompt); |
if (re_pat[0] == '\0') |
else s = ereply("%s: (default %s) ", tpat, NPAT, prompt, re_pat); |
s = ereply("%s: ", tpat, NPAT, prompt); |
|
else |
|
s = ereply("%s: (default %s) ", tpat, NPAT, prompt, re_pat); |
|
|
if (s == TRUE) { |
if (s == TRUE) { |
/* New pattern given */ |
/* New pattern given */ |
(VOID) strcpy(re_pat, tpat); |
(VOID) strcpy(re_pat, tpat); |
if (casefoldsearch) |
if (casefoldsearch) |
flags = REG_EXTENDED|REG_ICASE; |
flags = REG_EXTENDED | REG_ICASE; |
else |
else |
flags = REG_EXTENDED; |
flags = REG_EXTENDED; |
if (dofree) |
if (dofree) |
regfree(&re_buff); |
regfree(&re_buff); |
error = regcomp(&re_buff, re_pat, flags); |
error = regcomp(&re_buff, re_pat, flags); |
if (error) { |
if (error) { |
char message[256]; |
char message[256]; |
regerror(error, &re_buff, message, sizeof(message)); |
regerror(error, &re_buff, message, sizeof(message)); |
ewprintf("Regex Error: %s", message); |
ewprintf("Regex Error: %s", message); |
re_pat[0] = '\0'; |
re_pat[0] = '\0'; |
return(FALSE); |
return (FALSE); |
} |
} |
dofree = 1; |
dofree = 1; |
} |
} else if (s == FALSE && re_pat[0] != '\0') |
else if (s==FALSE && re_pat[0]!='\0') |
/* Just using old pattern */ |
/* Just using old pattern */ |
s = TRUE; |
s = TRUE; |
|
return (s); |
return (s); |
} |
} |
|
|
|
|
|
|
/* Cause case to not matter in searches. This is the default. If |
/* |
* called with argument cause case to matter. |
* Cause case to not matter in searches. This is the default. If called |
|
* with argument cause case to matter. |
*/ |
*/ |
setcasefold(f, n) { |
setcasefold(f, n) |
|
{ |
|
|
if (f & FFARG) { |
if (f & FFARG) { |
casefoldsearch = FALSE; |
casefoldsearch = FALSE; |
ewprintf("Case-fold-search unset"); |
ewprintf("Case-fold-search unset"); |
} |
} else { |
else { |
casefoldsearch = TRUE; |
casefoldsearch = TRUE; |
ewprintf("Case-fold-search set"); |
ewprintf("Case-fold-search set"); |
} |
} |
|
|
|
/* Invalidate the regular expression pattern since I'm too lazy |
/* |
* to recompile it. |
* Invalidate the regular expression pattern since I'm too lazy to |
*/ |
* recompile it. |
|
*/ |
|
|
re_pat[0] = '\0'; |
re_pat[0] = '\0'; |
|
|
return(TRUE); |
return (TRUE); |
|
|
} /* end setcasefold */ |
} /* end setcasefold */ |
|
|
|
|
/* Delete all lines after dot that contain a string matching regex |
/* |
|
* Delete all lines after dot that contain a string matching regex |
*/ |
*/ |
delmatchlines(f, n) { |
delmatchlines(f, n) |
int s; |
{ |
|
int s; |
|
|
if ((s=re_readpattern("Flush lines (containing match for regexp)")) != TRUE) |
if ((s = re_readpattern("Flush lines (containing match for regexp)")) != TRUE) |
return (s); |
return (s); |
|
|
s = killmatches(TRUE); |
s = killmatches(TRUE); |
|
|
return(s); |
return (s); |
} |
} |
|
|
|
|
|
|
/* Delete all lines after dot that don't contain a string matching regex |
/* |
|
* Delete all lines after dot that don't contain a string matching regex |
*/ |
*/ |
delnonmatchlines(f, n) { |
delnonmatchlines(f, n) |
int s; |
{ |
|
int s; |
|
|
|
|
if ((s=re_readpattern("Keep lines (containing match for regexp)")) != TRUE) |
if ((s = re_readpattern("Keep lines (containing match for regexp)")) != TRUE) |
return (s); |
return (s); |
|
|
s = killmatches(FALSE); |
s = killmatches(FALSE); |
|
|
return(s); |
return (s); |
} |
} |
|
|
|
|
|
|
/* This function does the work of deleting matching lines */ |
/* This function does the work of deleting matching lines */ |
killmatches(cond) |
killmatches(cond) |
int cond; |
int cond; |
{ |
{ |
int s, error; |
int s, error; |
int count = 0; |
int count = 0; |
LINE *clp; |
LINE *clp; |
|
|
clp = curwp->w_dotp; |
clp = curwp->w_dotp; |
if (curwp->w_doto == llength(clp)) |
if (curwp->w_doto == llength(clp)) |
/* Consider dot on next line */ |
/* Consider dot on next line */ |
clp = lforw(clp); |
clp = lforw(clp); |
|
|
while (clp != (curbp->b_linep)) { |
while (clp != (curbp->b_linep)) { |
|
|
/* see if line matches */ |
/* see if line matches */ |
re_match[0].rm_so = 0; |
re_match[0].rm_so = 0; |
re_match[0].rm_eo = llength(clp); |
re_match[0].rm_eo = llength(clp); |
error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND); |
error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND); |
|
|
/* Delete line when appropriate */ |
/* Delete line when appropriate */ |
if ((cond == FALSE && error) || (cond == TRUE && !error)) { |
if ((cond == FALSE && error) || (cond == TRUE && !error)) { |
curwp->w_doto = 0; |
curwp->w_doto = 0; |
curwp->w_dotp = clp; |
curwp->w_dotp = clp; |
count++; |
count++; |
s = ldelete(llength(clp)+1, KNONE); |
s = ldelete(llength(clp) + 1, KNONE); |
clp = curwp->w_dotp; |
clp = curwp->w_dotp; |
curwp->w_flag |= WFMOVE; |
curwp->w_flag |= WFMOVE; |
if (s == FALSE) return(FALSE); |
if (s == FALSE) |
} |
return (FALSE); |
else |
} else |
clp = lforw(clp); |
clp = lforw(clp); |
} |
} |
|
|
ewprintf("%d line(s) deleted", count); |
ewprintf("%d line(s) deleted", count); |
if (count > 0) curwp->w_flag |= WFMOVE; |
if (count > 0) |
|
curwp->w_flag |= WFMOVE; |
|
|
return(TRUE); |
return (TRUE); |
} |
} |
|
|
|
|
petersfunc(f, n) { |
petersfunc(f, n) |
|
{ |
|
|
int s; |
int s; |
LINE *clp; |
LINE *clp; |
char c; |
char c; |
|
|
curwp->w_doto = 0; |
curwp->w_doto = 0; |
s = ldelete(llength(curwp->w_dotp)+1, KNONE); |
s = ldelete(llength(curwp->w_dotp) + 1, KNONE); |
curwp->w_flag |= WFMOVE; |
curwp->w_flag |= WFMOVE; |
return(s); |
return (s); |
|
|
} |
} |
|
|
|
|
/* Count lines matching regex |
/* |
|
* Count lines matching regex |
*/ |
*/ |
cntmatchlines(f, n) { |
cntmatchlines(f, n) |
int s; |
{ |
|
int s; |
|
|
if ((s=re_readpattern("Count lines (matching regexp)")) != TRUE) |
if ((s = re_readpattern("Count lines (matching regexp)")) != TRUE) |
return (s); |
return (s); |
|
|
s = countmatches(TRUE); |
s = countmatches(TRUE); |
|
|
return(s); |
return (s); |
} |
} |
|
|
|
|
|
|
/* Count lines that fail to match regex |
/* |
|
* Count lines that fail to match regex |
*/ |
*/ |
cntnonmatchlines(f, n) { |
cntnonmatchlines(f, n) |
int s; |
{ |
|
int s; |
|
|
|
|
if ((s=re_readpattern("Count lines (not matching regexp)")) != TRUE) |
if ((s = re_readpattern("Count lines (not matching regexp)")) != TRUE) |
return (s); |
return (s); |
|
|
s = countmatches(FALSE); |
s = countmatches(FALSE); |
|
|
return(s); |
return (s); |
} |
} |
|
|
|
|
|
|
/* This function does the work of counting matching lines */ |
/* This function does the work of counting matching lines */ |
countmatches(cond) |
countmatches(cond) |
int cond; |
int cond; |
{ |
{ |
int s, error; |
int s, error; |
int count = 0; |
int count = 0; |
LINE *clp; |
LINE *clp; |
|
|
clp = curwp->w_dotp; |
clp = curwp->w_dotp; |
if (curwp->w_doto == llength(clp)) |
if (curwp->w_doto == llength(clp)) |
/* Consider dot on next line */ |
/* Consider dot on next line */ |
clp = lforw(clp); |
clp = lforw(clp); |
|
|
while (clp != (curbp->b_linep)) { |
while (clp != (curbp->b_linep)) { |
|
|
/* see if line matches */ |
/* see if line matches */ |
re_match[0].rm_so = 0; |
re_match[0].rm_so = 0; |
re_match[0].rm_eo = llength(clp); |
re_match[0].rm_eo = llength(clp); |
error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND); |
error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND); |
|
|
/* Count line when appropriate */ |
/* Count line when appropriate */ |
if ((cond == FALSE && error) || (cond == TRUE && !error)) count++; |
if ((cond == FALSE && error) || (cond == TRUE && !error)) |
clp = lforw(clp); |
count++; |
} |
clp = lforw(clp); |
|
} |
|
|
if (cond) |
if (cond) |
ewprintf("Number of lines matching: %d", count); |
ewprintf("Number of lines matching: %d", count); |
else |
else |
ewprintf("Number of lines not matching: %d", count); |
ewprintf("Number of lines not matching: %d", count); |
|
|
return(TRUE); |
return (TRUE); |
} |
} |
#endif |
#endif |