DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T t

⟦f1dd2dd18⟧ TextFile

    Length: 14562 (0x38e2)
    Types: TextFile
    Names: »te_srch.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/teco/te_srch.c« 

TextFile

/* 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 */
	}