v23i069: Complete reposting of TRN at patchlevel 1, Part10/14

Rich Salz rsalz at bbn.com
Sat Jan 5 08:05:56 AEST 1991


Submitted-by: Wayne Davison <0004475895 at mcimail.com>
Posting-number: Volume 23, Issue 69
Archive-name: trn/part10

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents:  Configure.02 getdate.y kfile.c mt-read.c patchlevel
#   search.c
# Wrapped by rsalz at litchi.bbn.com on Thu Dec 27 11:34:09 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 10 (of 14)."'
if test -f 'Configure.02' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Configure.02'\"
else
  echo shar: Extracting \"'Configure.02'\" \(12351 characters\)
  sed "s/^X//" >'Configure.02' <<'END_OF_FILE'
X    dflt=`loc . /bin /usr/local/bin /usr/lbin /usr/local /usr/bin`
X    ;;
X*)  dflt="$rnbin"
X    ;;
Xesac
Xrnbin='blurfl/dyick'
Xwhile $test ! -d "$rnbin" ; do
X    case $rnbin in
X      blurfl*) ;;
X      *) $echo "$rnbin does not appear to exist." ;;
X    esac
X    $echo " "
X    $echo $n "Where do you want to put the public executables? [$dflt] $c"
X    . myread
X    rnbin="$ans"
X    rnbin=`filexp $rnbin`
X    case $rnbin in
X      '') rnbin=$dflt ;;
X    esac
Xdone
X
X: determine where private executables go
Xcase "$rnlib" in
X'')
X    case "$isrrn" in
X	define) dflt=/usr/local/lib/trn ;;
X	*) dflt=$lib/trn ;;
X    esac
X    ;;
X*)  dflt="$rnlib"
X    ;;
Xesac
X$echo " "
X$echo "Trn has a number of auxiliary programs that need not be visible to the"
X$echo "whole world.  Where do you want to put these private executables?"
X$echo $n "[$dflt] (~name ok) $c"
X. myread
Xrnlib="$ans"
Xcase $rnlib in
X  '') rnlib=$dflt ;;
Xesac
Xcase $portable in
Xundef)
X    rnlib=`filexp $rnlib`
X    ;;
Xesac
X: must not allow self reference
Xcase $rnlib in
X  /*)
X    filexp=$rnlib/filexp
X    ;;
X  *)
X    filexp=`pwd`/filexp
X    ;;
Xesac
X
X: get the local distribution prefixes
Xif $test -f $libexp/sys ; then
X    $sed <$libexp/sys -n -e "s/^$sitename://p" | \
X    $sed -e "s/:.*//" -e "s/,/ /g" | tr ' ' '\012' | \
X    $sed -e "/^to./d" -e "/^net$/d" -e "/^fa$/d" -e "/^mod$/d" > .distlist
Xfi
X
X$cat <<'EOH'
X 
XDistribution groups are the things you use on the Distribution line to limit
Xwhere an article will go to.  You are likely to be a member of several
Xdistribution groups, such as organization, city, state, province, country,
Xcontinent, etc.  For example, Los Angeles has the distribution prefix "la",
XNew Jersey has the prefix "nj", and Europe has the prefix "eunet".
X
XThe categories you will be asked are: 
X
Xlocal organization	(Could be just one machine or a cluster or an office)
Xorganization		att, dec, kgb, ...
Xcity			la, ny, mosc, ...
Xstate/province		ca, nj, bc, ...
Xcountry			usa, can, rok, whatever
Xcontinent		na (North America, not "Not Applicable"), asia, etc.
X
X(If you don't have a distribution prefix in any of these categories then
Xjust hit return.)
X
XEOH
Xif $test -f .distlist; then
X    distlist=`tr '\012' ' ' <.distlist`
X    if $test "$distlist" ; then
X	$echo "(These are the distributions in your sys file: $distlist)"
X	$echo " "
X    fi
Xfi
Xcase "$locpref" in
X'') dflt="";;
X*)  dflt="[$locpref] ";;
Xesac
X$echo $n "What is the distribution prefix for your local organization? $dflt$c"
X. myread
Xcase "$ans" in
X'') ;;
X*)  locpref="$ans";;
Xesac
Xcase $locpref in
X  '') locpref=none ;;
Xesac
Xcase "$orgpref" in
X'') dflt="";;
X*)  dflt="[$orgpref] ";;
Xesac
X$echo $n "What is the distribution prefix for your organization? $dflt$c"
X. myread
Xcase "$ans" in
X'') ;;
X*)  orgpref="$ans";;
Xesac
Xcase $orgpref in
X  '') orgpref=none ;;
Xesac
Xcase "$citypref" in
X'') dflt="";;
X*)  dflt="[$citypref] ";;
Xesac
X$echo $n "What is the distribution prefix for your city? $dflt$c"
X. myread
Xcase "$ans" in
X'') ;;
X*)  citypref="$ans";;
Xesac
Xcase $citypref in
X  '') citypref=none ;;
Xesac
Xcase "$statepref" in
X'') dflt="";;
X*)  dflt="[$statepref] ";;
Xesac
X$echo $n "What is the distribution prefix for your state/province? $dflt$c"
X. myread
Xcase "$ans" in
X'') ;;
X*)  statepref="$ans";;
Xesac
Xcase $statepref in
X  '') statepref=none ;;
Xesac
Xcase "$cntrypref" in
X'') dflt="";;
X*)  dflt="[$cntrypref] ";;
Xesac
X$echo $n "What is the distribution prefix for your country? $dflt$c"
X. myread
Xcase "$ans" in
X'') ;;
X*)  cntrypref="$ans";;
Xesac
Xcase $cntrypref in
X  '') cntrypref=none ;;
Xesac
Xcase "$contpref" in
X'') dflt="";;
X*)  dflt="[$contpref] ";;
Xesac
X$echo $n "What is the distribution prefix for your continent? $dflt$c"
X. myread
Xcase "$ans" in
X'') ;;
X*)  contpref="$ans";;
Xesac
Xcase $contpref in
X  '') contpref=none ;;
Xesac
X
X$echo " "
X$echo "If you have any other distribution groups you will need to edit Pnews"
X$echo "and newsetup to add them."
X$echo " "
X
X: determine root id
Xrootid=`$sed </etc/passwd -e "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/" -e "q" -e "}" -e "d"`
Xcase $rootid in
X  '') rootid=0 ;;
X  *)  $echo "Root uid = $rootid" ;;
Xesac
X
X: weed out incompatibilities
Xcase $douname in
X  define) whoami=undef ;;
Xesac
X
X: preserve RCS keywords in files with variable substitution, grrr
XLog='$Log'
XHeader='$Header'
X
X: Warnings
Xif v7; then
X    cat <<'EOM'
X 
XNOTE: the V7 compiler may ignore some #undefs that trn uses.  If so, you will
Xget messages about redefining EXT.  Some V7 compilers also have difficulties
Xwith #defines near buffer boundaries, so beware.  You may have to play with
Xthe spacing in common.h.
XEOM
Xfi
X
Xif pdp11; then
X    cat <<'EOM'
X 
XNOTE: the PDP-11 does not have enough data space to do subject caching
Xreliably.  That feature will be disabled automatically.  Subject searching
Xwill tend to be slow.
XEOM
Xfi
Xcase "$isrrn" in
X	define) ;;
X	*) socketlib=""
X	   rrninclude=""
X	 ;;
Xesac
X
X$echo " "
X$echo "End of configuration questions."
X$echo " "
X
X: create config.sh file
X$echo " "
X$echo "Creating config.sh..."
X$spitshell <<EOT >config.sh
X$startsh
X# config.sh
X# This file was produced by running the Configure script.
X
Xn='$n'
Xc='$c'
Xlibc='$libc'
Xeunicefix='$eunicefix'
Xeunice='$eunice'
Xcpp='$cpp'
Xshsharp='$shsharp'
Xstartsh='$startsh'
Xspitshell='$spitshell'
Xtest='$test'
Xexpr='$expr'
Xsed='$sed'
Xecho='$echo'
Xcat='$cat'
Xrm='$rm'
Xmv='$mv'
Xcp='$cp'
Xtail='$tail'
Xtr='$tr'
Xmkdir='$mkdir'
Xsort='$sort'
Xuniq='$uniq'
Xinews='$inews'
Xgrep='$grep'
Xegrep='$egrep'
Xypmatch='$ypmatch'
Xcontains='$contains'
Xlib='$lib'
Xlibexp='$libexp'
Xnametype='$nametype'
Xcc='$cc'
Xiandd='$iandd'
Xinclude='$include'
Xrrninclude='$rrninclude'
Xtermlib='$termlib'
Xjobslib='$jobslib'
Xsocketlib='$socketlib'
Xgetcwd='$getcwd'
Xdirtype='$dirtype'
Xndirlib='$ndirlib'
Xlibndir='$libndir'
Xusendir='$usendir'
Xndirc='$ndirc'
Xndiro='$ndiro'
Xpager='$pager'
Xmailer='$mailer'
Xinternet='$internet'
Xrnbin='$rnbin'
Xfilexp='$filexp'
Xdistlist='$distlist'
XLog='$Log'
XHeader='$Header'
Xsitename='$sitename'
Xhostfile='$hostfile'
Xdomain='$domain'
Xorgname='$orgname'
Xisadmin='$isadmin'
Xnewsadmin='$newsadmin'
Xrnlib='$rnlib'
Xmansrc='$mansrc'
Xmanext='$manext'
Xmaildir='$maildir'
Xspool='$spool'
Xactive='$active'
Xmyactive='$myactive'
Xmininact='$mininact'
Xpref='$pref'
Xdefeditor='$defeditor'
Xrootid='$rootid'
Xmboxchar='$mboxchar'
Xlocpref='$locpref'
Xorgpref='$orgpref'
Xcitypref='$citypref'
Xstatepref='$statepref'
Xcntrypref='$cntrypref'
Xcontpref='$contpref'
Xstrchr='$strchr'
Xmemcpy='$memcpy'
Xrename='$rename'
Xtruncate='$truncate'
Xchsize='$chsize'
Xsysptem='$sysptem'
Xtzset='$tzset'
Xthreaddef='$threaddef'
Xselectdef='$selectdef'
Xthreaddir='$threaddir'
Xnovoid='$novoid'
Xnovfork='$novfork'
Xportable='$portable'
Xpassnam='$passnam'
Xberknam='$berknam'
Xusgnam='$usgnam'
Xwhoami='$whoami'
Xtermio='$termio'
Xfcntl='$fcntl'
Xioctl='$ioctl'
Xnormsig='$normsig'
Xsigblock='$sigblock'
Xsigret='$sigret'
Xgetuidgid='$getuidgid'
Xhavetlib='$havetlib'
Xgetpwent='$getpwent'
Xgethostname='$gethostname'
Xdouname='$douname'
Xphostname='$phostname'
Xhostcmd='$hostcmd'
Xnorelay='$norelay'
Xrdchk='$rdchk'
Xisrrn='$isrrn'
Xserverfile='$serverfile'
XNNTPSRC='$NNTPSRC'
XCONFIG=true
XCTRLA='$CTRLA'
XEOT
X
X: create config.h file
X$echo " "
X$echo "Creating config.h..."
Xcase "$threaddir" in
X'.')	threaddir='/usr/spool/threads'
X	tdir='/*';;
X*)	tdir='';;
Xesac
Xcase "$strchr" in
Xdefine)	strchr='';;
X*)	strchr='/*';;
Xesac
Xcase "$memcpy" in
Xdefine)	memcpy='';;
X*)	memcpy='/*';;
Xesac
Xcase "$novoid" in
Xdefine)	novoid='';;
X*)	novoid='/*';;
Xesac
Xcase "$novfork" in
Xdefine)	novfork='';;
X*)	novfork='/*';;
Xesac
Xcase "$phostname" in
Xdefine)	phostname='';;
X*)	phostname='/*';;
Xesac
Xcase "$isrrn" in
Xdefine)	isrrn2='';;
X*)	isrrn2='/*';;
Xesac
Xcase "$hostfile" in
X'')	usehostfile='/*';;
X*)	usehostfile='';;
Xesac
X$cat <<EOT >config.h
X/* config.h
X * This file was produced by running the Configure script.
X * Feel free to modify any of this as the need arises.
X */
X
X/* name of the site.  May be overridden by HOSTFILE, gethostname, uname, etc. */
X#define SITENAME "$sitename"
X$usehostfile#define HOSTFILE "$hostfile"
X
X/* OURDOMAIN is added to the site name if no "." is in it. */
X#define OURDOMAIN "$domain"
X
X/* name of the organization, may be a file name */
X#define ORGNAME "$orgname"
X
X/* login name of news administrator, if any. */
X#$isadmin NEWSADMIN "$newsadmin"
X
X/* news library, may use only ~ and %l expansion */
X#define LIB "$lib"
X
X/* rn private library, may use ~ expansion, %x and %l */
X#define RNLIB "$rnlib"
X
X/* location of the news spool directory, may use ~ expansion, %x and %l */
X#define SPOOL "$spool"
X
X/* put thread files in each spool directory, unless THREAD_DIR is defined */
X$tdir#define THREAD_DIR "$threaddir"	/* base directory */
X
X/* save in subdirectories unless LONG_THREAD_NAMES & THREAD_DIR are defined */
X#undef LONG_THREAD_NAMES		/* not for short-name systems */
X
X/* location of the active file, may use ~ expansion, %x and %l */
X#define ACTIVE "$active"
X
X/* location of spooled mail */
X#define MAILFILE "$maildir"
X
X/* default shell--ok to be a slow shell like csh */
X#define PREFSHELL "$pref"
X
X/* default editor */
X#define DEFEDITOR "$defeditor"
X
X/* root uid */
X#define ROOTID $rootid
X
X/* what is the first character of a mailbox? */
X#define MBOXCHAR '$mboxchar'
X
X/* how to cancel an article */
X#define CANCEL "$inews -h <%h"
X
X/* distribution groups */
X#define LOCDIST "$locpref"
X#define ORGDIST "$orgpref"
X#define CITYDIST "$citypref"
X#define STATEDIST "$statepref"
X#define CNTRYDIST "$cntrypref"
X#define CONTDIST "$contpref"
X
X#define THREAD_INIT $threaddef
X#define SELECT_INIT $selectdef
X
X$strchr#define index   strchr	/* cultural */
X$strchr#define rindex  strrchr	/*  differences? */
X$memcpy#define bcopy(s,d,n)	memcpy((char*)d,(char*)s,(int)n)	/* Different */
X$memcpy#define bzero(d,n)	memset((char*)d,0,(int)n)		/*  flavors. */
X#$rename	RENAME		/* is rename() a system call? */
X#$truncate	TRUNCATE	/* is truncate() available? */
X#$chsize	CHSIZE		/* is chsize() available? */
X#$sysptem	SYS_PTEM	/* is /usr/include/sys/ptem.h needed? */
X#$tzset	TZSET		/* modern timezone functions? */
X$novoid#define void int	/* is void to be avoided? */
X$novfork#define vfork fork	/* is vfork too virtual? */
X#$eunice	EUNICE		/* no linking? */
X#$eunice	VMS		/* not currently used, here just in case */
X#$getcwd	GETCWD		/* do we have getcwd()? */
X#$usendir	USENDIR		/* include ndir.c? */
X#$libndir	LIBNDIR		/* include /usr/include/ndir.h? */
X#define	DIRTYPE   $dirtype
X#ifndef USENDIR
X#define	DIRINC	  $dirinc
X#endif
X#$mininact	MININACT	/* include 2.10.2 optimization? */
X#$portable	PORTABLE	/* do we do extra lookups to start up? */
X#$passnam	PASSNAMES	/* do names come from the passwd file? */
X			/*  (undef to take name from ~/.fullname) */
X#$berknam	BERKNAMES	/* if so, are they Berkeley format? */
X			/* (that is, ":name,stuff:") */
X#$usgnam	USGNAMES	/* or are they USG format? */
X			/* (that is, ":stuff-name(stuff):") */
X#$whoami	WHOAMI		/* should we include whoami.h? */
X#$rdchk	RDCHK		/* do we have rdchk()? */
X#$termio	TERMIO		/* is this a termio system? */
X#$fcntl	FCNTL		/* should we include fcntl.h? */
X#$ioctl	IOCTL		/* are ioctl args all defined in one place? */
X#$normsig	NORMSIG		/* use signal rather than sigset? */
X#$sigblock	SIGBLOCK	/* use sigblock and sigsetmask */
X#define	SIGRET	$sigret	/* what does signal() return? */
X#$havetlib	HAVETERMLIB	/* do we have termlib-style routines? */
X#$getuidgid	GETUIDGID	/* allow setuid (if possible) */
X#$getpwent	GETPWENT	/* should we include getpwent? */
X#$internet	INTERNET	/* does our mailer do INTERNET addressing? */
X#$gethostname	GETHOSTNAME	/* do we have a gethostname function? */
X#$douname	DOUNAME		/* do we have a uname function? */
X$phostname#define PHOSTNAME "$hostcmd"	/* how to get host name with popen */
X#$norelay	NORELAY		/* 2.10.3 doesn't have Relay-Version line */
X#$isrrn	SERVER		/* rrn server code */
X$isrrn2#define SERVER_FILE	"$serverfile"	/* news server file */
XEOT
X
XCONFIG=true
X
X$rm -f libc.list .distlist kit*isdone 
X
X$echo " "
X$echo "Doing variable substitutions on various files..."
X$echo " "
Xset `$grep <MANIFEST '\.SH' | awk '{print $1}'`
Xfor file in $*; do
X    . $file
Xdone
X
X$echo " "
X$echo 'Now you need to generate make dependencies by running "makedepend".'
X$echo 'You might prefer to run it in background: "makedepend > makedepend.out &"'
X$echo $n "Would you like me to run it for you (it takes quite a while)? [n] $c" 
X. myread
Xcase "$ans" in
Xy*) makedepend;;
Xesac
X$rm -f myread
X: end of Configure
END_OF_FILE
  if test 12351 -ne `wc -c <'Configure.02'`; then
    echo shar: \"'Configure.02'\" unpacked with wrong size!
  fi
  # end of 'Configure.02'
fi
if test -f 'getdate.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getdate.y'\"
else
  echo shar: Extracting \"'getdate.y'\" \(12373 characters\)
  sed "s/^X//" >'getdate.y' <<'END_OF_FILE'
X%token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
X%{
X	/* 	Steven M. Bellovin (unc!smb)			*/
X	/*	Dept. of Computer Science			*/
X	/*	University of North Carolina at Chapel Hill	*/
X	/*	@(#)getdate.y	2.13	9/16/86 */
X
X#include <sys/types.h>
X#include <ctype.h>
X#include <time.h>
X
X#define	NULL	0
X
X#define daysec (24L*60L*60L)
X
X	static int timeflag, zoneflag, dateflag, dayflag, relflag;
X	static time_t relsec, relmonth;
X	static int hh, mm, ss, merid, daylight;
X	static int dayord, dayreq;
X	static int month, day, year;
X	static int ourzone;
X
X#define AM 1
X#define PM 2
X#define DAYLIGHT 1
X#define STANDARD 2
X#define MAYBE    3
X%}
X
X%%
Xtimedate: 		/* empty */
X	| timedate item;
X
Xitem:	tspec =
X		{timeflag++;}
X	| zone =
X		{zoneflag++;}
X	| dtspec =
X		{dateflag++;}
X	| dyspec =
X		{dayflag++;}
X	| rspec =
X		{relflag++;}
X	| nspec;
X
Xnspec:	NUMBER =
X		{if (timeflag && dateflag && !relflag) year = $1;
X		else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
X
Xtspec:	NUMBER MERIDIAN =
X		{hh = $1; mm = 0; ss = 0; merid = $2;}
X	| NUMBER ':' NUMBER =
X		{hh = $1; mm = $3; merid = 24;}
X	| NUMBER ':' NUMBER MERIDIAN =
X		{hh = $1; mm = $3; merid = $4;}
X	| NUMBER ':' NUMBER NUMBER =
X		{hh = $1; mm = $3; merid = 24;
X		daylight = STANDARD; ourzone = -($4%100 + 60*$4/100);}
X	| NUMBER ':' NUMBER ':' NUMBER =
X		{hh = $1; mm = $3; ss = $5; merid = 24;}
X	| NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
X		{hh = $1; mm = $3; ss = $5; merid = $6;}
X	| NUMBER ':' NUMBER ':' NUMBER NUMBER =
X		{hh = $1; mm = $3; ss = $5; merid = 24;
X		daylight = STANDARD; ourzone = -($6%100 + 60*$6/100);};
X
Xzone:	ZONE =
X		{ourzone = $1; daylight = STANDARD;}
X	| DAYZONE =
X		{ourzone = $1; daylight = DAYLIGHT;};
X
Xdyspec:	DAY =
X		{dayord = 1; dayreq = $1;}
X	| DAY ',' =
X		{dayord = 1; dayreq = $1;}
X	| NUMBER DAY =
X		{dayord = $1; dayreq = $2;};
X
Xdtspec:	NUMBER '/' NUMBER =
X		{month = $1; day = $3;}
X	| NUMBER '/' NUMBER '/' NUMBER =
X		{month = $1; day = $3; year = $5;}
X	| MONTH NUMBER =
X		{month = $1; day = $2;}
X	| MONTH NUMBER ',' NUMBER =
X		{month = $1; day = $2; year = $4;}
X	| NUMBER MONTH =
X		{month = $2; day = $1;}
X	| NUMBER MONTH NUMBER =
X		{month = $2; day = $1; year = $3;};
X
X
Xrspec:	NUMBER UNIT =
X		{relsec +=  60L * $1 * $2;}
X	| NUMBER MUNIT =
X		{relmonth += $1 * $2;}
X	| NUMBER SUNIT =
X		{relsec += $1;}
X	| UNIT =
X		{relsec +=  60L * $1;}
X	| MUNIT =
X		{relmonth += $1;}
X	| SUNIT =
X		{relsec++;}
X	| rspec AGO =
X		{relsec = -relsec; relmonth = -relmonth;};
X%%
X
Xstatic int mdays[12] =
X	{31, 0, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31};
X#define epoch 1970
X
Xextern struct tm *localtime();
Xtime_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
Xint mm, dd, yy, h, m, s, mer, zone, dayflag;
X{
X	time_t tod, jdate;
X	register int i;
X	time_t timeconv();
X
X	if (yy < 0) yy = -yy;
X	if (yy < 100) yy += 1900;
X	mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
X	if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
X		dd < 1 || dd > mdays[--mm]) return (-1);
X	jdate = dd-1;
X        for (i=0; i<mm; i++) jdate += mdays[i];
X	for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
X	jdate *= daysec;
X	jdate += zone * 60L;
X	if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
X	jdate += tod;
X	if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
X		jdate += -1*60*60;
X	return (jdate);
X}
X
Xtime_t dayconv(ord, day, now) int ord, day; time_t now;
X{
X	register struct tm *loctime;
X	time_t tod;
X	time_t daylcorr();
X
X	tod = now;
X	loctime = localtime(&tod);
X	tod += daysec * ((day - loctime->tm_wday + 7) % 7);
X	tod += 7*daysec*(ord<=0?ord:ord-1);
X	return daylcorr(tod, now);
X}
X
Xtime_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer;
X{
X	if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
X	switch (mer) {
X		case AM: if (hh < 1 || hh > 12) return(-1);
X			 return (60L * ((hh%12)*60L + mm)+ss);
X		case PM: if (hh < 1 || hh > 12) return(-1);
X			 return (60L * ((hh%12 +12)*60L + mm)+ss);
X		case 24: if (hh < 0 || hh > 23) return (-1);
X			 return (60L * (hh*60L + mm)+ss);
X		default: return (-1);
X	}
X}
Xtime_t monthadd(sdate, relmonth) time_t sdate, relmonth;
X{
X	struct tm *ltime;
X	time_t dateconv();
X	time_t daylcorr();
X	int mm, yy;
X
X	if (relmonth == 0) return 0;
X	ltime = localtime(&sdate);
X	mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
X	yy = mm/12;
X	mm = mm%12 + 1;
X	return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
X		ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
X}
X
Xtime_t daylcorr(future, now) time_t future, now;
X{
X	int fdayl, nowdayl;
X
X	nowdayl = (localtime(&now)->tm_hour+1) % 24;
X	fdayl = (localtime(&future)->tm_hour+1) % 24;
X	return (future-now) + 60L*60L*(nowdayl-fdayl);
X}
X
Xstatic char *lptr;
X
Xyylex()
X{
X	extern int yylval;
X	int sign;
X	register char c;
X	register char *p;
X	char idbuf[20];
X	int pcnt;
X
X	for (;;) {
X		while (isspace(*lptr)) lptr++;
X
X		if (isdigit(c = *lptr) || c == '-' || c == '+') {
X			if (c== '-' || c == '+') {
X				if (c=='-') sign = -1;
X				else sign = 1;
X				if (!isdigit(*++lptr)) {
X					/* yylval = sign; return (NUMBER); */
X					return yylex();	/* skip the '-' sign */
X				}
X			} else sign = 1;
X			yylval = 0;
X			while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
X			yylval *= sign;
X			lptr--;
X			return (NUMBER);
X
X		} else if (isalpha(c)) {
X			p = idbuf;
X			while (isalpha(c = *lptr++) || c=='.')
X				if (p < &idbuf[sizeof(idbuf)-1])
X					*p++ = c;
X			*p = '\0';
X			lptr--;
X			return (lookup(idbuf));
X		}
X
X		else if (c == '(') {
X			pcnt = 0;
X			do {
X				c = *lptr++;
X				if (c == '\0') return(c);
X				else if (c == '(') pcnt++;
X				else if (c == ')') pcnt--;
X			} while (pcnt > 0);
X		}
X
X		else return (*lptr++);
X	}
X}
X
Xstruct table {
X	char *name;
X	int type, value;
X};
X
Xstruct table mdtab[] = {
X	{"January", MONTH, 1},
X	{"February", MONTH, 2},
X	{"March", MONTH, 3},
X	{"April", MONTH, 4},
X	{"May", MONTH, 5},
X	{"June", MONTH, 6},
X	{"July", MONTH, 7},
X	{"August", MONTH, 8},
X	{"September", MONTH, 9},
X	{"Sept", MONTH, 9},
X	{"October", MONTH, 10},
X	{"November", MONTH, 11},
X	{"December", MONTH, 12},
X
X	{"Sunday", DAY, 0},
X	{"Monday", DAY, 1},
X	{"Tuesday", DAY, 2},
X	{"Tues", DAY, 2},
X	{"Wednesday", DAY, 3},
X	{"Wednes", DAY, 3},
X	{"Thursday", DAY, 4},
X	{"Thur", DAY, 4},
X	{"Thurs", DAY, 4},
X	{"Friday", DAY, 5},
X	{"Saturday", DAY, 6},
X	{0, 0, 0}};
X
X#define HRS *60
X#define HALFHR 30
Xstruct table mztab[] = {
X	{"a.m.", MERIDIAN, AM},
X	{"am", MERIDIAN, AM},
X	{"p.m.", MERIDIAN, PM},
X	{"pm", MERIDIAN, PM},
X	{"nst", ZONE, 3 HRS + HALFHR},		/* Newfoundland */
X	{"n.s.t.", ZONE, 3 HRS + HALFHR},
X	{"ast", ZONE, 4 HRS},		/* Atlantic */
X	{"a.s.t.", ZONE, 4 HRS},
X	{"adt", DAYZONE, 4 HRS},
X	{"a.d.t.", DAYZONE, 4 HRS},
X	{"est", ZONE, 5 HRS},		/* Eastern */
X	{"e.s.t.", ZONE, 5 HRS},
X	{"edt", DAYZONE, 5 HRS},
X	{"e.d.t.", DAYZONE, 5 HRS},
X	{"cst", ZONE, 6 HRS},		/* Central */
X	{"c.s.t.", ZONE, 6 HRS},
X	{"cdt", DAYZONE, 6 HRS},
X	{"c.d.t.", DAYZONE, 6 HRS},
X	{"mst", ZONE, 7 HRS},		/* Mountain */
X	{"m.s.t.", ZONE, 7 HRS},
X	{"mdt", DAYZONE, 7 HRS},
X	{"m.d.t.", DAYZONE, 7 HRS},
X	{"pst", ZONE, 8 HRS},		/* Pacific */
X	{"p.s.t.", ZONE, 8 HRS},
X	{"pdt", DAYZONE, 8 HRS},
X	{"p.d.t.", DAYZONE, 8 HRS},
X	{"yst", ZONE, 9 HRS},		/* Yukon */
X	{"y.s.t.", ZONE, 9 HRS},
X	{"ydt", DAYZONE, 9 HRS},
X	{"y.d.t.", DAYZONE, 9 HRS},
X	{"hst", ZONE, 10 HRS},		/* Hawaii */
X	{"h.s.t.", ZONE, 10 HRS},
X	{"hdt", DAYZONE, 10 HRS},
X	{"h.d.t.", DAYZONE, 10 HRS},
X
X	{"gmt", ZONE, 0 HRS},
X	{"g.m.t.", ZONE, 0 HRS},
X	{"bst", DAYZONE, 0 HRS},		/* British Summer Time */
X	{"b.s.t.", DAYZONE, 0 HRS},
X	{"eet", ZONE, 0 HRS},		/* European Eastern Time */
X	{"e.e.t.", ZONE, 0 HRS},
X	{"eest", DAYZONE, 0 HRS},	/* European Eastern Summer Time */
X	{"e.e.s.t.", DAYZONE, 0 HRS},
X	{"met", ZONE, -1 HRS},		/* Middle European Time */
X	{"m.e.t.", ZONE, -1 HRS},
X	{"mest", DAYZONE, -1 HRS},	/* Middle European Summer Time */
X	{"m.e.s.t.", DAYZONE, -1 HRS},
X	{"wet", ZONE, -2 HRS },		/* Western European Time */
X	{"w.e.t.", ZONE, -2 HRS },
X	{"west", DAYZONE, -2 HRS},	/* Western European Summer Time */
X	{"w.e.s.t.", DAYZONE, -2 HRS},
X
X	{"jst", ZONE, -9 HRS},		/* Japan Standard Time */
X	{"j.s.t.", ZONE, -9 HRS},	/* Japan Standard Time */
X					/* No daylight savings time */
X
X	{"aest", ZONE, -10 HRS},	/* Australian Eastern Time */
X	{"a.e.s.t.", ZONE, -10 HRS},
X	{"aesst", DAYZONE, -10 HRS},	/* Australian Eastern Summer Time */
X	{"a.e.s.s.t.", DAYZONE, -10 HRS},
X	{"acst", ZONE, -(9 HRS + HALFHR)},	/* Australian Central Time */
X	{"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
X	{"acsst", DAYZONE, -(9 HRS + HALFHR)},	/* Australian Central Summer */
X	{"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
X	{"awst", ZONE, -8 HRS},		/* Australian Western Time */
X	{"a.w.s.t.", ZONE, -8 HRS},	/* (no daylight time there, I'm told */
X	{0, 0, 0}};
X
Xstruct table unittb[] = {
X	{"year", MUNIT, 12},
X	{"month", MUNIT, 1},
X	{"fortnight", UNIT, 14*24*60},
X	{"week", UNIT, 7*24*60},
X	{"day", UNIT, 1*24*60},
X	{"hour", UNIT, 60},
X	{"minute", UNIT, 1},
X	{"min", UNIT, 1},
X	{"second", SUNIT, 1},
X	{"sec", SUNIT, 1},
X	{0, 0, 0}};
X
Xstruct table othertb[] = {
X	{"tomorrow", UNIT, 1*24*60},
X	{"yesterday", UNIT, -1*24*60},
X	{"today", UNIT, 0},
X	{"now", UNIT, 0},
X	{"last", NUMBER, -1},
X	{"this", UNIT, 0},
X	{"next", NUMBER, 2},
X	{"first", NUMBER, 1},
X	/* {"second", NUMBER, 2}, */
X	{"third", NUMBER, 3},
X	{"fourth", NUMBER, 4},
X	{"fifth", NUMBER, 5},
X	{"sixth", NUMBER, 6},
X	{"seventh", NUMBER, 7},
X	{"eigth", NUMBER, 8},
X	{"ninth", NUMBER, 9},
X	{"tenth", NUMBER, 10},
X	{"eleventh", NUMBER, 11},
X	{"twelfth", NUMBER, 12},
X	{"ago", AGO, 1},
X	{0, 0, 0}};
X
Xstruct table milzone[] = {
X	{"a", ZONE, 1 HRS},
X	{"b", ZONE, 2 HRS},
X	{"c", ZONE, 3 HRS},
X	{"d", ZONE, 4 HRS},
X	{"e", ZONE, 5 HRS},
X	{"f", ZONE, 6 HRS},
X	{"g", ZONE, 7 HRS},
X	{"h", ZONE, 8 HRS},
X	{"i", ZONE, 9 HRS},
X	{"k", ZONE, 10 HRS},
X	{"l", ZONE, 11 HRS},
X	{"m", ZONE, 12 HRS},
X	{"n", ZONE, -1 HRS},
X	{"o", ZONE, -2 HRS},
X	{"p", ZONE, -3 HRS},
X	{"q", ZONE, -4 HRS},
X	{"r", ZONE, -5 HRS},
X	{"s", ZONE, -6 HRS},
X	{"t", ZONE, -7 HRS},
X	{"u", ZONE, -8 HRS},
X	{"v", ZONE, -9 HRS},
X	{"w", ZONE, -10 HRS},
X	{"x", ZONE, -11 HRS},
X	{"y", ZONE, -12 HRS},
X	{"z", ZONE, 0 HRS},
X	{0, 0, 0}};
X
Xlookup(id) char *id;
X{
X#define gotit (yylval=i->value,  i->type)
X#define getid for(j=idvar, k=id; *j++ = *k++; )
X
X	char idvar[20];
X	register char *j, *k;
X	register struct table *i;
X	int abbrev;
X
X	getid;
X	if (strlen(idvar) == 3) abbrev = 1;
X	else if (strlen(idvar) == 4 && idvar[3] == '.') {
X		abbrev = 1;
X		idvar[3] = '\0';
X	}
X	else abbrev = 0;
X
X	if (islower(*idvar)) *idvar = toupper(*idvar);
X
X	for (i = mdtab; i->name; i++) {
X		k = idvar;
X		for (j = i->name; *j++ == *k++;) {
X			if (abbrev && j==i->name+3) return gotit;
X			if (j[-1] == 0) return gotit;
X		}
X	}
X
X	getid;
X	for (i = mztab; i->name; i++)
X		if (strcmp(i->name, idvar) == 0) return gotit;
X
X	for (j = idvar; *j; j++)
X		if (isupper(*j)) *j = tolower(*j);
X	for (i=mztab; i->name; i++)
X		if (strcmp(i->name, idvar) == 0) return gotit;
X
X	getid;
X	for (i=unittb; i->name; i++)
X		if (strcmp(i->name, idvar) == 0) return gotit;
X
X	if (idvar[strlen(idvar)-1] == 's')
X		idvar[strlen(idvar)-1] = '\0';
X	for (i=unittb; i->name; i++)
X		if (strcmp(i->name, idvar) == 0) return gotit;
X
X	getid;
X	for (i = othertb; i->name; i++)
X		if (strcmp(i->name, idvar) == 0) return gotit;
X
X	getid;
X	if (strlen(idvar) == 1 && isalpha(*idvar)) {
X		if (isupper(*idvar)) *idvar = tolower(*idvar);
X		for (i = milzone; i->name; i++)
X			if (strcmp(i->name, idvar) == 0) return gotit;
X	}
X
X	return(ID);
X}
X
Xtime_t getdate(p, now, zone) char *p; time_t now; long zone;
X{
X#define mcheck(f)	if (f>1) err++
X	time_t monthadd();
X	int err;
X	struct tm *lt;
X	time_t sdate, tod;
X
X	lptr = p;
X	if (now <= 0)
X		(void) time(&now);
X	lt = localtime(&now);
X	year = lt->tm_year;
X	month = lt->tm_mon+1;
X	day = lt->tm_mday;
X	relsec = 0; relmonth = 0;
X	timeflag=zoneflag=dateflag=dayflag=relflag=0;
X	daylight = MAYBE;
X	hh = mm = ss = 0;
X	merid = 24;
X	ourzone = zone;
X
X	if (err = yyparse()) return (-1);
X
X	mcheck(timeflag);
X	mcheck(zoneflag);
X	mcheck(dateflag);
X	mcheck(dayflag);
X
X	if (err) return (-1);
X	if (dateflag || timeflag || dayflag) {
X		sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
X		if (sdate < 0) return -1;
X	}
X	else {
X		sdate = now;
X		if (relflag == 0)
X			sdate -= (lt->tm_sec + lt->tm_min*60 +
X				lt->tm_hour*(60L*60L));
X	}
X
X	sdate += relsec;
X	sdate += monthadd(sdate, relmonth);
X
X	if (dayflag && !dateflag) {
X		tod = dayconv(dayord, dayreq, sdate);
X		sdate += tod;
X	}
X
X	return sdate;
X}
X
Xyyerror(s) char *s;
X{}
END_OF_FILE
  if test 12373 -ne `wc -c <'getdate.y'`; then
    echo shar: \"'getdate.y'\" unpacked with wrong size!
  fi
  # end of 'getdate.y'
fi
if test -f 'kfile.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kfile.c'\"
else
  echo shar: Extracting \"'kfile.c'\" \(7167 characters\)
  sed "s/^X//" >'kfile.c' <<'END_OF_FILE'
X/* $Header: kfile.c,v 4.3.3.1 90/06/20 22:38:06 davison Trn $
X *
X * $Log:	kfile.c,v $
X * Revision 4.3.3.1  90/06/20  22:38:06  davison
X * Initial Trn Release
X * 
X * Revision 1.2  90/03/22  23:04:41  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.1.3  85/05/29  09:11:52  lwall
X * Suppressed some killing messages on -t.
X * 
X * Revision 4.3.1.2  85/05/10  14:21:29  lwall
X * Prevented THRU from setting art < absfirst.
X * 
X * Revision 4.3.1.1  85/05/10  11:34:33  lwall
X * Branch for patches.
X * 
X * Revision 4.3  85/05/01  11:41:53  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "term.h"
X#include "util.h"
X#include "artsrch.h"
X#include "ng.h"
X#include "bits.h"
X#include "intrp.h"
X#include "ngstuff.h"
X#include "rcstuff.h"
X#include "rn.h"
X#ifdef USETHREADS
X#include "rthreads.h"
X#endif
X#include "INTERN.h"
X#include "kfile.h"
X
Xstatic bool exitcmds = FALSE;
X
Xvoid
Xkfile_init()
X{
X    ;
X}
X
X#ifndef KILLFILES
Xint
Xedit_kfile()
X{
X    notincl("^K");
X    return -1;
X}
X
X#else /* KILLFILES */
X
Xchar killglobal[] = KILLGLOBAL;
Xchar killlocal[] = KILLLOCAL;
X
Xvoid
Xmention(str)
Xchar *str;
X{
X#ifdef VERBOSE
X    IF(verbose) {
X#ifdef NOFIREWORKS
X	no_sofire();
X#endif
X	standout();
X	fputs(str,stdout);
X	un_standout();
X	putchar('\n');
X    }
X    ELSE
X#endif
X#ifdef TERSE
X	putchar('.');
X#endif
X    fflush(stdout);
X}
X
Xbool kill_mentioned;
X
Xint
Xdo_kfile(kfp,entering)
XFILE *kfp;
Xint entering;
X{
X#ifdef USETHREADS
X    int i;
X    ART_NUM kill_thread;
X#endif
X
X    art = lastart+1;
X    fseek(kfp,0L,0);			/* rewind file */
X    while (fgets(buf,LBUFLEN,kfp) != Nullch) {
X	buf[strlen(buf)-1] = '\0';
X	if (strnEQ(buf,"THRU",4)) {
X	    ART_NUM tmpart;
X
X	    tmpart = atol(buf+4)+1;
X	    if (tmpart < absfirst)
X		tmpart = absfirst;
X	    check_first(tmpart);
X	    firstart = tmpart;
X	    continue;
X	}
X	if (*buf == 'X') {		/* exit command? */
X	    if (entering) {
X		exitcmds = TRUE;
X		continue;
X	    }
X	    strcpy(buf,buf+1);
X	}
X	else {
X	    if (!entering)
X		continue;
X	}
X	if (*buf == '&') {
X	    mention(buf);
X	    switcheroo();
X	}
X	else if (*buf == '/' && firstart <= lastart) {
X	    mention(buf);
X	    kill_mentioned = TRUE;
X	    switch (art_search(buf, (sizeof buf), FALSE)) {
X	    case SRCH_ABORT:
X		continue;
X	    case SRCH_INTR:
X#ifdef VERBOSE
X		IF(verbose)
X		    printf("\n(Interrupted at article %ld)\n",(long)art)
X		      FLUSH;
X		ELSE
X#endif
X#ifdef TERSE
X		    printf("\n(Intr at %ld)\n",(long)art) FLUSH;
X#endif
X		return -1;
X	    case SRCH_DONE:
X		break;
X	    case SRCH_SUBJDONE:
X		fputs("\tsubject not found (???)\n",stdout) FLUSH;
X		break;
X	    case SRCH_NOTFOUND:
X		fputs("\tnot found\n",stdout) FLUSH;
X		break;
X	    case SRCH_FOUND:
X		fputs("\tfound\n",stdout) FLUSH;
X	    }
X	}
X#ifdef USETHREADS
X	else if (*buf == 'T' && firstart <= lastart && p_roots) {
X	    /* kill a thread by its root id number */
X	    kill_thread = atol(buf+1);
X	    for (i = 0; i < total.root; i++) {
X		if (p_roots[i].root_num == kill_thread) {
X		    if (count_one_root(i) != 0) {
X			mention(buf);
X			kill_mentioned = TRUE;
X			printf("%ldx%d ",(long)kill_thread,
X					 root_article_cnts[i]);
X			p_art = p_articles + p_roots[i].articles;
X			art = p_art->num;
X			follow_thread('k');
X		    }
X		    break;
X		}
X	    }
X	}
X#endif
X    }
X
X    return 0;
X}
X
Xvoid
Xkill_unwanted(starting,message,entering)
XART_NUM starting;
Xchar *message;
Xint entering;
X{
X    bool intr = FALSE;			/* did we get an interrupt? */
X    ART_NUM oldfirst;
X    bool anytokill = (toread[ng] > 0);
X
X    if (localkfp || globkfp) {
X	if (!entering && !exitcmds)
X	    return;
X	exitcmds = FALSE;
X	oldfirst = firstart;
X	firstart = starting;
X	clear();
X#ifdef VERBOSE
X# ifdef TERSE
X	if (message && (verbose || entering))
X# else
X	if (message)
X# endif
X#else
X	if (message && entering)
X#endif
X	    fputs(message,stdout) FLUSH;
X
X	kill_mentioned = FALSE;
X	if (localkfp)
X	    intr = do_kfile(localkfp,entering);
X	if (globkfp && !intr)
X	    intr = do_kfile(globkfp,entering);
X	if (entering && localkfp && !intr)
X	    setthru(lastart);
X	putchar('\n') FLUSH;
X	if (entering && kill_mentioned)
X#ifdef VERBOSE
X	    IF(verbose)
X		get_anything();
X	    ELSE
X#endif
X#ifdef TERSE
X		pad(just_a_sec);
X#endif
X	if (anytokill)			/* if there was anything to kill */
X	    forcelast = FALSE;		/* allow for having killed it all */
X	firstart = oldfirst;
X    }
X}
X
Xvoid
Xsetthru(thru)
XART_NUM thru;
X{
X    FILE *newkfp;
X    bool no_kills = 0;
X#ifdef USETHREADS
X    int i;
X    ART_NUM kill_thread;
X#endif
X
X    fseek(localkfp,0L,0);		/* rewind current file */
X    if (fgets(buf,LBUFLEN,localkfp) != Nullch
X     && (strnNE(buf,"THRU",4) || fgets(buf,LBUFLEN,localkfp) != Nullch))
X	fseek(localkfp,0L,0);
X    else
X	no_kills = 1;
X    strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
X    UNLINK(buf);			/* to prevent file reuse */
X    if (no_kills)
X	open_kfile(KF_LOCAL);		/* close file and reset open flag */
X    else if (newkfp = fopen(buf,"w")) {
X	fprintf(newkfp,"THRU %ld\n",(long)thru);
X	while (fgets(buf,LBUFLEN,localkfp) != Nullch) {
X	    if (strnEQ(buf,"THRU",4))
X		continue;
X#ifdef USETHREADS
X	    /* Leave out any outdated thread kills */
X	    if (*buf == 'T' && p_roots) {
X		kill_thread = atol(buf+1);
X		for (i = 0; i < total.root; i++) {
X		    if (p_roots[i].root_num == kill_thread) {
X			break;
X		    }
X		}
X		if (i == total.root)
X		    continue;
X	    }
X#endif
X	    fputs(buf,newkfp);
X	}
X	fclose(newkfp);
X	open_kfile(KF_LOCAL);		/* and reopen local file */
X    }
X    else
X	printf(cantcreate,buf) FLUSH;
X}
X
X/* edit KILL file for newsgroup */
X
Xint
Xedit_kfile()
X{
X    int r = -1;
X
X    if (in_ng)
X	strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
X    else
X	strcpy(buf,filexp(getval("KILLGLOBAL",killglobal)));
X    if ((r = makedir(buf,MD_FILE)) >= 0) {
X	sprintf(cmd_buf,"%s %s",
X	    filexp(getval("VISUAL",getval("EDITOR",defeditor))),buf);
X	printf("\nEditing %s KILL file:\n%s\n",
X	    (in_ng?"local":"global"),cmd_buf) FLUSH;
X	resetty();			/* make sure tty is friendly */
X	r = doshell(sh,cmd_buf);/* invoke the shell */
X	noecho();			/* and make terminal */
X	crmode();			/*   unfriendly again */
X	open_kfile(in_ng);
X    }
X    else
X	printf("Can't make %s\n",buf) FLUSH;
X    return r;
X}
X
Xvoid
Xopen_kfile(local)
Xint local;
X{
X    char *kname = filexp(local ?
X	getval("KILLLOCAL",killlocal) :
X	getval("KILLGLOBAL",killglobal)
X	);
X    
X    stat(kname,&filestat);
X    if (!filestat.st_size)		/* nothing in the file? */
X	UNLINK(kname);			/* delete the file */
X    if (local) {
X	if (localkfp)
X	    fclose(localkfp);
X	localkfp = fopen(kname,"r");
X    }
X    else {
X	if (globkfp)
X	    fclose(globkfp);
X	globkfp = fopen(kname,"r");
X    }
X}
X
Xvoid
Xkf_append(cmd)
Xchar *cmd;
X{
X    strcpy(cmd_buf,filexp(getval("KILLLOCAL",killlocal)));
X    if (makedir(cmd_buf,MD_FILE) >= 0) {
X#ifdef VERBOSE
X	IF(verbose)
X	    printf("\nDepositing command in %s...",cmd_buf);
X	ELSE
X#endif
X#ifdef TERSE
X	    printf("\n--> %s...",cmd_buf);
X#endif
X	fflush(stdout);
X	sleep(2);
X	if ((tmpfp = fopen(cmd_buf,"a")) != Nullfp) {
X	    fseek(tmpfp,0L,2);		/* get to EOF for sure */
X	    fprintf(tmpfp,"%s\n",cmd);
X	    fclose(tmpfp);
X	    fputs("done\n",stdout) FLUSH;
X	}
X	else
X	    printf(cantopen,cmd_buf) FLUSH;
X    }
X}
X#endif /* KILLFILES */
END_OF_FILE
  if test 7167 -ne `wc -c <'kfile.c'`; then
    echo shar: \"'kfile.c'\" unpacked with wrong size!
  fi
  # end of 'kfile.c'
fi
if test -f 'mt-read.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mt-read.c'\"
else
  echo shar: Extracting \"'mt-read.c'\" \(12568 characters\)
  sed "s/^X//" >'mt-read.c' <<'END_OF_FILE'
X/* $Header: mt-read.c,v 4.3.3.1 90/07/24 23:51:12 davison Trn $
X**
X** $Log:	mt-read.c,v $
X** Revision 4.3.3.1  90/07/24  23:51:12  davison
X** Initial Trn Release
X** 
X*/
X
X#include "EXTERN.h"
X#include "common.h"
X#include "mthreads.h"
X
Xstatic FILE *fp_in;
X
Xvoid tweak_roots();
X
X/* Attempt to open the thread file.  If it's there, only grab the totals
X** from the start of the file.  This should give them enough information
X** to decide if they need to read the whole thing into memory.
X*/
Xint
Xinit_data( filename )
Xchar *filename;
X{
X    root_root = Null(ROOT*);
X    author_root = Null(AUTHOR*);
X    unk_domain.ids = Nullart;
X    unk_domain.link = Null(DOMAIN*);
X
X    if( (fp_in = fopen( filename, "r" )) == Nullfp ) {
X	bzero( &total, sizeof (TOTAL) );
X	return 0;
X    }
X    if( fread( &total, 1, sizeof (TOTAL), fp_in ) < sizeof (TOTAL) ) {
X	fclose( fp_in );
X	bzero( &total, sizeof (TOTAL) );
X	return 0;
X    }
X    return 1;
X}
X
X/* They want everything.  Read in the packed information and transform it
X** into a set of linked structures that is easily manipulated.
X*/
Xint
Xread_data()
X{
X    if( read_authors()
X     && read_subjects()
X     && read_roots()
X     && read_articles()
X     && read_ids() )
X    {
X	tweak_roots();
X	fclose( fp_in );
X	return 1;
X    }
X    /* Something failed.  Free takes care of checking if we're partially
X    ** allocated.  Any linked-list structures we created were freed before
X    ** we got here.
X    */
X    Free( &strings );
X    Free( &subject_cnts );
X    Free( &author_cnts );
X    Free( &root_array );
X    Free( &subject_array );
X    Free( &article_array );
X    Free( &ids );
X    fclose( fp_in );
X    return 0;
X}
X
X/* They don't want to read the data.  Close the file if we opened it.
X*/
Xvoid
Xdont_read_data( open_flag )
Xint open_flag;		/* 0 == not opened, 1 == open failed, 2 == open */
X{
X    if( open_flag == 2 ) {
X	fclose( fp_in );
X    }
X}
X
X#define give_string_to( dest )	/* Comment for makedepend to	 \
X				** ignore the backslash above */ \
X{\
X    register MEM_SIZE len = strlen( string_ptr ) + 1;\
X    dest = safemalloc( len );\
X    bcopy( string_ptr, dest, (int)len );\
X    string_ptr += len;\
X}
X
Xchar *subject_strings;
X
X/* The author information is an array of use-counts, followed by all the
X** null-terminated strings crammed together.  The subject strings are read
X** in at the same time, since they are appended to the end of the author
X** strings.
X*/
Xint
Xread_authors()
X{
X    register int count;
X    register char *string_ptr;
X    register WORD *authp;
X    register AUTHOR *author, *last_author, **author_ptr;
X
X    if( !read_item( &author_cnts, (MEM_SIZE)total.author * sizeof (WORD) )
X     || !read_item( &strings, total.string1 ) ) {
X	return 0;
X    }
X
X    /* We'll use this array to point each article at its proper author
X    ** (packed values are saved as indexes).
X    */
X    author_array = (AUTHOR**)safemalloc( total.author * sizeof (AUTHOR*) );
X    author_ptr = author_array;
X
X    authp = author_cnts;
X    string_ptr = strings;
X
X    last_author = Null(AUTHOR*);
X    for( count = total.author; count--; ) {
X	*author_ptr++ = author = (AUTHOR*)safemalloc( sizeof (AUTHOR) );
X	if( !last_author ) {
X	    author_root = author;
X	} else {
X	    last_author->link = author;
X	}
X	give_string_to( author->name );
X	author->count = *authp++;
X	last_author = author;
X    }
X    last_author->link = Null(AUTHOR*);
X
X    subject_strings = string_ptr;
X
X    free( author_cnts );
X    author_cnts = Null(WORD*);
X
X    return 1;
X}
X
X/* The subject values consist of the crammed-together null-terminated strings
X** (already read in above) and the use-count array.  They were saved in the
X** order that the roots will need when they are unpacked.
X*/
Xint
Xread_subjects()
X{
X    if( !read_item( &subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD) ) ) {
X	return 0;
X    }
X    return 1;
X}
X
X/* Read in the packed root structures and recreate the linked list versions,
X** processing each root's subjects as we go.  Defer interpretation of article
X** offsets until we unpack the article structures.
X*/
Xint
Xread_roots()
X{
X    register int count;
X    register char *string_ptr;
X    register WORD *subjp;
X    ROOT *root, *last_root, **root_ptr;
X    SUBJECT *subject, *last_subject, **subj_ptr;
X    int ret;
X
X    /* Use this array when unpacking the article's subject offsets. */
X    subject_array = (SUBJECT**)safemalloc( total.subject * sizeof (SUBJECT*) );
X    subj_ptr = subject_array;
X    /* And this array points the article's root offsets that the right spot. */
X    root_array = (ROOT**)safemalloc( total.root * sizeof (ROOT*) );
X    root_ptr = root_array;
X
X    subjp = subject_cnts;
X    string_ptr = subject_strings;
X
X#ifndef lint
X    last_root = (ROOT*)&root_root;
X#else
X    last_root = Null(ROOT*);
X#endif
X    for( count = total.root; count--; ) {
X	ret = fread( &p_root, 1, sizeof (PACKED_ROOT), fp_in );
X	if( ret != sizeof (PACKED_ROOT) ) {
X	    log_error( "failed root read --  %d bytes instead of %d.\n",
X		ret, sizeof (PACKED_ROOT) );
X	    ret = 0;
X	    /* Free the roots we've read so far and their subjects. */
X	    while( root_ptr != root_array ) {
X		free( *--root_ptr );
X	    }
X	    while( subj_ptr != subject_array ) {
X		free( (*--subj_ptr)->str );
X		free( *subj_ptr );
X	    }
X	    goto finish_up;
X	}
X	*root_ptr++ = root = (ROOT*)safemalloc( sizeof (ROOT) );
X	root->link = Null(ROOT*);
X	root->seq = p_root.articles;
X	root->root_num = p_root.root_num;
X	root->thread_cnt = p_root.thread_cnt;
X	root->subject_cnt = p_root.subject_cnt;
X	last_subject = Null(SUBJECT*);
X	while( p_root.subject_cnt-- ) {
X	    *subj_ptr++ = subject = (SUBJECT*)safemalloc( sizeof (SUBJECT) );
X	    if( !last_subject ) {
X		root->subjects = subject;
X	    } else {
X		last_subject->link = subject;
X	    }
X	    give_string_to( subject->str );
X	    subject->count = *subjp++;
X	    last_subject = subject;
X	}
X	last_subject->link = Null(SUBJECT*);
X	last_root->link = root;
X	last_root = root;
X    }
X    ret = 1;
X
X  finish_up:
X    free( subject_cnts );
X    free( strings );
X    subject_cnts = Null(WORD*);
X    strings = Nullch;
X
X    return ret;
X}
X
X/* A simple routine that checks the validity of the article's subject value.
X** A -1 means that it is NULL, otherwise it should be an offset into the
X** subject array we just unpacked.
X*/
XSUBJECT *
Xvalid_subject( num, art_num )
XWORD num;
Xlong art_num;
X{
X    if( num == -1 ) {
X	return Null(SUBJECT*);
X    }
X    if( num < 0 || num >= total.subject ) {
X	log_error( "Invalid subject in data file: %d [%ld]\n", num, art_num );
X	return Null(SUBJECT*);
X    }
X    return subject_array[num];
X}
X
X/* Ditto for author checking. */
XAUTHOR *
Xvalid_author( num, art_num )
XWORD num;
Xlong art_num;
X{
X    if( num == -1 ) {
X	return Null(AUTHOR*);
X    }
X    if( num < 0 || num >= total.author ) {
X	log_error( "Invalid author in data file: %d [%ld]\n", num, art_num );
X	return Null(AUTHOR*);
X    }
X    return author_array[num];
X}
X
X/* Our parent/sibling information is a relative offset in the article array.
X** zero for none.  Child values are always found in the very next array
X** element if child_cnt is non-zero.
X*/
X#define valid_node( rel, num ) (!(rel)? Nullart : article_array[(rel)+(num)])
X
X/* Read the articles into their linked lists.  Point everything everywhere. */
Xint
Xread_articles()
X{
X    register int count;
X    register ARTICLE *article, **article_ptr;
X    int ret;
X
X    /* Build an array to interpret interlinkages of articles. */
X    article_array = (ARTICLE**)safemalloc( total.article * sizeof (ARTICLE*) );
X    article_ptr = article_array;
X
X    /* Allocate all the structures up-front so that we can point to un-read
X    ** siblings as we go.
X    */
X    for( count = total.article; count--; ) {
X	*article_ptr++ = (ARTICLE*)safemalloc( sizeof (ARTICLE) );
X    }
X    article_ptr = article_array;
X    for( count = 0; count < total.article; count++ ) {
X	ret = fread( &p_article, 1, sizeof (PACKED_ARTICLE), fp_in );
X	if( ret != sizeof (PACKED_ARTICLE) ) {
X	    log_error( "failed article read --  %d bytes instead of %d.\n", ret, sizeof (PACKED_ARTICLE) );
X	    ret = 0;
X	    goto finish_up;
X	}
X	article = *article_ptr++;
X	article->num = p_article.num;
X	article->date = p_article.date;
X	article->subject = valid_subject( p_article.subject, p_article.num );
X	article->author = valid_author( p_article.author, p_article.num );
X	article->flags = p_article.flags;
X	article->child_cnt = p_article.child_cnt;
X	article->parent = valid_node( p_article.parent, count );
X	article->children = article->child_cnt?article_array[count+1]:Nullart;
X	article->siblings = valid_node( p_article.siblings, count );
X	article->root = root_array[p_article.root];
X    }
X    ret = 1;
X
X  finish_up:
X    /* We're done with most of the pointer arrays. */
X    free( root_array );
X    free( subject_array );
X    free( author_array );
X    root_array = Null(ROOT**);
X    subject_array = Null(SUBJECT**);
X    author_array = Null(AUTHOR**);
X
X    return ret;
X}
X
X/* Read the message-id strings and attach them to each article.  The data
X** format consists of the mushed-together null-terminated strings (a domain
X** name followed by all its unique-id prefixes) and then the article offsets
X** to which they belong.  The first domain name was omitted, as it is the
X** ".unknown." domain for those truly weird message-id's without '@'s.
X*/
Xint
Xread_ids()
X{
X    register DOMAIN *domain, *last;
X    register ARTICLE *article;
X    register char *string_ptr;
X    register int i, count;
X
X    if( !read_item( &strings, total.string2 ) ) {
X	return 0;
X    }
X    if( !read_item( &ids,
X		(MEM_SIZE)(total.article+total.domain+1) * sizeof (WORD) ) ) {
X	return 0;
X    }
X    string_ptr = strings;
X
X    last = Null(DOMAIN*);
X    for( i = 0, count = total.domain + 1; count--; i++ ) {
X	if( i ) {
X	    domain = (DOMAIN*)safemalloc( sizeof (DOMAIN) );
X	    give_string_to( domain->name );
X	} else {
X	    domain = &unk_domain;
X	}
X	if( ids[i] == -1 ) {
X	    domain->ids = Nullart;
X	} else {
X	    article = article_array[ids[i]];
X	    domain->ids = article;
X	    for( ;; ) {
X		give_string_to( article->id );
X		article->domain = domain;
X		if( ids[++i] != -1 ) {
X		    article = article->id_link = article_array[ids[i]];
X		} else {
X		    article->id_link = Nullart;
X		    break;
X		}
X	    }
X	}
X	if( last ) {
X	    last->link = domain;
X	}
X	last = domain;
X    }
X    last->link = Null(DOMAIN*);
X    free( ids );
X    free( strings );
X    ids = Null(WORD*);
X    strings = Nullch;
X
X    return 1;
X}
X
X/* And finally, point all the roots at their root articles and get rid
X** of anything left over that was used to aid our unpacking.
X*/
Xvoid
Xtweak_roots()
X{
X    register ROOT *root;
X
X    for( root = root_root; root; root = root->link ) {
X	root->articles = article_array[root->seq];
X    }
X    free( article_array );
X    article_array = Null(ARTICLE**);
X}
X
X/* A short-hand for reading a chunk of the file into a malloc'ed array.
X*/
Xint
Xread_item( dest, len )
Xchar **dest;
XMEM_SIZE len;
X{
X    int ret;
X
X    *dest = safemalloc( len );
X    ret = fread( *dest, 1, (int)len, fp_in );
X    if( ret != len ) {
X	log_error( "Only read %ld bytes instead of %ld.\n",
X		(long)ret, (long)len );
X	free( *dest );
X	*dest = Nullch;
X	return 0;
X    }
X    return 1;
X}
X
X/* Interpret rn's '%X' and '%x' path prefixes without including all their
X** source.  Names that don't start with '%' or '/' are prefixed with the
X** SPOOL directory.
X*/
Xchar *
Xfile_exp( name )
Xchar *name;
X{
X    static char name_buff[256];
X
X    if( *name == '/' ) {	/* fully qualified names are left alone */
X	return name;
X    } else if( *name != '%' ) {	/* all normal names are relative to SPOOL */
X	sprintf( name_buff, "%s/%s", SPOOL, name );
X    } else {			/* interpret %x (LIB) & %X (RNLIB) */
X	if( name[1] == 'x' ) {
X	    strcpy( name_buff, LIB );
X	} else if( name[1] == 'X' ) {
X	    strcpy( name_buff, RNLIB );
X	} else {
X	    log_entry( "Unknown expansion: %s", name );
X	    exit( 1 );
X	}
X	strcat( name_buff, name+2 );
X    }
X    return name_buff;
X}
X
X#ifndef lint
X/* A malloc that bombs-out when memory is exhausted. */
Xchar *
Xsafemalloc( amount )
XMEM_SIZE amount;
X{
X    register char *cp;
X    extern char *malloc();
X
X    if( (cp = malloc( amount )) == Nullch ) {
X	log_error( "malloc(%ld) failed.\n", (long)amount );
X	exit( 1 );
X    }
X    return cp;
X}
X#endif
X
X/* Create a malloc'ed copy of a string. */
Xchar *
Xsavestr( str )
Xchar *str;
X{
X    register MEM_SIZE len = strlen( str ) + 1;
X    register char *newaddr = safemalloc( len );
X
X    bcopy( str, newaddr, (int)len );
X
X    return newaddr;
X}
X
X#ifndef lint
X/* Free some memory if it hasn't already been freed. */
Xvoid
XFree( pp )
Xchar **pp;
X{
X    if( *pp ) {
X	free( *pp );
X	*pp = Nullch;
X    }
X}
X#endif
END_OF_FILE
  if test 12568 -ne `wc -c <'mt-read.c'`; then
    echo shar: \"'mt-read.c'\" unpacked with wrong size!
  fi
  # end of 'mt-read.c'
fi
if test -f 'patchlevel' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel'\"
else
  echo shar: Extracting \"'patchlevel'\" \(11 characters\)
  sed "s/^X//" >'patchlevel' <<'END_OF_FILE'
XTrn v1.0.1
END_OF_FILE
  if test 11 -ne `wc -c <'patchlevel'`; then
    echo shar: \"'patchlevel'\" unpacked with wrong size!
  fi
  # end of 'patchlevel'
fi
if test -f 'search.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'search.c'\"
else
  echo shar: Extracting \"'search.c'\" \(13460 characters\)
  sed "s/^X//" >'search.c' <<'END_OF_FILE'
X/* $Header: search.c,v 4.3.2.2 90/03/22 23:05:31 sob Exp $
X *
X * $Log:	search.c,v $
X * Revision 4.3.2.2  90/03/22  23:05:31  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.2.1  90/03/17  17:46:29  sob
X * Added changes to insure that null search strings won't result in core dumps
X * on non-VAX computers.
X * 
X * Revision 4.3  85/05/01  11:50:16  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X/* string search routines */
X 
X/*		Copyright (c) 1981,1980 James Gosling		*/
X 
X/* Modified Aug. 12, 1981 by Tom London to include regular expressions
X   as in ed.  RE stuff hacked over by jag to correct a few major problems,
X   mainly dealing with searching within the buffer rather than copying
X   each line to a separate array.  Newlines can now appear in RE's */
X
X/* Ripped to shreds and glued back together to make a search package,
X * July 6, 1984, by Larry Wall. (If it doesn't work, it's probably my fault.)
X * Changes include:
X *	Buffer, window, and mlisp stuff gone.
X *	Translation tables reduced to 1 table.
X *	Expression buffer is now dynamically allocated.
X *	Character classes now implemented with a bitmap.
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "util.h"
X#include "INTERN.h"
X#include "search.h"
X
X#ifndef BITSPERBYTE
X#define BITSPERBYTE 8
X#endif
X
X#define BMAPSIZ (127 / BITSPERBYTE + 1)
X
X/* meta characters in the "compiled" form of a regular expression */
X#define	CBRA	2		/* \( -- begin bracket */
X#define	CCHR	4		/* a vanilla character */
X#define	CDOT	6		/* . -- match anything except a newline */
X#define	CCL	8		/* [...] -- character class */
X#define	NCCL	10		/* [^...] -- negated character class */
X#define	CDOL	12		/* $ -- matches the end of a line */
X#define	CEND	14		/* The end of the pattern */
X#define	CKET	16		/* \) -- close bracket */
X#define	CBACK	18		/* \N -- backreference to the Nth bracketed
X				   string */
X#define CIRC	20		/* ^ matches the beginning of a line */
X
X#define WORD	32		/* matches word character \w */
X#define NWORD	34		/* matches non-word characer \W */
X#define WBOUND	36		/* matches word boundary \b */
X#define NWBOUND	38		/* matches non-(word boundary) \B */
X 
X#define	STAR	01		/* * -- Kleene star, repeats the previous
X				   REas many times as possible; the value
X				   ORs with the other operator types */
X 
X#define ASCSIZ 0200
Xtypedef char	TRANSTABLE[ASCSIZ];
X
Xstatic	TRANSTABLE trans = {
X0000,0001,0002,0003,0004,0005,0006,0007,
X0010,0011,0012,0013,0014,0015,0016,0017,
X0020,0021,0022,0023,0024,0025,0026,0027,
X0030,0031,0032,0033,0034,0035,0036,0037,
X0040,0041,0042,0043,0044,0045,0046,0047,
X0050,0051,0052,0053,0054,0055,0056,0057,
X0060,0061,0062,0063,0064,0065,0066,0067,
X0070,0071,0072,0073,0074,0075,0076,0077,
X0100,0101,0102,0103,0104,0105,0106,0107,
X0110,0111,0112,0113,0114,0115,0116,0117,
X0120,0121,0122,0123,0124,0125,0126,0127,
X0130,0131,0132,0133,0134,0135,0136,0137,
X0140,0141,0142,0143,0144,0145,0146,0147,
X0150,0151,0152,0153,0154,0155,0156,0157,
X0160,0161,0162,0163,0164,0165,0166,0167,
X0170,0171,0172,0173,0174,0175,0176,0177,
X};
Xstatic bool folding = FALSE;
X
Xstatic int err;
Xstatic char *FirstCharacter;
X
Xvoid
Xsearch_init()
X{
X#ifdef UNDEF
X    register int    i;
X    
X    for (i = 0; i < ASCSIZ; i++)
X	trans[i] = i;
X#else
X    ;
X#endif
X}
X
Xvoid
Xinit_compex(compex)
Xregister COMPEX *compex;
X{
X    /* the following must start off zeroed */
X
X    compex->eblen = 0;
X    compex->brastr = Nullch;
X}
X
Xvoid
Xfree_compex(compex)
Xregister COMPEX *compex;
X{
X    if (compex->eblen) {
X	free(compex->expbuf);
X	compex->eblen = 0;
X    }
X    if (compex->brastr) {
X	free(compex->brastr);
X	compex->brastr = Nullch;
X    }
X}
X
Xstatic char *gbr_str = Nullch;
Xstatic int gbr_siz = 0;
X
Xchar *
Xgetbracket(compex,n)
Xregister COMPEX *compex;
Xint n;
X{
X    int length = compex->braelist[n] - compex->braslist[n];
X
X    if (!compex->nbra || n > compex->nbra || !compex->braelist[n] || length<0)
X	return nullstr;
X    growstr(&gbr_str, &gbr_siz, length+1);
X    safecpy(gbr_str, compex->braslist[n], length+1);
X    return gbr_str;
X}
X
Xvoid
Xcase_fold(which)
Xint which;
X{
X    register int i;
X
X    if (which != folding) {
X	if (which) {
X	    for (i = 'A'; i <= 'Z'; i++)
X		trans[i] = tolower(i);
X	}
X	else {
X	    for (i = 'A'; i <= 'Z'; i++)
X		trans[i] = i;
X	}
X	folding = which;
X    }
X}
X
X/* Compile the given regular expression into a [secret] internal format */
X
Xchar *
Xcompile (compex, strp, RE, fold)
Xregister COMPEX *compex;
Xregister char   *strp;
Xint RE;
Xint fold;
X{
X    register int c;
X    register char  *ep;
X    char   *lastep;
X    char    bracket[NBRA],
X	   *bracketp;
X    char **alt = compex->alternatives;
X    char *retmes = "Badly formed search string";
X 
X    case_fold(compex->do_folding = fold);
X    if (!compex->eblen) {
X	compex->expbuf = safemalloc(84);
X	compex->eblen = 80;
X    }
X    ep = compex->expbuf;		/* point at expression buffer */
X    *alt++ = ep;			/* first alternative starts here */
X    bracketp = bracket;			/* first bracket goes here */
X    if (*strp == 0) {			/* nothing to compile? */
X	if (*ep == 0)			/* nothing there yet? */
X	    return "Null search string";
X	return Nullch;			/* just keep old expression */
X    }
X    compex->nbra = 0;			/* no brackets yet */
X    lastep = 0;
X    for (;;) {
X	if (ep - compex->expbuf >= compex->eblen)
X	    grow_eb(compex);
X	c = *strp++;			/* fetch next char of pattern */
X	if (c == 0) {			/* end of pattern? */
X	    if (bracketp != bracket) {	/* balanced brackets? */
X#ifdef VERBOSE
X		retmes = "Unbalanced parens";
X#endif
X		goto cerror;
X	    }
X	    *ep++ = CEND;		/* terminate expression */
X	    *alt++ = 0;			/* terminal alternative list */
X	    /*
X	    compex->eblen = ep - compex->expbuf + 1;
X	    compex->expbuf = saferealloc(compex->expbuf,compex->eblen+4); */
X	    return Nullch;		/* return success */
X	}
X	if (c != '*')
X	    lastep = ep;
X	if (!RE) {			/* just a normal search string? */
X	    *ep++ = CCHR;		/* everything is a normal char */
X	    *ep++ = c;
X	}
X	else				/* it is a regular expression */
X	    switch (c) {
X 
X		case '\\':		/* meta something */
X		    switch (c = *strp++) {
X		    case '(':
X			if (compex->nbra >= NBRA) {
X#ifdef VERBOSE
X			    retmes = "Too many parens";
X#endif
X			    goto cerror;
X			}
X			*bracketp++ = ++compex->nbra;
X			*ep++ = CBRA;
X			*ep++ = compex->nbra;
X			break;
X		    case '|':
X			if (bracketp>bracket) {
X#ifdef VERBOSE
X			    retmes = "No \\| in parens";	/* Alas! */
X#endif
X			    goto cerror;
X			}
X			*ep++ = CEND;
X			*alt++ = ep;
X			break;
X		    case ')':
X			if (bracketp <= bracket) {
X#ifdef VERBOSE
X			    retmes = "Unmatched right paren";
X#endif
X			    goto cerror;
X			}
X			*ep++ = CKET;
X			*ep++ = *--bracketp;
X			break;
X		    case 'w':
X			*ep++ = WORD;
X			break;
X		    case 'W':
X			*ep++ = NWORD;
X			break;
X		    case 'b':
X			*ep++ = WBOUND;
X			break;
X		    case 'B':
X			*ep++ = NWBOUND;
X			break;
X		    case '0': case '1': case '2': case '3': case '4':
X		    case '5': case '6': case '7': case '8': case '9':
X			*ep++ = CBACK;
X			*ep++ = c - '0';
X			break;
X		    default:
X			*ep++ = CCHR;
X			if (c == '\0')
X			    goto cerror;
X			*ep++ = c;
X			break;
X		    }
X		    break;
X		case '.':
X		    *ep++ = CDOT;
X		    continue;
X 
X		case '*':
X		    if (lastep == 0 || *lastep == CBRA || *lastep == CKET
X			|| *lastep == CIRC
X			|| (*lastep&STAR)|| *lastep>NWORD)
X			goto defchar;
X		    *lastep |= STAR;
X		    continue;
X 
X		case '^':
X		    if (ep != compex->expbuf && ep[-1] != CEND)
X			goto defchar;
X		    *ep++ = CIRC;
X		    continue;
X 
X		case '$':
X		    if (*strp != 0 && (*strp != '\\' || strp[1] != '|'))
X			goto defchar;
X		    *ep++ = CDOL;
X		    continue;
X 
X		case '[': {		/* character class */
X		    register int i;
X		    
X		    if (ep - compex->expbuf >= compex->eblen - BMAPSIZ)
X			grow_eb(compex);	/* reserve bitmap */
X		    for (i = BMAPSIZ; i; --i)
X			ep[i] = 0;
X		    
X		    if ((c = *strp++) == '^') {
X			c = *strp++;
X			*ep++ = NCCL;	/* negated */
X		    }
X		    else
X			*ep++ = CCL;	/* normal */
X		    
X		    i = 0;		/* remember oldchar */
X		    do {
X			if (c == '\0') {
X#ifdef VERBOSE
X			    retmes = "Missing ]";
X#endif
X			    goto cerror;
X			}
X			if (*strp == '-' && *(++strp))
X			    i = *strp++;
X			else
X			    i = c;
X			while (c <= i) {
X			    ep[c / BITSPERBYTE] |= 1 << (c % BITSPERBYTE);
X			    if (fold && isalpha(c))
X				ep[(c ^ 32) / BITSPERBYTE] |=
X				    1 << ((c ^ 32) % BITSPERBYTE);
X					/* set the other bit too */
X			    c++;
X			}
X		    } while ((c = *strp++) != ']');
X		    ep += BMAPSIZ;
X		    continue;
X		}
X 
X	    defchar:
X		default:
X		    *ep++ = CCHR;
X		    *ep++ = c;
X	    }
X    }
Xcerror:
X    compex->expbuf[0] = 0;
X    compex->nbra = 0;
X    return retmes;
X}
X
Xvoid
Xgrow_eb(compex)
Xregister COMPEX *compex;
X{
X    compex->eblen += 80;
X    compex->expbuf = saferealloc(compex->expbuf, (MEM_SIZE)compex->eblen + 4);
X}
X
Xchar *
Xexecute (compex, addr)
Xregister COMPEX *compex;
Xchar *addr;
X{
X    register char *p1 = addr;
X    register char *trt = trans;
X    register int c;
X 
X    if (addr == Nullch || compex->expbuf == Nullch)
X	return Nullch;
X    if (compex->nbra) {			/* any brackets? */
X	for (c = 0; c <= compex->nbra; c++)
X	    compex->braslist[c] = compex->braelist[c] = Nullch;
X	if (compex->brastr)
X	    free(compex->brastr);
X	compex->brastr = savestr(p1);	/* in case p1 is not static */
X	p1 = compex->brastr;		/* ! */
X    }
X    case_fold(compex->do_folding);	/* make sure table is correct */
X    FirstCharacter = p1;		/* for ^ tests */
X    if (compex->expbuf[0] == CCHR && !compex->alternatives[1]) {
X	c = trt[compex->expbuf[1]];	/* fast check for first character */
X	do {
X	    if (trt[*p1] == c && advance (compex, p1, compex->expbuf))
X		return p1;
X	    p1++;
X	} while (*p1 && !err);
X	return Nullch;
X    }
X    else {			/* regular algorithm */
X	do {
X	    register char **alt = compex->alternatives;
X	    while (*alt) {
X		if (advance (compex, p1, *alt++))
X		    return p1;
X	    }
X	    p1++;
X	} while (*p1 && !err);
X	return Nullch;
X    }
X}
X 
X/* advance the match of the regular expression starting at ep along the
X   string lp, simulates an NDFSA */
Xbool
Xadvance (compex, lp, ep)
Xregister COMPEX *compex;
Xregister char *ep;
Xregister char *lp;
X{
X    register char *curlp;
X    register char *trt = trans;
X    register int i;
X 
X    while ((*ep & STAR) || *lp || *ep == CIRC || *ep == CKET)
X	switch (*ep++) {
X 
X	    case CCHR:
X		if (trt[*ep++] != trt[*lp]) return FALSE;
X		lp++;
X		continue;
X 
X	    case CDOT:
X		if (*lp == '\n') return FALSE;
X		lp++;
X		continue;
X 
X	    case CDOL:
X		if (!*lp || *lp == '\n')
X		    continue;
X		return FALSE;
X 
X	    case CIRC:
X		if (lp == FirstCharacter || lp[-1]=='\n')
X		    continue;
X		return FALSE;
X 
X	    case WORD:
X		if (isalnum(*lp)) {
X		    lp++;
X		    continue;
X		}
X		return FALSE;
X 
X	    case NWORD:
X		if (!isalnum(*lp)) {
X		    lp++;
X		    continue;
X		}
X		return FALSE;
X 
X	    case WBOUND:
X		if ((lp == FirstCharacter || !isalnum(lp[-1])) !=
X			(!*lp || !isalnum(*lp)) )
X		    continue;
X		return FALSE;
X 
X	    case NWBOUND:
X		if ((lp == FirstCharacter || !isalnum(lp[-1])) ==
X			(!*lp || !isalnum(*lp)))
X		    continue;
X		return FALSE;
X 
X	    case CEND:
X		return TRUE;
X 
X	    case CCL:
X		if (cclass (ep, *lp, 1)) {
X		    ep += BMAPSIZ;
X		    lp++;
X		    continue;
X		}
X		return FALSE;
X 
X	    case NCCL:
X		if (cclass (ep, *lp, 0)) {
X		    ep += BMAPSIZ;
X		    lp++;
X		    continue;
X		}
X		return FALSE;
X 
X	    case CBRA:
X		compex->braslist[*ep++] = lp;
X		continue;
X 
X	    case CKET:
X		i = *ep++;
X		compex->braelist[i] = lp;
X		compex->braelist[0] = lp;
X		compex->braslist[0] = compex->braslist[i];
X		continue;
X 
X	    case CBACK:
X		if (compex->braelist[i = *ep++] == 0) {
X		    fputs("bad braces\n",stdout) FLUSH;
X		    err = TRUE;
X		    return FALSE;
X		}
X		if (backref (compex, i, lp)) {
X		    lp += compex->braelist[i] - compex->braslist[i];
X		    continue;
X		}
X		return FALSE;
X 
X	    case CBACK | STAR:
X		if (compex->braelist[i = *ep++] == 0) {
X		    fputs("bad braces\n",stdout) FLUSH;
X		    err = TRUE;
X		    return FALSE;
X		}
X		curlp = lp;
X		while (backref (compex, i, lp)) {
X		    lp += compex->braelist[i] - compex->braslist[i];
X		}
X		while (lp >= curlp) {
X		    if (advance (compex, lp, ep))
X			return TRUE;
X		    lp -= compex->braelist[i] - compex->braslist[i];
X		}
X		continue;
X 
X	    case CDOT | STAR:
X		curlp = lp;
X		while (*lp++ && lp[-1] != '\n');
X		goto star;
X 
X	    case WORD | STAR:
X		curlp = lp;
X		while (*lp++ && isalnum(lp[-1]));
X		goto star;
X 
X	    case NWORD | STAR:
X		curlp = lp;
X		while (*lp++ && !isalnum(lp[-1]));
X		goto star;
X 
X	    case CCHR | STAR:
X		curlp = lp;
X		while (*lp++ && trt[lp[-1]] == trt[*ep]);
X		ep++;
X		goto star;
X 
X	    case CCL | STAR:
X	    case NCCL | STAR:
X		curlp = lp;
X		while (*lp++ && cclass (ep, lp[-1], ep[-1] == (CCL | STAR)));
X		ep += BMAPSIZ;
X		goto star;
X 
X	star:
X		do {
X		    lp--;
X		    if (advance (compex, lp, ep))
X			return TRUE;
X		} while (lp > curlp);
X		return FALSE;
X 
X	    default:
X		fputs("Badly compiled pattern\n",stdout) FLUSH;
X		err = TRUE;
X		return -1;
X	}
X	if (*ep == CEND || *ep == CDOL) {
X	    return TRUE;
X    }
X    return FALSE;
X}
X 
Xbool
Xbackref (compex, i, lp)
Xregister COMPEX *compex;
Xregister int i;
Xregister char *lp;
X{
X    register char *bp;
X 
X    bp = compex->braslist[i];
X    while (*lp && *bp == *lp) {
X	bp++;
X	lp++;
X	if (bp >= compex->braelist[i])
X	    return TRUE;
X    }
X    return FALSE;
X}
X
Xbool
Xcclass (set, c, af)
Xregister char  *set;
Xregister int c;
X{
X    c &= 0177;
X#if BITSPERBYTE == 8
X    if (set[c >> 3] & 1 << (c & 7))
X#else
X    if (set[c / BITSPERBYTE] & 1 << (c % BITSPERBYTE))
X#endif
X	return af;
X    return !af;
X}
END_OF_FILE
  if test 13460 -ne `wc -c <'search.c'`; then
    echo shar: \"'search.c'\" unpacked with wrong size!
  fi
  # end of 'search.c'
fi
echo shar: End of archive 10 \(of 14\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 14 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list