home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-11-26 | 52.8 KB | 2,307 lines |
- Newsgroups: comp.sources.misc
- From: Panos Tsirigotis (panos@cs.colorado.edu)
- Subject: v40i172: pst - extract text from a postscript file, Part01/06
- Message-ID: <csm-v40i172=pst.110518@sparky.Sterling.COM>
- X-Md4-Signature: 2f7b3216aa279e0492f29c35ad6658e2
- Sender: kent@sparky.sterling.com (Kent Landfield)
- Organization: Sterling Software
- Date: Fri, 26 Nov 1993 17:05:38 GMT
- Approved: kent@sparky.sterling.com
-
- Submitted-by: Panos Tsirigotis (panos@cs.colorado.edu)
- Posting-number: Volume 40, Issue 172
- Archive-name: pst/part01
- Environment: BSD, SUNOS, ULTRIX, SYSVR4, SYSVR3, POSIX
-
- pst is a program that will extract the text of a postscript file and
- will try to make that text appear as it does in the postscript
- document. This means that words will not be split, paragraph
- boundaries will be observed etc. In order to achieve this, pst first
- tries to identify how the postscript file was produced, so that it can
- use an appropriate text extraction algorithm. It is also possible for
- the user to specify which of the available algorithms to use to extract
- text.
- -------------------------
- #! /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".
- # Contents: README libs libs/include libs/lib libs/man libs/src
- # libs/src/sio libs/src/sio/siosup.c libs/src/sio/sprint.c
- # libs/src/sio/suite libs/src/str pst pst/common.c
- # Wrapped by kent@sparky on Fri Nov 26 11:02:45 1993
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 6)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(762 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X
- Xpst is a program that will extract the text of a postscript file and
- Xwill try to make that text appear as it does in the postscript
- Xdocument. This means that words will not be split, paragraph
- Xboundaries will be observed etc. In order to achieve this, pst first
- Xtries to identify how the postscript file was produced so that it can
- Xuse an appropriate text extraction algorithm. It is also possible for
- Xthe user to specify which of the available algorithms to use to extract
- Xtext.
- X
- XThe INSTALL file has instructions on how to compile and setup pst.
- X
- XThis program used to be called 'pstext' but was renamed to 'pst' due
- Xto a naming conflict with another program that does the inverse job
- Xof 'pst'.
- X
- XPlease send any comments/bug-reports to panos@cs.colorado.edu
- X
- END_OF_FILE
- if test 762 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test ! -d 'libs' ; then
- echo shar: Creating directory \"'libs'\"
- mkdir 'libs'
- fi
- if test ! -d 'libs/include' ; then
- echo shar: Creating directory \"'libs/include'\"
- mkdir 'libs/include'
- fi
- if test ! -d 'libs/lib' ; then
- echo shar: Creating directory \"'libs/lib'\"
- mkdir 'libs/lib'
- fi
- if test ! -d 'libs/man' ; then
- echo shar: Creating directory \"'libs/man'\"
- mkdir 'libs/man'
- fi
- if test ! -d 'libs/src' ; then
- echo shar: Creating directory \"'libs/src'\"
- mkdir 'libs/src'
- fi
- if test ! -d 'libs/src/sio' ; then
- echo shar: Creating directory \"'libs/src/sio'\"
- mkdir 'libs/src/sio'
- fi
- if test -f 'libs/src/sio/siosup.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libs/src/sio/siosup.c'\"
- else
- echo shar: Extracting \"'libs/src/sio/siosup.c'\" \(24088 characters\)
- sed "s/^X//" >'libs/src/sio/siosup.c' <<'END_OF_FILE'
- X/*
- 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
- Xstatic char RCSid[] = "$Id: siosup.c,v 8.4 1993/03/17 07:35:24 panos Exp $" ;
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <fcntl.h>
- X
- X#include "impl.h"
- X#include "sio.h"
- X
- X#ifdef EVENTS
- X#include "events.h"
- X#endif
- X
- Xchar *malloc() ;
- Xchar *realloc() ;
- X
- X
- Xstatic __sio_descriptor_t static_descriptor_array[ N_SIO_DESCRIPTORS ] ;
- Xstatic int n_descriptors = N_SIO_DESCRIPTORS ;
- X__sio_descriptor_t *__sio_descriptors = static_descriptor_array ;
- X
- X#ifdef EVENTS
- Xstatic events_s static___sio_events[ N_SIO_DESCRIPTORS ] ;
- Xevents_s *__sio_events = static___sio_events ;
- X#endif
- X
- X
- X/*
- X * Code for finalization
- X */
- X#ifdef HAS_FINALIZATION_FUNCTION
- Xstatic int finalizer_installed ;
- X
- XSIO_DEFINE_FIN( sio_cleanup )
- X{
- X (void) Sflush( SIO_FLUSH_ALL ) ;
- X}
- X#endif /* HAS_FINALIZATION_FUNCTION */
- X
- X
- X
- X#ifdef HAS_MMAP
- X
- X#define CHAR_NULL ((char *)0)
- X
- X/*
- X * PAGES_MAPPED gives the size of each map unit in pages
- X */
- X#define PAGES_MAPPED 2
- X
- Xstatic size_t map_unit_size = 0 ; /* bytes */
- Xstatic size_t page_size = 0 ; /* bytes */
- X
- Xstatic mapd_s static_mapd_array[ N_SIO_DESCRIPTORS ] ;
- Xstatic mapd_s *mmap_descriptors = static_mapd_array ;
- X
- X#define MDP( fd ) ( mmap_descriptors + (fd) )
- X
- X
- X/*
- X * NOTES ON MEMORY MAPPING:
- X *
- X * 1. Memory mapping works only for file descriptors opened for input
- X * 2. Mapping an object to a part of the address space where another
- X * object is mapped will cause the old mapping to disappear (i.e. mmap
- X * will not fail)
- X *
- X * Memory mapping interface:
- X * SIO_MMAP : maps a file into a portion of the address space.
- X * SIO_MUNMAP: unmap a portion of the address space
- X * SIO_MNEED: indicate to the OS that we will need a portion of
- X * our address space.
- X *
- X * The map_unit_size variable defines how much of the file is mapped at
- X * a time. It is a multiple of the operating system page size. It is
- X * not less than SIO_BUFFER_SIZE unless SIO_BUFFER_SIZE is not a
- X * multiple of the page size (so the SIO_BUFFER_SIZE overrides
- X * PAGES_MAPPED).
- X *
- X * NOTE: All memory mapping code is in this file only
- X */
- X
- X
- X/*
- X * Macros used by the memory mapping code
- X */
- X#define FIRST_TIME( dp ) ( dp->buf == NULL )
- X#define FATAL_ERROR( msg ) perror( msg ), exit( 1 )
- X
- X/*
- X * Functions to support memory mapping:
- X *
- X * try_memory_mapping
- X * buffer_setup
- X * __sio_switch
- X * initial_map
- X * map_unit
- X */
- X
- X/*
- X * try_memory_mapping attempts to setup the specified descriptor
- X * for memory mapping.
- X * It returns FAILURE if it fails and SUCCESS if it is successful.
- X * If HAS_MMAP is not defined, the function is defined to be FAILURE.
- X *
- X * Sets fields:
- X * memory_mapped: TRUE or FALSE
- X *
- X * Also sets the following fields if memory_mapped is TRUE:
- X * file_offset, file_size, buffer_size
- X *
- X */
- XPRIVATE status_e try_memory_mapping( fd, idp, stp )
- X int fd ;
- X register __sio_id_t *idp ;
- X struct stat *stp ;
- X{
- X int access ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_TRY_MEMORY_MAPPING ) ;
- X#endif
- X
- X /*
- X * Do not try memory mapping if:
- X * 1) The file is not a regular file
- X * 2) The file is a regular file but has zero-length
- X * 3) The file pointer is not positioned at the beginning of the file
- X * 4) The fcntl to obtain the file descriptor flags fails
- X * 5) The access mode is not O_RDONLY or O_RDWR
- X *
- X * The operations are done in this order to avoid the system calls
- X * if possible.
- X */
- X if ( ( ( stp->st_mode & S_IFMT ) != S_IFREG ) ||
- X ( stp->st_size == 0 ) ||
- X ( lseek( fd, (long)0, 1 ) != 0 ) ||
- X ( ( access = fcntl( fd, F_GETFL, 0 ) ) == -1 ) ||
- X ( ( access &= 0x3 ) != O_RDONLY && access != O_RDWR ) )
- X {
- X idp->memory_mapped = FALSE ;
- X return( FAILURE ) ;
- X }
- X
- X /*
- X * Determine page_size and map_unit_size.
- X * Note that the code works even if PAGES_MAPPED is 0.
- X */
- X if ( page_size == 0 )
- X {
- X page_size = getpagesize() ;
- X map_unit_size = page_size * PAGES_MAPPED ;
- X if ( map_unit_size < SIO_BUFFER_SIZE )
- X if ( map_unit_size > 0 && SIO_BUFFER_SIZE % map_unit_size == 0 )
- X map_unit_size = SIO_BUFFER_SIZE ;
- X else
- X map_unit_size = page_size ;
- X }
- X
- X MDP(fd)->file_offset = 0 ;
- X MDP(fd)->file_size = stp->st_size ;
- X idp->buffer_size = map_unit_size ;
- X idp->buf = CHAR_NULL ;
- X idp->memory_mapped = TRUE ;
- X
- X return( SUCCESS ) ;
- X}
- X
- X
- X/*
- X * Copy the current_unit to the primary buffer
- X *
- X * Sets fields: start, end, nextb
- X * Also sets the file pointer
- X */
- XPRIVATE void buffer_setup( idp, fd, mu_cur, mu_next )
- X __sio_id_t *idp ;
- X int fd ;
- X struct map_unit *mu_cur ;
- X struct map_unit *mu_next ;
- X{
- X off_t new_offset ;
- X
- X sio_memcopy( mu_cur->addr, idp->buf, mu_cur->valid_bytes ) ;
- X idp->start = idp->buf ;
- X idp->end = idp->buf + mu_cur->valid_bytes ;
- X idp->nextb = idp->buf + ( idp->nextb - mu_cur->addr ) ;
- X
- X if ( mu_next->addr != CHAR_NULL )
- X new_offset = MDP(fd)->file_offset - mu_next->valid_bytes ;
- X else
- X new_offset = MDP(fd)->file_offset ;
- X (void) lseek( fd, new_offset, 0 ) ;
- X}
- X
- X
- X/*
- X * Switch from memory mapping to buffered I/O
- X * If any mapping has occured, then the current unit is
- X * copied into the buffer that is allocated.
- X * Any data in the next unit is ignored.
- X * We rely on idp->buf to identify the current unit (so it
- X * better be equal to the address of one of the units).
- X *
- X * Sets fields:
- X * start, end, nextb
- X */
- Xstatus_e __sio_switch( idp, fd )
- X register __sio_id_t *idp ;
- X int fd ;
- X{
- X register mapd_s *mdp = MDP( fd ) ;
- X struct map_unit *mu_cur, *mu_next ;
- X unsigned buffer_size = idp->buffer_size ;
- X char *buf_addr = idp->buf ;
- X int first_time = FIRST_TIME( idp ) ;
- X void buffer_setup() ;
- X status_e setup_read_buffer() ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_SIO_SWITCH ) ;
- X#endif
- X
- X /*
- X * Initialize stream for buffering
- X */
- X if ( setup_read_buffer( idp, buffer_size ) == FAILURE )
- X return( FAILURE ) ;
- X
- X if ( ! first_time )
- X {
- X /*
- X * Find current, next unit
- X */
- X if ( buf_addr == mdp->first_unit.addr )
- X {
- X mu_cur = &mdp->first_unit ;
- X mu_next = &mdp->second_unit ;
- X }
- X else
- X {
- X mu_cur = &mdp->second_unit ;
- X mu_next = &mdp->first_unit ;
- X }
- X
- X buffer_setup( idp, fd, mu_cur, mu_next ) ;
- X /*
- X * Destroy all mappings
- X */
- X (void) SIO_MUNMAP( mu_cur->addr, mu_cur->mapped_bytes ) ;
- X if ( mu_next->addr != NULL )
- X (void) SIO_MUNMAP( mu_next->addr, mu_next->mapped_bytes ) ;
- X }
- X else
- X idp->start = idp->end = idp->nextb = idp->buf ;
- X
- X idp->memory_mapped = FALSE ;
- X return( SUCCESS ) ;
- X}
- X
- X
- X/*
- X * initial_map does the first memory map on the file descriptor.
- X * It attempts to map both units.
- X * The mapping always starts at file offset 0.
- X *
- X * SETS FIELDS:
- X * first_unit.*, second_unit.*
- X * file_offset
- X *
- X * Returns:
- X * number of bytes mapped in first_unit
- X * or
- X * 0 to indicate that mmap failed.
- X */
- XPRIVATE int initial_map( mdp, fd )
- X register mapd_s *mdp ;
- X int fd ;
- X{
- X register caddr_t addr ;
- X register size_t requested_length = 2 * map_unit_size ;
- X register size_t mapped_length = MIN( mdp->file_size, requested_length ) ;
- X size_t bytes_left ;
- X register size_t bytes_in_unit ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_INITIAL_MAP ) ;
- X#endif
- X
- X addr = SIO_MMAP( CHAR_NULL, mapped_length, fd, 0 ) ;
- X if ( (int) addr == -1 )
- X return( 0 ) ;
- X
- X SIO_MNEED( addr, mapped_length ) ;
- X
- X /*
- X * Map as much as possible in the first unit
- X */
- X bytes_in_unit = MIN( mapped_length, map_unit_size ) ;
- X mdp->first_unit.addr = addr ;
- X mdp->first_unit.mapped_bytes = bytes_in_unit ;
- X mdp->first_unit.valid_bytes = bytes_in_unit ;
- X
- X /*
- X * If there is more, map it in the second unit.
- X */
- X bytes_left = mapped_length - bytes_in_unit ;
- X if ( bytes_left > 0 )
- X {
- X mdp->second_unit.addr = addr + bytes_in_unit ;
- X mdp->second_unit.mapped_bytes = bytes_left ;
- X mdp->second_unit.valid_bytes = bytes_left ;
- X }
- X else
- X mdp->second_unit.addr = CHAR_NULL ;
- X
- X mdp->file_offset = mapped_length ;
- X
- X return( mdp->first_unit.valid_bytes ) ;
- X}
- X
- X
- X/*
- X * ALGORITHM:
- X *
- X * if ( there are more bytes in the file )
- X * {
- X * map them at the given unit
- X * update offset
- X * issue SIO_MNEED()
- X * }
- X * else
- X * unmap the unit
- X */
- XPRIVATE status_e map_unit( mdp, fd, mup )
- X register mapd_s *mdp ;
- X int fd ;
- X register struct map_unit *mup ;
- X{
- X register size_t bytes_left = mdp->file_size - mdp->file_offset ;
- X register size_t bytes_to_map = MIN( bytes_left, map_unit_size ) ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_MAP_UNIT ) ;
- X#endif
- X
- X if ( bytes_to_map > 0 )
- X {
- X if ( (int) SIO_MMAP( mup->addr, bytes_to_map,
- X fd, mdp->file_offset ) == -1 )
- X return( FAILURE ) ; /* XXX: need to do more ? */
- X
- X mup->valid_bytes = bytes_to_map ;
- X ASSERT( mup->valid_bytes <= mup->mapped_bytes ) ;
- X mdp->file_offset += bytes_to_map ;
- X SIO_MNEED( mup->addr, mup->valid_bytes ) ;
- X }
- X else
- X {
- X (void) SIO_MUNMAP( mup->addr, mup->mapped_bytes ) ;
- X mup->addr = CHAR_NULL ;
- X }
- X return( SUCCESS ) ;
- X}
- X
- X#else
- X
- X#define try_memory_mapping( x, y, z ) FAILURE
- X
- X#endif /* HAS_MMAP */
- X
- X
- XPRIVATE status_e setup_read_buffer( idp, buf_size )
- X register __sio_id_t *idp ;
- X unsigned buf_size ;
- X{
- X register char *buf ;
- X
- X /*
- X * First allocate space for 2 buffers: primary and auxiliary
- X */
- X buf = malloc( buf_size * 2 ) ;
- X if ( buf == NULL )
- X return( FAILURE ) ;
- X
- X /*
- X * The descriptor buf field should point to the start of the main buffer
- X */
- X idp->buf = buf + buf_size ;
- X idp->buffer_size = buf_size ;
- X return( SUCCESS ) ;
- X}
- X
- X
- XPRIVATE status_e init_input_stream( idp, fd, stp )
- X register __sio_id_t *idp ;
- X int fd ;
- X struct stat *stp ;
- X{
- X#ifdef EVENTS
- X EVENT( fd, EV_INIT_INPUT_STREAM ) ;
- X#endif
- X
- X /*
- X * First initialize the fields relevant to buffering: buf, buffer_size
- X */
- X if ( try_memory_mapping( fd, idp, stp ) == FAILURE )
- X {
- X /*
- X * Try to use normal buffering
- X */
- X unsigned buf_size = (unsigned)
- X ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
- X
- X if ( setup_read_buffer( idp, buf_size ) == FAILURE )
- X return( FAILURE ) ;
- X }
- X
- X /*
- X * Initialize remaining descriptor fields
- X */
- X idp->max_line_length = 2 * idp->buffer_size - 1 ;
- X idp->start = idp->end = idp->nextb = idp->buf ;
- X idp->tied_fd = SIO_NO_TIED_FD ;
- X
- X return( SUCCESS ) ;
- X}
- X
- X
- XPRIVATE status_e init_output_stream( odp, fd, stp )
- X register __sio_od_t *odp ;
- X int fd ;
- X struct stat *stp ;
- X{
- X register unsigned buf_size ;
- X register char *buf ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_INIT_OUTPUT_STREAM ) ;
- X#endif
- X
- X buf_size = (unsigned)
- X ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
- X buf = malloc( buf_size ) ;
- X if ( buf == NULL )
- X return( FAILURE ) ;
- X
- X /*
- X * Initialize buffering fields
- X */
- X odp->buf = buf ;
- X odp->buffer_size = buf_size ;
- X odp->buf_end = odp->buf + buf_size ;
- X
- X /*
- X * Initialize remaining fields
- X */
- X odp->start = odp->nextb = odp->buf ;
- X if ( isatty( fd ) )
- X odp->buftype = SIO_LINEBUF ;
- X
- X if ( fd == 2 )
- X odp->buftype = SIO_NOBUF ;
- X
- X return( SUCCESS ) ;
- X}
- X
- X
- X#ifndef HAS_ISATTY
- X
- X#ifdef HAS_SYSVTTY
- X
- X#include <termio.h>
- X
- XPRIVATE int isatty( fd )
- X int fd ;
- X{
- X struct termio t ;
- X
- X if ( ioctl( fd, TCGETA, &t ) == -1 && errno == ENOTTY )
- X return( FALSE ) ;
- X else
- X return( TRUE ) ;
- X}
- X#endif /* HAS_SYSVTTY */
- X
- X#ifdef HAS_BSDTTY
- X
- X#include <sgtty.h>
- X
- XPRIVATE int isatty( fd )
- X int fd ;
- X{
- X struct sgttyb s ;
- X
- X if ( ioctl( fd, TIOCGETP, &s ) == -1 && errno == ENOTTY )
- X return( FALSE ) ;
- X else
- X return( TRUE ) ;
- X}
- X#endif /* HAS_BSDTTY */
- X
- X#endif /* ! HAS_ISATTY */
- X
- X
- X/*
- X * Initialize stream I/O for a file descriptor.
- X *
- X * Arguments:
- X * fd: file descriptor
- X * dp: descriptor pointer
- X * stream_type: either __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
- X *
- X * Returns
- X * 0 if successful
- X * SIO_ERR if the file descriptor is not valid (sets errno)
- X * exits if stream_type is not __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
- X */
- Xint __sio_init( dp, fd, stream_type )
- X register __sio_descriptor_t *dp ;
- X int fd ;
- X enum __sio_stream stream_type ;
- X{
- X struct stat st ;
- X void terminate() ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_SIO_INIT ) ;
- X#endif
- X
- X if ( fstat( fd, &st ) == -1 )
- X return( SIO_ERR ) ;
- X
- X switch ( stream_type )
- X {
- X case __SIO_INPUT_STREAM:
- X if ( init_input_stream( IDP( dp ), fd, &st ) == FAILURE )
- X return( SIO_ERR ) ;
- X break ;
- X
- X case __SIO_OUTPUT_STREAM:
- X if ( init_output_stream( ODP( dp ), fd, &st ) == FAILURE )
- X return( SIO_ERR ) ;
- X break ;
- X
- X default:
- X terminate( "SIO __sio_init: bad stream type (internal error).\n" ) ;
- X /* NOTREACHED */
- X }
- X dp->stream_type = stream_type ;
- X dp->initialized = TRUE ;
- X
- X#ifdef HAS_FINALIZATION_FUNCTION
- X if ( ! finalizer_installed )
- X {
- X if ( ! SIO_FINALIZE( sio_cleanup ) )
- X {
- X char *s = "SIO __sio_init: finalizer installation failed\n" ;
- X
- X (void) write( 2, s, strlen( s ) ) ;
- X }
- X else
- X finalizer_installed = TRUE ;
- X }
- X#endif /* HAS_FINALIZATION_FUNCTION */
- X
- X return( 0 ) ;
- X}
- X
- X
- X/*
- X * __sio_writef writes the data in the buffer to the file descriptor.
- X *
- X * It tries to write as much data as possible until either all data
- X * are written or an error occurs. EINTR is the only error that is
- X * ignored.
- X * In case an error occurs but some data were written, that number
- X * is returned instead of SIO_ERR.
- X *
- X * Fields modified:
- X * When successful: start, nextb
- X * When not successful: start
- X *
- X * Return value:
- X * Number of bytes written
- X * SIO_ERR, if write(2) fails and no data were written
- X */
- Xint __sio_writef( odp, fd )
- X register __sio_od_t *odp ;
- X int fd ;
- X{
- X register int b_in_buffer ;
- X register int cc_total = 0 ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_SIO_WRITEF ) ;
- X#endif
- X
- X /*
- X * Make sure we don't exceed the buffer limits
- X * Maybe we should log this ? XXX
- X */
- X if ( odp->nextb > odp->buf_end )
- X odp->nextb = odp->buf_end ;
- X
- X b_in_buffer = odp->nextb - odp->start ;
- X
- X if ( b_in_buffer == 0 )
- X return( 0 ) ;
- X
- X for ( ;; )
- X {
- X register int cc ;
- X
- X cc = write( fd, odp->start, b_in_buffer ) ;
- X if ( cc == b_in_buffer )
- X {
- X odp->start = odp->nextb = odp->buf ;
- X cc_total += cc ;
- X break ;
- X }
- X else if ( cc == -1 )
- X {
- X if ( errno == EINTR )
- X continue ;
- X else
- X /*
- X * If some bytes were written, return that number, otherwise
- X * return SIO_ERR
- X */
- X return( ( cc_total != 0 ) ? cc_total : SIO_ERR ) ;
- X }
- X else /* some bytes were written */
- X {
- X odp->start += cc ; /* advance start of buffer */
- X b_in_buffer -= cc ; /* decrease number bytes left in buffer */
- X cc_total += cc ; /* count the bytes that were written */
- X }
- X }
- X return( cc_total ) ;
- X}
- X
- X
- X/*
- X * __sio_readf reads data from the file descriptor into the buffer.
- X * Unlike __sio_writef it does NOT try to read as much data as will fit
- X * in the buffer. It ignores EINTR.
- X *
- X * Returns: # of bytes read or SIO_ERR
- X *
- X * Fields set:
- X * If it does not return SIO_ERR, it sets start, nextb, end
- X * If it returns SIO_ERR, it does not change anything
- X */
- Xint __sio_readf( idp, fd )
- X register __sio_id_t *idp ;
- X int fd ;
- X{
- X register int cc ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_SIO_READF ) ;
- X#endif
- X
- X /*
- X * First check for a tied fd and flush the stream if necessary
- X *
- X * XXX the return value of __sio_writef is not checked.
- X * Is that right ?
- X */
- X if ( idp->tied_fd != SIO_NO_TIED_FD )
- X (void) __sio_writef( &__SIO_OD( idp->tied_fd ), idp->tied_fd ) ;
- X
- X#ifdef HAS_MMAP
- X if ( idp->memory_mapped )
- X {
- X register mapd_s *mdp = MDP( fd ) ;
- X
- X /*
- X * The functions initial_map and map_unit may fail.
- X * In either case, we switch to buffered I/O.
- X * If initial_map fails, we have read no data, so we
- X * should perform a read(2).
- X * If map_unit fails (for the next unit), we still have
- X * the data in the current unit, so we can return.
- X */
- X if ( FIRST_TIME( idp ) )
- X {
- X cc = initial_map( mdp, fd ) ;
- X if ( cc > 0 )
- X idp->buf = mdp->first_unit.addr ;
- X else
- X {
- X if ( __sio_switch( idp, fd ) == FAILURE )
- X return( SIO_ERR ) ;
- X cc = -1 ;
- X }
- X }
- X else
- X {
- X register struct map_unit *mu_cur, *mu_next ;
- X
- X if ( idp->buf == mdp->first_unit.addr )
- X {
- X mu_cur = &mdp->first_unit ;
- X mu_next = &mdp->second_unit ;
- X }
- X else
- X {
- X mu_cur = &mdp->second_unit ;
- X mu_next = &mdp->first_unit ;
- X }
- X
- X if ( mu_next->addr != NULL )
- X {
- X idp->buf = mu_next->addr ;
- X cc = mu_next->valid_bytes ;
- X /*
- X * XXX: Here we may return SIO_ERR even though there
- X * are data in the current unit because the switch
- X * fails (possibly because malloc failed).
- X */
- X if ( map_unit( mdp, fd, mu_cur ) == FAILURE &&
- X __sio_switch( idp, fd ) == FAILURE )
- X return( SIO_ERR ) ;
- X }
- X else
- X cc = 0 ;
- X }
- X if ( cc >= 0 )
- X {
- X idp->end = idp->buf + cc ;
- X idp->start = idp->nextb = idp->buf ;
- X return( cc ) ;
- X }
- X }
- X#endif /* HAS_MMAP */
- X
- X for ( ;; )
- X {
- X cc = read( fd, idp->buf, (int) idp->buffer_size ) ;
- X if ( cc == -1 )
- X if ( errno == EINTR )
- X continue ;
- X else
- X return( SIO_ERR ) ;
- X else
- X break ;
- X }
- X
- X idp->end = idp->buf + cc ;
- X idp->start = idp->nextb = idp->buf ;
- X return( cc ) ;
- X}
- X
- X
- X/*
- X * __sio_extend_buffer is used by Srdline to extend the buffer
- X * If successful, it returns the number of bytes that have been read.
- X * If it fails (because of end-of-file or I/O error), it returns 0 or -1.
- X *
- X * Fields modified:
- X * idp->start points to the start of the buffer area (which is in the
- X * auxiliary buffer)
- X * Also, if successful, idp->nextb is set to idp->buf, idp->end is modified.
- X */
- Xint __sio_extend_buffer( idp, fd, b_left )
- X register __sio_id_t *idp ;
- X int fd ;
- X register int b_left ;
- X{
- X register int b_read ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_SIO_EXTEND_BUFFER ) ;
- X#endif
- X
- X /*
- X * copy to auxiliary buffer
- X */
- X if ( b_left )
- X sio_memcopy( idp->nextb, idp->buf - b_left, b_left ) ;
- X b_read = __sio_readf( idp, fd ) ;
- X idp->start = idp->buf - b_left ;
- X return( b_read ) ;
- X}
- X
- X
- X/*
- X * __sio_more tries to read more data from the given file descriptor iff
- X * there is free space in the buffer.
- X * __sio_more is used only by Srdline and only AFTER __sio_extend_buffer
- X * has been called. This implies that
- X * a) this is not a memory mapped file
- X * b) __sio_readf has been called (so we don't need to check for tied fd's
- X *
- X * Fields modified (only if successful):
- X * idp->end
- X *
- X * Return value: the number of bytes read.
- X */
- Xint __sio_more( idp, fd )
- X register __sio_id_t *idp ;
- X int fd ;
- X{
- X register int b_left = &idp->buf[ idp->buffer_size ] - idp->end ;
- X register int cc ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_SIO_MORE ) ;
- X#endif
- X
- X if ( b_left <= 0 )
- X return( 0 ) ;
- X
- X for ( ;; )
- X {
- X cc = read( fd, idp->end, b_left ) ;
- X if ( cc >= 0 )
- X {
- X idp->end += cc ;
- X return( cc ) ;
- X }
- X else
- X if ( errno == EINTR )
- X continue ;
- X else
- X return( SIO_ERR ) ;
- X }
- X}
- X
- X
- X/*
- X * Finalize a buffer by unmapping the file or freeing the malloc'ed memory
- X */
- Xint Sdone( fd )
- X int fd ;
- X{
- X register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
- X
- X#ifdef EVENTS
- X EVENT( fd, EV_SDONE ) ;
- X#endif
- X
- X if ( ! DESCRIPTOR_INITIALIZED( dp ) )
- X {
- X errno = EBADF ;
- X return( SIO_ERR ) ;
- X }
- X
- X switch ( dp->stream_type )
- X {
- X case __SIO_INPUT_STREAM:
- X {
- X register __sio_id_t *idp = IDP( dp ) ;
- X
- X#ifdef HAS_MMAP
- X if ( idp->memory_mapped )
- X {
- X register mapd_s *mdp = MDP( fd ) ;
- X
- X if ( mdp->first_unit.addr != CHAR_NULL )
- X (void) SIO_MUNMAP( mdp->first_unit.addr,
- X mdp->first_unit.mapped_bytes ) ;
- X if ( mdp->second_unit.addr != CHAR_NULL )
- X (void) SIO_MUNMAP( mdp->second_unit.addr,
- X mdp->second_unit.mapped_bytes ) ;
- X idp->memory_mapped = FALSE ;
- X }
- X else
- X#endif /* HAS_MMAP */
- X free( idp->buf - idp->buffer_size ) ;
- X idp->nextb = idp->end = NULL ;
- X }
- X break ;
- X
- X case __SIO_OUTPUT_STREAM:
- X {
- X register __sio_od_t *odp = ODP( dp ) ;
- X
- X if ( Sflush( fd ) == SIO_ERR )
- X return( SIO_ERR ) ;
- X free( odp->buf ) ;
- X odp->nextb = odp->buf_end = NULL ;
- X }
- X break ;
- X
- X default:
- X terminate( "SIO Sdone: bad stream type\n" ) ;
- X }
- X
- X dp->initialized = FALSE ;
- X return( 0 ) ;
- X}
- X
- X
- XPRIVATE char *expand( area, old_size, new_size, is_static )
- X char *area ;
- X unsigned old_size, new_size ;
- X int is_static ;
- X{
- X char *new_area ;
- X
- X if ( is_static )
- X {
- X if ( ( new_area = malloc( new_size ) ) == NULL )
- X return( NULL ) ;
- X sio_memcopy( area, new_area, old_size ) ;
- X }
- X else
- X if ( ( new_area = realloc( area, new_size ) ) == NULL )
- X return( NULL ) ;
- X return( new_area ) ;
- X}
- X
- X
- X#include <sys/time.h>
- X#include <sys/resource.h>
- X
- XPRIVATE int get_fd_limit()
- X{
- X#ifdef RLIMIT_NOFILE
- X
- X struct rlimit rl ;
- X
- X (void) getrlimit( RLIMIT_NOFILE, &rl ) ;
- X return( rl.rlim_cur ) ;
- X
- X#else
- X
- X return( N_SIO_DESCRIPTORS ) ;
- X
- X#endif
- X}
- X
- X/*
- X * Expand the descriptor array (and if we use memory mapping the
- X * memory mapping descriptors). We first expand the memory mapping
- X * descriptors.
- X * There is no problem if the expansion of the SIO descriptors fails
- X * (i.e. there is no need to undo anything).
- X */
- Xint Smorefds()
- X{
- X char *p ;
- X int is_static ;
- X unsigned new_size, old_size ;
- X int n_fds = get_fd_limit() ;
- X
- X if ( n_fds <= n_descriptors )
- X return( 0 ) ;
- X
- X#ifdef EVENTS
- X old_size = n_descriptors * sizeof( events_s ) ;
- X new_size = n_fds * sizeof( events_s ) ;
- X is_static = ( __sio_events == static___sio_events ) ;
- X p = expand( (char *)__sio_events, old_size, new_size, is_static ) ;
- X if ( p == NULL )
- X return( SIO_ERR ) ;
- X __sio_events = (events_s *) p ;
- X
- X /*
- X * Clear the codes field of the extra events structs.
- X * We have to do this because a non-null codes field implies that
- X * events recording is on for that fd
- X */
- X {
- X int i ;
- X
- X for ( i = n_descriptors ; i < n_fds ; i++ )
- X __sio_events[i].codes = NULL ;
- X }
- X#endif /* EVENTS */
- X
- X#ifdef HAS_MMAP
- X old_size = n_descriptors * sizeof( mapd_s ) ;
- X new_size = n_fds * sizeof( mapd_s ) ;
- X is_static = ( mmap_descriptors == static_mapd_array ) ;
- X p = expand( (char *)mmap_descriptors, old_size, new_size, is_static ) ;
- X if ( p == NULL )
- X return( SIO_ERR ) ;
- X mmap_descriptors = (mapd_s *) p ;
- X#endif /* HAS_MMAP */
- X
- X old_size = n_descriptors * sizeof( __sio_descriptor_t ) ;
- X new_size = n_fds * sizeof( __sio_descriptor_t ) ;
- X is_static = ( __sio_descriptors == static_descriptor_array ) ;
- X p = expand( (char *)__sio_descriptors, old_size, new_size, is_static ) ;
- X if ( p == NULL )
- X return( SIO_ERR ) ;
- X __sio_descriptors = (__sio_descriptor_t *) p ;
- X
- X n_descriptors = n_fds ;
- X return( 0 ) ;
- X}
- X
- X
- X#ifdef EVENTS
- X
- X/*
- X * Enable recording of events for the specified file descriptor
- X */
- Xint __sio_enable_events( fd )
- X int fd ;
- X{
- X char *p = malloc( EVENT_ENTRIES * sizeof( short ) ) ;
- X
- X if ( p == NULL )
- X return( SIO_ERR ) ;
- X
- X __sio_events[ fd ].codes = (short *) p ;
- X return( 0 ) ;
- X}
- X
- X
- X/*
- X * Disable recording of events for the specified file descriptor
- X */
- Xvoid __sio_disable_events( fd )
- X int fd ;
- X{
- X if ( __sio_events[ fd ].codes != NULL )
- X {
- X free( (char *) __sio_events[ fd ].codes ) ;
- X __sio_events[ fd ].codes = NULL ;
- X }
- X}
- X
- X
- X/*
- X * Move stored events to buf
- X */
- Xint __sio_get_events( fd, buf, size )
- X int fd ;
- X char *buf ;
- X int size ;
- X{
- X events_s *evp = &__sio_events[ fd ] ;
- X int bufentries ;
- X int range1, range2 ;
- X int diff ;
- X char *p ;
- X int cc ;
- X int cc_total ;
- X int move_entries ;
- X
- X if ( evp->codes == NULL )
- X return( 0 ) ;
- X
- X diff = evp->next - evp->start ;
- X if ( diff == 0 )
- X return( 0 ) ;
- X
- X if ( diff > 0 )
- X {
- X range1 = diff ;
- X range2 = 0 ;
- X }
- X else
- X {
- X range1 = EVENT_ENTRIES - evp->start ;
- X range2 = evp->next ;
- X }
- X
- X bufentries = size / sizeof( short ) ;
- X p = buf ;
- X cc_total = 0 ;
- X
- X move_entries = MIN( range1, bufentries ) ;
- X cc = move_entries * sizeof( short ) ;
- X sio_memcopy( (char *) &evp->codes[ evp->start ], p, cc ) ;
- X cc_total += cc ;
- X p += cc ;
- X bufentries -= range1 ;
- X ADD( evp->start, move_entries ) ;
- X
- X if ( bufentries == 0 || range2 == 0 )
- X return( cc_total ) ;
- X
- X move_entries = MIN( range2, bufentries ) ;
- X cc = move_entries * sizeof( short ) ;
- X sio_memcopy( (char *) &evp->codes[ evp->start ], p, cc ) ;
- X cc_total += cc ;
- X ADD( evp->start, move_entries ) ;
- X
- X return( cc_total ) ;
- X}
- X
- X#endif /* EVENTS */
- X
- X
- X/*
- X * Simple function that prints the string s at stderr and then calls
- X * exit
- X */
- XPRIVATE void terminate( s )
- X char *s ;
- X{
- X (void) write( 2, s, strlen( s ) ) ;
- X (void) abort() ;
- X exit( 1 ) ; /* in case abort fails */
- X}
- X
- END_OF_FILE
- if test 24088 -ne `wc -c <'libs/src/sio/siosup.c'`; then
- echo shar: \"'libs/src/sio/siosup.c'\" unpacked with wrong size!
- fi
- # end of 'libs/src/sio/siosup.c'
- fi
- if test -f 'libs/src/sio/sprint.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libs/src/sio/sprint.c'\"
- else
- echo shar: Extracting \"'libs/src/sio/sprint.c'\" \(17542 characters\)
- sed "s/^X//" >'libs/src/sio/sprint.c' <<'END_OF_FILE'
- X/*
- 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
- X
- Xstatic char RCSid[] = "$Id: sprint.c,v 8.3 1993/03/30 21:33:44 panos Exp $" ;
- X
- X#include <ctype.h>
- X
- X#include "sio.h"
- X#include "impl.h"
- X
- X#ifndef WIDE_INT
- X#define WIDE_INT long
- X#endif
- X
- Xtypedef WIDE_INT wide_int ;
- Xtypedef unsigned WIDE_INT u_wide_int ;
- Xtypedef int bool_int ;
- X
- X#define S_NULL "(null)"
- X#define S_NULL_LEN 6
- X
- X#define FLOAT_DIGITS 6
- X#define EXPONENT_LENGTH 10
- X
- X/*
- X * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
- X *
- X * XXX: this is a magic number; do not decrease it
- X */
- X#define NUM_BUF_SIZE 512
- X
- X/*
- X * The INS_CHAR macro inserts a character in the buffer and writes
- X * the buffer back to disk if necessary
- X * It uses the char pointers sp and bep:
- X * sp points to the next available character in the buffer
- X * bep points to the end-of-buffer+1
- X * While using this macro, note that the nextb pointer is NOT updated.
- X *
- X * No I/O is performed if fd is not positive. Negative fd values imply
- X * conversion with the output directed to a string. Excess characters
- X * are discarded if the string overflows.
- X *
- X * NOTE: Evaluation of the c argument should not have any side-effects
- X */
- X#define INS_CHAR( c, sp, bep, odp, cc, fd ) \
- X { \
- X if ( sp < bep ) \
- X { \
- X *sp++ = c ; \
- X cc++ ; \
- X } \
- X else \
- X { \
- X if ( fd >= 0 ) \
- X { \
- X odp->nextb = sp ; \
- X if ( __sio_writef( odp, fd ) != bep - odp->start ) \
- X return( ( cc != 0 ) ? cc : SIO_ERR ) ; \
- X sp = odp->nextb ; \
- X *sp++ = c ; \
- X cc++ ; \
- X } \
- X } \
- X if ( __SIO_MUST_FLUSH( *odp, c ) && fd >= 0 ) \
- X { \
- X int b_in_buffer = sp - odp->start ; \
- X \
- X odp->nextb = sp ; \
- X if ( __sio_writef( odp, fd ) != b_in_buffer ) \
- X return( cc ) ; \
- X sp = odp->nextb ; \
- X } \
- X }
- X
- X
- X
- X#define NUM( c ) ( c - '0' )
- X
- X#define STR_TO_DEC( str, num ) \
- X num = NUM( *str++ ) ; \
- X while ( isdigit( *str ) ) \
- X { \
- X num *= 10 ; \
- X num += NUM( *str++ ) ; \
- X }
- X
- X/*
- X * This macro does zero padding so that the precision
- X * requirement is satisfied. The padding is done by
- X * adding '0's to the left of the string that is going
- X * to be printed.
- X */
- X#define FIX_PRECISION( adjust, precision, s, s_len ) \
- X if ( adjust ) \
- X while ( s_len < precision ) \
- X { \
- X *--s = '0' ; \
- X s_len++ ; \
- X }
- X
- X/*
- X * Macro that does padding. The padding is done by printing
- X * the character ch.
- X */
- X#define PAD( width, len, ch ) do \
- X { \
- X INS_CHAR( ch, sp, bep, odp, cc, fd ) ; \
- X width-- ; \
- X } \
- X while ( width > len )
- X
- X/*
- X * Prefix the character ch to the string str
- X * Increase length
- X * Set the has_prefix flag
- X */
- X#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES
- X
- X
- X/*
- X * Sprint is the equivalent of printf for SIO.
- X * It returns the # of chars written
- X * Assumptions:
- X * - all floating point arguments are passed as doubles
- X */
- X/* VARARGS2 */
- Xint Sprint( fd, fmt, va_alist )
- X int fd ;
- X register char *fmt ;
- X va_dcl
- X{
- X __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
- X register __sio_od_t *odp = ODP( dp ) ;
- X register int cc ;
- X va_list ap ;
- X
- X IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
- X
- X va_start( ap ) ;
- X cc = __sio_converter( odp, fd, fmt, ap ) ;
- X va_end( ap ) ;
- X return( cc ) ;
- X}
- X
- X
- X/*
- X * This is the equivalent of vfprintf for SIO
- X */
- Xint Sprintv( fd, fmt, ap )
- X int fd ;
- X char *fmt ;
- X va_list ap ;
- X{
- X __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
- X register __sio_od_t *odp = ODP( dp ) ;
- X
- X IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
- X return( __sio_converter( odp, fd, fmt, ap ) ) ;
- X}
- X
- X
- X/*
- X * Convert a floating point number to a string formats 'f', 'e' or 'E'.
- X * The result is placed in buf, and len denotes the length of the string
- X * The sign is returned in the is_negative argument (and is not placed
- X * in buf).
- X */
- XPRIVATE char *conv_fp( format, num, add_dp, precision, is_negative, buf, len )
- X register char format ;
- X register double num ;
- X boolean_e add_dp ; /* always add decimal point if YES */
- X int precision ;
- X bool_int *is_negative ;
- X char buf[] ;
- X int *len ;
- X{
- X register char *s = buf ;
- X register char *p ;
- X int decimal_point ;
- X char *ecvt(), *fcvt() ;
- X char *conv_10() ;
- X char *strcpy() ;
- X
- X if ( format == 'f' )
- X p = fcvt( num, precision, &decimal_point, is_negative ) ;
- X else /* either e or E format */
- X p = ecvt( num, precision+1, &decimal_point, is_negative ) ;
- X
- X /*
- X * Check for Infinity and NaN
- X */
- X if ( isalpha( *p ) )
- X {
- X *len = strlen( strcpy( buf, p ) ) ;
- X *is_negative = FALSE ;
- X return( buf ) ;
- X }
- X
- X if ( format == 'f' )
- X if ( decimal_point <= 0 )
- X {
- X *s++ = '0' ;
- X if ( precision > 0 )
- X {
- X *s++ = '.' ;
- X while ( decimal_point++ < 0 )
- X *s++ = '0' ;
- X }
- X else if ( add_dp )
- X *s++ = '.' ;
- X }
- X else
- X {
- X while ( decimal_point-- > 0 )
- X *s++ = *p++ ;
- X if ( precision > 0 || add_dp ) *s++ = '.' ;
- X }
- X else
- X {
- X *s++ = *p++ ;
- X if ( precision > 0 || add_dp ) *s++ = '.' ;
- X }
- X
- X /*
- X * copy the rest of p, the NUL is NOT copied
- X */
- X while ( *p ) *s++ = *p++ ;
- X
- X if ( format != 'f' )
- X {
- X char temp[ EXPONENT_LENGTH ] ; /* for exponent conversion */
- X int t_len ;
- X bool_int exponent_is_negative ;
- X
- X *s++ = format ; /* either e or E */
- X decimal_point-- ;
- X if ( decimal_point != 0 )
- X {
- X p = conv_10( (wide_int)decimal_point, FALSE, &exponent_is_negative,
- X &temp[ EXPONENT_LENGTH ], &t_len ) ;
- X *s++ = exponent_is_negative ? '-' : '+' ;
- X
- X /*
- X * Make sure the exponent has at least 2 digits
- X */
- X if ( t_len == 1 )
- X *s++ = '0' ;
- X while ( t_len-- ) *s++ = *p++ ;
- X }
- X else
- X {
- X *s++ = '+' ;
- X *s++ = '0' ;
- X *s++ = '0' ;
- X }
- X }
- X
- X *len = s - buf ;
- X return( buf ) ;
- X}
- X
- X
- X/*
- X * Convert num to a base X number where X is a power of 2. nbits determines X.
- X * For example, if nbits is 3, we do base 8 conversion
- X * Return value:
- X * a pointer to a string containing the number
- X *
- X * The caller provides a buffer for the string: that is the buf_end argument
- X * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
- X * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
- X */
- XPRIVATE char *conv_p2( num, nbits, format, buf_end, len )
- X register u_wide_int num ;
- X register int nbits ;
- X char format ;
- X char *buf_end ;
- X register int *len ;
- X{
- X register int mask = ( 1 << nbits ) - 1 ;
- X register char *p = buf_end ;
- X static char low_digits[] = "0123456789abcdef" ;
- X static char upper_digits[] = "0123456789ABCDEF" ;
- X register char *digits = ( format == 'X' ) ? upper_digits : low_digits ;
- X
- X do
- X {
- X *--p = digits[ num & mask ] ;
- X num >>= nbits ;
- X }
- X while( num ) ;
- X
- X *len = buf_end - p ;
- X return( p ) ;
- X}
- X
- X
- X
- X/*
- X * Convert num to its decimal format.
- X * Return value:
- X * - a pointer to a string containing the number (no sign)
- X * - len contains the length of the string
- X * - is_negative is set to TRUE or FALSE depending on the sign
- X * of the number (always set to FALSE if is_unsigned is TRUE)
- X *
- X * The caller provides a buffer for the string: that is the buf_end argument
- X * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
- X * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
- X */
- XPRIVATE char *conv_10( num, is_unsigned, is_negative, buf_end, len )
- X register wide_int num ;
- X register bool_int is_unsigned ;
- X register bool_int *is_negative ;
- X char *buf_end ;
- X register int *len ;
- X{
- X register char *p = buf_end ;
- X register u_wide_int magnitude ;
- X
- X if ( is_unsigned )
- X {
- X magnitude = (u_wide_int) num ;
- X *is_negative = FALSE ;
- X }
- X else
- X {
- X *is_negative = ( num < 0 ) ;
- X
- X /*
- X * On a 2's complement machine, negating the most negative integer
- X * results in a number that cannot be represented as a signed integer.
- X * Here is what we do to obtain the number's magnitude:
- X * a. add 1 to the number
- X * b. negate it (becomes positive)
- X * c. convert it to unsigned
- X * d. add 1
- X */
- X if ( *is_negative )
- X {
- X wide_int t = num + 1 ;
- X
- X magnitude = ( (u_wide_int) -t ) + 1 ;
- X }
- X else
- X magnitude = (u_wide_int) num ;
- X }
- X
- X /*
- X * We use a do-while loop so that we write at least 1 digit
- X */
- X do
- X {
- X register u_wide_int new_magnitude = magnitude / 10 ;
- X
- X *--p = magnitude - new_magnitude*10 + '0' ;
- X magnitude = new_magnitude ;
- X }
- X while ( magnitude ) ;
- X
- X *len = buf_end - p ;
- X return( p ) ;
- X}
- X
- X
- X/*
- X * Do format conversion placing the output in odp
- X */
- Xint __sio_converter( odp, fd, fmt, ap )
- X register __sio_od_t *odp ;
- X int fd ;
- X register char *fmt ;
- X va_list ap ;
- X{
- X register char *sp ;
- X register char *bep ;
- X register int cc = 0 ;
- X register int i ;
- X
- X register char *s ;
- X char *q ;
- X int s_len ;
- X
- X register int min_width ;
- X int precision ;
- X enum { LEFT, RIGHT } adjust ;
- X char pad_char ;
- X char prefix_char ;
- X
- X double fp_num ;
- X wide_int i_num ;
- X u_wide_int ui_num ;
- X
- X char num_buf[ NUM_BUF_SIZE ] ;
- X char char_buf[ 2 ] ; /* for printing %% and %<unknown> */
- X
- X /*
- X * Flag variables
- X */
- X boolean_e is_long ;
- X boolean_e alternate_form ;
- X boolean_e print_sign ;
- X boolean_e print_blank ;
- X boolean_e adjust_precision ;
- X boolean_e adjust_width ;
- X bool_int is_negative ;
- X
- X char *conv_10(), *conv_p2(), *conv_fp() ;
- X char *gcvt() ;
- X char *strchr() ;
- X
- X
- X sp = odp->nextb ;
- X bep = odp->buf_end ;
- X
- X while ( *fmt )
- X {
- X if ( *fmt != '%' )
- X {
- X INS_CHAR( *fmt, sp, bep, odp, cc, fd ) ;
- X }
- X else
- X {
- X /*
- X * Default variable settings
- X */
- X adjust = RIGHT ;
- X alternate_form = print_sign = print_blank = NO ;
- X pad_char = ' ' ;
- X prefix_char = NUL ;
- X
- X fmt++ ;
- X
- X /*
- X * Try to avoid checking for flags, width or precision
- X */
- X if ( isascii( *fmt ) && ! islower( *fmt ) )
- X {
- X /*
- X * Recognize flags: -, #, BLANK, +
- X */
- X for ( ;; fmt++ )
- X {
- X if ( *fmt == '-' )
- X adjust = LEFT ;
- X else if ( *fmt == '+' )
- X print_sign = YES ;
- X else if ( *fmt == '#' )
- X alternate_form = YES ;
- X else if ( *fmt == ' ' )
- X print_blank = YES ;
- X else if ( *fmt == '0' )
- X pad_char = '0' ;
- X else
- X break ;
- X }
- X
- X /*
- X * Check if a width was specified
- X */
- X if ( isdigit( *fmt ) )
- X {
- X STR_TO_DEC( fmt, min_width ) ;
- X adjust_width = YES ;
- X }
- X else if ( *fmt == '*' )
- X {
- X min_width = va_arg( ap, int ) ;
- X fmt++ ;
- X adjust_width = YES ;
- X if ( min_width < 0 )
- X {
- X adjust = LEFT ;
- X min_width = -min_width ;
- X }
- X }
- X else
- X adjust_width = NO ;
- X
- X /*
- X * Check if a precision was specified
- X *
- X * XXX: an unreasonable amount of precision may be specified
- X * resulting in overflow of num_buf. Currently we
- X * ignore this possibility.
- X */
- X if ( *fmt == '.' )
- X {
- X adjust_precision = YES ;
- X fmt++ ;
- X if ( isdigit( *fmt ) )
- X {
- X STR_TO_DEC( fmt, precision ) ;
- X }
- X else if ( *fmt == '*' )
- X {
- X precision = va_arg( ap, int ) ;
- X fmt++ ;
- X if ( precision < 0 )
- X precision = 0 ;
- X }
- X else
- X precision = 0 ;
- X }
- X else
- X adjust_precision = NO ;
- X }
- X else
- X adjust_precision = adjust_width = NO ;
- X
- X /*
- X * Modifier check
- X */
- X if ( *fmt == 'l' )
- X {
- X is_long = YES ;
- X fmt++ ;
- X }
- X else
- X is_long = NO ;
- X
- X /*
- X * Argument extraction and printing.
- X * First we determine the argument type.
- X * Then, we convert the argument to a string.
- X * On exit from the switch, s points to the string that
- X * must be printed, s_len has the length of the string
- X * The precision requirements, if any, are reflected in s_len.
- X *
- X * NOTE: pad_char may be set to '0' because of the 0 flag.
- X * It is reset to ' ' by non-numeric formats
- X */
- X switch( *fmt )
- X {
- X case 'd':
- X case 'i':
- X case 'u':
- X if ( is_long )
- X i_num = va_arg( ap, wide_int ) ;
- X else
- X i_num = (wide_int) va_arg( ap, int ) ;
- X s = conv_10( i_num, (*fmt) == 'u', &is_negative,
- X &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
- X FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
- X
- X if ( *fmt != 'u' )
- X {
- X if ( is_negative )
- X prefix_char = '-' ;
- X else if ( print_sign )
- X prefix_char = '+' ;
- X else if ( print_blank )
- X prefix_char = ' ' ;
- X }
- X break ;
- X
- X
- X case 'o':
- X if ( is_long )
- X ui_num = va_arg( ap, u_wide_int ) ;
- X else
- X ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
- X s = conv_p2( ui_num, 3, *fmt,
- X &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
- X FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
- X if ( alternate_form && *s != '0' )
- X {
- X *--s = '0' ;
- X s_len++ ;
- X }
- X break ;
- X
- X
- X case 'x':
- X case 'X':
- X if ( is_long )
- X ui_num = (u_wide_int) va_arg( ap, u_wide_int ) ;
- X else
- X ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
- X s = conv_p2( ui_num, 4, *fmt,
- X &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
- X FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
- X if ( alternate_form && i_num != 0 )
- X {
- X *--s = *fmt ; /* 'x' or 'X' */
- X *--s = '0' ;
- X s_len += 2 ;
- X }
- X break ;
- X
- X
- X case 's':
- X s = va_arg( ap, char * ) ;
- X if ( s != NULL )
- X {
- X s_len = strlen( s ) ;
- X if ( adjust_precision && precision < s_len )
- X s_len = precision ;
- X }
- X else
- X {
- X s = S_NULL ;
- X s_len = S_NULL_LEN ;
- X }
- X pad_char = ' ' ;
- X break ;
- X
- X
- X case 'f':
- X case 'e':
- X case 'E':
- X fp_num = va_arg( ap, double ) ;
- X
- X s = conv_fp( *fmt, fp_num, alternate_form,
- X ( adjust_precision == NO ) ? FLOAT_DIGITS : precision,
- X &is_negative, &num_buf[ 1 ], &s_len ) ;
- X if ( is_negative )
- X prefix_char = '-' ;
- X else if ( print_sign )
- X prefix_char = '+' ;
- X else if ( print_blank )
- X prefix_char = ' ' ;
- X break ;
- X
- X
- X case 'g':
- X case 'G':
- X if ( adjust_precision == NO )
- X precision = FLOAT_DIGITS ;
- X else if ( precision == 0 )
- X precision = 1 ;
- X /*
- X * We use &num_buf[ 1 ], so that we have room for the sign
- X */
- X s = gcvt( va_arg( ap, double ), precision, &num_buf[ 1 ] ) ;
- X if ( *s == '-' )
- X prefix_char = *s++ ;
- X else if ( print_sign )
- X prefix_char = '+' ;
- X else if ( print_blank )
- X prefix_char = ' ' ;
- X
- X s_len = strlen( s ) ;
- X
- X if ( alternate_form && ( q = strchr( s, '.' ) ) == NULL )
- X s[ s_len++ ] = '.' ;
- X if ( *fmt == 'G' && ( q = strchr( s, 'e' ) ) != NULL )
- X *q = 'E' ;
- X break ;
- X
- X
- X case 'c':
- X char_buf[ 0 ] = (char) (va_arg( ap, int )) ;
- X s = &char_buf[ 0 ] ;
- X s_len = 1 ;
- X pad_char = ' ' ;
- X break ;
- X
- X
- X case '%':
- X char_buf[ 0 ] = '%' ;
- X s = &char_buf[ 0 ] ;
- X s_len = 1 ;
- X pad_char = ' ' ;
- X break ;
- X
- X
- X case 'n':
- X *(va_arg( ap, int * )) = cc ;
- X break ;
- X
- X /*
- X * Always extract the argument as a "char *" pointer. We
- X * should be using "void *" but there are still machines
- X * that don't understand it.
- X * If the pointer size is equal to the size of an unsigned
- X * integer we convert the pointer to a hex number, otherwise
- X * we print "%p" to indicate that we don't handle "%p".
- X */
- X case 'p':
- X ui_num = (u_wide_int) va_arg( ap, char * ) ;
- X
- X if ( sizeof( char * ) <= sizeof( u_wide_int ) )
- X s = conv_p2( ui_num, 4, 'x',
- X &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
- X else
- X {
- X s = "%p" ;
- X s_len = 2 ;
- X }
- X pad_char = ' ' ;
- X break ;
- X
- X
- X case NUL:
- X /*
- X * The last character of the format string was %.
- X * We ignore it.
- X */
- X continue ;
- X
- X
- X /*
- X * The default case is for unrecognized %'s.
- X * We print %<char> to help the user identify what
- X * option is not understood.
- X * This is also useful in case the user wants to pass
- X * the output of __sio_converter to another function
- X * that understands some other %<char> (like syslog).
- X * Note that we can't point s inside fmt because the
- X * unknown <char> could be preceded by width etc.
- X */
- X default:
- X char_buf[ 0 ] = '%' ;
- X char_buf[ 1 ] = *fmt ;
- X s = char_buf ;
- X s_len = 2 ;
- X pad_char = ' ' ;
- X break ;
- X }
- X
- X if ( prefix_char != NUL )
- X {
- X *--s = prefix_char ;
- X s_len++ ;
- X }
- X
- X if ( adjust_width && adjust == RIGHT && min_width > s_len )
- X {
- X if ( pad_char == '0' && prefix_char != NUL )
- X {
- X INS_CHAR( *s, sp, bep, odp, cc, fd )
- X s++ ;
- X s_len-- ;
- X min_width-- ;
- X }
- X PAD( min_width, s_len, pad_char ) ;
- X }
- X
- X /*
- X * Print the string s.
- X */
- X for ( i = s_len ; i != 0 ; i-- )
- X {
- X INS_CHAR( *s, sp, bep, odp, cc, fd ) ;
- X s++ ;
- X }
- X
- X if ( adjust_width && adjust == LEFT && min_width > s_len )
- X PAD( min_width, s_len, pad_char ) ;
- X }
- X fmt++ ;
- X }
- X odp->nextb = sp ;
- X return( cc ) ;
- X}
- X
- END_OF_FILE
- if test 17542 -ne `wc -c <'libs/src/sio/sprint.c'`; then
- echo shar: \"'libs/src/sio/sprint.c'\" unpacked with wrong size!
- fi
- # end of 'libs/src/sio/sprint.c'
- fi
- if test ! -d 'libs/src/sio/suite' ; then
- echo shar: Creating directory \"'libs/src/sio/suite'\"
- mkdir 'libs/src/sio/suite'
- fi
- if test ! -d 'libs/src/str' ; then
- echo shar: Creating directory \"'libs/src/str'\"
- mkdir 'libs/src/str'
- fi
- if test ! -d 'pst' ; then
- echo shar: Creating directory \"'pst'\"
- mkdir 'pst'
- fi
- if test -f 'pst/common.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pst/common.c'\"
- else
- echo shar: Extracting \"'pst/common.c'\" \(4850 characters\)
- sed "s/^X//" >'pst/common.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: common.c,v 1.4 1993/02/10 21:16:10 panos Exp $" ;
- X
- X#include <varargs.h>
- X
- Xvoid exit() ;
- Xchar *malloc() ;
- Xchar *realloc() ;
- X
- X#include "sio.h"
- X
- X#include "defs.h"
- X
- X/*
- X * Skip all characters in the input until you find the character in 'c'
- X */
- Xvoid skip_until( fd, c )
- X int fd ;
- X int c ;
- X{
- X int ic ;
- X
- X for ( ;; )
- X {
- X NEXT_CHAR( fd, ic ) ;
- X if ( ic == SIO_EOF || ic == c )
- X return ;
- X }
- X}
- X
- X
- X/*
- X * Skip procedure definition: we assume that a procedure starts with an
- X * open curly bracket.
- X */
- Xvoid skip_bracket( fd, open_bracket, closed_bracket )
- X int fd ;
- X char open_bracket, closed_bracket ;
- X{
- X int c ;
- X int bracket_level = 1 ;
- X int start_line = line_count ;
- X
- X while ( bracket_level > 0 )
- X {
- X NEXT_CHAR( fd, c ) ;
- X if ( c == SIO_EOF )
- X error(
- X "Reached EOF while looking for '%c' (search started at line %d)\n",
- X closed_bracket, start_line ) ;
- X if ( c == closed_bracket )
- X bracket_level-- ;
- X else if ( c == open_bracket )
- X bracket_level++ ;
- X }
- X}
- X
- X
- Xint next_char( fd )
- X int fd ;
- X{
- X int c ;
- X
- X NEXT_CHAR( fd, c ) ;
- X if ( c == SIO_EOF )
- X error( "Unexpected end of file\n" ) ;
- X return( c ) ;
- X}
- X
- X
- X#define BUF_INCREMENT 1000
- X
- Xstatic char *outbuf ;
- Xstatic int buflen ;
- Xstatic int used ;
- Xstatic int replace_space_with_newline ;
- X
- Xvoid printout( c )
- X int c ;
- X{
- X if ( outbuf == NULL )
- X {
- X buflen = BUF_INCREMENT ;
- X outbuf = malloc( buflen ) ;
- X if ( outbuf == NULL )
- X error( "out of memory\n" ) ;
- X used = 0 ;
- X }
- X
- X if ( c == NEWLINE )
- X {
- X if ( outbuf[ used-1 ] == '-' )
- X {
- X used-- ; /* remove the '-' */
- X replace_space_with_newline = TRUE ;
- X return ;
- X }
- X }
- X else if ( c == SPACE && replace_space_with_newline )
- X {
- X c = NEWLINE ;
- X replace_space_with_newline = FALSE ;
- X }
- X
- X /*
- X * We only output complete lines
- X */
- X if ( c != NEWLINE )
- X {
- X if ( used == buflen )
- X {
- X char *newbuf ;
- X
- X buflen += BUF_INCREMENT ;
- X newbuf = realloc( outbuf, buflen ) ;
- X if ( newbuf == NULL )
- X error( "out of memory\n" ) ;
- X outbuf = newbuf ;
- X }
- X outbuf[ used++ ] = c ;
- X }
- X else
- X {
- X Swrite( 1, outbuf, used ) ;
- X Sputchar( 1, NEWLINE ) ;
- X used = 0 ;
- X }
- X}
- X
- X
- Xvoid printout_flush()
- X{
- X if ( used )
- X {
- X Swrite( 1, outbuf, used ) ;
- X Sputchar( 1, NEWLINE ) ;
- X used = 0 ;
- X }
- X}
- X
- X
- Xvoid start_paragraph()
- X{
- X printout_flush() ;
- X Sputchar( 1, NEWLINE ) ;
- X}
- X
- X
- Xvoid error( fmt, va_alist )
- X char *fmt ;
- X va_dcl
- X{
- X va_list ap ;
- X
- X va_start( ap ) ;
- X Sprint( 2, "Line %d: ", line_count ) ;
- X Sprintv( 2, fmt, ap ) ;
- X exit( 1 ) ;
- X}
- X
- X
- Xvoid decode_string( get_char, arg )
- X int (*get_char)() ;
- X void *arg ;
- X{
- X int c ;
- X int skip_input = FALSE ;
- X
- X for ( ;; )
- X {
- X if ( ! skip_input )
- X c = (*get_char)( arg ) ;
- X skip_input = FALSE ;
- X
- X if ( c == CLOSE_PAREN )
- X return ;
- X
- X if ( c != BACKSLASH )
- X {
- X printout( c ) ;
- X continue ;
- X }
- X
- X /*
- X * Interpret the character after the backslash
- X */
- X c = (*get_char) ( arg ) ;
- X if ( c == OPEN_PAREN || c == CLOSE_PAREN )
- X printout( c ) ;
- X else if ( c == 't' )
- X printout( TAB ) ;
- X else if ( c == 'n' )
- X printout( NEWLINE ) ;
- X else if ( c == BACKSLASH )
- X printout( BACKSLASH ) ;
- X else if ( isdigit( c ) )
- X {
- X int i ;
- X int num = NUM( c ) ;
- X
- X /*
- X * We ignore numbers; Postscript allows up to 3 digits in \ddd
- X * and we have already consumed one.
- X */
- X for ( i = 0 ; i < 2 ; i++ )
- X {
- X c = (*get_char)( arg ) ;
- X if ( isdigit( c ) )
- X {
- X num *= 8 ;
- X num += NUM( c ) ;
- X }
- X else
- X {
- X skip_input = TRUE ;
- X break ;
- X }
- X }
- X
- X if ( num == 013 )
- X {
- X printout( 'f' ) ;
- X printout( 'f' ) ;
- X }
- X else if ( num == 016 )
- X {
- X printout( 'f' ) ;
- X printout( 'f' ) ;
- X printout( 'i' ) ;
- X }
- X else if ( num == 0244 )
- X printout( '/' ) ;
- X else if ( num == 0251 || num == 0270 )
- X printout( '\'' ) ;
- X else if ( num == 0252 || num == 0271 || num == 0272 )
- X printout( '"' ) ;
- X else if ( num == 0253 )
- X {
- X printout( '<' ) ;
- X printout( '<' ) ;
- X }
- X else if ( num == 0254 )
- X printout( '<' ) ;
- X else if ( num == 0255 )
- X printout( '>' ) ;
- X else if ( num == 014 || num == 0256 )
- X {
- X printout( 'f' ) ;
- X printout( 'i' ) ;
- X }
- X else if ( num == 015 || num == 0257 )
- X {
- X printout( 'f' ) ;
- X printout( 'l' ) ;
- X }
- X else if ( num == 0261 )
- X printout( '-' ) ;
- X else if ( num == 0267 ) /* bullet point */
- X printout( '*' ) ;
- X else if ( num == 0273 )
- X {
- X printout( '>' ) ;
- X printout( '>' ) ;
- X }
- X else if ( num == 274 )
- X {
- X printout( '.' ) ;
- X printout( '.' ) ;
- X printout( '.' ) ;
- X }
- X else if ( num == 0303 )
- X printout( '^' ) ;
- X else if ( num == 0304 )
- X printout( '~' ) ;
- X else if ( isascii( num ) && isprint( num ) )
- X printout( num ) ;
- X }
- X }
- X}
- X
- END_OF_FILE
- if test 4850 -ne `wc -c <'pst/common.c'`; then
- echo shar: \"'pst/common.c'\" unpacked with wrong size!
- fi
- # end of 'pst/common.c'
- fi
- echo shar: End of archive 1 \(of 6\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-