|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 14562 (0x38e2)
Types: TextFile
Names: »te_srch.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/teco/te_srch.c«
/* TECO for Ultrix Copyright 1986 Matt Fichtenbaum */
/* This program and its components belong to GenRad Inc, Concord MA 01742 */
/* They may be copied if this copyright notice is included */
/* te_srch.c routines associated with search operations 2/5/86 */
#include "te_defs.h"
/* routine to read in a string with string-build characters */
/* used for search, tag, file name operations */
/* returns 0 if empty string entered, nonzero otherwise */
int build_string(buff)
struct qh *buff; /* arg is addr of q-reg header */
{
int count; /* char count */
struct buffcell *tp; /* pointer to temporary string */
char c; /* temp character */
term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* read terminator */
count = atflag = 0; /* initialize char count */
if (!peekcmdc(term_char)) /* if string is not empty */
{
/* create a temporary string and read chars into it until the terminator */
for (tp = bb.p = get_bcell(), bb.c = 0; (c = getcmdc(trace_sw)) != term_char; )
{
if ((c == '^') && !(ed_val & ED_CARET)) /* read next char as CTL */
{
if ((c = getcmdc(trace_sw)) == term_char) ERROR(msp <= &mstack[0] ? E_UTC : E_UTM);
c &= 0x1f;
}
if ((c &= 0177) < ' ') /* if a control char */
{
switch (c)
{
case CTL (Q): /* take next char literally */
case CTL (R):
if ((c = getcmdc(trace_sw)) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
break; /* fetch character and go store */
case CTL (V): /* take next char as lower case */
if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
c = mapch_l[cmdc];
break;
case CTL (W): /* take next char as upper case */
if ((c = getcmdc(trace_sw)) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
if (islower(c)) c = toupper(c);
break;
case CTL (E): /* expanded constructs */
if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
switch (mapch_l[cmdc])
{
case 'u': /* use char in q-reg */
if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
c = qreg[getqspec(1, cmdc)].v & 0x7f;
break;
\f
case 'q': /* use string in q-reg */
if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
ll = getqspec(1, cmdc); /* read the reg spec */
aa.p = qreg[ll].f; /* set a pointer to it */
aa.c = 0;
for (mm = 0; mm < qreg[ll].z; mm++)
{
bb.p->ch[bb.c] = aa.p->ch[aa.c]; /* store char */
fwdcx(&bb); /* store next char */
fwdc(&aa);
++count;
}
continue; /* repeat loop without storing */
default:
bb.p->ch[bb.c] = CTL (E); /* not special: store the ^E */
fwdcx(&bb);
++count;
c = cmdc; /* and go store the following char */
break;
} /* end ^E switch */
} /* end outer switch */
} /* end "if a control char */
bb.p->ch[bb.c] = c; /* store character */
fwdcx(&bb); /* advance pointer */
++count; /* count characters */
} /* end "for" loop */
free_blist(buff->f); /* return old buffer */
buff->f = tp; /* put in new one */
buff->f->b = (struct buffcell *) buff;
buff->z = count; /* store count of chars in string */
} /* end non-null string */
else getcmdc(trace_sw); /* empty string: consume terminator */
return(count); /* return char count */
}
/* routine to handle end of a search operation */
/* called with pass/fail result from search */
/* returns same pass/fail result */
int end_search(result)
int result;
{
if (!result) /* if search failed */
{
if (!(esp->flag2 || (ed_val & ED_SFAIL))) dot = 0; /* if an unbounded search failed, clear ptr */
if (!colonflag && !peekcmdc(';')) ERROR(E_SRH); /* if no real or implied colon, error if failure */
}
esp->flag1 = colonflag; /* return a value if a :S command */
srch_result = esp->val1 = result; /* and leave it for next ";" */
esp->flag2 = colonflag = atflag = 0; /* consume arguments */
esp->op = OP_START;
return(result);
}
\f
/* routine to set up for search operation */
/* reads search arguments, returns search count */
static struct qp sm, sb; /* match-string and buffer pointers */
static char *pmap; /* pointer to character mapping table */
static int locb; /* reverse search limit */
static int last_z; /* end point for reverse search */
int setup_search()
{
int count; /* string occurrence counter */
set_pointer(dot, &aa); /* set a pointer to start of search */
if (colonflag >= 2) esp->flag2 = esp->flag1 = esp->val2 = esp->val1 = 1; /* ::S is 1,1S */
if ((count = get_value(1)) == 0) ERROR(E_ISA); /* read search count: default is 1 */
else if (count > 0) /* search forward */
{
if (esp->flag2) /* if bounded search */
{
if (esp->val2 < 0) esp->val2 = -(esp->val2); /* set limit */
if ((aa.z = dot + esp->val2) > z) aa.z = z; /* or z, whichever less */
}
else aa.z = z;
}
else
{
if (esp->flag2) /* if bounded search */
{
if (esp->val2 < 0) esp->val2 = -(esp->val2); /* set limit */
if ((locb = dot - esp->val2) < 0) locb = 0; /* or 0, whichever greater */
}
else locb = 0;
}
return(count);
}
\f
/* routine to do N, _, E_ searches: search, if search fails, then get */
/* next page and continue */
do_nsearch(arg)
char arg; /* arg is 'n', '_', or 'e' to define which search */
{
int scount; /* search count */
build_string(&sbuf); /* read the search string */
if ((scount = get_value(1)) <= 0) ERROR(E_ISA); /* count must be >0 */
set_pointer(dot, &aa); /* start search at dot */
esp->flag2 = locb = 0; /* make it unbounded */
while (scount > 0) /* search until found */
{
if (!do_search(1)) /* search forwards */
{ /* if search fails... */
if (infile->eofsw || !infile->fd) break; /* if no input, quit */
if (arg == 'n')
{
set_pointer(0, &aa); /* write file if 'n' */
write_file(&aa, z, ctrl_e);
}
/* not 'n': if _, and an output file, and data to lose, error */
else if ((arg == '_') && (outfile->fd) && (z) && (ed_val & ED_YPROT)) ERROR(E_YCA);
buff_mod = dot = z = 0; /* clear buffer */
set_pointer(0, &aa);
read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) ); /* read next page */
set_pointer(0, &aa); /* search next page from beginning */
}
else --scount; /* search successful: one fewer to look for */
}
return( end_search( (scount == 0) ? -1 : 0) ); /* use end_search to clean up */
}
/* routine to do "FB" search - m,nFB is search from m to n, */
/* nFB is search from . to nth line */
/* convert arguments to args of normal m,nS command */
int do_fb() /* returns search result */
{
if (esp->flag1 && esp->flag2) /* if two arguments */
{
dot = esp->val2; /* start from "m" arg */
esp->val2 = esp->val1 - esp->val2; /* get number of chars */
}
else /* if no or one args, treat as number of lines */
{
esp->val2 = lines(get_value(1)); /* number of chars */
esp->flag2 = esp->flag1 = 1; /* conjure up two args */
}
esp->val1 = (esp->val2 > 0) ? 1 : -1; /* set search direction */
build_string(&sbuf); /* read search string and terminator */
return(end_search( do_search( setup_search() ) )); /* do search and return result */
}
\f
/* routine to do search operation: called with search count as argument */
/* returns -1 (pass) or 0 (fail) */
int do_search(count)
int count;
{
pmap = (ctrl_x) ? &mapch[0] : &mapch_l[0]; /* set approp. mapping table */
sm.z = sbuf.z; /* copy # of chars in search buffer */
if (count > 0)
{
for (sm.dot = 0; count > 0; count--) /* loop to count occurrences */
{
for (; aa.dot < aa.z; aa.dot++) /* loop to advance search pointer */
{
for (sb.p = aa.p, sb.c = aa.c, sb.dot = aa.dot, sm.p = sbuf.f, sm.dot = sm.c = 0;
(sb.dot < z) && (sm.dot < sm.z); sm.dot++, sb.dot++)
{ /* for each char in search string */
if (spec_chars[ sm.p->ch[sm.c] ] & A_A) /* if search string char is "special" */
{
if (!srch_cmp()) break; /* then use expanded comparison routine */
}
else if (*(pmap + sb.p->ch[sb.c]) != *(pmap + sm.p->ch[sm.c])) break; /* else just compare */
if (++sm.c > CELLSIZE-1) /* advance search-string ptr */
{
sm.p = sm.p->f;
sm.c = 0;
}
if (++sb.c > CELLSIZE-1) /* advance buffer ptr */
{
sb.p = sb.p->f;
sb.c = 0;
}
} /* end comparison loop */
if (sm.dot >= sm.z) break; /* exit if found */
if (++aa.c > CELLSIZE-1) /* else not found: advance buffer pointer */
{
aa.p = aa.p->f;
aa.c = 0;
}
} /* end search loop */
if (sm.dot < sm.z) break; /* if one search failed, don't do more */
else
{
ctrl_s = aa.dot - sb.dot; /* otherwise save -length of string found */
if ((ed_val & ED_SMULT) && (count > 1)) /* if funny "advance by 1" mode */
{
++aa.dot; /* advance buffer pointer by one only */
if (++aa.c > CELLSIZE-1)
{
aa.p = aa.p->f;
aa.c = 0;
}
}
\f
else
{
aa.dot = sb.dot; /* advance search pointer past string */
aa.p = sb.p;
aa.c = sb.c;
}
}
} /* end "search n times" */
} /* end "search forwards" */
\f
else /* search backwards */
{
for (last_z = z, sm.dot = 0; count < 0; count++) /* loop to count occurrences */
{
for (; aa.dot >= locb; aa.dot--) /* loop to advance (backwards) search pointer */
{
for (sb.p = aa.p, sb.c = aa.c, sb.dot = aa.dot, sm.p = sbuf.f, sm.dot = sm.c = 0;
(sb.dot < last_z) && (sm.dot < sm.z); sm.dot++, sb.dot++)
{ /* loop to compare string */
if (spec_chars[ sm.p->ch[sm.c] ] & A_A) /* if search string char is "special" */
{
if (!srch_cmp()) break; /* then use expanded comparison routine */
}
else if (*(pmap + sb.p->ch[sb.c]) != *(pmap + sm.p->ch[sm.c])) break; /* else just compare */
if (++sm.c > CELLSIZE-1) /* advance search-string ptr */
{
sm.p = sm.p->f;
sm.c = 0;
}
if (++sb.c > CELLSIZE-1) /* advance buffer ptr */
{
sb.p = sb.p->f;
sb.c = 0;
}
} /* end comparison loop */
if (sm.dot >= sm.z) /* search matches: */
{
if (!(ed_val & ED_SMULT)) last_z = aa.dot; /* set last_z to point where this string was found */
break;
}
if (sb.dot >= last_z) /* or if string is beyond end of buffer */
{
sm.dot = sm.z; /* make search appear to have succeeded */
--count; /* so as to back up pointer, and force one more look */
break;
}
if (--aa.c < 0) /* else advance buffer pointer (backwards) */
{
aa.p = aa.p->b;
aa.c = CELLSIZE-1;
}
} /* end search loop */
if (sm.dot < sm.z) break; /* if one search failed, don't do more */
else
{
if (count < -1) backc(&aa); /* if this is not last search, back pointer up one */
else
{
ctrl_s = aa.dot - sb.dot; /* otherwise save -length of string found */
aa.dot = sb.dot; /* advance pointer past string */
aa.p = sb.p;
aa.c = sb.c;
}
}
} /* end "search n times" */
} /* end "search backwards" */
if (sm.dot >= sm.z) dot = aa.dot; /* if search succeeded, update pointer */
search_flag = 1; /* set "search occurred" (for ES) */
return((sm.dot >= sm.z) ? -1 : 0); /* and return -1 (pass) or 0 (fail) */
} /* end "do_search" */
\f
/* expanded search comparison */
/* returns 1 if match, 0 if not */
int srch_cmp()
{
int tq; /* q-reg name for ^EGq */
struct qp tqp; /* pointer to read q reg */
switch (mapch_l[sm.p->ch[sm.c]]) /* what is search character */
{
case CTL (N): /* match anything but following construct */
if (sm.dot >= sm.z) ERROR(E_ISS); /* don't read past end of string */
fwdc(&sm); /* skip the ^N */
return(!srch_cmp());
case CTL (X): /* match any character */
return(1);
case CTL (Q): /* take next char literally */
case CTL (R):
if (sm.dot >= sm.z) ERROR(E_ISS); /* don't read past end of string */
fwdc(&sm); /* skip the ^Q */
return(*(pmap + sb.p->ch[sb.c]) == *(pmap + sm.p->ch[sm.c]));
case CTL (S): /* match any nonalphanumeric */
return(!isalnum(sb.p->ch[sb.c]));
case CTL (E):
if (sm.dot >= sm.z) ERROR(E_ISS); /* don't read past end of string */
fwdc(&sm); /* skip the ^E */
switch (mapch_l[sm.p->ch[sm.c]])
{
case 'a': /* match any alpha */
return(isalpha(sb.p->ch[sb.c]));
case 'b': /* match any nonalpha */
return(!isalnum(sb.p->ch[sb.c]));
case 'c': /* rad50 symbol constituent */
return(!isalnum(sb.p->ch[sb.c]) || (sb.p->ch[sb.c] == '$') || (sb.p->ch[sb.c] == '.'));
case 'd': /* digit */
return(isdigit(sb.p->ch[sb.c]));
case 'l': /* line terminator LF, VT, FF */
return((sb.p->ch[sb.c] == LF) || (sb.p->ch[sb.c] == FF) || (sb.p->ch[sb.c] == VT));
case 'r': /* alphanumeric */
return(isalnum(sb.p->ch[sb.c]));
case 'v': /* lower case */
return(islower(sb.p->ch[sb.c]));
case 'w': /* upper case */
return(isupper(sb.p->ch[sb.c]));
case 's': /* any non-null string of spaces or tabs */
if (((sb.p->ch[sb.c]&0177) != ' ') && ((sb.p->ch[sb.c]&0177) != TAB)) return(0); /* failure */
/* skip remaining spaces or tabs */
for ( fwdc(&sb); ((sb.p->ch[sb.c]&0177) == ' ') || ((sb.p->ch[sb.c]&0177) == TAB); fwdc(&sb) );
backc(&sb); /* back up one char (calling routine will skip it) */
return(1); /* success */
\f
case 'g': /* any char in specified q register */
if (sm.dot >= sm.z) ERROR(E_ISS); /* don't read past end of string */
fwdc(&sm); /* get to the next char */
tq = getqspec(1, sm.p->ch[sm.c]); /* read q-reg spec */
for (tqp.dot = tqp.c = 0, tqp.p = qreg[tq].f; tqp.dot < qreg[tq].z; fwdc(&tqp))
if (*(pmap + tqp.p->ch[tqp.c]) == *(pmap + sb.p->ch[sb.c])) return(1); /* match */
return(0); /* fail */
default:
ERROR(E_ISS);
} /* end ^E constructions */
default:
return(*(pmap + sb.p->ch[sb.c]) == *(pmap + sm.p->ch[sm.c]));
} /* end other constructions */
}