home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume15
/
window-srch
< prev
next >
Wrap
Text File
|
1988-07-06
|
15KB
|
615 lines
Subject: v15i082: Windowing search (not unlike context grep)
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: "Mark E. Mallett" <mem@zinn.mv.com>
Posting-number: Volume 15, Issue 82
Archive-name: window-srch
I got a few requests for this, and I figured I'd mail it to you for your
consideration for posting in comp.sources.unix (or wherever it is appropriate).
It is a short little program that allows one to find an occurance of a pattern
in a text file, and print a window of lines around the match point(s).
-mm-
--
Mark E. Mallett PO Box 4188/ Manchester NH/ 03103
Bus. Phone: 603 645 5069 Home: 603 424 8129
uucp: mem@zinn.MV.COM (...decvax!elrond!zinn!mem or ...sii!zinn!mem)
BIX: mmallett
#------ cut here -------
#! /bin/sh
#
# This is a shell archive; feed it to /bin/sh (not csh) to create:
# Makefile
# README
# wns.1
# wns.c
if test -f 'Makefile'; then
echo shar: will not over-write existing file 'Makefile'
else
sed -e 's/^@//g' << 'SHAR_EOF' > Makefile
@# Makefile for wns
@#
@# Define in CFLAGS:
@# SYSINC if include file hierarchy includes the sys/ directory
@# REGEX if using berkeley-style re_exec() and re_comp()
@# REGCMP if using regcmp() and regex()
@# OS_UNIX if running under unix
@# OS_CPM if running under CP/M80
@#
@#
@CFLAGS=-DOS_UNIX -DREGCMP -DSYSINC
@#
@# Define LIBS to reflect the librar[y][ies] needed to fetch the r/e routines.
@#
@LIBS=-lPW
@
@#
@WNSOBJS=wns.o
@
@wns: $(WNSOBJS)
@ cc -o wns $(WNSOBJS) $(LIBS)
SHAR_EOF
fi
if test -f 'README'; then
echo shar: will not over-write existing file 'README'
else
sed -e 's/^@//g' << 'SHAR_EOF' > README
@wns - Windowing Search Mark E. Mallett (mem@zinn.MV.COM)
@
@This is a program to search for occurances of a pattern in a text file, and
@print a window of lines around (before and after) each match point. The
@size of the window is specified on the command line.
@
@This is one of my earliest C programs, so don't be too critical of the
@implementation. It was originally written on a CP/M system and later
@moved to other environments (such as unix).
@
@As for installation - there is not much to explain. The Makefile and the
@manual source should be enough.
@
@-mm-
@April 19, 1988
SHAR_EOF
fi
if test -f 'wns.1'; then
echo shar: will not over-write existing file 'wns.1'
else
sed -e 's/^@//g' << 'SHAR_EOF' > wns.1
@.TH WNS 1
@.SH NAME
@wns \- windowing search
@.SH SYNOPSIS
@.B wns
@[-a nnn]
@[-b nnn]
@[-l nnn]
@[-w nnn]
@pattern
@[file ... ]
@.SH DESCRIPTION
@.I wns
@searches through a file or list of files for occurances of a particular
@pattern, and prints a window of lines around each match point.
@.PP
@Options which may be given are as follows:
@.TP
@.B \-a\ nnn
@(After) specifies that nnn lines following the matching line will be
@printed. default is 0.
@.TP
@.B \-b\ nnn
@(Before) specifies that nnn lines preceding the matching line will be
@printed. default is 0.
@.TP
@.B \-d
@Enables debugging information. Not a very interesting option.
@.TP
@.B \-f
@Suppress printing of the filename on each output line.
@.TP
@.B \-l\ nnn
@Sets the maximum line length to nnn. Lines longer than this will be
@truncated to this length before attempting to match them to the pattern as
@well as when printing them. Default is 100.
@.TP
@.B \-n
@Suppress printing of the line number on each output line.
@.TP
@.B \-w\ nnn
@Sets the window size to nnn. This is the same as -a nnn -b nnn.
@.PP
@.I wns
@outputs lines in the following format:
@.PP
@filename @nnnnn: text
@.PP
@where
@.I filename
@is the name of the file containing the matching text and may be suppressed
@with the -f option,
@.I lnnnn
@is the line number of the displayed line and may be suppressed with the
@-n option, and
@.I text
@is the line from the file.
@Additionally, if the total window size is greater than 1 (that is, more than
@zero lines before or after), then non-adjacent text areas are separated by
@a short dashed line.
@.SH FILES
@/usr/local/bin/wns /usr/local/src/wns/*
@.SH "CREDITS TO"
@M. Mallett (mem@zinn.MV.COM)
@.SH BUGS
@You tell me..
SHAR_EOF
fi
if test -f 'wns.c'; then
echo shar: will not over-write existing file 'wns.c'
else
awk << 'SHAR_EOF' > wns.c \
'{\
n=split($0,f,"@");\
n=f[1];\
while(n>=4){printf(" ");n=n-4}\
while(n>=1){printf(" ");--n}\
printf("%s\n",substr($0,length(f[1])+2,length))\
}'
@/* wns.c - Search for string and print window of lines around it.
8@Nov 19 1984 Mark Mallett (mem@zinn.MV.COM)
@mem 860224 Modified to do r/e (regular expression) parsing on unix
@mem 860324 Added -f, -n; added code to number lines correctly on
@ output.
@mem 870325 Added support for regcmp()/regex() style regular expression
@ library; redid some conditionals to provide better mix'n'match.
@mem 870326 Don't try to print the filename if reading from stdin.
@ Add -w option. Fix a small problem which occasionally allowed
@ the separator to come out between adjacent lines of the file.
@mem 871119 Fix semantics of call to regcmp(): the NULL terminating the
@ argument list was missing. It worked, but probably only
@ due to some bizarre coincidence.
@*/
@/* The appropriate defines are done in the makefile */
@/* #define OS_UNIX */ /* Define this for unix systems */
@/* #define SYSINC */ /* Define this for sys/ include hierarchy */
@/* #define REGEX */ /* Define this for re_comp/re_exec library */
@/* #define REGCMP */ /* Define this to use regcmp/regex */
@/* #define OS_CPM */ /* Define this for CP/M-80 */
@/* Don't touch these */
@#define NOREGEXP /* Set this for no regular expression */
@#ifdef REGEX
@#undef NOREGEXP
@#endif REGEX
@#ifdef REGCMP
@#undef NOREGEXP
@#endif REGCMP
@#ifdef OS_CPM
@#include "stdio.h"
@#include "ctype.h"
@#endif OS_CPM
@#ifdef OS_UNIX
@#include <stdio.h>
@#include <ctype.h>
@#ifdef SYSINC
@#include <sys/types.h>
@#include <sys/dir.h>
@#else /* !SYSINC */
@#include <types.h>
@#include <dir.h>
@#endif SYSINC
@#endif OS_UNIX
@/* Local definitions */
@#ifndef NULL
@#define NULL ((char *)0)
@#endif NULL
@#ifndef NUL
@#define NUL '\000'
@#endif
@#ifndef TRUE
@#define TRUE 1
@#define FALSE 0
@#endif
@/* Internal data declared global */
@/* Internal routines */
@/* External data */
@/* External routines */
@#ifdef REGEX /* re_comp/ re_exec */
@extern char *re_comp(); /* r/e compile */
@extern int re_exec(); /* r/e exec */
@#endif REGEX
@#ifdef REGCMP /* regcmp/regex */
@extern char *regcmp(); /* r/e compile */
@extern char *regex(); /* r/e exec */
@#endif REGCMP
@/* Local data */
@static int Debug={FALSE}; /* Debug enabled flag */
@static int Lcur = {0}; /* Current line (in Lines array) */
@static char **Lines = {(char **)NULL}; /* Lines pointer array */
@static int Linlen = {100}; /* Line length */
@static int Lone = {0}; /* Line one (in Lines array) */
@static int Nmr = {0}; /* Number of matched regions */
@static char *Pat = {NULL}; /* Pattern */
@static char Shwfile = {TRUE}; /* Show file name... */
@static char Shwline = {TRUE}; /* Show line number */
@static int Waft = {0}; /* Window after */
@static int Wbef = {0}; /* Window before */
@static int Wsiz = {0}; /* Window size */
@#ifdef REGEX /* regex style r/e manipulations */
@char *Re; /* Result from re_comp() */
@#endif REGEX
@#ifdef REGCMP /* regcmp style r/e */
@char *Re; /* Result from regcmp() */
@#endif REGCMP
@main (argc, argv)
@int argc; /* Argument count */
@char **argv; /* Argument values */
@{
@int i; /* Scratch */
@int n; /* Scratch again */
@int c; /* A character */
@char *aptr; /* Argument pointer */
@int nf; /* number of files on command line */
@nf = 0; /* No files on line */
@for (i = 1; i < argc; i++) /* Look at args */
4@{
4@if (argv[i][0] != '-') /* If option */
8@{
8@if (Pat == NULL) /* If no pattern yet given */
@ {
12@Pat = argv[i]; /* point here */
@#ifdef REGEX
@ if ((Re = re_comp(Pat)) != NULL)
@ {
@ fprintf(stderr, "wns: %s\n", re);
@ exit(1);
@ }
@#endif REGEX
@#ifdef REGCMP
@ if ((Re = regcmp(Pat, NULL)) == NULL)
@ {
@ fprintf(stderr, "wns: error in regular expression.\n");
@ exit(1);
@ }
@#endif REGCMP
@ }
8@else /* This must be a file to search */
12@{
12@nf++; /* Count it */
12@dosrch (argv[i]); /* Search */
12@}
8@}
4@else /* Option char */
8@{
8@c = argv[i][1]; /* Get option char */
8@if (isupper(c)) /* Trap idiot definition of tolower */
12@c = tolower(c); /* Don't care about case */
8@n = i;
8@aptr = NULL; /* Find arg, if any */
8@if (argv[i][2] != NUL)
12@{
12@aptr = &argv[i][2];
12@n = i; /* Where to set i if we use this arg */
12@}
8@else if (i < argc-1) /* use next.. */
12@{
12@n = i+1;
12@aptr = argv[n];
12@}
8@switch (c) /* Process the option */
12@{
12@case 'a': /* Lines after */
16@Waft = atoi (aptr);
16@Lines = NULL;
16@i = n;
16@break;
12@case 'b': /* Lines before */
16@Wbef = atoi (aptr);
16@Lines = (char **)NULL;
16@i = n;
16@break;
12@case 'd': /* Enable debugging */
16@Debug = TRUE;
16@break;
@ case 'f': /* Suppress filename on output */
@ Shwfile = FALSE;
@ break;
12@case 'l': /* Line length */
16@Linlen = atoi (aptr);
16@Lines = NULL;
16@i = n;
16@break;
@ case 'n': /* Suppress line number on output */
@ Shwline = FALSE;
@ break;
12@case 'w': /* Window: lines before and after */
16@Waft = Wbef = atoi (aptr);
16@Lines = NULL;
16@i = n;
16@break;
12@default:
16@fprintf (stderr, "Invalid option %s\n",argv[i]);
16@exit();
12@}
8@}
4@}
@if ( Pat == NULL ) /* If no pattern given */
4@{
4@fprintf(stderr,
@"usage: wns [-a n] [-b n] [-d] [-f] [-l n] [-n] [-w n] pattern [filename... ]\n");
4@exit(1);
4@}
@if (nf == 0) /* No files processed ? */
4@dosrch (NULL); /* Do standard input */
@}
@/*
@
@*//* dosrch (ifnm)
8@Perform the search
@Accepts :
8@ifn Input file name
@Returns :
@*/
@dosrch (ifnm)
@char *ifnm; /* Input filelname */
@{
@FILE *ifp; /* Input fp */
@char *lptr; /* Line pointer */
@int i; /* Scratch */
@int prtaft; /* Print-after count */
@int linnum; /* Line number */
@int nlb; /* Number of lines buffered */
@if (ifnm != NULL) /* If file name given */
4@{
4@ifp = fopen (ifnm, "r"); /* Open it for read access */
4@if (ifp == NULL)
8@{
8@fprintf (stderr, "Can not open file %s\n", ifnm);
8@return;
8@}
4@}
@else
4@ifp = stdin;
@if (Lines == NULL) /* If no line table allocated.. */
4@{
4@Wsiz = Wbef+2; /* Determine total window size */
4@Lines = (char **) calloc (Wsiz, sizeof (char *));
32@/* Allocate pointer table */
4@for (i = 0; i < Wsiz; i++) /* Allocate line buffers */
8@Lines[i] = (char *) calloc (Linlen, sizeof(char));
4@}
@Lcur = Lone = 0; /* Setup line pointers */
@nlb = 0; /* No lines buffered */
@linnum = 0; /* Line number is zero */
@prtaft = -(Wbef+1); /* Make sure separator given first time */
@for (;;) /* Loop through the file */
4@{
4@lptr = Lines[Lcur]; /* Get pointer to current line */
4@if (++Lcur == Wsiz) /* Bump curr pointer and wrap */
8@Lcur = 0; /* if hit end */
4@if (Lone == Lcur) /* If wrapped to beginning of window */
8@if (++Lone == Wsiz) /* Bump beginning */
12@Lone = 0; /* and wrap if hit end */
4@if (fgets (lptr, Linlen, ifp) != lptr)
8@break; /* if end of file */
4@linnum++; /* Count line number */
4@if (matlin (lptr)) /* If matching line */
8@{
8@if (prtaft < (-Wbef) ) /* Check for separator needed */
12@if ( (Nmr++ > 0 ) && ((Wbef > 0) || (Waft > 0)) )
16@printf ("-------------------\n");
8@while (Lone != Lcur) /* Until we close the window */
12@{
12@shwlin (ifnm, linnum-nlb, Lines[Lone]);
32@/* Show the line */
12@if (++Lone == Wsiz)
16@Lone = 0;
@ nlb--;
12@}
@ nlb = 0; /* No lines buffered */
8@prtaft = Waft; /* Print n lines after */
8@}
4@else /* Didn't match */
8@{
8@if (prtaft-- > 0) /* If must print lines after */
12@{
12@shwlin (ifnm, linnum, lptr);
32@/* Show the line */
12@Lone = Lcur; /* Match pointers */
12@}
@ else if (nlb < Wbef) /* Count lines buffered */
@ nlb++;
8@}
4@}
@if (ifnm != NULL)
4@fclose (ifp);
@}
@/*
@
@*//* shwlin (fnm, linnum, line)
8@Show a matching line
@Accepts :
8@fnm File name
8@linnum Line number
8@line Line to show
@Returns :
@*/
@shwlin (fnm, linnum, line)
@char *fnm; /* File name */
@int linnum; /* Line number */
@char *line; /* Line (with newline at end) to print */
@{
@if (Shwfile && ( fnm != NULL) )
4@printf("%s%s", fnm, Shwline?" ":":");
@if (Shwline)
4@printf("@%05d%:", linnum);
@printf ("%s", line);
@}
@/*
@
@*//* matlin (line)
8@Perform match against pattern and line
@Accepts :
8@line Address of line to match
@Returns :
8@<value> TRUE if match
24@FALSE if not
@*/
@int matlin (line)
@char *line; /* Line to match */
@{
@int rtncode; /* Return value from this routine */
@#ifdef NOREGEXP
@char *pptr, *lptr, *tlptr;
@int c1,c2;
@#endif NOREGEXP
@if (Debug)
4@printf ("Matching %s against %s", Pat, line);
@#ifdef REGEX
@rtncode = re_exec(line); /* Hand off to r/e evaluator */
@#endif REGEX
@#ifdef REGCMP
@rtncode = ( regex( Re, line ) != NULL );
@#endif REGCMP
@#ifdef NOREGEX /* Have to do menial comparison.. */
@lptr = line; /* Init line pointer */
@for ( rtncode = -1; rtncode < 0; )
4@{
4@tlptr = lptr++; /* Get temp ptr to line */
4@pptr = Pat; /* Get ptr to pattern */
4@while (TRUE)
8@{
8@if ((c1 = *pptr++) == NUL)
12@{
@ rtncode = 1; /* GOOD return value */
@ break;
12@}
8@if ((c2 = *tlptr++) == NUL)
12@{
@ rtncode = 0; /* BAD return value */
@ break;
12@}
8@if (isupper(c1))
12@c1 = tolower(c1);
8@if (isupper(c2))
12@c2 = tolower(c2);
8@if (c1 != c2)
12@break;
8@}
4@}
@#endif NOREGEX
@if (Debug)
4@printf("matlin returned %s\n", rtncode?"TRUE":"FALSE");
@return(rtncode);
@}
SHAR_EOF
fi