File:  [OS/2 SDKs] / os2sdk / demos / apps / cpgrep / cpgrep.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:26:03 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: os2sdk-1988, HEAD
Microsoft OS/2 SDK 03-01-1988

/* cpgrep - string searches
 *
 * Created by Microsoft Corp. 1986
 *
 *
 */

#include		<os2def.h>
#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#define INCL_DOSQUEUES
#define INCL_DOSMEMMGR
#define INCL_DOSMISC
#include		<bsedos.h>
#include		<stdio.h>
#include		<fcntl.h>
#include		<ctype.h>

#define	BEGLINE		0x40
#define	DEBUG		0x08
#define	ENDLINE		0x80
#define	FILBUFLEN	(SECTORLEN*30)
#define	FILNAMLEN	80
#define	INVERT		0x10
#define	ISCOT		0x0002
#define	LG2SECLEN	9
#define	LINELEN		128
#define	LINENOS		0x04
#define	LNOLEN		8
#define	MAXSTRLEN	128
#define	NAMEONLY	0x02
#define	OUTBUFLEN	(SECTORLEN*4)
#define	SECTORLEN	(1 << LG2SECLEN)
#define	SHOWNAME	0x01
#define	STKLEN		256
#define	TIMER		0x20
#define	TRTABLEN	256
#define	s_text(x)	(((char *)(x)) - ((x)->s_must))

typedef struct stringnode
  {
    struct stringnode	*s_alt;		/* List of alternates */
    struct stringnode	*s_suf;		/* List of suffixes */
    int			s_must;		/* Length of portion that must match */
  }
			STRINGNODE;

char			filbuf[(FILBUFLEN + 2)*2];
char			*bufptr[] = { filbuf, filbuf + FILBUFLEN + 2 };
char			outbuf[OUTBUFLEN*2];
char			*obuf[] = { outbuf, outbuf + OUTBUFLEN };
char			*optr[] = { outbuf, outbuf + OUTBUFLEN };
USHORT			ocnt[] = { OUTBUFLEN, OUTBUFLEN };
int			oi = 0;
char			transtab[TRTABLEN] = { 0 };
STRINGNODE		*stringlist[TRTABLEN/2];
USHORT			arrc;		/* I/O return code for DosRead */
USHORT			awrc;		/* I/O return code for DosWrite */
int			casesen = 1;	/* Assume case-sensitivity */
USHORT			cbread; 	/* Bytes read by DosRead */
USHORT			cbwrite;	/* Bytes written by DosWrite */
int			clists = 1;	/* One is first available index */
int			flags;		/* Flags */
int			lineno;		/* Current line number */
char			pmode;		/* Protected mode flag */
LONG			readdone;	/* Async read done semaphore */
LONG			readpending;	/* Async read pending semaphore */
int			status = 1;	/* Assume failure */
char			*t2buf;		/* Async read buffer */
USHORT			t2buflen;	/* Async read buffer length */
HFILE			t2fd;		/* Async read file */
char			*t3buf;		/* Async write buffer */
USHORT			t3buflen;	/* Async write buffer length */
HFILE			t3fd;		/* Async write file */
LONG			writedone;	/* Async write done semaphore */
LONG			writepending;	/* Async write pending semaphore */
char			target[MAXSTRLEN];
					/* Last string added */
int			targetlen;	/* Length of last string added */

int			countlines();	/* See CPGREPSB.ASM */
int			countmatched();	/* See CPGREPSB.ASM */
char			*findlist();	/* See CPGREPSB.ASM */
char			*findone();	/* See CPGREPSB.ASM */
void			flush1buf();	/* See below */
int			grepbuffer();	/* See below */
int			revfind();	/* See CPGREPSB.ASM */
void			write1buf();	/* See below */
char			*(*find)() = findlist;
void			(*flush1)() = flush1buf;
int			(*grep)() = grepbuffer;
void			(*write1)() = write1buf;

void			freenode(x)
register STRINGNODE	*x;		/* Pointer to node to free */
  {
    register STRINGNODE	*y;		/* Pointer to next node in list */

    while(x != NULL)			/* While not at end of list */
      {
	if(x->s_suf != NULL) freenode(x->s_suf);
					/* Free suffix list */
	y = x;				/* Save pointer */
	x = x->s_alt;			/* Move down the list */
	free(y);			/* Free the node */
      }
  }


STRINGNODE		*newnode(s,n)
char			*s;		/* String */
int			n;		/* Length of string */
  {
    register STRINGNODE	*new;		/* Pointer to new node */
    char		*t;		/* String pointer */
    char		*malloc();	/* Storage allocator */

    if((t = malloc(sizeof(STRINGNODE) + n + (n & 1))) == NULL)
      {					/* If allocation fails */
	fprintf(stderr,"Out of memory\n");
	DosExit( EXIT_PROCESS, 2);	/* Print error message and die */
      }
    if(n & 1) ++t;			/* END of string word-aligned */
    strncpy(t,s,n);			/* Copy string text */
    new = (STRINGNODE *)(t + n);	/* Set pointer to node */
    new->s_alt = NULL;			/* No alternates yet */
    new->s_suf = NULL;			/* No suffixes yet */
    new->s_must = n;			/* Set string length */
    return(new);			/* Return pointer to new node */
  }


void			reallocnode(node,s,n)
register STRINGNODE	*node;		/* Pointer to node */
char			*s;		/* String */
register int		n;		/* Length of string */
  {
    if(n > node->s_must)		/* If node must grow */
      {
	fprintf(stderr,"Internal error\n");
					/* Error message */
	DosExit( EXIT_PROCESS, 2);			  /* Error exit */
      }
    node->s_must = n;			/* Set new length */
    memcpy(s_text(node),s,n);		/* Copy new text */
  }


void			addstring(s,n)
char			*s;		/* String to add */
int			n;		/* Length of string */
  {
    register STRINGNODE	*cur;		/* Current string */
    register STRINGNODE	**pprev;	/* Pointer to previous link */
    STRINGNODE		*new;		/* New string */
    int			i;		/* Index */
    int			j;		/* Count */
    int			k;		/* Count */

    if(n <= 0 || n > 127) return;	/* Should never happen */
    i = transtab[*s];			/* Get current index */
    if(i == 0)				/* If no existing list */
      {
	/*
	 *  We have to start a new list
	 */
	if((i = clists++) >= TRTABLEN/2)
	  {				/* If too many string lists */
	    fprintf(stderr,"Too many string lists\n");
					/* Error message */
	    DosExit( EXIT_PROCESS, 2);	/* Die */
	  }
	stringlist[i] = NULL;		/* Initialize */
	transtab[*s] = i;		/* Set pointer to new list */
	if(!casesen && isalpha(*s)) transtab[*s ^ '\x20'] = i;
					/* Set pointer for other case */
      }
    else if(stringlist[i] == NULL) return;
					/* Check for existing 1-byte string */
    if(--n == 0)			/* If 1-byte string */
      {
	freenode(stringlist[i]);	/* Free any existing stuff */
	stringlist[i] = NULL;		/* No record here */
	return;				/* Done */
      }
    ++s;				/* Skip first char */
    pprev = stringlist + i;		/* Get pointer to link */
    cur = *pprev;			/* Get pointer to node */
    while(cur != NULL)			/* Loop to traverse match tree */
      {
	i = (n > cur->s_must)? cur->s_must: n;
					/* Find minimum of string lengths */
	matchstrings(s,s_text(cur),i,&j,&k);
					/* Compare the strings */
	if(j == 0)			/* If complete mismatch */
	  {
	    if(k < 0) break;		/* Break if insertion point found */
	    pprev = &(cur->s_alt);	/* Get pointer to alternate link */
	    cur = *pprev;		/* Follow the link */
	  }
	else if(i == j)			/* Else if strings matched */
	  {
	    if(i == n)			/* If new is prefix of current */
	      {
		reallocnode(cur,s_text(cur),n);
					/* Shorten text of node */
		if(cur->s_suf != NULL)	/* If there are suffixes */
		  {
		    freenode(cur->s_suf);
					/* Suffixes no longer needed */
		    cur->s_suf = NULL;
		  }
		return;			/* All done */
	      }
	    pprev = &(cur->s_suf);	/* Get pointer to suffix link */
	    if((cur = *pprev) == NULL) return;
					/* Done if current is prefix of new */
	    s += i;			/* Skip matched portion */
	    n -= i;
	  }
	else				/* Else partial match */
	  {
	    /*
	     *	We must split an existing node.
	     *	This is the trickiest case.
	     */
	    new = newnode(s_text(cur) + j,cur->s_must - j);
					/* Unmatched part of current string */
	    reallocnode(cur,s_text(cur),j);
					/* Set length to matched portion */
	    new->s_suf = cur->s_suf;	/* Current string's suffixes */
	    if(k < 0)			/* If new preceded current */
	      {
		cur->s_suf = newnode(s + j,n - j);
					/* FIrst suffix is new string */
		cur->s_suf->s_alt = new;/* Alternate is part of current */
	      }
	    else			/* Else new followed current */
	      {
		new->s_alt = newnode(s + j,n - j);
					/* Unmatched new string is alternate */
	        cur->s_suf = new;	/* New suffix list */
	      }
	    return;
	  }
      }
    *pprev = newnode(s,n);		/* Set pointer to new node */
    (*pprev)->s_alt = cur;		/* Attach alternates */
  }


int			addfancy(buffer,buflen,seplist)
register char		*buffer;	/* Buffer */
int			buflen;		/* Length of buffer */
char			*seplist;	/* List of separators */
  {
    register char	*bufend;	/* Pointer to end of buffer */
    int			strcnt = 0;	/* String count */
    int			len;		/* String length */
    char		c;		/* One char buffer */

    bufend = buffer + buflen;		/* Set end pointer */
    while(buffer < bufend)		/* Loop through all strings */
      {
	len = strncspn(buffer,seplist,bufend - buffer);
					/* Length of string */
	if(flags & ENDLINE)		/* If match must be at end of line */
	  {
	    c = buffer[len];		/* Save 1st character past string */
	    buffer[len++] = '\r';	/* Carriage return marks end of line */
	  }
	if(findlist(buffer,buffer + len) == NULL)
	  {				/* If no match within string */
	    addstring(buffer,len);	/* Add string to list */
	    if(strcnt++ == 0)		/* If first string */
	      {
		memcpy(target,buffer,len);
					/* Save first string in buffer */
		targetlen = len;	/* Remember length */
	      }
	  }
	buffer += len;			/* Skip over string */
	if(flags & ENDLINE) (--buffer)[0] = c;
					/* Restore saved character */
	buffer += strnspn(buffer,seplist,bufend - buffer);
					/* Skip over trailing separators */
      }
    return(strcnt);			/* Return string count */
  }


int			addplain(buffer,buflen,seplist)
register char		*buffer;	/* String list buffer */
int			buflen;		/* Buffer length */
char			*seplist;	/* List of separators */
  {
    int			strcnt;		/* String count */
    register int	len;		/* String length */
    char		c;		/* One char buffer */

    strcnt = 0;
    while((len = strncspn(buffer,seplist,buflen)) > 0)
      {					/* While not at end of input list */
	if(flags & ENDLINE)		/* If match must be at end of line */
	  {
	    c = buffer[len];		/* Save 1st character past string */
	    buffer[len++] = '\r';	/* Carriage return marks end of line */
	  }
	if(strcnt == 0)			/* Save first string */
	  {
	    strncpy(target,buffer,len);	/* Save string in buffer */
	    targetlen = len;		/* Save string length */
	  }
	addstring(buffer,len);		/* Add the string to the table */
	if(flags & ENDLINE) buffer[--len] = c;
					/* Restore saved character */
	buffer += len;			/* Skip the string */
	buflen -= len;
	len = strnspn(buffer,seplist,buflen);
					/* Skip separators */
	buffer += len;
	buflen -= len;
	++strcnt;			/* Increment string count */
      }
    return(strcnt);			/* Return string count */
  }


void			dumplist(node,indent)
register STRINGNODE	*node;		/* Pointer to list to dump */
int			indent;		/* Current length of buffer */
  {
    int			i;		/* Counter */

    while(node != NULL)			/* While not at end of list */
      {
	for(i = 0; i < indent; ++i) fputc(' ',stderr);
	fwrite(s_text(node),sizeof(char),node->s_must,stderr);
	fprintf(stderr,"\n");
	if(node->s_suf != NULL)
	  dumplist(node->s_suf,indent + node->s_must);
					/* Recurse to do suffixes */
	node = node->s_alt;		/* Do next alternate in list */
      }
  }


void			dumpstrings()
  {
    int			i;		/* Index */

    for(i = 0; i < TRTABLEN; ++i)	/* Loop through translation table */
      {
	if(transtab[i] == 0) continue;	/* Skip null entries */
	fprintf(stderr,"%c\n",i);	/* Print the first byte */
	dumplist(stringlist[transtab[i]],1);
					/* Dump the list */
      }
  }


HFILE			openfile(name)
char			*name;		/* File name */
  {
    HFILE		fd;		/* File descriptor */

    if((fd = open(name,0)) == -1)	/* If error opening file */
      {
	fprintf(stderr,"Cannot open %s\r\n",name);
					/* Print error message */
      }
    return(fd);				/* Return file descriptor */
  }


void far		thread2()	/* Read thread */
  {
    while(DosSemRequest( &readpending, -1L) == 0)
      {					/* While there is work to do */
	arrc = DosRead( t2fd, t2buf, t2buflen, &cbread);
					/* Do the read */
	DosSemClear( &readdone);	/* Signal read completed */
      }
    fprintf(stderr,"Thread 2: DosSemRequest failed\n");
					/* Print error message */
    DosExit( EXIT_PROCESS, 2);		/* Die */
  }


void far		thread3()	/* Write thread */
  {
    while(DosSemRequest((long far *) &writepending,-1L) == 0)
      {					/* While there is work to do */
	awrc = DosWrite(t3fd, t3buf, t3buflen, &cbwrite);
					/* Do the write */
	DosSemClear( &writedone);	/* Signal write completed */
      }
    fprintf(stderr,"Thread 3: DosSemRequest failed\n");
					/* Print error message */
    DosExit( EXIT_PROCESS, 2);		/* Die */
  }


void			startread(fd,buffer,buflen)
HFILE			fd;		/* File handle */
char			*buffer;	/* Buffer */
USHORT			buflen; 	/* Buffer length */
  {
    if(pmode)				/* If protected mode */
      {
	if(DosSemRequest( &readdone, -1L) != 0)
	  {				/* If we fail to get the semaphore */
	    fprintf(stderr,"DosSemRequest failed\n");
					/* Error message */
	    DosExit( EXIT_PROCESS, 2);	/* Die */
	  }
	t2fd = fd;			/* Set parameters for read */
	t2buf = buffer;
	t2buflen = buflen;
	DosSemClear( &readpending);	/* Wake thread 2 for read */
	DosSleep(0L);			/* Yield the CPU */
      }
    else arrc = DosRead( fd, buffer, buflen, &cbread);
  }


int			finishread()
  {
    if(pmode && DosSemWait( &readdone, -1L) != 0)
      {					/* If protected mode and wait fails */
	fprintf(stderr,"DosSemWait failed\n");
					/* Print error message */
	DosExit( EXIT_PROCESS, 2);			  /* Die */
      }
    return((arrc == 0)? cbread: -1);	/* Return number of bytes read */
  }


void			startwrite(fd,buffer,buflen)
HFILE			fd;		/* File handle */
char			*buffer;	/* Buffer */
USHORT			buflen; 	/* Buffer length */
  {
    if(pmode)				/* If protected mode */
      {
	if(DosSemRequest( &writedone, -1L) != 0)
	  {				/* If we fail to get the semaphore */
	    fprintf(stderr,"DosSemRequest failed\n");
					/* Error message */
	    DosExit( EXIT_PROCESS, 2);	/* Die */
	  }
	t3fd = fd;			/* Set parameters for write */
	t3buf = buffer;
	t3buflen = buflen;
	DosSemClear( &writepending);	/* Wake thread 3 for read */
	DosSleep(0L);			/* Yield the CPU */
      }
    else awrc = DosWrite(fd, buffer, buflen, &cbwrite);
  }


int			finishwrite()
  {
    if(pmode && DosSemWait( &writedone, -1L) != 0)
      {					/* If protected mode and wait fails */
	fprintf(stderr,"DosSemWait failed\n");
					/* Print error message */
	DosExit( EXIT_PROCESS, 2);	/* Die */
      }
    return((awrc == 0)? cbwrite: -1);	/* Return number of bytes written */
  }


void			write1nobuf(buffer,buflen)
char			*buffer;	/* Buffer */
USHORT			buflen; 	/* Buffer length */
  {
    int			cb;		/* Count of bytes written */

    if( DosWrite(1, buffer, buflen, &cb) != 0 || cb != buflen)
					/* If write fails */
      {
	fprintf(stderr,"write error %d\n",awrc);
					/* Print error message */
	DosExit( EXIT_PROCESS, 2);	/* Die */
      }
  }


void			write1buf(buffer,buflen)
char			*buffer;	/* Buffer */
USHORT			buflen; 	/* Buffer length */
  {
    USHORT		cb;		/* Byte count */

    while(buflen > 0)			/* While bytes remain */
      {
	if(awrc != 0)			/* If previous write failed */
	  {
	    fprintf(stderr,"write error %d\n",awrc);
					/* Print error message */
	    DosExit( EXIT_PROCESS, 2);			  /* Die */
	  }
	if((cb = ocnt[oi]) == 0)	/* If buffer full */
	  {
	    startwrite(1,obuf[oi],OUTBUFLEN);
					/* Write the buffer */
	    ocnt[oi] = OUTBUFLEN;	/* Reset count and pointer */
	    optr[oi] = obuf[oi];
	    oi ^= 1;			/* Switch buffers */
	    cb = ocnt[oi];		/* Get space remaining */
	  }
	if(cb > buflen) cb = buflen;	/* Get minimum */
	memcpy(optr[oi],buffer,cb);	/* Copy bytes to buffer */
	ocnt[oi] -= cb;			/* Update buffer length and pointers */
	optr[oi] += cb;
	buflen -= cb;
	buffer += cb;
      }
  }


void			flush1nobuf()
  {
  }


void			flush1buf()
  {
    int			cb;		/* Byte count */

    if((cb = OUTBUFLEN - ocnt[oi]) > 0)	/* If buffer not empty */
      {
	startwrite(1,obuf[oi],cb);	/* Start write */
	if(finishwrite() != cb)		/* If write failed */
	  {
	    fprintf(stderr,"write error %d\n",awrc);
					/* Print error message */
	    DosExit( EXIT_PROCESS, 2);	/* Die */
	  }
      }
  }


int			grepnull(cp,endbuf,name)
register char		*cp;		/* Buffer pointer */
char			*endbuf;	/* End of buffer */
char			*name;		/* File name */
  {
    return(0);				/* Do nothing */
  }


int			grepbuffer(startbuf,endbuf,name)
char			*startbuf;	/* Start of buffer */
char			*endbuf;	/* End of buffer */
char			*name;		/* File name */
  {
    register char	*cp;		/* Buffer pointer */
    char		*lastmatch;	/* Last matching line */
    int			linelen;	/* Line length */
    int			namlen = 0;	/* Length of name */
    char		lnobuf[LNOLEN];	/* Line number buffer */
    char		nambuf[LINELEN];/* Name buffer */

    cp = startbuf;			/* Initialize to start of buffer */
    lastmatch = cp;			/* No previous match yet */
    while((cp = (*find)(cp,endbuf)) != NULL)
      {					/* While matches are found */
	if((flags & BEGLINE) && cp[-1] != '\n' && cp > startbuf)
	  {				/* If begin line conditions not met */
	    ++cp;			/* Skip first char of match */
	    continue;			/* Keep looking */
	  }
	status = 0;			/* Match found */
	if(flags & NAMEONLY)		/* If filename only wanted */
	  {
	    (*write1)(nambuf,sprintf(nambuf,"%s\r\n",name));
					/* Print the name */
	    return(1);			/* Punt remainder of buffer */
	  }
	cp -= revfind(cp,'\n',cp - startbuf);
					/* Point at last linefeed */
	if(*cp == '\n') ++cp;		/* Point at start of line */
	if(flags & SHOWNAME)		/* If name wanted */
	  {
	    if(namlen == 0) namlen = sprintf(nambuf,"%s:",name);
					/* Format name if not done already */
	    (*write1)(nambuf,namlen);	/* Show name */
	  }
	if(flags & LINENOS)		/* If line number wanted */
	  {
	    lineno += countlines(lastmatch,cp);
					/* Count lines since last match */
	    (*write1)(lnobuf,sprintf(lnobuf,"%d:",lineno));
					/* Print line number */
	    lastmatch = cp;		/* New last match */
	  }
	linelen = strncspn(cp,"\n",endbuf - cp) + 1;
					/* Calculate line length */
	(*write1)(cp,linelen);		/* Print the line */
	cp += linelen;			/* Skip the line */
      }
    if(flags & LINENOS) lineno += countlines(lastmatch,endbuf);
					/* Count remaining lines in buffer */
    return(0);				/* Keep searching */
  }


void			showv(name,lastmatch,thismatch)
char			*name;
register char		*lastmatch;
char			*thismatch;
  {
    register int	linelen;
    int			namlen = 0;	/* Length of name */
    char		lnobuf[LNOLEN];	/* Line number buffer */
    char		nambuf[LINELEN];/* Name buffer */

    if(flags & (SHOWNAME | LINENOS))
      {
	while(lastmatch < thismatch)
	  {
	    if(flags & SHOWNAME)	/* If name wanted */
	      {
		if(namlen == 0) namlen = sprintf(nambuf,"%s:",name);
					/* Format name if not done already */
		(*write1)(nambuf,namlen);
					/* Write the name */
	      }
	    if(flags & LINENOS)
	      {
		(*write1)(lnobuf,sprintf(lnobuf,"%d:",lineno++));
	      }
	    linelen = strncspn(lastmatch,"\n",thismatch - lastmatch) + 1;
	    (*write1)(lastmatch,linelen);
	    lastmatch += linelen;
	  }
      }
    else (*write1)(lastmatch,thismatch - lastmatch);
  }


int			grepvbuffer(startbuf,endbuf,name)
char			*startbuf;	/* Start of buffer */
char			*endbuf;	/* End of buffer */
char			*name;		/* File name */
  {
    register char	*cp;		/* Buffer pointer */
    register char	*lastmatch;	/* Pointer to line after last match */

    cp = startbuf;			/* Initialize to start of buffer */
    lastmatch = cp;
    while((cp = (*find)(cp,endbuf)) != NULL)
      {
	if((flags & BEGLINE) && cp[-1] != '\n' && cp > startbuf)
	  {				/* If begin line conditions not met */
	    ++cp;			/* Skip first char of match */
	    continue;			/* Keep looking */
	  }
	status = 1;			/* Match found */
	if(flags & NAMEONLY) return(1);	/* Skip rest of file if NAMEONLY */
	cp -= revfind(cp,'\n',cp - startbuf);
					/* Point at last linefeed */
	if(*cp == '\n') ++cp;		/* Point at start of line */
	showv(name,lastmatch,cp);	/* Show from last match to this */
	cp += strncspn(cp,"\n",endbuf - cp) + 1;
					/* Skip over line with match */
	lastmatch = cp;			/* New "last" match */
	++lineno;			/* Increment line count */
      }
    if(!(flags & NAMEONLY)) showv(name,lastmatch,endbuf);
					/* Show buffer tail if not NAMEONLY */
    return(0);				/* Keep searching file */
  }


void			qgrep(name,fd)
char			*name;		/* File name */
HFILE			fd;		/* File descriptor */
  {
    register int	cb;		/* Byte count */
    register char	*cp;		/* Buffer pointer */
    char		*endbuf;	/* End of buffer */
    int			taillen;	/* Length of buffer tail */
    int			bufi;		/* Buffer index */
    char		line[LINELEN];	/* Line buffer */

    lineno = 1;				/* File starts on line 1 */
    taillen = 0;			/* No buffer tail yet */
    bufi = 0;				/* Initialize buffer index */
    cp = bufptr[0];			/* Initialize to start of buffer */
    finishread();			/* Make sure no I/O activity */
    arrc = DosRead( fd, cp, FILBUFLEN, &cbread);
					/* Do first read synchronously */
    while((cb = finishread()) + taillen > 0)
      {					/* While search incomplete */
	if(cb == 0)			/* If buffer tail is all that's left */
	  {
	    taillen = 0;		/* Set tail length to zero */
	    *cp++ = '\r';		/* Add end of line sequence */
	    *cp++ = '\n';
	    endbuf = cp;		/* Note end of buffer */
	  }
	else				/* Else start next read */
	  {
	    taillen = revfind(cp + cb - 1,'\n',cb);
					/* Find length of partial line */
	    endbuf = cp + cb - taillen;	/* Get pointer to end of buffer */
	    cp = bufptr[bufi ^ 1];	/* Pointer to other buffer */
	    memcpy(cp,endbuf,taillen);	/* Copy tail to head of other buffer */
	    cp += taillen;		/* Skip over tail */
	    startread(fd,cp,(FILBUFLEN - taillen) & (~0 << LG2SECLEN));
					/* Start next read */
	  }
	if((*grep)(bufptr[bufi],endbuf,name)) return;
					/* Done if NAMEONLY and match found */
	bufi ^= 1;			/* Switch buffers */
      }
    if((flags & (NAMEONLY | INVERT)) == (NAMEONLY | INVERT))
      (*write1)(line,sprintf(line,"%s\r\n",name));
					/* Write name if -lv */
  }


void			usage(verbose)
int			verbose;	/* Verbose message flag */
  {
    static char		*opts[] =
      {
	"-? - print this message",
	"-B - match pattern if at beginning of line",
	"-E - match pattern if at end of line",
	"-l - print only file name if file contains match",
	"-n - print line number before each matching line",
	"-v - print only lines not containing a match",
	"-x - print lines that match exactly (-BE)",
	"-y - treat upper and lower case as equivalent",
	"-e - treat next argument as the search string",
	"-f - read search strings from file named by next argument",
	"-i - read file list from file named by next argument",
	0
      };
    register char	**opt = opts;	/* Option list */

    fprintf(stderr,"usage: CPGREP [-?BElnvxy][-e][-f <file>][-i <file>][<strings>][<files>]\n");
    if(verbose)				/* If verbose message wanted */
      {
	while(*opt != 0) fprintf(stderr,"%s\n",*opt++);
					/* Print option list */
      }
    DosExit( EXIT_PROCESS, 2);		/* Error exit */
  }


void			main(argc,argv)
int			argc;
char			**argv;
  {
    register char	*cp;
    HFILE		fd;
    FILE		*fi;
    char		filnam[FILNAMLEN];
    USHORT		handType;
    USHORT		handAttrib;
    int			i;
    char		*inpfile = NULL;
    int 		j;
    char		*seplist = " \t";
    int			strcnt;
    char		*strfile = NULL;
    long		start;		/* Start time */
    int			(*add)();
    BYTE		t2stk[2*STKLEN];  /* Read thread stack */
    BYTE		t3stk[2*STKLEN];  /* Write thread stack */
    long		time();		/* Time and date in seconds */

    DosGetMachineMode((char far *) &pmode);
    flags = 0;
    for(i = 1; i < argc && argv[i][0] == '-'; ++i)
      {
	switch(argv[i][1])
	  {
	    case 'f':
	    case 'i':
	      if(i == argc - 1)
		{
		  fprintf(stderr,"File name missing after -%c\n",argv[i][1]);
		  DosExit( EXIT_PROCESS, 2);
		}
	      if(argv[i++][1] == 'i') inpfile = argv[i];
	      else strfile = argv[i];
	      break;

	    case '?':
	    case 'B':
	    case 'E':
	    case 'N':
	    case 'S':
	    case 'd':
	    case 'l':
	    case 'n':
	    case 't':
	    case 'v':
	    case 'x':
	    case 'y':
	      for(cp = &argv[i][1]; *cp != '\0'; ++cp)
		{
		  switch(*cp)
		    {
		      case '?':
			usage(1);	/* Verbose usage message */

		      case 'B':
			flags |= BEGLINE;
			break;

		      case 'E':
			flags |= ENDLINE;
			break;

		      case 'N':
			grep = grepnull;
			break;

		      case 'S':
			pmode = 0;	/* Force synchronous I/O */
			break;

		      case 'd':
			flags |= DEBUG;
			break;

		      case 'l':
			flags |= NAMEONLY;
			break;

		      case 'n':
			flags |= LINENOS;
			break;

		      case 't':
			flags |= TIMER;
			break;

		      case 'v':
			status = 0;	/* Assume success */
			flags |= INVERT;
			grep = grepvbuffer;
			break;

		      case 'x':
			flags |= BEGLINE | ENDLINE;
			break;

		      case 'y':
			casesen = 0;
			break;

		      default:
			fprintf(stderr,"-%c ignored\n",*cp);
			break;
		    }
	        }
	      break;

	    case 'e':
	      if(strfile == NULL)
		{
		  ++i;
		  seplist = "";		/* Allow anything in string */
		  goto endfor0;
		}
	      /* Drop through to "default" */

	    default:
	      fprintf(stderr,"%s ignored\n",argv[i]);
	      break;
	  }
      }
    endfor0:

    if(i == argc && strfile == NULL) usage(0);
					/* Simple usage message if arg error */
    if(flags & TIMER) start = time(NULL);
					/* Get start time if timer on */
    if(pmode)				/* Initialize semaphores and threads */
      {
	TID threadId;

	DosSemClear( &readdone);
	DosSemClear( &writedone);
	DosSemSet( &readpending);
	DosSemSet( &writepending);
	if(DosCreateThread(thread2, &threadId, t2stk + 2*STKLEN) != 0 ||
	   DosCreateThread(thread3, &threadId, t3stk + 2*STKLEN) != 0)
	  {				/* If thread creation fails */
	    fprintf(stderr,"Failed to create child threads\n");
					/* Print error message */
	    DosExit( EXIT_PROCESS, 2);	/* Die */
	  }
      }
    setmode(fileno(stdout),O_BINARY);
    add = addplain;			/* Assume plain string adds */
    if(strfile != NULL)			/* If strings from file */
      {
	if(!(flags & BEGLINE)) add = addfancy;
					/* Try to add intelligently */
	if((fd = open(strfile,0)) == -1)
	  {				/* If open fails */
	    fprintf(stderr,"Cannot read strings from %s\n",strfile);
	    DosExit( EXIT_PROCESS, 2);			  /* Print message and die */
	  }
	for(cp = filbuf, j = 0; (j = read(fd,cp,FILBUFLEN*2 - j)) > 0; cp += j);
					/* Read strings file into buffer */
	j = cp - filbuf;		/* Get total length of buffer */
	close(fd);			/* Close strings file */
	filbuf[j] = '\0';		/* Null-terminate the buffer */
	cp = filbuf;			/* Set pointer to string list */
	seplist = "\r\n";		/* Only '\r' and '\n' are separators */
      }
    else				/* Else strings on command line */
      {
	cp = argv[i++];			/* Set pointer to strings */
	j = strlen(cp);			/* Get length of strings */
      }
    if((strcnt = (*add)(cp,j,seplist)) == 0)
      {					/* If no strings */
	fprintf(stderr,"No search strings\n");
	DosExit( EXIT_PROCESS, 2);	/* Print error message and die */
      }

    /*
     *  Check type of handle for std. out.
     */
    if(DosQHandType(fileno(stdout), &handType, &handAttrib) != 0)
      {					/* If error */
	fprintf(stderr,"Standard output bad handle\n");
					/* Print error message */
	DosExit( EXIT_PROCESS, 2);	/* Die */
      }
    if(handType != 0 && (handAttrib & ISCOT))
      { 				/* If handle is console output */
	write1 = write1nobuf;		/* Use unbuffered output */
	flush1 = flush1nobuf;
      }

    if(strcnt > 1)			/* If more than one string */
      {
	if(flags & DEBUG)		/* Print debug info maybe */
	  {
	    fprintf(stderr,"Here are the strings:\n");
	    dumpstrings();
	  }
      }
    else if(casesen) find = findone;	/* Else use findone() */
    if(inpfile != NULL)			/* If file list from file */
      {
	flags |= SHOWNAME;		/* Always show name of file */
	if((fi = fopen(inpfile,"r")) == NULL)
	  {				/* If open fails */
	    fprintf(stderr,"Cannot read file list from %s\r\n",inpfile);
					/* Error message */
	    DosExit( EXIT_PROCESS, 2);	/* Error exit */
	  }
	while(fgets(filnam,FILNAMLEN,fi) != NULL)
	  {				/* While there are names */
	    filnam[strcspn(filnam,"\r\n")] = '\0';
					/* Null-terminate the name */
	    if((fd = openfile(filnam)) == -1) continue;
					/* Skip file if it cannot be opened */
	    qgrep(filnam,fd);		/* Do the work */
	    close(fd);			/* Close the file */
	  }
	fclose(fi);			/* Close the list file */
      }
    else if(i == argc)
      {
	flags &= ~(NAMEONLY | SHOWNAME);
	setmode(fileno(stdin),O_BINARY);
	qgrep(NULL,fileno(stdin));
      }
    if(argc > i + 1) flags |= SHOWNAME;
    for(; i < argc; ++i)
      {
	if((fd = openfile(argv[i])) == -1) continue;
	qgrep(argv[i],fd);
	close(fd);
      }
    (*flush1)();
    if(flags & TIMER) fprintf(stderr,"%ld seconds\n",time(NULL) - start);
					/* Print elapsed time if timer on */
    DosExit( EXIT_PROCESS, status);
  }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.