home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-11-28 | 30.4 KB | 1,180 lines |
- Newsgroups: comp.sources.unix
- From: panos@anchor.cs.colorado.edu (Panos Tsirigotis)
- Subject: v27i123: clc - C Libraries Collection, Part17/20
- References: <1.754527080.23891@gw.home.vix.com>
- Sender: unix-sources-moderator@gw.home.vix.com
- Approved: vixie@gw.home.vix.com
-
- Submitted-By: panos@anchor.cs.colorado.edu (Panos Tsirigotis)
- Posting-Number: Volume 27, Issue 123
- Archive-Name: clc/part17
-
- #! /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 17 (of 20)."
- # Contents: libs/src/dict/bst.c libs/src/sio/sio.3
- # Wrapped by panos@eclipse on Sun Nov 28 14:48:17 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'libs/src/dict/bst.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libs/src/dict/bst.c'\"
- else
- echo shar: Extracting \"'libs/src/dict/bst.c'\" \(14392 characters\)
- sed "s/^X//" >'libs/src/dict/bst.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1993 by Panagiotis Tsirigotis
- X * All rights reserved. The file named COPYRIGHT specifies the terms
- X * and conditions for redistribution.
- X */
- X
- Xstatic char RCSid[] = "$Id: bst.c,v 3.3 93/09/28 21:06:50 panos Exp $" ;
- X
- X#include "bstimpl.h"
- X
- X
- X#define NODE_ALLOC( hp ) TNP( fsm_alloc( (hp)->alloc ) )
- X#define NODE_FREE( hp, np ) fsm_free( (hp)->alloc, (char *)(np) )
- X
- X
- X/*
- X * Find the minimum node of the subtree with root 'start'
- X */
- X#define FIND_MINIMUM( hp, start, x ) \
- X x = start ; \
- X while ( LEFT( x ) != NIL( hp ) ) x = LEFT( x )
- X
- X/*
- X * Find the maximum node of the subtree with root 'start'
- X */
- X#define FIND_MAXIMUM( hp, start, x ) \
- X x = start ; \
- X while ( RIGHT( x ) != NIL( hp ) ) x = RIGHT( x )
- X
- X
- X/*
- X * Returns a pointer to the node that contains the specified object
- X * or NIL( hp ) if the object is not found
- X */
- XPRIVATE tnode_s *find_object( hp, object )
- X header_s *hp ;
- X dict_obj object ;
- X{
- X dheader_s *dhp = DHP( hp ) ;
- X register tnode_s *np = ROOT( hp ) ;
- X register tnode_s *null = NIL( hp ) ;
- X register int v ;
- X
- X while ( np != null )
- X {
- X v = (*dhp->oo_comp)( object, OBJ( np ) ) ;
- X if ( v == 0 )
- X if ( object == OBJ( np ) )
- X break ;
- X else
- X v = -1 ;
- X np = ( v < 0 ) ? LEFT( np ) : RIGHT( np ) ;
- X }
- X return( np ) ;
- X}
- X
- X
- X
- X/*
- X * Create a tree (either simple or red-black)
- X */
- Xdict_h bst_create( oo_comp, ko_comp, flags, errnop )
- X dict_function oo_comp ; /* object-object comparator */
- X dict_function ko_comp ; /* key-object comparator */
- X int flags ;
- X int *errnop ;
- X{
- X register header_s *hp ;
- X unsigned tnode_size ;
- X bool_int balanced_tree = flags & DICT_BALANCED_TREE ;
- X char *id = "bst_create" ;
- X
- X if ( ! __dict_args_ok( id, flags, errnop, oo_comp, ko_comp, DICT_ORDERED ) )
- X return( NULL_HANDLE ) ;
- X
- X hp = THP( malloc( sizeof( header_s ) ) ) ;
- X if ( hp == NULL_HEADER )
- X return( __dict_create_error( id, flags, errnop, DICT_ENOMEM ) ) ;
- X
- X /*
- X * Create an allocator
- X */
- X tnode_size = sizeof( struct tree_node ) ;
- X if ( balanced_tree )
- X tnode_size = sizeof( struct balanced_tree_node ) ;
- X
- X hp->alloc = fsm_create( tnode_size, 0,
- X ( flags & DICT_RETURN_ERROR ) ? FSM_RETURN_ERROR : FSM_NOFLAGS ) ;
- X if ( hp->alloc == NULL )
- X {
- X free( (char *)hp ) ;
- X return( __dict_create_error( id, flags, errnop, DICT_ENOMEM ) ) ;
- X }
- X
- X LEFT( ANCHOR( hp ) ) = RIGHT( ANCHOR( hp ) ) = NIL( hp ) ;
- X OBJ( ANCHOR( hp ) ) = NULL_OBJ ;
- X OBJ( NIL( hp ) ) = NULL_OBJ ;
- X
- X if ( balanced_tree )
- X {
- X COLOR( ANCHOR( hp ) ) = BLACK ;
- X COLOR( NIL( hp ) ) = BLACK ;
- X }
- X
- X /*
- X * Initialize dictionary header, hints
- X */
- X __dict_init_header( DHP( hp ), oo_comp, ko_comp, flags, errnop ) ;
- X HINT_CLEAR( hp, last_search ) ;
- X HINT_CLEAR( hp, last_successor ) ;
- X HINT_CLEAR( hp, last_predecessor ) ;
- X
- X return( (dict_h) hp ) ;
- X}
- X
- X
- X/*
- X * Destroy a tree
- X */
- Xvoid bst_destroy( handle )
- X dict_h handle ;
- X{
- X header_s *hp = THP( handle ) ;
- X
- X fsm_destroy( hp->alloc ) ;
- X free( (char *)hp ) ;
- X}
- X
- X
- X
- X/*
- X * Common code for tree insertions
- X */
- XPRIVATE int tree_insert( hp, uniq, object, objectp )
- X header_s *hp ;
- X register int uniq ;
- X dict_obj object ;
- X dict_obj *objectp ;
- X{
- X dheader_s *dhp = DHP( hp ) ;
- X register tnode_s *x = ROOT( hp ) ;
- X register tnode_s *px = ANCHOR( hp ) ;
- X tnode_s *new ;
- X register int v ;
- X
- X if ( object == NULL_OBJ )
- X HANDLE_ERROR( dhp, "tree_insert", DICT_ENULLOBJECT, DICT_ERR ) ;
- X
- X /*
- X * On exit from this loop, 'px' will point to a leaf node
- X * Furthermore, 'v' will hold the comparison value between the
- X * object stored at this node and the new 'object'.
- X *
- X * v must be initialized to -1 so that when we insert a node into an
- X * empty tree that node will be the *left* child of the anchor node
- X */
- X v = -1 ;
- X while ( x != NIL( hp ) )
- X {
- X v = (*dhp->oo_comp)( object, OBJ( x ) ) ;
- X
- X if ( v == 0 )
- X if ( uniq )
- X {
- X if ( objectp != NULL )
- X *objectp = OBJ( x ) ;
- X ERRNO( dhp ) = DICT_EEXISTS ;
- X return( DICT_ERR ) ;
- X }
- X else
- X v = -1 ; /* i.e. LESS THAN */
- X
- X px = x ;
- X x = ( v < 0 ) ? LEFT( x ) : RIGHT( x ) ;
- X }
- X
- X /*
- X * Allocate a new node and initialize all its fields
- X */
- X new = NODE_ALLOC( hp ) ;
- X if ( new == NULL_NODE )
- X {
- X ERRNO( dhp ) = DICT_ENOMEM ;
- X return( DICT_ERR ) ;
- X }
- X LEFT( new ) = RIGHT( new ) = NIL( hp ) ;
- X OBJ( new ) = object ;
- X PARENT( new ) = px ;
- X
- X if ( v < 0 )
- X LEFT( px ) = new ;
- X else
- X RIGHT( px ) = new ;
- X
- X if ( dhp->flags & DICT_BALANCED_TREE )
- X __dict_rbt_insfix( hp, new ) ;
- X
- X if ( objectp != NULL )
- X *objectp = object ;
- X
- X return( DICT_OK ) ;
- X}
- X
- X
- X/*
- X * Insert the specified object in the tree
- X */
- Xint bst_insert( handle, object )
- X dict_h handle ;
- X dict_obj object ;
- X{
- X header_s *hp = THP( handle ) ;
- X
- X return( tree_insert( hp,
- X hp->dh.flags & DICT_UNIQUE_KEYS, object, (dict_obj *)NULL ) ) ;
- X}
- X
- X
- X/*
- X * Insert the specified object in the tree only if it is unique
- X */
- Xint bst_insert_uniq( handle, object, objectp )
- X dict_h handle ;
- X dict_obj object ;
- X dict_obj *objectp ;
- X{
- X return( tree_insert( THP( handle ), TRUE, object, objectp ) ) ;
- X}
- X
- X
- X/*
- X * Delete the specified object
- X */
- Xint bst_delete( handle, object )
- X dict_h handle ;
- X dict_obj object ;
- X{
- X header_s *hp = THP( handle ) ;
- X dheader_s *dhp = DHP( hp ) ;
- X register tnode_s *null = NIL( hp ) ;
- X tnode_s *delnp ;
- X register tnode_s *y, *x ;
- X tnode_s *py ;
- X
- X if ( object == NULL_OBJ )
- X HANDLE_ERROR( dhp, "bst_delete", DICT_ENULLOBJECT, DICT_ERR ) ;
- X
- X if ( HINT_MATCH( hp, last_search, object ) )
- X delnp = HINT_GET( hp, last_search ) ;
- X else
- X {
- X delnp = find_object( hp, object ) ;
- X if ( delnp == null )
- X {
- X ERRNO( dhp ) = DICT_ENOTFOUND ;
- X return( DICT_ERR ) ;
- X }
- X }
- X
- X HINT_CLEAR( hp, last_search ) ;
- X HINT_CLEAR( hp, last_successor ) ;
- X HINT_CLEAR( hp, last_predecessor ) ;
- X
- X /*
- X * y is the node actually being removed. It may be 'delnp' if
- X * 'delnp' has at most 1 child, otherwise it is 'delnp's successor
- X */
- X if ( LEFT( delnp ) == null || RIGHT( delnp ) == null )
- X y = delnp ;
- X else
- X {
- X /*
- X * We can use the FIND_MINIMUM macro since we are guaranteed
- X * there is a right child
- X */
- X FIND_MINIMUM( hp, RIGHT( delnp ), y ) ;
- X OBJ( delnp ) = OBJ( y ) ;
- X }
- X
- X /*
- X * Set x to one of y's children:
- X * Case 1: y == delnp
- X * pick any child
- X * Case 2: y == successor( delnp )
- X * y can only have a right child (if any), so pick that.
- X * Next, we link x to y's parent.
- X *
- X * The use of the NIL and ANCHOR nodes relieves us from checking
- X * boundary conditions:
- X * existence of x (when setting the PARENT field of x)
- X * y being the root of the tree
- X */
- X x = ( LEFT( y ) != null ) ? LEFT( y ) : RIGHT( y ) ;
- X py = PARENT( y ) ;
- X PARENT( x ) = py ;
- X if ( y == LEFT( py ) )
- X LEFT( py ) = x ;
- X else
- X RIGHT( py ) = x ;
- X
- X /*
- X * If this is a balanced tree and we unbalanced it, do the necessary repairs
- X */
- X if ( ( dhp->flags & DICT_BALANCED_TREE ) && COLOR( y ) == BLACK )
- X __dict_rbt_delfix( hp, x ) ;
- X
- X NODE_FREE( hp, y ) ;
- X
- X return( DICT_OK ) ;
- X}
- X
- X
- X/*
- X * Find an object with the specified key
- X */
- Xdict_obj bst_search( handle, key )
- X dict_h handle ;
- X dict_key key ;
- X{
- X header_s *hp = THP( handle ) ;
- X dheader_s *dhp = DHP( hp ) ;
- X register tnode_s *np = ROOT( hp ) ;
- X register tnode_s *null = NIL( hp ) ;
- X register int v ;
- X
- X while ( np != null )
- X {
- X v = (*dhp->ko_comp)( key, OBJ( np ) ) ;
- X if ( v == 0 )
- X break ;
- X else
- X np = ( v < 0 ) ? LEFT( np ) : RIGHT( np ) ;
- X }
- X HINT_SET( hp, last_search, np ) ; /* update search hint */
- X return( OBJ( np ) ) ;
- X}
- X
- X
- X/*
- X * Returns a pointer to the object with the smallest key value or
- X * NULL_OBJ if the tree is empty.
- X */
- Xdict_obj bst_minimum( handle )
- X dict_h handle ;
- X{
- X register header_s *hp = THP( handle ) ;
- X register tnode_s *np ;
- X
- X if ( TREE_EMPTY( hp ) )
- X return( NULL_OBJ ) ;
- X FIND_MINIMUM( hp, ROOT( hp ), np ) ;
- X HINT_SET( hp, last_successor, np ) ;
- X return( OBJ( np ) ) ;
- X}
- X
- X
- X/*
- X * Returns a pointer to the object with the greatest key value or
- X * NULL_OBJ if the tree is empty.
- X */
- Xdict_obj bst_maximum( handle )
- X dict_h handle ;
- X{
- X register header_s *hp = THP( handle ) ;
- X register tnode_s *np ;
- X
- X if ( TREE_EMPTY( hp ) )
- X return( NULL_OBJ ) ;
- X FIND_MAXIMUM( hp, ROOT( hp ), np ) ;
- X HINT_SET( hp, last_predecessor, np ) ;
- X return( OBJ( np ) ) ;
- X}
- X
- X
- X/*
- X * When there is no next node, this function returns ANCHOR( hp )
- X */
- XPRIVATE tnode_s *next_node( hp, x )
- X register header_s *hp ;
- X register tnode_s *x ;
- X{
- X register tnode_s *px ;
- X register tnode_s *next ;
- X
- X if ( RIGHT( x ) != NIL( hp ) )
- X {
- X FIND_MINIMUM( hp, RIGHT( x ), next ) ;
- X }
- X else
- X {
- X px = PARENT( x ) ;
- X /*
- X * This loop will end at the root since the root is the *left*
- X * child of the anchor
- X */
- X while ( x == RIGHT( px ) )
- X {
- X x = px ;
- X px = PARENT( x ) ;
- X }
- X next = px ;
- X }
- X return( next ) ;
- X}
- X
- X
- X/*
- X * Returns a pointer to the object with the next >= key value or
- X * NULL_OBJ if the given object is the last one on the tree.
- X * It is an error to apply this function to an empty tree.
- X */
- Xdict_obj bst_successor( handle, object )
- X dict_h handle ;
- X dict_obj object ;
- X{
- X register header_s *hp = THP( handle ) ;
- X dheader_s *dhp = DHP( hp ) ;
- X register tnode_s *x ;
- X register tnode_s *successor ;
- X char *id = "bst_successor" ;
- X
- X if ( object == NULL_OBJ )
- X HANDLE_ERROR( dhp, id, DICT_ENULLOBJECT, NULL_OBJ ) ;
- X
- X if ( TREE_EMPTY( hp ) )
- X HANDLE_ERROR( dhp, id, DICT_EBADOBJECT, NULL_OBJ ) ;
- X
- X if ( HINT_MATCH( hp, last_successor, object ) )
- X x = HINT_GET( hp, last_successor ) ;
- X else
- X {
- X x = find_object( hp, object ) ;
- X if ( x == NIL( hp ) )
- X HANDLE_ERROR( dhp, id, DICT_EBADOBJECT, NULL_OBJ ) ;
- X }
- X
- X successor = next_node( hp, x ) ;
- X
- X HINT_SET( hp, last_successor, successor ) ;
- X ERRNO( DHP( hp ) ) = DICT_ENOERROR ; /* in case we return NULL_OBJ */
- X return( OBJ( successor ) ) ;
- X}
- X
- X
- X
- X/*
- X * When there is no next node, this function returns ANCHOR( hp )
- X */
- XPRIVATE tnode_s *previous_node( hp, x )
- X register header_s *hp ;
- X register tnode_s *x ;
- X{
- X register tnode_s *px ;
- X register tnode_s *previous ;
- X
- X if ( LEFT( x ) != NIL( hp ) )
- X {
- X FIND_MAXIMUM( hp, LEFT( x ), previous ) ;
- X }
- X else
- X {
- X /*
- X * XXX: To avoid testing against the ANCHOR we can temporarily make the
- X * root of the tree the *right* child of the anchor
- X */
- X px = PARENT( x ) ;
- X while ( px != ANCHOR( hp ) && x == LEFT( px ) )
- X {
- X x = px ;
- X px = PARENT( x ) ;
- X }
- X previous = px ;
- X }
- X return( previous ) ;
- X}
- X
- X
- X
- X/*
- X * Returns a pointer to the object with the next <= key value or
- X * NULL if the given object is the first one on the tree.
- X * It is an error to apply this function to an empty tree.
- X */
- Xdict_obj bst_predecessor( handle, object )
- X dict_h handle ;
- X dict_obj object ;
- X{
- X register header_s *hp = THP( handle ) ;
- X dheader_s *dhp = DHP( hp ) ;
- X tnode_s *predecessor ;
- X register tnode_s *x ;
- X char *id = "bst_predecessor" ;
- X
- X if ( object == NULL_OBJ )
- X HANDLE_ERROR( dhp, id, DICT_ENULLOBJECT, NULL_OBJ ) ;
- X
- X if ( TREE_EMPTY( hp ) )
- X HANDLE_ERROR( dhp, id, DICT_EBADOBJECT, NULL_OBJ ) ;
- X
- X if ( HINT_MATCH( hp, last_predecessor, object ) )
- X x = HINT_GET( hp, last_predecessor ) ;
- X else
- X {
- X x = find_object( hp, object ) ;
- X if ( x == NIL( hp ) )
- X HANDLE_ERROR( dhp, id, DICT_EBADOBJECT, NULL_OBJ ) ;
- X }
- X
- X predecessor = previous_node( hp, x ) ;
- X
- X HINT_SET( hp, last_predecessor, predecessor ) ;
- X ERRNO( DHP( hp ) ) = DICT_ENOERROR ;
- X return( OBJ( predecessor ) ) ;
- X}
- X
- X
- X
- Xvoid bst_iterate( handle, direction )
- X dict_h handle ;
- X enum dict_direction direction ;
- X{
- X register header_s *hp = THP( handle ) ;
- X struct tree_iterator *tip = &hp->iter ;
- X tnode_s *np ;
- X
- X tip->direction = direction ;
- X if ( TREE_EMPTY( hp ) )
- X tip->next = NULL ;
- X else
- X {
- X if ( direction == DICT_FROM_START )
- X {
- X FIND_MINIMUM( hp, ROOT( hp ), np ) ;
- X }
- X else
- X {
- X FIND_MAXIMUM( hp, ROOT( hp ), np ) ;
- X }
- X tip->next = np ;
- X }
- X}
- X
- X
- Xdict_obj bst_nextobj( handle )
- X dict_h handle ;
- X{
- X register header_s *hp = THP( handle ) ;
- X struct tree_iterator *tip = &hp->iter ;
- X tnode_s *current = tip->next ;
- X
- X if ( current == NULL )
- X return( NULL_OBJ ) ;
- X
- X if ( tip->direction == DICT_FROM_START )
- X tip->next = next_node( hp, current ) ;
- X else
- X tip->next = previous_node( hp, current ) ;
- X
- X if ( tip->next == ANCHOR( hp ) )
- X tip->next = NULL ;
- X return( OBJ( current ) ) ;
- X}
- X
- X
- X#ifdef BST_DEBUG
- X
- X#include <stdio.h>
- X
- X
- XPRIVATE void preorder( hp, np, action )
- X header_s *hp ;
- X tnode_s *np ;
- X void (*action)() ;
- X{
- X if ( np == NIL( hp ) )
- X return ;
- X
- X (*action)( OBJ( np ) ) ;
- X preorder( hp, LEFT( np ), action ) ;
- X preorder( hp, RIGHT( np ), action ) ;
- X}
- X
- X
- XPRIVATE void inorder( hp, np, action )
- X header_s *hp ;
- X tnode_s *np ;
- X void (*action)() ;
- X{
- X if ( np == NIL( hp ) )
- X return ;
- X
- X inorder( hp, LEFT( np ), action ) ;
- X (*action)( OBJ( np ) ) ;
- X inorder( hp, RIGHT( np ), action ) ;
- X}
- X
- X
- XPRIVATE void postorder( hp, np, action )
- X header_s *hp ;
- X tnode_s *np ;
- X void (*action)() ;
- X{
- X if ( np == NIL( hp ) )
- X return ;
- X
- X postorder( hp, LEFT( np ), action ) ;
- X postorder( hp, RIGHT( np ), action ) ;
- X (*action)( OBJ( np ) ) ;
- X}
- X
- X
- Xvoid bst_traverse( handle, order, action )
- X dict_h handle ;
- X bst_order_e order ;
- X void (*action)() ;
- X{
- X header_s *hp = THP( handle ) ;
- X
- X switch ( order )
- X {
- X case BST_INORDER:
- X inorder( hp, ROOT( hp ), action ) ;
- X break ;
- X
- X case BST_PREORDER:
- X preorder( hp, ROOT( hp ), action ) ;
- X break ;
- X
- X case BST_POSTORDER:
- X postorder( hp, ROOT( hp ), action ) ;
- X break ;
- X }
- X}
- X
- X
- X#ifdef MIN
- X#undef MIN
- X#endif
- X#define MIN( a, b ) ( a < b ? a : b )
- X
- X#ifdef MAX
- X#undef MAX
- X#endif
- X#define MAX( a, b ) ( a > b ? a : b )
- X
- Xvoid get_depth( hp, np, dp )
- X header_s *hp ;
- X tnode_s *np ;
- X struct bst_depth *dp ;
- X{
- X struct bst_depth ldep, rdep ;
- X
- X if ( np == NIL( hp ) )
- X {
- X dp->depth_min = dp->depth_max = 0 ;
- X return ;
- X }
- X get_depth( hp, LEFT( np ), &ldep ) ;
- X get_depth( hp, RIGHT( np ), &rdep ) ;
- X dp->depth_min = MIN( ldep.depth_min, rdep.depth_min ) + 1 ;
- X dp->depth_max = MAX( ldep.depth_max, rdep.depth_max ) + 1 ;
- X if ( DHP( hp )->flags & DICT_BALANCED_TREE )
- X {
- X if ( dp->depth_max > 2*dp->depth_min )
- X (void) fprintf( stderr, "tree is not balanced\n" ) ;
- X }
- X}
- X
- Xvoid bst_getdepth( handle, dp )
- X dict_h handle ;
- X struct bst_depth *dp ;
- X{
- X header_s *hp = THP( handle ) ;
- X
- X get_depth( hp, ROOT( hp ), dp ) ;
- X}
- X
- X#endif /* BST_DEBUG */
- X
- END_OF_FILE
- if test 14392 -ne `wc -c <'libs/src/dict/bst.c'`; then
- echo shar: \"'libs/src/dict/bst.c'\" unpacked with wrong size!
- fi
- # end of 'libs/src/dict/bst.c'
- fi
- if test -f 'libs/src/sio/sio.3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libs/src/sio/sio.3'\"
- else
- echo shar: Extracting \"'libs/src/sio/sio.3'\" \(13341 characters\)
- sed "s/^X//" >'libs/src/sio/sio.3' <<'END_OF_FILE'
- X.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
- X.\"All rights reserved. The file named COPYRIGHT specifies the terms
- X.\"and conditions for redistribution.
- X.\"
- X.\" $Id: sio.3,v 8.2 1993/11/22 19:00:24 panos Exp $
- X.TH SIO 3X "29 May 1992"
- X.SH NAME
- XSread, Sgetc, Srdline, Sfetch, Swrite, Sputc, Sprint, Sprintv, Sdone, Sundo, Stie, Suntie, Sflush, Sclose, Sbuftype, Smorefds, Sgetchar, Sputchar, SIOLINELEN, SIOMAXLINELEN - fast stream I/O
- X.SH SYNOPSIS
- X.LP
- X.nf
- X.ft B
- X#include "sio.h"
- X.LP
- X.ft B
- Xint Sread( fd, buf, nbytes )
- Xint fd ;
- Xchar *buf ;
- Xint nbytes ;
- X.LP
- X.ft B
- Xint Sgetc( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xchar *Srdline( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xchar *Sfetch( fd, length )
- Xint fd ;
- Xlong *length ;
- X.LP
- X.ft B
- Xint Swrite( fd, buf, nbytes )
- Xint fd ;
- Xchar *buf ;
- Xint nbytes ;
- X.LP
- X.ft B
- Xint Sputc( fd, c )
- Xint fd ;
- Xchar c ;
- X.LP
- X.ft B
- Xint Sprint( fd, format [ , ... ] )
- Xint fd ;
- Xchar *format ;
- X.LP
- X.ft B
- Xint Sprintv( fd, format, ap )
- Xint fd ;
- Xchar *format ;
- Xva_list ap ;
- X.LP
- X.ft B
- Xint Sdone( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xint Sundo( fd, type )
- Xint fd ;
- Xint type ;
- X.LP
- X.ft B
- Xint Stie( ifd, ofd )
- Xint ifd, ofd ;
- X.LP
- X.ft B
- Xint Suntie( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xint Sbuftype( fd, type )
- Xint fd, type ;
- X.LP
- X.ft B
- Xint Smorefds()
- X.LP
- X.ft B
- Xint Sflush( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xint Sclose( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xint Sgetchar( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xint Sputchar( fd, c )
- Xint fd;
- Xchar c ;
- X.LP
- X.ft B
- Xint SIOLINELEN( fd )
- Xint fd ;
- X.LP
- X.ft B
- Xint SIOMAXLINELEN( fd )
- Xint fd ;
- X.SH DESCRIPTION
- XThe \fISIO\fR library provides support
- Xfor \fIstream\fR I/O on file descriptors.
- XThe first argument of every function
- Xor macro is a file descriptor. The file descriptor may be used either for
- Xinput or for output, but not both. Attempting to use a descriptor for
- Xboth input and output will cause the call for the latter use to fail.
- XWhen you are
- Xdone with using a file descriptor, you should inform \fISIO\fR
- Xby invoking \fBSdone()\fR (unless the program is about to
- Xcall \fIexit(3)\fR).
- XYou can also use \fBSdone()\fR if
- Xyou want to perform a different type of operation on the same
- Xfile descriptor (e.g. first you were reading data from the file
- Xdescriptor and then you want to write some data).
- XAnother possibility is to do stream I/O at different file offsets
- Xby using \fBSdone()\fR before using \fBlseek(2)\fR to move to a
- Xnew file offset.
- X.LP
- XI/O operations on different file descriptors do not interfere
- X(unless the file descriptors refer to the same file, in which case
- Xthe results are undefined).
- X.LP
- XFor disk files, I/O always starts at the current file offset.
- XIf that offset is not a multiple of the preferred block size for file
- Xsystem I/O, performance will not be optimal
- X(the preferred block size is determined from the
- X\fIst_blksize\fR field in \fIstruct stat\fR).
- XFor optimal performance, it is recommended that no I/O operations
- X(like \fIread(2)\fR or \fIwrite(2)\fR)
- Xare applied to the file descriptor if it is to be used by \fISIO\fR.
- X.LP
- XRead I/O is either buffered, or is done using memory mapping whenever
- Xthat is possible and appropriate.
- X.LP
- XThe library functions that do stream I/O resemble system calls
- X(for example \fBSread()\fR resembles \fIread(2)\fR) so that modifying
- Xa program that uses the system calls to use the \fISIO\fR functions
- Xis easy (e.g. just replace \fIread(2)\fR with \fBSread()\fR; the function
- Xsignatures as well as the return values are exactly the same; also make
- Xsure to replace calls to \fIclose(2)\fP with \fBSclose()\fP).
- X.LP
- X\fISIO\fR uses the underlying system calls \fIread(2)\fR and \fIwrite(2)\fR
- Xto do I/O (except when reading files using memory mapping).
- XThese calls may be interrupted (i.e. they may return -1 with
- X.I errno
- Xset to EINTR). Such interruptions are ignored by \fISIO\fR which
- Xsimply reissues the system call
- X(this means that a \fISIO\fP call will never fail because the
- Xunderlying I/O system call was interrupted).
- X.LP
- X.B Sread()
- Xreads \fInbytes\fR bytes from the stream associated with file
- Xdescriptor \fIfd\fR into the buffer pointed to by \fIbuf\fR.
- X.LP
- X.B Sgetc()
- Xreads a character from the stream
- Xassociated with file descriptor \fIfd\fR.
- XIt returns \fBSIO_EOF\fR if the end of file has been reached.
- X.LP
- X.B Sgetchar()
- X(a macro) performs exactly the same function as \fBSgetc()\fR but
- Xit is much faster.
- X.LP
- X.B Srdline()
- Xreads a line from the stream
- Xassociated with file descriptor \fIfd\fR.
- XThe newline at the end of the line is replaced by a NUL byte. Lines
- Xlonger than the maximum line length supported by \fISIO\fR will
- Xhave characters deleted.
- X.LP
- X.B SIOLINELEN()
- X(a macro) returns the length of
- Xthe line returned by the last call to \fBSrdline()\fR
- X(the value returned by \fBSIOLINELEN()\fR is valid only after
- X\fBSrdline()\fR and as long as no other
- X\fISIO\fR calls are performed on that file descriptor).
- X.LP
- X.B SIOMAXLINELEN()
- X(a macro) returns
- Xthe maximul line length supported by \fISIO\fR for the file
- Xdescriptor. As a side-effect it initializes \fIfd\fR for input.
- X.LP
- X.B Sfetch()
- Xreturns a pointer to data coming from the stream
- Xassociated with file
- Xdescriptor \fIfd\fR. The amount of data available is indicated
- Xby the \fIlength\fR argument. One possible use for this function
- Xis to copy files.
- X.LP
- X.B Swrite()
- Xwrites \fInbytes\fR bytes to the stream associated with file
- Xdescriptor \fIfd\fR from the buffer pointed to by \fIbuf\fR.
- X.LP
- X.B Sputc()
- Xwrites a single character to the stream
- Xassociated with file descriptor \fIfd\fR.
- X.LP
- X.B Sputchar()
- X(a macro) performs exactly the same function as \fBSputc()\fR
- Xbut it is much faster.
- X.LP
- X.B Sprint()
- Ximitates the behavior of printf(3) as defined in the
- XANSI C Standard. There are some limitations. Check the \fBSprint()\fR
- Xman page for more information.
- X.LP
- X.B Sprintv()
- Xis the same as \fBSprint()\fR except that it uses a
- X\fIvarargs\fR argument list.
- X.LP
- X.B Sundo()
- Xreturns the characters returned by the last call to
- X\fBSrdline()\fR, \fBSgetc()\fR or \fBSgetchar()\fR to the stream
- Xso that they can be reread. The \fItype\fR argument to \fBSundo()\fR
- Xcan be \fBSIO_UNDO_LINE\fR or \fBSIO_UNDO_CHAR\fR depending
- Xon whether the call whose effect needs to be undone was
- X\fBSrdline()\fR or \fBSgetc()\fR/\fBSgetchar()\fR respectively.
- XThere is no check on
- Xwhether the last function invoked on \fIfd\fR was one of the above
- Xand the results are undefined if there is no correspondence
- Xbetween the \fItype\fR and the last operation on \fIfd\fR.
- X(i.e. the result is undefined if you try \fBSIO_UNDO_CHAR\fR
- Xand the last operation was not \fBSgetchar()\fR or \fBSgetc()\fR).
- X.LP
- X.B Stie()
- Xties the file descriptor \fIifd\fR to the file descriptor \fIofd\fR.
- XThis means that whenever a \fIread(2)\fR is done on \fIifd\fR, it is
- Xpreceded by a \fIwrite(2)\fR on \fIofd\fR.
- XFor filters it is useful to do \fIStie( 0, 1 )\fR to maximize concurrency.
- XIt is also useful to do the same thing when you issue prompts to the
- Xuser and you want the user reply to appear on the same line with the
- Xprompt.
- X\fIifd\fR, \fIofd\fR will be initialized for input, output respectively
- X(if any of them is initialized, it must be for the appropriate
- Xstream type (input or output)).
- XIf \fIifd\fR was tied to another file descriptor, the old tie is broken.
- X.LP
- X.B Suntie()
- Xundoes the effect of \fBStie()\fR for the specified input file descriptor.
- X.LP
- X.B Sbuftype()
- Xdetermines the buffering type for the output stream associated with
- Xfile descriptor \fIfd\fR.
- XBy default output directed to terminals is line buffered, output
- Xdirected to file descriptor 2 (standard error) is unbuffered and
- Xeverything else is fully buffered.
- XPossible values for the \fItype\fR argument are
- X.RS
- X.TP 15
- X.SB SIO_FULLBUF
- Xfor full buffering
- X.TP
- X.SB SIO_LINEBUF
- Xfor line buffering
- X.TP
- X.SB SIO_NOBUF
- Xfor no buffering
- X.RE
- X.LP
- X.B Smorefds()
- Xshould be used to inform \fBSIO\fR that the number of available file
- Xdescriptors has been increased. \fBSIO\fR uses an array of internal
- Xstream descriptors which are indexed by the file descriptor number. Some
- Xoperating systems (ex. SunOS 4.1[.x]) allow the number of available
- Xfile descriptors to vary. If that number is increased beyond its initial
- Xvalue \fBSIO\fR needs to know in order to allocate more stream descriptors.
- X.LP
- X.B Sdone()
- Xflushes any buffered output for \fIfd\fR
- Xand releases the \fISIO\fR resources used. \fBSdone()\fR
- Xis useful in case the program needs to reprocess the
- Xdata of a file descriptor (assuming the file descriptor corresponds
- Xto a file). The program can call \fBSdone()\fR,
- X\fIlseek(2)\fR to the beginning of the file
- Xand then proceed to reread the file.
- X.LP
- X.B Sflush()
- Xcauses any buffered stream output to be written to the
- Xfile descriptor. If its argument is the special value \fBSIO_FLUSH_ALL\fR
- Xthen all output streams will be flushed.
- X.LP
- X.B Sclose()
- Xcloses a file descriptor used for stream I/O, flushes
- Xany buffered output and releases the \fISIO\fR resources used.
- X.SH EXAMPLES
- X.LP
- XThe following code implements a (poor) substitute for the tee command
- X(it copies standard input to a file as well as to standard output).
- X.ne 10
- X.RS
- X.nf
- X.ft B
- X#include "sio.h"
- X.sp .5
- Xmain( argc, argv )
- X int argc ;
- X char *argv[] ;
- X{
- X char *file = (argc > 1) ? argv[ 1 ] : "tee.file" ;
- X int fd = creat( file, 0644 ) ;
- X long length ;
- X char *s ;
- X.sp .5
- X while ( s = Sfetch( 0, &length ) )
- X {
- X Swrite( 1, s, length ) ;
- X Swrite( fd, s, length ) ;
- X }
- X exit( 0 ) ;
- X}
- X.fi
- X.ft R
- X.RE
- X.SH RETURN VALUES
- X.LP
- X.B Sread()
- Xreturns the number of bytes read on success
- X(0 means end-of-file)
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Sgetc()
- Xreturns the character read on success,
- XSIO_EOF when the end-of-file is reached,
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Srdline()
- Xreturns a pointer to the next line on success.
- XOn failure or when the end-of-file is reached it returns
- X.SM NULL.
- XIf the end-of-file is reached \fIerrno\fR is set to 0, otherwise it indicates
- Xthe error.
- X.LP
- X.B Sfetch()
- Xreturns a pointer to file data on success.
- X(the \fIlength\fR argument indicates how many bytes
- Xare available).
- XOn failure or when the end-of-file is reached it returns
- X.SM NULL.
- XIf the end-of-file is reached \fIerrno\fR is set to 0, otherwise it indicates
- Xthe error.
- X.LP
- X.B Swrite()
- Xreturns the number of bytes written on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Sputc()
- Xreturns the character it was given as an argument on success
- X.B Sprint()
- Xreturns the number of characters printed on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Sdone()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Sundo()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Stie()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Suntie()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure
- X(\fIerrno\fR is set to \fBEBADF\fR if there
- Xwas no tied file descriptor).
- X.LP
- X.B Sbuftype()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure
- X(\fIerrno\fR is set to \fBEBADF\fR if this is not an output stream
- Xor to \fBEINVAL\fR if an unknown \fItype\fR is specified).
- X.LP
- X.B Smorefds()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure (because of lack of memory).
- X.LP
- X.B Sflush()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Sclose()
- Xreturns \fB0\fR on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Sgetchar()
- Xreturns the character read on success,
- XSIO_EOF when the end-of-file is reached,
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B Sputchar()
- Xreturns the character it was given as an argument on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- X.B SIOLINELEN()
- Xreturns the length of the last line read by \fBSrdline()\fR.
- X.LP
- X.B SIOMAXLINELEN()
- Xreturns the length of the longest line supported by \fISIO\fR on success
- Xor \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
- X.LP
- XAttempting a read operation on a descriptor opened for writing or vice
- Xversa will cause the operation to fail with \fIerrno\fR set to \fBEBADF\fR.
- X.LP
- XThe first \fISIO\fR operation on a descriptor must be a read or write
- Xoperation. It cannot be a control operation (like \fBSflush()\fR). Such
- Xan operation will fail with \fIerrno\fR set to \fBEBADF\fR.
- X.LP
- X.IP "\fBNOTE 1:\fR" 15
- X\fBStie()\fR is an input/output operation for the
- Xrespective file descriptors, not a control operation. \fBSuntie()\fR
- Xis a control operation.
- X.IP "\fBNOTE 2:\fR"
- X\fBSIO_ERR\fR is defined to be \fB-1\fR.
- X.SH "SEE ALSO"
- X.LP
- XSprint(3)
- X.SH BUGS
- X.LP
- XIf the operating system does not provide for invocation of a
- Xfinalization function upon exit, the program will have to
- Xexplicitly flush all output streams.
- XThe following operating systems provide such a facility:
- XSunOS 4.x, Ultrix 4.x, SunOS 5.x
- X.LP
- XSocket file descriptors can be used for input as well as output but
- X\fBSIO\fR does not support this.
- X.LP
- XThe current implementation will not try to use memory mapping to
- Xread a file if the file offset is not 0 (it will use buffered I/O instead).
- X.LP
- XPointers returned by \fBSfetch()\fR point to read-only memory.
- XAttempting to modify this memory will result in a segmentation
- Xviolation.
- END_OF_FILE
- if test 13341 -ne `wc -c <'libs/src/sio/sio.3'`; then
- echo shar: \"'libs/src/sio/sio.3'\" unpacked with wrong size!
- fi
- # end of 'libs/src/sio/sio.3'
- fi
- echo shar: End of archive 17 \(of 20\).
- cp /dev/null ark17isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 20 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-