POSIX/SVID/X3J11 standard routines (libposix.a) (Part 4 of 5)

Lenny Tropiano lenny at icus.islp.ny.us
Thu Aug 3 11:53:09 AEST 1989



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 5)."
# Contents:  getdents.c string.3 tsearch.3c
# Wrapped by lenny at icus on Wed Aug  2 21:40:33 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f getdents.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"getdents.c\"
else
echo shar: Extracting \"getdents.c\" \(8062 characters\)
sed "s/^X//" >getdents.c <<'END_OF_getdents.c'
X/*
X	getdents -- get directory entries in a file system independent format
X			(SVR3 system call emulation)
X
X	last edit:	15-Feb-1988	D A Gwyn
X
X	This single source file supports several different methods of
X	getting directory entries from the operating system.  Define
X	whichever one of the following describes your system:
X
X	UFS	original UNIX filesystem (14-character name limit)
X	BFS	4.2BSD (also 4.3BSD) native filesystem (long names)
X	NFS	getdirentries() system call
X
X	Also define any of the following that are pertinent:
X
X	ATT_SPEC	check user buffer address for longword alignment
X	BSD_SYSV	BRL UNIX System V emulation environment on 4.nBSD
X	UNK		have _getdents() system call, but kernel may not
X			support it
X      UW_NFS          You are running an NFS filesystem with an
X                      underlying 4.2 BSD filesystem.  This is true
X                      in particular if you running the NFS port from
X                      the University of Wisconsin.
X
X	If your C library has a getdents() system call interface, but you
X	can't count on all kernels on which your application binaries may
X	run to support it, change the system call interface name to
X	_getdents() and define "UNK" to enable the system-call validity
X	test in this "wrapper" around _getdents().
X
X	If your system has a getdents() system call that is guaranteed 
X	to always work, you shouldn't be using this source file at all.
X*/
X
X#define UFS
X#define ATT_SPEC
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#ifdef BSD_SYSV
X#include	<sys/_dir.h>		/* BSD flavor, not System V */
X#else
X#include	<sys/dir.h>
X#undef	MAXNAMLEN			/* avoid conflict with SVR3 */
X	/* Good thing we don't need to use the DIRSIZ() macro! */
X#ifdef d_ino				/* 4.3BSD/NFS using d_fileno */
X#undef	d_ino				/* (not absolutely necessary) */
X#else
X#define	d_fileno	d_ino		/* (struct direct) member */
X#endif
X#endif
X#include	<sys/dirent.h>
X#include	<sys/stat.h>
X#ifdef UNK
X#ifndef UFS
X#include "***** ERROR ***** UNK applies only to UFS"
X/* One could do something similar for getdirentries(), but I didn't bother. */
X#endif
X#include	<signal.h>
X#endif
X
X#if defined(UFS) + defined(BFS) + defined(NFS) != 1	/* sanity check */
X#include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined"
X#endif
X
X#ifdef BSD_SYSV
Xstruct dirent	__dirent;		/* (just for the DIRENTBASESIZ macro) */
X#endif
X
X#ifdef UFS
X#define	RecLen( dp )	(sizeof(struct direct))	/* fixed-length entries */
X#else	/* BFS || NFS */
X#define	RecLen( dp )	((dp)->d_reclen)	/* variable-length entries */
X#endif
X
X#ifdef NFS
X#ifdef BSD_SYSV
X#define	getdirentries	_getdirentries	/* package hides this system call */
X#endif
Xextern int	getdirentries();
Xstatic long	dummy;			/* getdirentries() needs basep */
X#define	GetBlock( fd, buf, n )	getdirentries( fd, buf, (unsigned)n, &dummy )
X#else	/* UFS || BFS */
X#ifdef BSD_SYSV
X#define read	_read			/* avoid emulation overhead */
X#endif
Xextern int	read();
X#define	GetBlock( fd, buf, n )	read( fd, buf, (unsigned)n )
X#endif
X
X#ifdef UNK
Xextern int	_getdents();		/* actual system call */
X#endif
X
Xextern char	*strncpy();
Xextern int	fstat();
Xextern off_t	lseek();
X
Xextern int	errno;
X
X#ifndef DIRBLKSIZ
X#define	DIRBLKSIZ	4096		/* directory file read buffer size */
X#endif
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
X#ifndef SEEK_CUR
X#define	SEEK_CUR	1
X#endif
X
X#ifndef S_ISDIR				/* macro to test for directory file */
X#define	S_ISDIR( mode )		(((mode) & S_IFMT) == S_IFDIR)
X#endif
X
X#ifdef UFS
X
X/*
X	The following routine is necessary to handle DIRSIZ-long entry names.
X	Thanks to Richard Todd for pointing this out.
X*/
X
Xstatic int
XNameLen( name )				/* return # chars in embedded name */
X	char		name[];		/* -> name embedded in struct direct */
X	{
X	register char	*s;		/* -> name[.] */
X	register char	*stop = &name[DIRSIZ];	/* -> past end of name field */
X
X	for ( s = &name[1];		/* (empty names are impossible) */
X	      *s != '\0'		/* not NUL terminator */
X	   && ++s < stop;		/* < DIRSIZ characters scanned */
X	    )
X		;
X
X	return s - name;		/* # valid characters in name */
X	}
X
X#else	/* BFS || NFS */
X
Xextern int	strlen();
X
X#define	NameLen( name )	strlen( name )	/* names are always NUL-terminated */
X
X#endif
X
X#ifdef UNK
Xstatic enum	{ maybe, no, yes }	state = maybe;
X					/* does _getdents() work? */
X
X/*ARGSUSED*/
Xstatic void
Xsig_catch( sig )
X	int	sig;			/* must be SIGSYS */
X	{
X	state = no;			/* attempted _getdents() faulted */
X	}
X#endif
X
Xint
Xgetdents( fildes, buf, nbyte )		/* returns # bytes read;
X					   0 on EOF, -1 on error */
X	int			fildes;	/* directory file descriptor */
X	char			*buf;	/* where to put the (struct dirent)s */
X	unsigned		nbyte;	/* size of buf[] */
X	{
X	int			serrno;	/* entry errno */
X	off_t			offset;	/* initial directory file offset */
X	struct stat		statb;	/* fstat() info */
X	union	{
X		char		dblk[DIRBLKSIZ
X#ifdef UFS
X				     +1	/* for last entry name terminator */
X#endif
X				    ];
X					/* directory file block buffer */
X		struct direct	dummy;	/* just for alignment */
X		}	u;		/* (avoids having to malloc()) */
X	register struct direct	*dp;	/* -> u.dblk[.] */
X	register struct dirent	*bp;	/* -> buf[.] */
X
X#ifdef UNK
X	switch ( state )
X		{
X		void		(*shdlr)();	/* entry SIGSYS handler */
X		register int	retval;	/* return from _getdents() if any */
X
X	case yes:			/* _getdents() is known to work */
X		return _getdents( fildes, buf, nbyte );
X
X	case maybe:			/* first time only */
X		shdlr = signal( SIGSYS, sig_catch );
X		retval = _getdents( fildes, buf, nbyte );	/* try it */
X		(void)signal( SIGSYS, shdlr );
X
X		if ( state == maybe )	/* SIGSYS did not occur */
X			{
X			state = yes;	/* so _getdents() must have worked */
X			return retval;
X			}
X		/* else fall through into emulation */
X
X/*	case no:	/* fall through into emulation */
X		}
X#endif
X
X	if ( buf == NULL
X#ifdef ATT_SPEC
X	  || (unsigned long)buf % sizeof(long) != 0	/* ugh */
X#endif
X	   )	{
X		errno = EFAULT;		/* invalid pointer */
X		return -1;
X		}
X
X	if ( fstat( fildes, &statb ) != 0 )
X		return -1;		/* errno set by fstat() */
X
X	if ( !S_ISDIR( statb.st_mode ) )
X		{
X		errno = ENOTDIR;	/* not a directory */
X		return -1;
X		}
X
X	if ( (offset = lseek( fildes, (off_t)0, SEEK_CUR )) < 0 )
X		return -1;		/* errno set by lseek() */
X
X#ifdef BFS				/* no telling what remote hosts do */
X	if ( (unsigned long)offset % DIRBLKSIZ != 0 )
X		{
X		errno = ENOENT;		/* file pointer probably misaligned */
X		return -1;
X		}
X#endif
X
X	serrno = errno;			/* save entry errno */
X
X	for ( bp = (struct dirent *)buf; bp == (struct dirent *)buf; )
X		{			/* convert next directory block */
X		int	size;
X
X		do	size = GetBlock( fildes, u.dblk, DIRBLKSIZ );
X		while ( size == -1 && errno == EINTR );
X
X		if ( size <= 0 )
X			return size;	/* EOF or error (EBADF) */
X
X		for ( dp = (struct direct *)u.dblk;
X		      (char *)dp < &u.dblk[size];
X		      dp = (struct direct *)((char *)dp + RecLen( dp ))
X		    )	{
X#ifndef UFS
X			if ( dp->d_reclen <= 0 )
X				{
X				errno = EIO;	/* corrupted directory */
X				return -1;
X				}
X#endif
X
X			if ( dp->d_fileno != 0 )
X				{	/* non-empty; copy to user buffer */
X				register int	reclen =
X					DIRENTSIZ( NameLen( dp->d_name ) );
X
X				if ( (char *)bp + reclen > &buf[nbyte] )
X					{
X					errno = EINVAL;
X					return -1;	/* buf too small */
X					}
X
X				bp->d_ino = dp->d_fileno;
X				bp->d_off = offset + ((char *)dp - u.dblk);
X				bp->d_reclen = reclen;
X
X				{
X#ifdef UFS
X				/* Is the following kludge ugly?  You bet. */
X
X				register char	save = dp->d_name[DIRSIZ];
X					/* save original data */
X
X				dp->d_name[DIRSIZ] = '\0';
X					/* ensure NUL termination */
X#endif
X				(void)strncpy( bp->d_name, dp->d_name,
X					       reclen - DIRENTBASESIZ
X					     );	/* adds NUL padding */
X#ifdef UFS
X				dp->d_name[DIRSIZ] = save;
X					/* restore original data */
X#endif
X				}
X
X				bp = (struct dirent *)((char *)bp + reclen);
X				}
X			}
X
X#ifndef UW_NFS
X#if !(defined(BFS) || defined(sun))	/* 4.2BSD screwed up; fixed in 4.3BSD */
X		if ( (char *)dp > &u.dblk[size] )
X			{
X			errno = EIO;	/* corrupted directory */
X			return -1;
X			}
X#endif
X#endif
X		}
X
X	errno = serrno;			/* restore entry errno */
X	return (char *)bp - buf;	/* return # bytes read */
X	}
END_OF_getdents.c
if test 8062 -ne `wc -c <getdents.c`; then
    echo shar: \"getdents.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f string.3 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"string.3\"
else
echo shar: Extracting \"string.3\" \(6925 characters\)
sed "s/^X//" >string.3 <<'END_OF_string.3'
X.TH STRING 3 "ANSI/POSIX Standard"
X.SH NAME
Xstrcat, strdup, strncat, strcmp, strncmp, strcpy,
Xstrncpy, strlen, strchr, strrchr, strpbrk, strspn, strcspn,
Xstrtok \- string operations
X.SH SYNOPSIS
X.B #include <string.h>
X.br
X.B #include <sys/types.h>
X.P
X.B "char \(**strcat(s1, s2)"
X.br
X.B "char \(**s1, \(**s2;"
X.P
X.B "char \(**strdup(s1)"
X.br
X.B "char \(**s1;"
X.P
X.B "char \(**strncat(s1, s2, n)"
X.br
X.B "char \(**s1, \(**s2;"
X.br
X.B "size_t n;"
X.P
X.B "int strcmp(s1, s2)"
X.br
X.B "char \(**s1, \(**s2;"
X.P
X.B "strncmp(s1, s2, n)"
X.br
X.B "char \(**s1, \(**s2;"
X.br
X.B "size_t n;"
X.P
X.B "char \(**strcpy(s1, s2)"
X.br
X.B "char \(**s1, \(**s2;"
X.P
X.B "char \(**strncpy(s1, s2, n)"
X.br
X.B "char \(**s1, \(**s2;"
X.br
X.B "size_t n;"
X.P
X.B "int strlen(s)"
X.br
X.B "char \(**s;"
X.P
X.B "char \(**strchr(s, c)"
X.br
X.B "char \(**s;"
X.br
X.B "int c;"
X.P
X.B "char \(**strrchr(s, c)"
X.br
X.B "char \(**s;"
X.br
X.B "int c;"
X.P
X.B "char \(**strpbrk(s1, s2)"
X.br
X.B "char \(**s1, s2;"
X.P
X.B "int strspn(s1, s2)"
X.br
X.B "char \(**s1, \(**s2;"
X.P
X.B "int strcspn(s1, s2)"
X.br
X.B "char \(**s1, \(**s2;"
X.P
X.B "char \(**strtok(s1, s2)"
X.br
X.B "char \(**s1, s2;"
X.br
X.SH DESCRIPTION
XThe arguments \fBs1\fR, \fBs2\fR, and s point to strings (arrays of
Xcharacters terminated by a null character). The functions
Xstrcat, strncat, strcpy, and strncpy all alter \fBs1\fR. These
Xfunctions do not check for overflow of the array pointed to
Xby \fBs1\fR.
X.P
X\fBStrcat\fR appends a copy of string \fBs2\fR to the end of string \fBs1\fR.
X.P
X\fBStrdup\fR returns a pointer to a new string that is a duplicate
Xof the string pointed to by \fBs1\fR. The space for the new
Xstring is obtained using malloc(3C). If the new string
Xcannot be created, a null pointer is returned.
X.P
X\fBStrncat\fR appends at most n characters.  Each returns a
Xpointer to the null-terminated result.
X.P
X\fBStrcmp\fR compares its arguments and returns an integer less
Xthan, equal to, or greater than 0, according as \fBs1\fR is
Xlexicographically less than, equal to, or greater than \fBs2\fR.
X\fBStrncmp\fR makes the same comparison but looks at, at most, n
Xcharacters.
X.P
X\fBStrcpy\fR copies string \fBs2\fR to \fBs1\fR, stopping after the null
Xcharacter has been copied. \fBStrncpy\fR copies exactly n
Xcharacters, truncating \fBs2\fR or adding null characters to \fBs1\fR if
Xnecessary. The result will not be null-terminated if the
Xlength of \fBs2\fR is n or more. Each function returns \fBs1\fR.
X.P
X\fBStrlen\fR returns the number of characters in s, not including
Xthe terminating null character.
X.P
X\fBStrchr\fR (\fBstrrchr\fR) returns a pointer to the first (last)
Xoccurrence of character c in string s, or a NULL pointer if
Xc does not occur in the string. The null character
Xterminating a string is considered to be part of the string.
X.P
X\fBStrpbrk\fR returns a pointer to the first occurrence in string
X\fBS1\fR of any character from string \fBs2\fR, or a NULL pointer if no
Xcharacter from \fBs2\fR exists in \fBs1\fR.
X.P
X\fBStrspn\fR (\fBstrcspn\fR) returns the length of the initial segment
Xof string \fBs1\fR, which consists entirely of characters from
X(not from) string \fBs2\fR.
X.P
X\fBStrtok\fR considers the string \fBs1\fR to consist of a sequence of
Xzero or more text tokens separated by spans of one or more
Xcharacters from the separator string \fBs2\fR. The first call
X(with pointer \fBs1\fR specified) returns a pointer to the first
Xcharacter of the first token, and will have written a null
Xcharacter into \fBs1\fR immediately following the returned token.
XThe function keeps track of its position in the string
Xbetween separate calls, so that subsequent calls (which must
Xbe made with the first argument a NULL pointer) will work
Xthrough the string \fBs1\fR immediately following that token. In
Xthis way, subsequent calls will work through the string \fBs1\fR
Xuntil no tokens remain. The separator string \fBs2\fR may be
Xdifferent from call to call. When no token remains in \fBs1\fR, a
XNULL pointer is returned.
X.P
XFor user convenience, all these functions are declared in
Xthe optional <string.h> header file.
X.SH SEE ALSO
Xmalloc(3C), malloc(3X).
X.SH CAVEATS
X\fBStrcmp\fR and \fBstrncmp\fR are implemented by using the most natural
Xcharacter comparison on the machine. Thus, the sign of the
Xvalue returned when one of the characters has its high-order
Xbit set is not the same in all implementations and should
Xnot be relied upon.
X.P
XCharacter movement is performed differently in different
Ximplementations. Thus, overlapping moves may yield
Xsurprises.!STUFFY!FUNK!
Xchmod 644 src/D.posix/string.3
Xecho Extracting src/D.posix/getopt.3c
Xsed >src/D.posix/getopt.3c <<'!STUFFY!FUNK!' -e 's///'
X.TH GETOPT 3C "Standard Extensions"
X.SH NAME
Xgetopt \- parse arguments from an argument token vector
X.SH SYNOPSIS
X.B int getopt (argc, argv, optstring)
X.br
X.B int argc;
X.br
X.B char \(**\(**argv, \(**opstring;
X.PP
X.B extern char \(**optarg;
X.br
X.B extern int optind, opterr;
X.SH DESCRIPTION
X.I Getopt
Xreturns the next option letter in
X.I argv
Xthat matches
Xa letter in
X.IR optstring .
X.I Optstring
Xis a string of recognized option letters. If a letter is followed by a colon,
Xthe option is expected to have an argument that may or may not be separated
Xfrom it by white space.
X.I Optarg
Xis set to point to the start of the option argument on return from
X.IR getopt .
X.PP
X.I Getopt
Xplaces in
X.I optind
Xthe
X.I argv
Xindex of the next argument to be processed. Because
X.I optind
Xis external, it is normally initialized to zero automatically before the first
Xcall to
X.IR getopt .
X.PP
XWhen all options have been processed (i.e., up to the first non-option
Xargument),
X.I getopt
Xreturns
X.SM
X.BR EOF .
XThe special option
X.B \-\-
Xmay be used to delimit the end of the options;
X.SM
X.B EOF
Xwill be returned, and
X.B \-\-
Xwill be skipped.
X.SH DIAGNOSTICS
X.I Getopt
Xprints an error message on
X.I stderr
Xand returns a
Xquestion mark
X.RB ( ? )
Xwhen it encounters an option letter not included in
X.IR optstring .
XThis error message may be disabled by setting 
X.I opterr
Xto a non-zero value.
X.SH EXAMPLE
XThe following code fragment shows how one might process the arguments for a
Xcommand that can take the mutually exclusive options
X.B a
Xand
X.BR b ,
Xand the options
X.B f
Xand
X.BR o ,
Xboth of which require arguments:
X.PP
X.RS
X.nf
X.ss 18
Xmain (argc, argv)
Xint argc;
Xchar \(**\(**argv;
X{
X	int c;
X	extern char \(**optarg;
X	extern int optind;
X	\&\f3.\fP
X	\&\f3.\fP
X	\&\f3.\fP
X	while ((c = getopt(argc, argv, "abf:o:")) != \s-1EOF\s+1)
X		switch (c) {
X		case \(fma\(fm:
X			if (bflg)
X				errflg++;
X			else
X				aflg++;
X			break;
X		case \(fmb\(fm:
X			if (aflg)
X				errflg++;
X			else
X				bproc( );
X			break;
X		case \(fmf\(fm:
X			ifile = optarg;
X			break;
X		case \(fmo\(fm:
X			ofile = optarg;
X			break;
X		case \(fm?\(fm:
X			errflg++;
X		}
X	if (errflg) {
X		fprintf(stderr, "usage: . . . ");
X		exit (2);
X	}
X	for ( ; optind < argc; optind++) {
X		if (access(argv[optind], 4)) {
X	\&\f3.\fP
X	\&\f3.\fP
X	\&\f3.\fP
X}
X.ss 12
X.fi
END_OF_string.3
if test 6925 -ne `wc -c <string.3`; then
    echo shar: \"string.3\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tsearch.3c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"tsearch.3c\"
else
echo shar: Extracting \"tsearch.3c\" \(6251 characters\)
sed "s/^X//" >tsearch.3c <<'END_OF_tsearch.3c'
X.TH TSEARCH 3C "Standard Extension"
X.SH NAME
Xtsearch, tfind, tdelete, twalk \- manipulate binary search trees
X.SH SYNOPSIS
X.B #include <search.h>
X.PP
X.B "char \(**tsearch ((char \(**) key, (char \(**\(**) rootp, compar)"
X.br
X.B int (\(**compar)( );
X.PP
X.B "char \(**tfind ((char \(**) key, (char \(**\(**) rootp, compar)"
X.br
X.B int (\(**compar)( );
X.PP
X.B "char \(**tdelete ((char \(**) key, (char \(**\(**) rootp, compar)"
X.br
X.B int (\(**compar)( );
X.PP
X.B "void twalk ((char \(**) root, action)"
X.br
X.B void (\(**action)( );
X.SH DESCRIPTION
X.I Tsearch,
X.I tfind,
X.I tdelete,
Xand
X.I twalk
Xare routines for manipulating binary search trees.
XThey are generalized from Knuth (6.2.2) Algorithms T and D.
XAll comparisons are done with a user-supplied hook.
XThis routine is called with two arguments,
Xthe pointers to the elements being compared.
XIt returns an integer less than, equal to,
Xor greater than 0, according to whether the first argument
Xis to be considered less than, equal to or greater than the
Xsecond argument (this is the convention used by
X.IR strncmp (3)).
XThe comparison function need not compare every byte,
Xso arbitrary data may be contained in the elements
Xin addition to the key values being compared. 
X.PP
X.I Tsearch
Xis used to build and access the tree.
X.B Key
Xis a pointer to a datum to be accessed or stored.
XIf there is a datum in the tree
Xequal to \(**key (the value pointed to by key),
Xa pointer to this found datum is returned.
XOtherwise, \(**key is inserted, and a pointer to it returned.
XOnly pointers are copied, so the calling routine must store the data.
X.B Rootp
Xmust point to a variable that points to the root
Xof the tree.
XA
X.SM NULL
Xvalue for the variable pointed to by
X.B rootp
Xdenotes an empty tree; in this case,
Xthe variable will be set to point to the datum
Xwhich will be at the root of the new tree.
X.PP
XLike
X.IR tsearch ,
X.I tfind
Xwill search for a datum in the tree, returning a pointer
Xto it if found.
XHowever, if it is not found,
X.I tfind
Xwill return a
X.SM NULL
Xpointer.
XThe arguments for
X.I tfind
Xare the same as for
X.IR tsearch .
X.PP
X.I Tdelete
Xdeletes a node from a binary search tree.
XThe arguments are the same as for 
X.IR tsearch .
XThe variable pointed to by
X.B rootp
Xwill be changed if the deleted node was the root of the tree.
X.I Tdelete
Xreturns a pointer to the parent of the deleted node,
Xor a
X.SM NULL
Xpointer if the node is not found.
X.PP
X.I Twalk
Xtraverses a binary search tree.
X.B Root
Xis the root of the tree to be traversed.
X(Any node in a tree may be used as the root for a walk below that node.)
X.I Action
Xis the name of a routine
Xto be invoked at each node.
XThis routine is, in turn,
Xcalled with three arguments.
XThe first argument is the address of the node being visited.
XThe second argument is a value from an enumeration data type
X.I "typedef enum { preorder, postorder, endorder, leaf }"
X.SM
X.I VISIT;
X(defined in the 
X.RI < search.h >
Xheader file),
Xdepending on whether this is the first, second or third
Xtime that the node has been visited
X(during a depth-first, left-to-right traversal of the tree),
Xor whether the node is a leaf.
XThe third argument is the level of the node
Xin the tree, with the root being level zero.
X.PP
XThe pointers to the key and the root of the tree should be
Xof type pointer-to-element,
Xand cast to type pointer-to-character.
XSimilarly, although declared as type pointer-to-character,
Xthe value returned should be cast into type pointer-to-element.
X.SH EXAMPLE
XThe following code reads in strings and
Xstores structures containing a pointer to each string
Xand a count of its length.
XIt then walks the tree, printing out the stored strings
Xand their lengths in alphabetical order.
X.PP
X.RS
X.nf
X.ss 18
X#include <search.h>
X#include <stdio.h>
X
Xstruct node {		/\(** pointers to these are stored in the tree \(**/
X	char \(**string;
X	int length;
X};
Xchar string_space[10000];	/\(** space to store strings \(**/
Xstruct node nodes[500];		/\(** nodes to store \(**/
Xstruct node \(**root = \s-1NULL\s+1;	/\(** this points to the root \(**/
X
Xmain( )
X{
X	char \(**strptr = string_space;
X	struct node \(**nodeptr = nodes;
X	void print_node( ), twalk( );
X	int i = 0, node_compare( );
X
X	while (gets(strptr) != \s-1NULL\s+1 && i++ < 500)  {
X		/\(** set node \(**/
X		nodeptr\(mi>string = strptr;
X		nodeptr\(mi>length = strlen(strptr);
X		/\(** put node into the tree \(**/
X		(void) tsearch((char \(**)nodeptr, &root,
X			  node_compare);
X		/\(** adjust pointers, so we don't overwrite tree \(**/
X		strptr += nodeptr\(mi>length + 1;
X		nodeptr++;
X	}
X	twalk(root, print_node);
X}
X/\(**
X	This routine compares two nodes, based on an
X	alphabetical ordering of the string field.
X\(**/
Xint
Xnode_compare(node1, node2)
Xstruct node \(**node1, \(**node2;
X{
X	return strcmp(node1\(mi>string, node2\(mi>string);
X}
X/\(**
X	This routine prints out a node, the first time
X	twalk encounters it.
X\(**/
X.bp
Xvoid
Xprint_node(node, order, level)
Xstruct node \(**\(**node;
X\s-1VISIT\s+1 order;
Xint level;
X{
X	if (order == preorder \(or\(or order == leaf)  {
X		(void)printf("string = %20s,  length = %d\en",
X			(\(**node)\(mi>string, (\(**node)\(mi>length);
X	}
X}
X.fi
X.RE
X.SH SEE ALSO
Xbsearch(3C), hsearch(3C), lsearch(3C).
X.SH DIAGNOSTICS
XA
X.SM NULL
Xpointer is returned by 
X.I tsearch
Xif there is not enough space available to create a new node.
X.br
XA
X.SM NULL
Xpointer is returned by
X.I tsearch,
X.I tfind
Xand
X.I tdelete
Xif
X.B rootp
Xis
X.SM NULL
Xon entry.
X.br
XIf the datum is found, both 
X.I tsearch
Xand 
X.I tfind
Xreturn a pointer to it.
XIf not, 
X.I tfind
Xreturns \s-1NULL\s+1, and 
X.I tsearch
Xreturns a pointer to the inserted
Xitem.
X.SH WARNINGS
XThe
X.B root
Xargument to 
X.I twalk
Xis one level of indirection less than the
X.B rootp
Xarguments to
X.I tsearch
Xand
X.IR tdelete .
X.br
XThere are two nomenclatures used to refer to the order in which
Xtree nodes are visited.
X.I Tsearch
Xuses preorder, postorder and endorder to respectively refer to
Xvisting a node before any of its children, after its left child
Xand before its right, and after both its children.
XThe alternate nomenclature uses preorder, inorder and postorder to
Xrefer to the same visits, which could result in some confusion over
Xthe meaning of postorder.
X.SH BUGS
XIf the calling function alters the pointer to the
Xroot, results are unpredictable.
END_OF_tsearch.3c
if test 6251 -ne `wc -c <tsearch.3c`; then
    echo shar: \"tsearch.3c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 4 \(of 5\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Lenny Tropiano             ICUS Software Systems         [w] +1 (516) 589-7930
lenny at icus.islp.ny.us      Telex; 154232428 ICUS         [h] +1 (516) 968-8576
{ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny     attmail!icus!lenny
        ICUS Software Systems -- PO Box 1; Islip Terrace, NY  11752



More information about the Unix-pc.sources mailing list