/*	EDFIND.C						*/
/*								*/
/*	20-Nov-84 11:02:09 BDN  Modified for VMS, made 'INSTR'	*/
/*				STATIC so that INSTR calls get	*/
/*				Macro-32 version using MATCHC.	*/
/*								*/
/*	Notice:							*/
/*								*/
/*	 If the comments seem  obscure,  this code is being	*/
/*	written in C  by a comfirmed  Macro-11 and Macro-32	*/
/*	systems programmer who is used to doing the obscure	*/
/*	things assembly language  wizards do to their  code	*/
/*	to make each byte count, thus this code most likely 	*/
/*	looks like a Macro-11 version of C.  But this  same	*/
/*	Macro-??  expert is  now days interested in porting	*/
/*	applications to things like the RAINBOW, thus 'C'.	*/
/*								*/
/*								*/
/*	Copyright Notice					*/
/*								*/
/*	C version Copyright  (C) 1984 Change Software, Inc.	*/
/*	Copyright (C) 1978 1979 1980 1981 1982 1983 1984 by	*/
/*		      Change Software, Inc.			*/
/*								*/
/*								*/
/*	This software is furnished under a license and may	*/
/*	be  used  and  copied  only in accordance with the	*/
/*	terms of such license and with  the  inclusion  of	*/
/*	the  above copyright notice.  This software or any	*/
/*	other copies thereof may not be provided or other-	*/
/*	wise made available to any other person.  No title	*/
/*	to and ownership of the software is hereby  trans-	*/
/*	ferred.							*/
/*								*/
/*	The information in this  software  is  subject  to	*/
/*	change  without notice and should not be construed	*/
/*	as a commitment by the author.				*/
/*								*/
/*								*/
/*	05-Sep-84  18:38:09  Brian Nelson			*/




/*	instr (string1,length1,string2,length2)			*/
/*	finstr(string1,length1,string2,length2)			*/

/*	Avoid the VMS problem with 8bit characters		*/

#if	VAXVMS
typedef unsigned char pattern ;
#else
typedef char pattern ;
#endif

#define	CTRLA	1
#define	CTRLB	2
#define	CTRLC	3
#define	CTRLD	4
#define	CTRLE	5
#define	CTRLF	6
#define	CTRLG	7
#define	CTRLH	8
#define	CTRLI	9
#define	CTRLJ	10
#define	CTRLK	11
#define	CTRLL	12
#define	CTRLM	13
#define	CTRLN	14
#define	CTRLO	15
#define	CTRLP	16
#define	CTRLQ	17
#define	CTRLR	18
#define	CTRLS	19
#define	CTRLT	20
#define	CTRLU	21
#define	CTRLV	22
#define	CTRLW	23
#define	CTRLX	24
#define	CTRLY	25
#define	CTRLZ	26

#define	then
#define	true		1
#define	false		0
#define	metamin		192
#define	any		192
#define	notalfa		193
#define	let		195
#define	alfa		196
#define	digit		197
#define	letdig		200
#define	white		201
#define	smalllet	202
#define	biglet		203

#define	largea		0101
#define	largez		0132
#define	smalla		0141
#define	smallz		0172
#define	tab		'\011'
#define	TAB		'\011'




extern int matchflag ;


/*	FINSTR(sourcestring,sourcelength,patternstring,patternlength)	*/
/*									*/
/*	Look for the pattern, ignoring case.				*/
/*									*/
/*	 It would be nice  to have ENTRY or nested functions in C,	*/
/*	but since we don't... (the extra overhead).			*/
/*	If size proves not to be a problem, FINSTR should be coded	*/
/*	inline (actually, it should be Macro32 for speed, but that	*/
/*	can come later).						*/
/*	If this was only for VAX/VMS, size would not matter, but I	*/
/*	am doing this on a RSTS/E 11/70 for now (until the  11/785	*/
/*	gets here). Future plans are for the RAINBOW and MSDOS, as	*/
/*	the MSDOS editors available really ?%&#				*/
/*									*/
/*	We also have,  of course,  META characters for the pattern	*/
/*	matching, but to speed things up, we 'COMPILE' them first.	*/
/*	The meta constructs are the same as in TECO.  This is done	*/
/*	by calling SCOMPILE(pattern,pattern_size,compiled_pattern)	*/
/*	to generate the search pattern.					*/


finstr(s1,len1,s2,len2)
pattern *s1,*s2;
int  len1,len2 ;
{
	register int res,savematchflag ;

	savematchflag = matchflag ;
	matchflag = 1 ;
	res = instr(s1,len1,s2,len2) ;
	matchflag = savematchflag ;
	return(res) ;
}




/*	INSTR is the same as FINSTR, but case matters			*/



instr(src,len1,pat,len2)
pattern *src,*pat;
int  len1 ;
register int len2 ;

{
	register pattern *s1,*s2 ;
	pattern *s1save,*s2save ;
	int i,size,len2save ;

	s1 = src ;
	s2 = pat ;
	if ((len1==0) || (len2==0)) then return(0);
	size = len1 - len2 ;
	i = 0 ;
	while ( i <= size ) {
	  if ( ( *s1 == *s2 ) ? true : matchc(*s1,*s2) )
	   then {
		s1save = s1 ;
		s2save = s2 ;
		len2save = len2 ;
		if ( --len2 <= 0 ) then return( i+1 ) ;
		s1++ ; s2++ ;
		while ( len2 != 0 ) {
		  if (! matchc(*s1++,*s2++)) then break ;
		  len2-- ;
		  }
		if (len2 == 0) then return (i+1) ;
		len2 = len2save ;
		s2   = s2save ;
		s1   = s1save ;
		}
	  i++ ;
	  s1++ ;
	}
	return( 0 ) ;
}
		
		
		

/*	MATCH	return match status based on case setting and the	*/
/*	metacharacters.							*/
/*									*/
/*	Note: Should use a TOUPPER macro but the DECUS C compiler	*/
/*	does not seem to allow such things.  Of course, we can do	*/
/*	TOUPPER as a function,  which is more portable,  but much	*/
/*	more overhead  (re the VAX CALLS instruction, and so on).	*/
/*	So, for now, do it inline with BICB (C folks, CH & 0137).	*/
/*	Then again,  I could use the Whitesmiths compiler,  but I	*/
/*	like Bob's compiler						*/
/*									*/
/*	Some of the tests for matching in the case statement  are	*/
/*	expanded inline for execution speed,  while some are left	*/
/*	as function calls for consise reading, as well a avoiding	*/
/*	possible expression stack overflows in the compiler, as I	*/
/*	have had that happen with  the infamous NBS Pascal  which	*/
/*	I (regrettably) help foster upon many a naive user).		*/


matchc(c1,c2)
register int c1,c2;

{

	c1 &= 0377 ;
	c2 &= 0377 ;
	if ( c1==c2 ) then return (true) ;
	if ( c2 < metamin )
	  then	{
		if ( matchflag == 0 ) return (false) ;
		c2 &= 0137 ;
		if ( ( c2 < largea ) || ( c2 > largez ) ) then return(false);
		c1 &= 0137 ;
		if ( ( c1 < largea ) || ( c1 > largez ) ) then return(false);
		return( c1==c2 ) ;		
		}
	  else  {
	    switch( c2 ) {

		case any:
			return(true);
			break ;
		case notalfa:
			
			break ;
		case let:
			return(    (c1 >= smalla && c1 <= smallz)
				|| (c1 >= largea && c1 <= largez) ) ;
			break ;
		case alfa:
			return( isletter(c1)||isdigit(c1)||c1=='$'||c1=='.');
			break ;
		case digit:
			return( c1 >= '0' && c1 <= '9' ) ;
			break ;
		case letdig:
			return( isletter(c1) || isdigit(c1) ) ;
			break ;
		case white:
			return( c1 == ' ' || c1 == '\011' );
			break ;
		case smalllet:
			return( c1 >= smalla && c1 <= smallz ) ;
			break ;
		case biglet:
			return( c1 >= largea && c1 <= largez ) ;
			break ;
		default:
			return( false ) ;
			break ;
		}					/* end case	*/
	     }						/* end else	*/
}							/* end matchc()	*/


