mirror of
https://github.com/vbatts/bvi.git
synced 2025-08-02 23:50:28 +00:00
bvi-1.3.0.src.tar.gz
This commit is contained in:
commit
0220b756fa
80 changed files with 17347 additions and 0 deletions
640
re.c
Normal file
640
re.c
Normal file
|
@ -0,0 +1,640 @@
|
|||
/* re - regular expression search for bvi
|
||||
*
|
||||
* NOTE: Edit this file with tabstop=4 !
|
||||
*
|
||||
* 1996-01-06 created;
|
||||
* 1999-01-19 V 1.1.0
|
||||
* 1999-03-17 V 1.1.1
|
||||
* 1999-09-10 V 1.2.0
|
||||
* 2000-04-25 V 1.3.0 beta
|
||||
* 2000-09-29 V 1.3.0 final
|
||||
*
|
||||
* Copyright 1996-2000 by Gerhard Buergmann
|
||||
* Gerhard.Buergmann@altavista.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* See file COPYING for information on distribution conditions.
|
||||
*/
|
||||
|
||||
/* You cannot use a common regexp subroutine, because \0 is a regular
|
||||
* character in a binary string !
|
||||
*/
|
||||
|
||||
#include "bvi.h"
|
||||
#include "set.h"
|
||||
|
||||
static int sbracket();
|
||||
|
||||
char act_pat[MAXCMD]; /* found pattern */
|
||||
char pattern[MAXCMD + 1];
|
||||
char search_pat[BUFFER]; /* / or ? command */
|
||||
char *notfound = "Fail|Pattern not found";
|
||||
char *noprev = "No previous expression";
|
||||
char *emptyclass = "Bad character class|Empty byte class '[]' or '[^]' cannot match";
|
||||
|
||||
|
||||
|
||||
int
|
||||
bregexec(start, scan)
|
||||
PTR start;
|
||||
char *scan;
|
||||
{
|
||||
char *act;
|
||||
int count, test;
|
||||
|
||||
act = act_pat;
|
||||
while (*scan != 0) {
|
||||
switch (*scan++) {
|
||||
case ONE: /* exactly one character */
|
||||
count = *scan++;
|
||||
if (P(P_IC) && smode == ASCII) test = toupper(*start);
|
||||
else test = *start;
|
||||
if (count == 1) {
|
||||
if (test != *scan) return 0;
|
||||
scan++;
|
||||
} else if (count > 1) {
|
||||
if (sbracket(test, scan, count)) return 0;
|
||||
scan += count;
|
||||
}
|
||||
*act++ = *start++;
|
||||
break;
|
||||
case STAR: /* zero or more characters */
|
||||
count = *scan++;
|
||||
if (P(P_IC) && smode == ASCII) test = toupper(*start);
|
||||
else test = *start;
|
||||
if (count == 1) { /* only one character, 0 - n times */
|
||||
while(test == *scan) {
|
||||
*act++ = *start++;
|
||||
if (P(P_IC) && smode == ASCII) test = toupper(*start);
|
||||
else test = *start;
|
||||
}
|
||||
scan++;
|
||||
} else if (count > 1) { /* characters in bracket */
|
||||
if (*scan == '^') {
|
||||
while (start < maxpos) {
|
||||
if (bregexec(start, scan + count)) {
|
||||
*act = '\0';
|
||||
return 1;
|
||||
}
|
||||
if (sbracket(test, scan, count)) return 0;
|
||||
*act++ = *start++;
|
||||
if (P(P_IC) && smode == ASCII) test = toupper(*start);
|
||||
else test = *start;
|
||||
}
|
||||
} else {
|
||||
while(!sbracket(test, scan, count)) {
|
||||
*act++ = *start++;
|
||||
if (P(P_IC) && smode == ASCII) test = toupper(*start);
|
||||
else test = *start;
|
||||
}
|
||||
scan += count;
|
||||
}
|
||||
} else { /* ".*" */
|
||||
while (start < maxpos) {
|
||||
if (bregexec(start, scan)) { *act = '\0'; return 1; }
|
||||
start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*act = '\0';
|
||||
return 1; /* found */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sbracket(start, scan, count)
|
||||
int start;
|
||||
char *scan;
|
||||
int count;
|
||||
{
|
||||
if (*scan++ == '^') {
|
||||
if (!memchr(scan, start, --count)) return 0;
|
||||
} else {
|
||||
if (memchr(scan, start, --count)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
PTR
|
||||
end_word(start)
|
||||
PTR start;
|
||||
{
|
||||
PTR pos;
|
||||
|
||||
pos = start;
|
||||
if (!isprint(*pos & 0xff)) return start;
|
||||
while (isprint(*pos & 0xff)) if (pos++ > maxpos) return start;
|
||||
return --pos;
|
||||
}
|
||||
|
||||
|
||||
/* wordsearch serves the 'W' and 'w' - command
|
||||
*/
|
||||
PTR
|
||||
wordsearch(start, mode)
|
||||
PTR start;
|
||||
char mode;
|
||||
{
|
||||
PTR found;
|
||||
PTR pos;
|
||||
int ccount;
|
||||
|
||||
pos = start + 1;
|
||||
do {
|
||||
while (isprint(*pos & 0xff)) if (pos++ > maxpos) return start;
|
||||
while (!isprint(*pos & 0xff)) if (pos++ > maxpos) return start;
|
||||
found = pos;
|
||||
ccount = 0;
|
||||
while (isprint(*pos & 0xff)) {
|
||||
if (pos++ > maxpos) return start;
|
||||
ccount++; }
|
||||
if (ccount < P(P_WL)) continue;
|
||||
|
||||
if (mode == 'W') {
|
||||
if (*pos == '\0' || *pos == '\n') return found;
|
||||
} else {
|
||||
return found;
|
||||
}
|
||||
} while (pos < maxpos);
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
/* backsearch serves the 'b' and 'B' command
|
||||
*/
|
||||
PTR
|
||||
backsearch(start, mode)
|
||||
PTR start;
|
||||
char mode;
|
||||
{
|
||||
PTR pos;
|
||||
int ccount;
|
||||
|
||||
pos = start - 1;
|
||||
do {
|
||||
if (mode == 'B') {
|
||||
while (*pos != '\0' && *pos != '\n') if (pos-- < mem) return start;
|
||||
} else {
|
||||
while (!isprint(*pos & 0xff)) if (pos-- < mem) return start;
|
||||
}
|
||||
pos--;
|
||||
ccount = 0;
|
||||
while (isprint(*pos & 0xff)) {
|
||||
if (pos-- < mem) return start;
|
||||
ccount++; }
|
||||
if (ccount >= P(P_WL)) return (pos + 1);
|
||||
|
||||
} while (pos > mem);
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
/* used by :s
|
||||
*/
|
||||
int
|
||||
do_substitution(delim, line, startpos, endpos)
|
||||
int delim;
|
||||
char *line;
|
||||
PTR startpos;
|
||||
PTR endpos;
|
||||
{
|
||||
int n;
|
||||
char *found;
|
||||
char *cmd = NULL;
|
||||
int repl_count = 0;
|
||||
int global = 0;
|
||||
int conf = 0;
|
||||
static int direct;
|
||||
static int pat_len = -1;
|
||||
static int ch;
|
||||
static char find_pat[BUFFER];
|
||||
static char repl_pat[MAXCMD];
|
||||
|
||||
ignore_case = P(P_IC);
|
||||
magic = P(P_MA);
|
||||
switch (delim) {
|
||||
case '/':
|
||||
case '?':
|
||||
ch = delim;
|
||||
direct = (ch == '/' ? FORWARD : BACKWARD);
|
||||
cmd = patcpy(pattern, line, ch);
|
||||
if (pattern[0] == '\0') break;
|
||||
if (ascii_comp(find_pat, pattern)) return 0;
|
||||
cmd = patcpy(pattern, cmd, ch); /* Replace Pattern */
|
||||
poi = pattern;
|
||||
pat_len = 0;
|
||||
while (*poi) {
|
||||
if (*poi == '\\') {
|
||||
switch (*(++poi)) {
|
||||
case '0': repl_pat[pat_len++] = '\0'; break;
|
||||
case 'n': repl_pat[pat_len++] = '\n'; break;
|
||||
case 'r': repl_pat[pat_len++] = '\r'; break;
|
||||
case 't': repl_pat[pat_len++] = '\t'; break;
|
||||
case '\\': repl_pat[pat_len++] = '\\'; break;
|
||||
default: sprintf(string,
|
||||
"No such escape sequence \\%c", *poi);
|
||||
emsg(string);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
repl_pat[pat_len++] = *poi;
|
||||
}
|
||||
poi++;
|
||||
}
|
||||
break;
|
||||
case '#':
|
||||
case '\\':
|
||||
ch = delim;
|
||||
direct = (ch == '\\' ? FORWARD : BACKWARD);
|
||||
cmd = patcpy(pattern, line, ch);
|
||||
if (hex_comp(find_pat, pattern)) return 0;
|
||||
cmd = patcpy(pattern, cmd, ch); /* Replace Pattern */
|
||||
poi = pattern;
|
||||
pat_len = 0;
|
||||
while (*poi) {
|
||||
if (*poi == ' ' || *poi == '\t') {
|
||||
poi++;
|
||||
} else {
|
||||
if ((n = hexchar()) < 0) {
|
||||
emsg("Badly formed replacement pattern");
|
||||
return 0; }
|
||||
repl_pat[pat_len] = n;
|
||||
pat_len++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '\0':
|
||||
case 'g':
|
||||
case 'c':
|
||||
break;
|
||||
default:
|
||||
emsg("Extra chars|Extra characters at end of command");
|
||||
return -1;
|
||||
}
|
||||
if (pat_len == -1) {
|
||||
emsg("No previous substitute re|No previous substitute to repeat");
|
||||
return -1;
|
||||
}
|
||||
if (delim != '\0') {
|
||||
if (strchr(cmd, 'g')) global = 1;
|
||||
if (strchr(cmd, 'c')) conf = 1;
|
||||
}
|
||||
if ((strchr("\\#", ch) && loc == ASCII)
|
||||
|| (strchr("/?", ch) && loc == HEX))
|
||||
toggle();
|
||||
|
||||
startpos--;
|
||||
move(maxy, 0);
|
||||
refresh();
|
||||
|
||||
if (global) {
|
||||
if ((undo_count = alloc_buf(endpos - startpos, &undo_buf))) {
|
||||
memcpy(undo_buf, startpos + 1, undo_count);
|
||||
}
|
||||
undo_start = startpos + 1;
|
||||
edits = U_EDIT;
|
||||
}
|
||||
|
||||
AGAIN:
|
||||
if (direct == FORWARD) {
|
||||
found = fsearch(startpos + 1, endpos, find_pat);
|
||||
} else {
|
||||
found = rsearch(startpos - 1, mem, find_pat);
|
||||
}
|
||||
if (!found) {
|
||||
if (!repl_count) {
|
||||
if (P(P_WS)) {
|
||||
emsg(notfound);
|
||||
} else {
|
||||
if (P(P_TE))
|
||||
sprintf(string, "No match to %s", direct == FORWARD ? "BOTTOM" : "TOP");
|
||||
else
|
||||
sprintf(string, "Address search hit %s without matching pattern",
|
||||
direct == FORWARD ? "BOTTOM" : "TOP");
|
||||
emsg(string);
|
||||
}
|
||||
}
|
||||
return repl_count;
|
||||
} else {
|
||||
setpage(found);
|
||||
if (conf) {
|
||||
repaint();
|
||||
msg("Replace?");
|
||||
move(y, x);
|
||||
if (vgetc() != 'y') goto SKIP;
|
||||
}
|
||||
repl_count++;
|
||||
current_start = pagepos + y * Anzahl + xpos();
|
||||
if (!global) {
|
||||
if ((undo_count = alloc_buf(pat_len, &undo_buf))) {
|
||||
memcpy(undo_buf, current_start, undo_count);
|
||||
}
|
||||
undo_start = current_start;
|
||||
edits = U_EDIT;
|
||||
}
|
||||
memcpy(current_start, repl_pat, pat_len);
|
||||
SKIP:
|
||||
if (global) {
|
||||
startpos = found + pat_len - 1;
|
||||
goto AGAIN;
|
||||
}
|
||||
}
|
||||
return repl_count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Used by /, ?, \, #, n or N command
|
||||
* ch is this command
|
||||
* line are the characters after
|
||||
*
|
||||
* return address found
|
||||
*/
|
||||
PTR
|
||||
searching(ch, line, startpos, endpos, flag)
|
||||
int ch;
|
||||
char *line;
|
||||
PTR startpos;
|
||||
PTR endpos;
|
||||
int flag;
|
||||
{
|
||||
char *cmd = NULL;
|
||||
PTR found;
|
||||
int sdir;
|
||||
static char m[2];
|
||||
static int direct;
|
||||
|
||||
if (line[0] == '\0' && again == 0) {
|
||||
emsg(noprev);
|
||||
return 0L; }
|
||||
|
||||
ignore_case = (P(P_IC));
|
||||
magic = P(P_MA);
|
||||
start_addr--;
|
||||
if ((strchr("\\#", ch) && loc == ASCII)
|
||||
|| (strchr("/?", ch) && loc == HEX))
|
||||
toggle();
|
||||
|
||||
if (!strchr("Nn", ch)) {
|
||||
m[0] = ch;
|
||||
m[1] = '\0';
|
||||
switch (ch) {
|
||||
case '/':
|
||||
case '?':
|
||||
direct = (ch == '/' ? FORWARD : BACKWARD);
|
||||
cmd = patcpy(pattern, line, ch);
|
||||
if (pattern[0] != '\0') {
|
||||
if (ascii_comp(search_pat, pattern)) return 0L;
|
||||
again = 1;
|
||||
}
|
||||
break;
|
||||
case '#':
|
||||
case '\\':
|
||||
direct = (ch == '\\' ? FORWARD : BACKWARD);
|
||||
cmd = patcpy(pattern, line, ch);
|
||||
if (pattern[0] != '\0') {
|
||||
if (hex_comp(search_pat, pattern)) break;
|
||||
again = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!again) return 0L;
|
||||
} else {
|
||||
cmd = "";
|
||||
msg(m);
|
||||
}
|
||||
move(maxy, 0);
|
||||
refresh();
|
||||
sdir = (ch == 'N') ? !direct : direct;
|
||||
|
||||
if (sdir == FORWARD) {
|
||||
found = fsearch(startpos + 1, endpos, search_pat);
|
||||
if (flag & S_GLOBAL) return(found);
|
||||
if (!found)
|
||||
if (flag & 1) {
|
||||
msg("Search wrapped BOTTOM|Search wrapped around BOTTOM of buffer");
|
||||
found = fsearch(mem, startpos, search_pat);
|
||||
}
|
||||
} else {
|
||||
found = rsearch(startpos - 1, mem, search_pat);
|
||||
if (flag & S_GLOBAL) return(found);
|
||||
if (!found)
|
||||
if (flag & 1) {
|
||||
msg("Search wrapped TOP|Search wrapped around TOP of buffer");
|
||||
found = rsearch(endpos, startpos, search_pat);
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (flag & 1) {
|
||||
emsg(notfound);
|
||||
} else {
|
||||
if (P(P_TE))
|
||||
sprintf(string, "No match to %s", sdir == FORWARD ? "BOTTOM" : "TOP");
|
||||
else
|
||||
sprintf(string, "Address search hit %s without matching pattern",
|
||||
sdir == FORWARD ? "BOTTOM" : "TOP");
|
||||
emsg(string);
|
||||
}
|
||||
} else {
|
||||
setpage(found);
|
||||
if (cmd) {
|
||||
switch(*cmd) {
|
||||
case 'z': do_z(*++cmd);
|
||||
break;
|
||||
case 's': do_substitution(ch, cmd + 2, found, endpos);
|
||||
repaint();
|
||||
break;
|
||||
case ';': searching(*(cmd + 1), cmd + 2, found, maxpos - 1, flag);
|
||||
case '\0': break;
|
||||
default: beep();
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/* Copies a string from s2 to s1, up to delim or 0
|
||||
* returns pointer to next character
|
||||
*/
|
||||
char *
|
||||
patcpy(s1, s2, delim)
|
||||
char *s1, *s2;
|
||||
char delim;
|
||||
{
|
||||
while (*s2 != '\0' && *s2 != delim) {
|
||||
if (*s2 == '\\' && *(s2 + 1) == delim) s2++;
|
||||
*s1++ = *s2++;
|
||||
}
|
||||
*s1 = '\0';
|
||||
if (*s2 == delim) s2++;
|
||||
return s2;
|
||||
}
|
||||
|
||||
|
||||
PTR
|
||||
fsearch(start, end, smem)
|
||||
PTR start;
|
||||
PTR end;
|
||||
char *smem;
|
||||
{
|
||||
PTR spos;
|
||||
|
||||
signal(SIGINT, jmpproc);
|
||||
for (spos = start; spos <= end; spos++) {
|
||||
if (bregexec(spos, smem)) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
return(spos);
|
||||
}
|
||||
}
|
||||
signal(SIGINT, SIG_IGN);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
PTR
|
||||
rsearch(start, end, smem)
|
||||
PTR start;
|
||||
PTR end;
|
||||
char *smem;
|
||||
{
|
||||
PTR spos;
|
||||
|
||||
signal(SIGINT, jmpproc);
|
||||
for (spos = start; spos >= end; spos--) {
|
||||
if (bregexec(spos, smem)) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
return(spos);
|
||||
}
|
||||
}
|
||||
signal(SIGINT, SIG_IGN);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Calculates an address of a colon command
|
||||
* returns NULL on error or default_address, if nothing found
|
||||
*/
|
||||
PTR
|
||||
calc_addr(pointer, def_addr)
|
||||
char **pointer;
|
||||
PTR def_addr;
|
||||
{
|
||||
PTR addr;
|
||||
int ch, mark;
|
||||
char *cmd;
|
||||
|
||||
cmd = *pointer;
|
||||
addr = def_addr;
|
||||
SKIP_WHITE
|
||||
if (*cmd >= '1' && *cmd <= '9') {
|
||||
addr = mem + strtol(cmd, &cmd, 10) - P(P_OF);
|
||||
} else {
|
||||
ch = *cmd;
|
||||
switch (ch) {
|
||||
case '.': /* Current position */
|
||||
addr = current;
|
||||
cmd++;
|
||||
break;
|
||||
case '^':
|
||||
addr = mem;
|
||||
cmd++;
|
||||
break;
|
||||
case '$':
|
||||
addr = maxpos - 1;
|
||||
cmd++;
|
||||
break;
|
||||
case '\'': /* Mark */
|
||||
mark = (*++cmd);
|
||||
if (mark == '\'') {
|
||||
addr = last_motion;
|
||||
cmd++;
|
||||
break;
|
||||
} else if (mark < 'a' || mark > 'z') {
|
||||
emsg("Marks are ' and a-z");
|
||||
return NULL;
|
||||
}
|
||||
if (markbuf[mark - 'a'] == NULL) {
|
||||
emsg("Mark not defined");
|
||||
return NULL;
|
||||
}
|
||||
addr = markbuf[mark - 'a'];
|
||||
cmd++;
|
||||
break;
|
||||
case '\\':
|
||||
case '/':
|
||||
cmd = patcpy(pattern, cmd + 1, ch);
|
||||
if (pattern[0] == '\0' && again == 0) {
|
||||
emsg(noprev);
|
||||
return NULL;
|
||||
}
|
||||
if (pattern[0] != '\0') {
|
||||
again = 1;
|
||||
if (ch == '/') {
|
||||
if (ascii_comp(search_pat, pattern)) return NULL;
|
||||
} else {
|
||||
if (hex_comp(search_pat, pattern)) return NULL;
|
||||
}
|
||||
}
|
||||
addr = fsearch(mem, maxpos - 1, search_pat);
|
||||
break;
|
||||
case '#':
|
||||
case '?':
|
||||
cmd = patcpy(pattern, cmd + 1, ch);
|
||||
if (pattern[0] == '\0' && again == 0) {
|
||||
emsg(noprev);
|
||||
return NULL;
|
||||
}
|
||||
if (pattern[0] != '\0') {
|
||||
again = 1;
|
||||
if (ch == '?') {
|
||||
if (ascii_comp(search_pat, pattern)) return NULL;
|
||||
} else {
|
||||
if (hex_comp(search_pat, pattern)) return NULL;
|
||||
}
|
||||
}
|
||||
addr = rsearch(maxpos - 1, mem, search_pat);
|
||||
break;
|
||||
case '0':
|
||||
addr = mem + strtol(cmd, &cmd, 16) - P(P_OF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SKIP_WHITE
|
||||
while (*cmd == '+' || *cmd == '-') {
|
||||
if (*cmd == '+') {
|
||||
cmd++;
|
||||
SKIP_WHITE
|
||||
if (*cmd >= '1' && *cmd <= '9') {
|
||||
addr += strtol(cmd, &cmd, 10);
|
||||
} else if (*cmd == '0') {
|
||||
addr += strtol(cmd, &cmd, 16);
|
||||
}
|
||||
} else {
|
||||
cmd++;
|
||||
SKIP_WHITE
|
||||
if (*cmd >= '1' && *cmd <= '9') {
|
||||
addr -= strtol(cmd, &cmd, 10);
|
||||
} else if (*cmd == '0') {
|
||||
addr -= strtol(cmd, &cmd, 16);
|
||||
}
|
||||
}
|
||||
SKIP_WHITE
|
||||
}
|
||||
if (*pointer != cmd) {
|
||||
*pointer = cmd;
|
||||
addr_flag++;
|
||||
}
|
||||
return addr;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue