home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / pst / part01 < prev    next >
Encoding:
Text File  |  1993-11-26  |  52.8 KB  |  2,307 lines

  1. Newsgroups: comp.sources.misc
  2. From: Panos Tsirigotis (panos@cs.colorado.edu)
  3. Subject: v40i172:  pst - extract text from a postscript file, Part01/06
  4. Message-ID: <csm-v40i172=pst.110518@sparky.Sterling.COM>
  5. X-Md4-Signature: 2f7b3216aa279e0492f29c35ad6658e2
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Fri, 26 Nov 1993 17:05:38 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: Panos Tsirigotis (panos@cs.colorado.edu)
  12. Posting-number: Volume 40, Issue 172
  13. Archive-name: pst/part01
  14. Environment: BSD, SUNOS, ULTRIX, SYSVR4, SYSVR3, POSIX
  15.  
  16. pst is a program that will extract the text of a postscript file and
  17. will try to make that text appear as it does in the postscript
  18. document.  This means that words will not be split, paragraph
  19. boundaries will be observed etc. In order to achieve this, pst first
  20. tries to identify how the postscript file was produced, so that it can
  21. use an appropriate text extraction algorithm. It is also possible for
  22. the user to specify which of the available algorithms to use to extract
  23. text.
  24. -------------------------
  25. #! /bin/sh
  26. # This is a shell archive.  Remove anything before this line, then feed it
  27. # into a shell via "sh file" or similar.  To overwrite existing files,
  28. # type "sh file -c".
  29. # Contents:  README libs libs/include libs/lib libs/man libs/src
  30. #   libs/src/sio libs/src/sio/siosup.c libs/src/sio/sprint.c
  31. #   libs/src/sio/suite libs/src/str pst pst/common.c
  32. # Wrapped by kent@sparky on Fri Nov 26 11:02:45 1993
  33. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  34. echo If this archive is complete, you will see the following message:
  35. echo '          "shar: End of archive 1 (of 6)."'
  36. if test -f 'README' -a "${1}" != "-c" ; then 
  37.   echo shar: Will not clobber existing file \"'README'\"
  38. else
  39.   echo shar: Extracting \"'README'\" \(762 characters\)
  40.   sed "s/^X//" >'README' <<'END_OF_FILE'
  41. X
  42. Xpst is a program that will extract the text of a postscript file and
  43. Xwill try to make that text appear as it does in the postscript
  44. Xdocument.  This means that words will not be split, paragraph
  45. Xboundaries will be observed etc. In order to achieve this, pst first
  46. Xtries to identify how the postscript file was produced so that it can
  47. Xuse an appropriate text extraction algorithm. It is also possible for
  48. Xthe user to specify which of the available algorithms to use to extract
  49. Xtext.
  50. X
  51. XThe INSTALL file has instructions on how to compile and setup pst.
  52. X
  53. XThis program used to be called 'pstext' but was renamed to 'pst' due
  54. Xto a naming conflict with another program that does the inverse job
  55. Xof 'pst'.
  56. X
  57. XPlease send any comments/bug-reports to panos@cs.colorado.edu
  58. X
  59. END_OF_FILE
  60.   if test 762 -ne `wc -c <'README'`; then
  61.     echo shar: \"'README'\" unpacked with wrong size!
  62.   fi
  63.   # end of 'README'
  64. fi
  65. if test ! -d 'libs' ; then
  66.     echo shar: Creating directory \"'libs'\"
  67.     mkdir 'libs'
  68. fi
  69. if test ! -d 'libs/include' ; then
  70.     echo shar: Creating directory \"'libs/include'\"
  71.     mkdir 'libs/include'
  72. fi
  73. if test ! -d 'libs/lib' ; then
  74.     echo shar: Creating directory \"'libs/lib'\"
  75.     mkdir 'libs/lib'
  76. fi
  77. if test ! -d 'libs/man' ; then
  78.     echo shar: Creating directory \"'libs/man'\"
  79.     mkdir 'libs/man'
  80. fi
  81. if test ! -d 'libs/src' ; then
  82.     echo shar: Creating directory \"'libs/src'\"
  83.     mkdir 'libs/src'
  84. fi
  85. if test ! -d 'libs/src/sio' ; then
  86.     echo shar: Creating directory \"'libs/src/sio'\"
  87.     mkdir 'libs/src/sio'
  88. fi
  89. if test -f 'libs/src/sio/siosup.c' -a "${1}" != "-c" ; then 
  90.   echo shar: Will not clobber existing file \"'libs/src/sio/siosup.c'\"
  91. else
  92.   echo shar: Extracting \"'libs/src/sio/siosup.c'\" \(24088 characters\)
  93.   sed "s/^X//" >'libs/src/sio/siosup.c' <<'END_OF_FILE'
  94. X/*
  95. X * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  96. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  97. X * and conditions for redistribution.
  98. X */
  99. X
  100. Xstatic char RCSid[] = "$Id: siosup.c,v 8.4 1993/03/17 07:35:24 panos Exp $" ;
  101. X
  102. X#include <sys/types.h>
  103. X#include <sys/stat.h>
  104. X#include <fcntl.h>
  105. X
  106. X#include "impl.h"
  107. X#include "sio.h"
  108. X
  109. X#ifdef EVENTS
  110. X#include "events.h"
  111. X#endif
  112. X
  113. Xchar *malloc() ;
  114. Xchar *realloc() ;
  115. X
  116. X
  117. Xstatic __sio_descriptor_t static_descriptor_array[ N_SIO_DESCRIPTORS ] ;
  118. Xstatic int n_descriptors = N_SIO_DESCRIPTORS ;
  119. X__sio_descriptor_t *__sio_descriptors = static_descriptor_array ;
  120. X
  121. X#ifdef EVENTS
  122. Xstatic events_s static___sio_events[ N_SIO_DESCRIPTORS ] ;
  123. Xevents_s *__sio_events = static___sio_events ;
  124. X#endif
  125. X
  126. X
  127. X/*
  128. X * Code for finalization
  129. X */
  130. X#ifdef HAS_FINALIZATION_FUNCTION
  131. Xstatic int finalizer_installed ;
  132. X
  133. XSIO_DEFINE_FIN( sio_cleanup )
  134. X{
  135. X   (void) Sflush( SIO_FLUSH_ALL ) ;
  136. X}
  137. X#endif /* HAS_FINALIZATION_FUNCTION */
  138. X
  139. X
  140. X
  141. X#ifdef HAS_MMAP
  142. X
  143. X#define CHAR_NULL                ((char *)0)
  144. X
  145. X/*
  146. X * PAGES_MAPPED gives the size of each map unit in pages
  147. X */
  148. X#define PAGES_MAPPED                2
  149. X
  150. Xstatic size_t map_unit_size = 0 ;            /* bytes */
  151. Xstatic size_t page_size = 0 ;                    /* bytes */
  152. X
  153. Xstatic mapd_s static_mapd_array[ N_SIO_DESCRIPTORS ] ;
  154. Xstatic mapd_s *mmap_descriptors = static_mapd_array ;
  155. X
  156. X#define MDP( fd )                ( mmap_descriptors + (fd) )
  157. X
  158. X
  159. X/*
  160. X * NOTES ON MEMORY MAPPING:
  161. X *
  162. X *     1. Memory mapping works only for file descriptors opened for input
  163. X *        2. Mapping an object to a part of the address space where another
  164. X *            object is mapped will cause the old mapping to disappear (i.e. mmap
  165. X *            will not fail)
  166. X *
  167. X * Memory mapping interface:
  168. X *        SIO_MMAP : maps a file into a portion of the address space.
  169. X *        SIO_MUNMAP: unmap a portion of the address space
  170. X *        SIO_MNEED: indicate to the OS that we will need a portion of
  171. X *                         our address space.
  172. X *
  173. X * The map_unit_size variable defines how much of the file is mapped at
  174. X * a time. It is a multiple of the operating system page size. It is
  175. X * not less than SIO_BUFFER_SIZE unless SIO_BUFFER_SIZE is not a
  176. X * multiple of the page size (so the SIO_BUFFER_SIZE overrides
  177. X * PAGES_MAPPED).
  178. X *
  179. X * NOTE: All memory mapping code is in this file only
  180. X */
  181. X
  182. X
  183. X/*
  184. X * Macros used by the memory mapping code
  185. X */
  186. X#define FIRST_TIME( dp )                    ( dp->buf == NULL )
  187. X#define FATAL_ERROR( msg )                    perror( msg ), exit( 1 )
  188. X
  189. X/*
  190. X * Functions to support memory mapping:
  191. X *
  192. X *            try_memory_mapping
  193. X *            buffer_setup
  194. X *            __sio_switch
  195. X *            initial_map
  196. X *            map_unit
  197. X */
  198. X
  199. X/*
  200. X * try_memory_mapping attempts to setup the specified descriptor
  201. X * for memory mapping. 
  202. X * It returns FAILURE if it fails and SUCCESS if it is successful.
  203. X * If HAS_MMAP is not defined, the function is defined to be FAILURE.
  204. X *
  205. X * Sets fields:
  206. X *        memory_mapped:             TRUE or FALSE
  207. X *        
  208. X * Also sets the following fields if memory_mapped is TRUE:
  209. X *    file_offset, file_size, buffer_size
  210. X *
  211. X */
  212. XPRIVATE status_e try_memory_mapping( fd, idp, stp )
  213. X    int fd ;
  214. X    register __sio_id_t *idp ;
  215. X    struct stat *stp ;
  216. X{
  217. X    int access ;
  218. X
  219. X#ifdef EVENTS
  220. X    EVENT( fd, EV_TRY_MEMORY_MAPPING ) ;
  221. X#endif
  222. X
  223. X    /*
  224. X     * Do not try memory mapping if:
  225. X     *        1) The file is not a regular file
  226. X     *        2) The file is a regular file but has zero-length
  227. X     *        3) The file pointer is not positioned at the beginning of the file
  228. X     *        4) The fcntl to obtain the file descriptor flags fails
  229. X     *        5) The access mode is not O_RDONLY or O_RDWR
  230. X     *
  231. X     * The operations are done in this order to avoid the system calls
  232. X     * if possible.
  233. X     */
  234. X    if ( ( ( stp->st_mode & S_IFMT ) != S_IFREG ) ||
  235. X          ( stp->st_size == 0 ) ||
  236. X          ( lseek( fd, (long)0, 1 ) != 0 ) ||
  237. X          ( ( access = fcntl( fd, F_GETFL, 0 ) ) == -1 ) ||
  238. X          ( ( access &= 0x3 ) != O_RDONLY && access != O_RDWR ) )
  239. X    {
  240. X        idp->memory_mapped = FALSE ;
  241. X        return( FAILURE ) ;
  242. X    }
  243. X
  244. X    /*
  245. X     * Determine page_size and map_unit_size.
  246. X     * Note that the code works even if PAGES_MAPPED is 0.
  247. X     */
  248. X    if ( page_size == 0 )
  249. X    {
  250. X        page_size = getpagesize() ;
  251. X        map_unit_size = page_size * PAGES_MAPPED ;
  252. X        if ( map_unit_size < SIO_BUFFER_SIZE )
  253. X            if ( map_unit_size > 0 && SIO_BUFFER_SIZE % map_unit_size == 0 )
  254. X                map_unit_size = SIO_BUFFER_SIZE ;
  255. X            else
  256. X                map_unit_size = page_size ;
  257. X    }
  258. X    
  259. X    MDP(fd)->file_offset = 0 ;
  260. X    MDP(fd)->file_size = stp->st_size ;
  261. X    idp->buffer_size = map_unit_size ;
  262. X    idp->buf = CHAR_NULL ;
  263. X    idp->memory_mapped = TRUE ;
  264. X
  265. X    return( SUCCESS ) ;
  266. X}
  267. X
  268. X
  269. X/*
  270. X * Copy the current_unit to the primary buffer
  271. X *
  272. X * Sets fields: start, end, nextb
  273. X * Also sets the file pointer
  274. X */
  275. XPRIVATE void buffer_setup( idp, fd, mu_cur, mu_next )
  276. X    __sio_id_t *idp ;
  277. X    int fd ;
  278. X    struct map_unit *mu_cur ;
  279. X    struct map_unit *mu_next ;
  280. X{
  281. X    off_t new_offset ;
  282. X
  283. X    sio_memcopy( mu_cur->addr, idp->buf, mu_cur->valid_bytes ) ;
  284. X    idp->start = idp->buf ;
  285. X    idp->end = idp->buf + mu_cur->valid_bytes ;
  286. X    idp->nextb = idp->buf + ( idp->nextb - mu_cur->addr ) ;
  287. X
  288. X    if ( mu_next->addr != CHAR_NULL )
  289. X        new_offset = MDP(fd)->file_offset - mu_next->valid_bytes ;
  290. X    else
  291. X        new_offset = MDP(fd)->file_offset ;
  292. X    (void) lseek( fd, new_offset, 0 ) ;
  293. X}
  294. X
  295. X
  296. X/*
  297. X * Switch from memory mapping to buffered I/O
  298. X * If any mapping has occured, then the current unit is
  299. X * copied into the buffer that is allocated.
  300. X * Any data in the next unit is ignored.
  301. X * We rely on idp->buf to identify the current unit (so it
  302. X * better be equal to the address of one of the units).
  303. X *
  304. X * Sets fields:
  305. X *            start, end, nextb
  306. X */
  307. Xstatus_e __sio_switch( idp, fd )
  308. X    register __sio_id_t *idp ;
  309. X    int fd ;
  310. X{
  311. X    register mapd_s *mdp = MDP( fd ) ;
  312. X    struct map_unit *mu_cur, *mu_next ;
  313. X    unsigned buffer_size = idp->buffer_size ;
  314. X    char *buf_addr = idp->buf ;
  315. X    int first_time = FIRST_TIME( idp ) ;
  316. X    void buffer_setup() ;
  317. X    status_e setup_read_buffer() ;
  318. X
  319. X#ifdef EVENTS
  320. X    EVENT( fd, EV_SIO_SWITCH ) ;
  321. X#endif
  322. X
  323. X    /*
  324. X     * Initialize stream for buffering
  325. X     */
  326. X    if ( setup_read_buffer( idp, buffer_size ) == FAILURE )
  327. X        return( FAILURE ) ;
  328. X
  329. X    if ( ! first_time )
  330. X    {
  331. X        /*
  332. X         * Find current, next unit
  333. X         */
  334. X        if ( buf_addr == mdp->first_unit.addr )
  335. X        {
  336. X            mu_cur = &mdp->first_unit ;
  337. X            mu_next = &mdp->second_unit ;
  338. X        }
  339. X        else
  340. X        {
  341. X            mu_cur = &mdp->second_unit ;
  342. X            mu_next = &mdp->first_unit ;
  343. X        }
  344. X
  345. X        buffer_setup( idp, fd, mu_cur, mu_next ) ;
  346. X        /*
  347. X         * Destroy all mappings
  348. X         */
  349. X        (void) SIO_MUNMAP( mu_cur->addr, mu_cur->mapped_bytes ) ;
  350. X        if ( mu_next->addr != NULL )
  351. X            (void) SIO_MUNMAP( mu_next->addr, mu_next->mapped_bytes ) ;
  352. X    }
  353. X    else
  354. X        idp->start = idp->end = idp->nextb = idp->buf ;
  355. X
  356. X    idp->memory_mapped = FALSE ;
  357. X    return( SUCCESS ) ;
  358. X}
  359. X
  360. X
  361. X/*
  362. X * initial_map does the first memory map on the file descriptor.
  363. X * It attempts to map both units.
  364. X * The mapping always starts at file offset 0.
  365. X *
  366. X * SETS FIELDS:
  367. X *            first_unit.*, second_unit.*
  368. X *            file_offset
  369. X *
  370. X * Returns: 
  371. X *            number of bytes mapped in first_unit
  372. X *    or
  373. X *            0 to indicate that mmap failed.
  374. X */
  375. XPRIVATE int initial_map( mdp, fd )
  376. X    register mapd_s *mdp ;
  377. X    int fd ;
  378. X{
  379. X    register caddr_t addr ;
  380. X    register size_t requested_length = 2 * map_unit_size ;
  381. X    register size_t mapped_length = MIN( mdp->file_size, requested_length ) ;
  382. X    size_t bytes_left ;
  383. X    register size_t bytes_in_unit ;
  384. X
  385. X#ifdef EVENTS
  386. X    EVENT( fd, EV_INITIAL_MAP ) ;
  387. X#endif
  388. X
  389. X    addr = SIO_MMAP( CHAR_NULL, mapped_length, fd, 0 ) ;
  390. X    if ( (int) addr == -1 )
  391. X        return( 0 ) ;
  392. X
  393. X    SIO_MNEED( addr, mapped_length ) ;
  394. X
  395. X    /*
  396. X     * Map as much as possible in the first unit
  397. X     */
  398. X    bytes_in_unit = MIN( mapped_length, map_unit_size ) ;
  399. X    mdp->first_unit.addr             = addr ;
  400. X    mdp->first_unit.mapped_bytes     = bytes_in_unit ;
  401. X    mdp->first_unit.valid_bytes     = bytes_in_unit ;
  402. X
  403. X    /*
  404. X     * If there is more, map it in the second unit.
  405. X     */
  406. X    bytes_left = mapped_length - bytes_in_unit ;
  407. X    if ( bytes_left > 0 )
  408. X    {
  409. X        mdp->second_unit.addr             = addr + bytes_in_unit ;
  410. X        mdp->second_unit.mapped_bytes = bytes_left ;
  411. X        mdp->second_unit.valid_bytes     = bytes_left ;
  412. X    }
  413. X    else
  414. X        mdp->second_unit.addr             = CHAR_NULL ;
  415. X
  416. X    mdp->file_offset = mapped_length ;
  417. X
  418. X    return( mdp->first_unit.valid_bytes ) ;
  419. X}
  420. X
  421. X
  422. X/*
  423. X * ALGORITHM:
  424. X *
  425. X *        if ( there are more bytes in the file )
  426. X *        {
  427. X *            map them at the given unit
  428. X *            update offset
  429. X *            issue SIO_MNEED()
  430. X *        }
  431. X *        else
  432. X *            unmap the unit
  433. X */
  434. XPRIVATE status_e map_unit( mdp, fd, mup )
  435. X    register mapd_s *mdp ;
  436. X    int fd ;
  437. X    register struct map_unit *mup ;
  438. X{
  439. X    register size_t bytes_left = mdp->file_size - mdp->file_offset ;
  440. X    register size_t bytes_to_map = MIN( bytes_left, map_unit_size ) ;
  441. X
  442. X#ifdef EVENTS
  443. X    EVENT( fd, EV_MAP_UNIT ) ;
  444. X#endif
  445. X
  446. X    if ( bytes_to_map > 0 )
  447. X    {
  448. X        if ( (int) SIO_MMAP( mup->addr, bytes_to_map,
  449. X                                                            fd, mdp->file_offset ) == -1 )
  450. X            return( FAILURE ) ;            /* XXX: need to do more ? */
  451. X        
  452. X        mup->valid_bytes = bytes_to_map ;
  453. X        ASSERT( mup->valid_bytes <= mup->mapped_bytes ) ;
  454. X        mdp->file_offset += bytes_to_map ;
  455. X        SIO_MNEED( mup->addr, mup->valid_bytes ) ;
  456. X    }
  457. X    else
  458. X    {
  459. X        (void) SIO_MUNMAP( mup->addr, mup->mapped_bytes ) ;
  460. X        mup->addr = CHAR_NULL ;
  461. X    }
  462. X    return( SUCCESS ) ;
  463. X}
  464. X
  465. X#else
  466. X
  467. X#define try_memory_mapping( x, y, z )                FAILURE
  468. X
  469. X#endif /* HAS_MMAP */
  470. X
  471. X
  472. XPRIVATE status_e setup_read_buffer( idp, buf_size )
  473. X    register __sio_id_t *idp ;
  474. X    unsigned buf_size ;
  475. X{
  476. X    register char *buf ;
  477. X
  478. X    /*
  479. X     * First allocate space for 2 buffers: primary and auxiliary
  480. X     */
  481. X    buf = malloc( buf_size * 2 ) ;
  482. X    if ( buf == NULL )
  483. X        return( FAILURE ) ;
  484. X
  485. X    /*
  486. X     * The descriptor buf field should point to the start of the main buffer
  487. X     */
  488. X    idp->buf = buf + buf_size ;
  489. X    idp->buffer_size = buf_size ;
  490. X    return( SUCCESS ) ;
  491. X}
  492. X
  493. X
  494. XPRIVATE status_e init_input_stream( idp, fd, stp )
  495. X    register __sio_id_t *idp ;
  496. X    int fd ;
  497. X    struct stat *stp ;
  498. X{
  499. X#ifdef EVENTS
  500. X    EVENT( fd, EV_INIT_INPUT_STREAM ) ;
  501. X#endif
  502. X
  503. X    /*
  504. X     * First initialize the fields relevant to buffering: buf, buffer_size
  505. X     */
  506. X    if ( try_memory_mapping( fd, idp, stp ) == FAILURE )
  507. X    {
  508. X        /*
  509. X         * Try to use normal buffering
  510. X         */
  511. X        unsigned buf_size = (unsigned)
  512. X                            ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
  513. X        
  514. X        if ( setup_read_buffer( idp, buf_size ) == FAILURE )
  515. X            return( FAILURE ) ;
  516. X    }
  517. X
  518. X     /*
  519. X     * Initialize remaining descriptor fields
  520. X     */
  521. X    idp->max_line_length = 2 * idp->buffer_size - 1 ;
  522. X    idp->start = idp->end = idp->nextb = idp->buf ;
  523. X    idp->tied_fd = SIO_NO_TIED_FD ;
  524. X
  525. X    return( SUCCESS ) ;
  526. X}
  527. X
  528. X
  529. XPRIVATE status_e init_output_stream( odp, fd, stp )
  530. X    register __sio_od_t *odp ;
  531. X    int fd ;
  532. X    struct stat *stp ;
  533. X{
  534. X    register unsigned buf_size ;
  535. X    register char *buf ;
  536. X
  537. X#ifdef EVENTS
  538. X    EVENT( fd, EV_INIT_OUTPUT_STREAM ) ;
  539. X#endif
  540. X
  541. X    buf_size = (unsigned)
  542. X                        ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
  543. X    buf = malloc( buf_size ) ;
  544. X    if ( buf == NULL )
  545. X        return( FAILURE ) ;
  546. X    
  547. X    /*
  548. X     * Initialize buffering fields
  549. X     */
  550. X    odp->buf = buf ;
  551. X    odp->buffer_size = buf_size ;
  552. X    odp->buf_end = odp->buf + buf_size ;
  553. X
  554. X    /*
  555. X     * Initialize remaining fields
  556. X     */
  557. X    odp->start = odp->nextb = odp->buf ;
  558. X    if ( isatty( fd ) )
  559. X        odp->buftype = SIO_LINEBUF ;
  560. X
  561. X    if ( fd == 2 )
  562. X        odp->buftype = SIO_NOBUF ;
  563. X
  564. X    return( SUCCESS ) ;
  565. X}
  566. X
  567. X
  568. X#ifndef HAS_ISATTY
  569. X
  570. X#ifdef HAS_SYSVTTY
  571. X
  572. X#include <termio.h>
  573. X
  574. XPRIVATE int isatty( fd )
  575. X    int fd ;
  576. X{
  577. X    struct termio t ;
  578. X
  579. X    if ( ioctl( fd, TCGETA, &t ) == -1 && errno == ENOTTY )
  580. X        return( FALSE ) ;
  581. X    else
  582. X        return( TRUE ) ;
  583. X}
  584. X#endif    /* HAS_SYSVTTY */
  585. X
  586. X#ifdef HAS_BSDTTY
  587. X
  588. X#include <sgtty.h>
  589. X
  590. XPRIVATE int isatty( fd )
  591. X    int fd ;
  592. X{
  593. X    struct sgttyb s ;
  594. X
  595. X    if ( ioctl( fd, TIOCGETP, &s ) == -1 && errno == ENOTTY )
  596. X        return( FALSE ) ;
  597. X    else
  598. X        return( TRUE ) ;
  599. X}
  600. X#endif    /* HAS_BSDTTY */
  601. X
  602. X#endif    /* ! HAS_ISATTY */
  603. X
  604. X
  605. X/*
  606. X * Initialize stream I/O for a file descriptor.
  607. X *
  608. X * Arguments:
  609. X *        fd:                file descriptor
  610. X *        dp:                descriptor pointer
  611. X *        stream_type:     either __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
  612. X *
  613. X * Returns
  614. X *        0             if successful
  615. X *      SIO_ERR    if the file descriptor is not valid (sets errno)
  616. X *   exits        if stream_type is not __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
  617. X */
  618. Xint __sio_init( dp, fd, stream_type )
  619. X    register __sio_descriptor_t *dp ;
  620. X    int fd ;
  621. X    enum __sio_stream stream_type ;
  622. X{
  623. X    struct stat st ;
  624. X    void terminate() ;
  625. X
  626. X#ifdef EVENTS
  627. X    EVENT( fd, EV_SIO_INIT ) ;
  628. X#endif
  629. X
  630. X    if ( fstat( fd, &st ) == -1 )
  631. X        return( SIO_ERR ) ;
  632. X
  633. X    switch ( stream_type )
  634. X    {
  635. X        case __SIO_INPUT_STREAM:
  636. X            if ( init_input_stream( IDP( dp ), fd, &st ) == FAILURE )
  637. X                return( SIO_ERR ) ;
  638. X            break ;
  639. X
  640. X        case __SIO_OUTPUT_STREAM:
  641. X            if ( init_output_stream( ODP( dp ), fd, &st ) == FAILURE )
  642. X                return( SIO_ERR ) ;
  643. X            break ;
  644. X            
  645. X        default:
  646. X            terminate( "SIO __sio_init: bad stream type (internal error).\n" ) ;
  647. X            /* NOTREACHED */
  648. X    }
  649. X    dp->stream_type = stream_type ;
  650. X    dp->initialized = TRUE ;
  651. X
  652. X#ifdef HAS_FINALIZATION_FUNCTION
  653. X    if ( ! finalizer_installed )
  654. X    {
  655. X        if ( ! SIO_FINALIZE( sio_cleanup ) )
  656. X        {
  657. X            char *s = "SIO __sio_init: finalizer installation failed\n" ;
  658. X
  659. X            (void) write( 2, s, strlen( s ) ) ;
  660. X        }
  661. X        else
  662. X            finalizer_installed = TRUE ;
  663. X    }
  664. X#endif /* HAS_FINALIZATION_FUNCTION */
  665. X
  666. X    return( 0 ) ;
  667. X}
  668. X
  669. X
  670. X/*
  671. X * __sio_writef writes the data in the buffer to the file descriptor.
  672. X *
  673. X * It tries to write as much data as possible until either all data
  674. X * are written or an error occurs. EINTR is the only error that is
  675. X * ignored.
  676. X * In case an error occurs but some data were written, that number
  677. X * is returned instead of SIO_ERR.
  678. X *
  679. X * Fields modified:
  680. X *        When successful: start, nextb
  681. X *        When not successful: start
  682. X *
  683. X * Return value:
  684. X *        Number of bytes written
  685. X *        SIO_ERR, if write(2) fails and no data were written
  686. X */ 
  687. Xint __sio_writef( odp, fd )
  688. X    register __sio_od_t *odp ;
  689. X    int fd ;
  690. X{
  691. X    register int b_in_buffer ;
  692. X    register int cc_total = 0 ;
  693. X
  694. X#ifdef EVENTS
  695. X    EVENT( fd, EV_SIO_WRITEF ) ;
  696. X#endif
  697. X
  698. X    /*
  699. X     * Make sure we don't exceed the buffer limits
  700. X     *    Maybe we should log this ?            XXX
  701. X     */
  702. X    if ( odp->nextb > odp->buf_end )
  703. X        odp->nextb = odp->buf_end ;
  704. X
  705. X    b_in_buffer = odp->nextb - odp->start ;
  706. X
  707. X    if ( b_in_buffer == 0 )
  708. X        return( 0 ) ;
  709. X    
  710. X    for ( ;; )
  711. X    {
  712. X        register int cc ;
  713. X
  714. X        cc = write( fd, odp->start, b_in_buffer ) ;
  715. X        if ( cc == b_in_buffer )
  716. X        {
  717. X            odp->start = odp->nextb = odp->buf ;
  718. X            cc_total += cc ;
  719. X            break ;
  720. X        }
  721. X        else if ( cc == -1 )
  722. X        {
  723. X            if ( errno == EINTR )
  724. X                continue ;
  725. X            else
  726. X                /*
  727. X                 * If some bytes were written, return that number, otherwise
  728. X                 * return SIO_ERR
  729. X                 */
  730. X                return( ( cc_total != 0 ) ? cc_total : SIO_ERR ) ;
  731. X        }
  732. X        else            /* some bytes were written */
  733. X        {
  734. X            odp->start += cc ;            /* advance start of buffer */
  735. X            b_in_buffer -= cc ;            /* decrease number bytes left in buffer */
  736. X            cc_total += cc ;                /* count the bytes that were written */
  737. X        }
  738. X    }
  739. X    return( cc_total ) ;
  740. X}
  741. X
  742. X
  743. X/*
  744. X * __sio_readf reads data from the file descriptor into the buffer.
  745. X * Unlike __sio_writef it does NOT try to read as much data as will fit
  746. X * in the buffer. It ignores EINTR.
  747. X *
  748. X * Returns: # of bytes read or SIO_ERR
  749. X *
  750. X * Fields set:
  751. X *         If it does not return SIO_ERR, it sets start, nextb, end
  752. X *            If it returns SIO_ERR, it does not change anything
  753. X */
  754. Xint __sio_readf( idp, fd )
  755. X    register __sio_id_t *idp ;
  756. X    int fd ;
  757. X{
  758. X    register int cc ;
  759. X
  760. X#ifdef EVENTS
  761. X    EVENT( fd, EV_SIO_READF ) ;
  762. X#endif
  763. X
  764. X    /*
  765. X     * First check for a tied fd and flush the stream if necessary
  766. X     *
  767. X     *         XXX    the return value of __sio_writef is not checked.
  768. X     *                    Is that right ?
  769. X     */
  770. X    if ( idp->tied_fd != SIO_NO_TIED_FD )
  771. X        (void) __sio_writef( &__SIO_OD( idp->tied_fd ), idp->tied_fd ) ;
  772. X
  773. X#ifdef HAS_MMAP
  774. X    if ( idp->memory_mapped )
  775. X    {
  776. X        register mapd_s *mdp = MDP( fd ) ;
  777. X
  778. X        /*
  779. X         * The functions initial_map and map_unit may fail.
  780. X         * In either case, we switch to buffered I/O.
  781. X         * If initial_map fails, we have read no data, so we
  782. X         * should perform a read(2).
  783. X         * If map_unit fails (for the next unit), we still have
  784. X         * the data in the current unit, so we can return.
  785. X         */
  786. X        if ( FIRST_TIME( idp ) )
  787. X        {
  788. X            cc = initial_map( mdp, fd ) ;
  789. X            if ( cc > 0 )
  790. X                idp->buf = mdp->first_unit.addr ;
  791. X            else
  792. X            {
  793. X                if ( __sio_switch( idp, fd ) == FAILURE )
  794. X                    return( SIO_ERR ) ;
  795. X                cc = -1 ;
  796. X            }
  797. X        }
  798. X        else
  799. X        {
  800. X            register struct map_unit *mu_cur, *mu_next ;
  801. X
  802. X            if ( idp->buf == mdp->first_unit.addr )
  803. X            {
  804. X                mu_cur = &mdp->first_unit ;
  805. X                mu_next = &mdp->second_unit ;
  806. X            }
  807. X            else
  808. X            {
  809. X                mu_cur = &mdp->second_unit ;
  810. X                mu_next = &mdp->first_unit ;
  811. X            }
  812. X
  813. X            if ( mu_next->addr != NULL )
  814. X            {
  815. X                idp->buf = mu_next->addr ;
  816. X                cc = mu_next->valid_bytes ;
  817. X                /*
  818. X                 * XXX:  Here we may return SIO_ERR even though there
  819. X                 *           are data in the current unit because the switch
  820. X                 *           fails (possibly because malloc failed).
  821. X                 */
  822. X                if ( map_unit( mdp, fd, mu_cur ) == FAILURE &&
  823. X                                        __sio_switch( idp, fd ) == FAILURE )
  824. X                    return( SIO_ERR ) ;
  825. X            }
  826. X            else
  827. X                cc = 0 ;
  828. X        }
  829. X        if ( cc >= 0 )
  830. X        {
  831. X            idp->end = idp->buf + cc ;
  832. X            idp->start = idp->nextb = idp->buf ;
  833. X            return( cc ) ;
  834. X        }
  835. X    }
  836. X#endif /* HAS_MMAP */
  837. X
  838. X    for ( ;; )
  839. X    {
  840. X        cc = read( fd, idp->buf, (int) idp->buffer_size ) ;
  841. X        if ( cc == -1 )
  842. X            if ( errno == EINTR )
  843. X                continue ;
  844. X            else
  845. X                return( SIO_ERR ) ;
  846. X        else
  847. X            break ;
  848. X    }
  849. X
  850. X    idp->end = idp->buf + cc ;
  851. X    idp->start = idp->nextb = idp->buf ;
  852. X    return( cc ) ;
  853. X}
  854. X
  855. X
  856. X/*
  857. X * __sio_extend_buffer is used by Srdline to extend the buffer
  858. X * If successful, it returns the number of bytes that have been read.
  859. X * If it fails (because of end-of-file or I/O error), it returns 0 or -1.
  860. X *
  861. X * Fields modified:
  862. X *     idp->start points to the start of the buffer area (which is in the
  863. X *     auxiliary buffer)
  864. X *        Also, if successful, idp->nextb is set to idp->buf, idp->end is modified.
  865. X */
  866. Xint __sio_extend_buffer( idp, fd, b_left )
  867. X    register __sio_id_t *idp ;
  868. X    int fd ;
  869. X    register int b_left ;
  870. X{
  871. X    register int b_read ;
  872. X
  873. X#ifdef EVENTS
  874. X    EVENT( fd, EV_SIO_EXTEND_BUFFER ) ;
  875. X#endif
  876. X
  877. X    /*
  878. X     * copy to auxiliary buffer
  879. X     */
  880. X    if ( b_left )
  881. X        sio_memcopy( idp->nextb, idp->buf - b_left, b_left ) ;
  882. X    b_read = __sio_readf( idp, fd ) ;
  883. X    idp->start = idp->buf - b_left ;
  884. X    return( b_read ) ;
  885. X}
  886. X
  887. X
  888. X/*
  889. X * __sio_more tries to read more data from the given file descriptor iff
  890. X * there is free space in the buffer.
  891. X * __sio_more is used only by Srdline and only AFTER __sio_extend_buffer
  892. X * has been called. This implies that 
  893. X *        a) this is not a memory mapped file
  894. X *        b) __sio_readf has been called (so we don't need to check for tied fd's
  895. X *
  896. X * Fields modified (only if successful):
  897. X *            idp->end
  898. X *
  899. X * Return value: the number of bytes read.
  900. X */
  901. Xint __sio_more( idp, fd )
  902. X    register __sio_id_t *idp ;
  903. X    int fd ;
  904. X{
  905. X    register int b_left = &idp->buf[ idp->buffer_size ] - idp->end ;
  906. X    register int cc ;
  907. X
  908. X#ifdef EVENTS
  909. X    EVENT( fd, EV_SIO_MORE ) ;
  910. X#endif
  911. X
  912. X    if ( b_left <= 0 )
  913. X        return( 0 ) ;
  914. X    
  915. X    for ( ;; )
  916. X    {
  917. X        cc = read( fd, idp->end, b_left ) ;
  918. X        if ( cc >= 0 )
  919. X        {
  920. X            idp->end += cc ;
  921. X            return( cc ) ;
  922. X        }
  923. X        else
  924. X            if ( errno == EINTR )
  925. X                continue ;
  926. X            else
  927. X                return( SIO_ERR ) ;
  928. X    }
  929. X}
  930. X
  931. X
  932. X/*
  933. X * Finalize a buffer by unmapping the file or freeing the malloc'ed memory
  934. X */
  935. Xint Sdone( fd )
  936. X    int fd ;
  937. X{
  938. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  939. X
  940. X#ifdef EVENTS
  941. X    EVENT( fd, EV_SDONE ) ;
  942. X#endif
  943. X
  944. X    if ( ! DESCRIPTOR_INITIALIZED( dp ) )
  945. X    {
  946. X        errno = EBADF ;
  947. X        return( SIO_ERR ) ;
  948. X    }
  949. X
  950. X    switch ( dp->stream_type )
  951. X    {
  952. X        case __SIO_INPUT_STREAM:
  953. X            {
  954. X                register __sio_id_t *idp = IDP( dp ) ;
  955. X
  956. X#ifdef HAS_MMAP
  957. X                if ( idp->memory_mapped )
  958. X                {
  959. X                    register mapd_s *mdp = MDP( fd ) ;
  960. X
  961. X                    if ( mdp->first_unit.addr != CHAR_NULL )
  962. X                        (void) SIO_MUNMAP( mdp->first_unit.addr,
  963. X                                                        mdp->first_unit.mapped_bytes ) ;
  964. X                    if ( mdp->second_unit.addr != CHAR_NULL )
  965. X                        (void) SIO_MUNMAP( mdp->second_unit.addr,
  966. X                                                        mdp->second_unit.mapped_bytes ) ;
  967. X                    idp->memory_mapped = FALSE ;
  968. X                }
  969. X                else
  970. X#endif    /* HAS_MMAP */
  971. X                    free( idp->buf - idp->buffer_size ) ;
  972. X                    idp->nextb = idp->end = NULL ;
  973. X            }
  974. X            break ;
  975. X        
  976. X        case __SIO_OUTPUT_STREAM:
  977. X            {
  978. X                register __sio_od_t *odp = ODP( dp ) ;
  979. X
  980. X                if ( Sflush( fd ) == SIO_ERR )
  981. X                    return( SIO_ERR ) ;
  982. X                free( odp->buf ) ;
  983. X                odp->nextb = odp->buf_end = NULL ;
  984. X            }
  985. X            break ;
  986. X        
  987. X        default:
  988. X            terminate( "SIO Sdone: bad stream type\n" ) ;
  989. X    }
  990. X
  991. X    dp->initialized = FALSE ;
  992. X    return( 0 ) ;
  993. X}
  994. X
  995. X
  996. XPRIVATE char *expand( area, old_size, new_size, is_static )
  997. X    char *area ;
  998. X    unsigned old_size, new_size ;
  999. X    int is_static ;
  1000. X{
  1001. X    char *new_area ;
  1002. X
  1003. X    if ( is_static )
  1004. X    {
  1005. X        if ( ( new_area = malloc( new_size ) ) == NULL )
  1006. X            return( NULL ) ;
  1007. X        sio_memcopy( area, new_area, old_size ) ;
  1008. X    }
  1009. X    else
  1010. X        if ( ( new_area = realloc( area, new_size ) ) == NULL )
  1011. X            return( NULL ) ;
  1012. X    return( new_area ) ;
  1013. X}
  1014. X
  1015. X
  1016. X#include <sys/time.h>
  1017. X#include <sys/resource.h>
  1018. X
  1019. XPRIVATE int get_fd_limit()
  1020. X{
  1021. X#ifdef RLIMIT_NOFILE
  1022. X
  1023. X    struct rlimit rl ;
  1024. X
  1025. X    (void) getrlimit( RLIMIT_NOFILE, &rl ) ;
  1026. X    return( rl.rlim_cur ) ;
  1027. X
  1028. X#else
  1029. X
  1030. X    return( N_SIO_DESCRIPTORS ) ;
  1031. X
  1032. X#endif
  1033. X}
  1034. X
  1035. X/*
  1036. X * Expand the descriptor array (and if we use memory mapping the
  1037. X * memory mapping descriptors). We first expand the memory mapping
  1038. X * descriptors.
  1039. X * There is no problem if the expansion of the SIO descriptors fails
  1040. X * (i.e. there is no need to undo anything).
  1041. X */
  1042. Xint Smorefds()
  1043. X{
  1044. X    char *p ;
  1045. X    int is_static ;
  1046. X    unsigned new_size, old_size ;
  1047. X    int n_fds = get_fd_limit() ;
  1048. X
  1049. X    if ( n_fds <= n_descriptors )
  1050. X        return( 0 ) ;
  1051. X
  1052. X#ifdef EVENTS
  1053. X    old_size = n_descriptors * sizeof( events_s ) ;
  1054. X    new_size = n_fds * sizeof( events_s ) ;
  1055. X    is_static = ( __sio_events == static___sio_events ) ;
  1056. X    p = expand( (char *)__sio_events, old_size, new_size, is_static ) ;
  1057. X    if ( p == NULL )
  1058. X        return( SIO_ERR ) ;
  1059. X    __sio_events = (events_s *) p ;
  1060. X
  1061. X    /*
  1062. X     * Clear the codes field of the extra events structs.
  1063. X     * We have to do this because a non-null codes field implies that
  1064. X     * events recording is on for that fd
  1065. X     */
  1066. X    {
  1067. X        int i ;
  1068. X
  1069. X        for ( i = n_descriptors ; i < n_fds ; i++ )
  1070. X            __sio_events[i].codes = NULL ;
  1071. X    }
  1072. X#endif    /* EVENTS */
  1073. X
  1074. X#ifdef HAS_MMAP
  1075. X    old_size = n_descriptors * sizeof( mapd_s ) ;
  1076. X    new_size = n_fds * sizeof( mapd_s ) ;
  1077. X    is_static = ( mmap_descriptors == static_mapd_array ) ;
  1078. X    p = expand( (char *)mmap_descriptors, old_size, new_size, is_static ) ;
  1079. X    if ( p == NULL )
  1080. X        return( SIO_ERR ) ;
  1081. X    mmap_descriptors = (mapd_s *) p ;
  1082. X#endif    /* HAS_MMAP */
  1083. X    
  1084. X    old_size = n_descriptors * sizeof( __sio_descriptor_t ) ;
  1085. X    new_size = n_fds * sizeof( __sio_descriptor_t ) ;
  1086. X    is_static =  ( __sio_descriptors == static_descriptor_array ) ;
  1087. X    p = expand( (char *)__sio_descriptors, old_size, new_size, is_static ) ;
  1088. X    if ( p == NULL )
  1089. X        return( SIO_ERR ) ;
  1090. X    __sio_descriptors = (__sio_descriptor_t *) p ;
  1091. X
  1092. X    n_descriptors = n_fds ;
  1093. X    return( 0 ) ;
  1094. X}
  1095. X
  1096. X
  1097. X#ifdef EVENTS
  1098. X
  1099. X/*
  1100. X * Enable recording of events for the specified file descriptor
  1101. X */
  1102. Xint __sio_enable_events( fd )
  1103. X    int fd ;
  1104. X{
  1105. X    char *p = malloc( EVENT_ENTRIES * sizeof( short ) ) ;
  1106. X
  1107. X    if ( p == NULL )
  1108. X        return( SIO_ERR ) ;
  1109. X
  1110. X    __sio_events[ fd ].codes = (short *) p ;
  1111. X    return( 0 ) ;
  1112. X}
  1113. X
  1114. X
  1115. X/*
  1116. X * Disable recording of events for the specified file descriptor
  1117. X */
  1118. Xvoid __sio_disable_events( fd )
  1119. X    int fd ;
  1120. X{
  1121. X    if ( __sio_events[ fd ].codes != NULL )
  1122. X    {
  1123. X        free( (char *) __sio_events[ fd ].codes ) ;
  1124. X        __sio_events[ fd ].codes = NULL ;
  1125. X    }
  1126. X}
  1127. X
  1128. X
  1129. X/*
  1130. X * Move stored events to buf
  1131. X */
  1132. Xint __sio_get_events( fd, buf, size )
  1133. X    int fd ;
  1134. X    char *buf ;
  1135. X    int size ;
  1136. X{
  1137. X    events_s *evp = &__sio_events[ fd ] ;
  1138. X    int bufentries ;
  1139. X    int range1, range2 ;
  1140. X    int diff ;
  1141. X    char *p ;
  1142. X    int cc ;
  1143. X    int cc_total ;
  1144. X    int move_entries ;
  1145. X
  1146. X    if ( evp->codes == NULL )
  1147. X        return( 0 ) ;
  1148. X    
  1149. X    diff = evp->next - evp->start ;
  1150. X    if ( diff == 0 )
  1151. X        return( 0 ) ;
  1152. X
  1153. X    if ( diff > 0 )
  1154. X    {
  1155. X        range1 = diff ;
  1156. X        range2 = 0 ;
  1157. X    }
  1158. X    else
  1159. X    {
  1160. X        range1 = EVENT_ENTRIES - evp->start ;
  1161. X        range2 = evp->next ;
  1162. X    }
  1163. X
  1164. X    bufentries = size / sizeof( short ) ;
  1165. X    p = buf ;
  1166. X    cc_total = 0 ;
  1167. X
  1168. X    move_entries = MIN( range1, bufentries ) ;
  1169. X    cc = move_entries * sizeof( short ) ;
  1170. X    sio_memcopy( (char *) &evp->codes[ evp->start ], p, cc ) ;
  1171. X    cc_total += cc ;
  1172. X    p += cc ;
  1173. X    bufentries -= range1 ;
  1174. X    ADD( evp->start, move_entries ) ;
  1175. X
  1176. X    if ( bufentries == 0 || range2 == 0 )
  1177. X        return( cc_total ) ;
  1178. X
  1179. X    move_entries = MIN( range2, bufentries ) ;
  1180. X    cc = move_entries * sizeof( short ) ;
  1181. X    sio_memcopy(  (char *) &evp->codes[ evp->start ], p, cc ) ;
  1182. X    cc_total += cc ;
  1183. X    ADD( evp->start, move_entries ) ;
  1184. X
  1185. X    return( cc_total ) ;
  1186. X}
  1187. X
  1188. X#endif     /* EVENTS */
  1189. X
  1190. X
  1191. X/*
  1192. X * Simple function that prints the string s at stderr and then calls
  1193. X * exit
  1194. X */
  1195. XPRIVATE void terminate( s )
  1196. X    char *s ;
  1197. X{
  1198. X    (void) write( 2, s, strlen( s ) ) ;
  1199. X    (void) abort() ;
  1200. X    exit( 1 ) ;                /* in case abort fails */
  1201. X}
  1202. X
  1203. END_OF_FILE
  1204.   if test 24088 -ne `wc -c <'libs/src/sio/siosup.c'`; then
  1205.     echo shar: \"'libs/src/sio/siosup.c'\" unpacked with wrong size!
  1206.   fi
  1207.   # end of 'libs/src/sio/siosup.c'
  1208. fi
  1209. if test -f 'libs/src/sio/sprint.c' -a "${1}" != "-c" ; then 
  1210.   echo shar: Will not clobber existing file \"'libs/src/sio/sprint.c'\"
  1211. else
  1212.   echo shar: Extracting \"'libs/src/sio/sprint.c'\" \(17542 characters\)
  1213.   sed "s/^X//" >'libs/src/sio/sprint.c' <<'END_OF_FILE'
  1214. X/*
  1215. X * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  1216. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  1217. X * and conditions for redistribution.
  1218. X */
  1219. X
  1220. X
  1221. Xstatic char RCSid[] = "$Id: sprint.c,v 8.3 1993/03/30 21:33:44 panos Exp $" ;
  1222. X
  1223. X#include <ctype.h>
  1224. X
  1225. X#include "sio.h"
  1226. X#include "impl.h"
  1227. X
  1228. X#ifndef WIDE_INT
  1229. X#define WIDE_INT                            long
  1230. X#endif
  1231. X
  1232. Xtypedef WIDE_INT                             wide_int ;
  1233. Xtypedef unsigned WIDE_INT                 u_wide_int ;
  1234. Xtypedef int                                 bool_int ;
  1235. X
  1236. X#define S_NULL                                "(null)"
  1237. X#define S_NULL_LEN                        6
  1238. X
  1239. X#define FLOAT_DIGITS                        6
  1240. X#define EXPONENT_LENGTH                    10
  1241. X
  1242. X/*
  1243. X * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
  1244. X *
  1245. X * XXX: this is a magic number; do not decrease it
  1246. X */
  1247. X#define NUM_BUF_SIZE                        512
  1248. X
  1249. X/*
  1250. X * The INS_CHAR macro inserts a character in the buffer and writes
  1251. X * the buffer back to disk if necessary
  1252. X * It uses the char pointers sp and bep:
  1253. X *     sp points to the next available character in the buffer
  1254. X *     bep points to the end-of-buffer+1
  1255. X * While using this macro, note that the nextb pointer is NOT updated.
  1256. X *
  1257. X * No I/O is performed if fd is not positive. Negative fd values imply
  1258. X * conversion with the output directed to a string. Excess characters
  1259. X * are discarded if the string overflows.
  1260. X *
  1261. X * NOTE: Evaluation of the c argument should not have any side-effects
  1262. X */
  1263. X#define INS_CHAR( c, sp, bep, odp, cc, fd )                                            \
  1264. X            {                                                                                        \
  1265. X                if ( sp < bep )                                                                \
  1266. X                {                                                                                    \
  1267. X                    *sp++ = c ;                                                                    \
  1268. X                    cc++ ;                                                                        \
  1269. X                }                                                                                    \
  1270. X                else                                                                                \
  1271. X                {                                                                                    \
  1272. X                    if ( fd >= 0 )                                                                \
  1273. X                    {                                                                                \
  1274. X                        odp->nextb = sp ;                                                        \
  1275. X                        if ( __sio_writef( odp, fd ) != bep - odp->start )            \
  1276. X                            return( ( cc != 0 ) ? cc : SIO_ERR ) ;                        \
  1277. X                        sp = odp->nextb ;                                                        \
  1278. X                        *sp++ = c ;                                                                \
  1279. X                        cc++ ;                                                                    \
  1280. X                    }                                                                                \
  1281. X                }                                                                                    \
  1282. X                if ( __SIO_MUST_FLUSH( *odp, c ) && fd >= 0 )                         \
  1283. X                {                                                                                    \
  1284. X                    int b_in_buffer = sp - odp->start ;                                    \
  1285. X                                                                                                    \
  1286. X                    odp->nextb = sp ;                                                            \
  1287. X                    if ( __sio_writef( odp, fd ) != b_in_buffer )                    \
  1288. X                        return( cc ) ;                                                            \
  1289. X                    sp = odp->nextb ;                                                            \
  1290. X                }                                                                                    \
  1291. X            }
  1292. X
  1293. X
  1294. X
  1295. X#define NUM( c )            ( c - '0' )
  1296. X
  1297. X#define STR_TO_DEC( str, num )                                    \
  1298. X                                    num = NUM( *str++ ) ;            \
  1299. X                                    while ( isdigit( *str ) )        \
  1300. X                                    {                                        \
  1301. X                                        num *= 10 ;                        \
  1302. X                                        num += NUM( *str++ ) ;        \
  1303. X                                    }
  1304. X
  1305. X/*
  1306. X * This macro does zero padding so that the precision
  1307. X * requirement is satisfied. The padding is done by
  1308. X * adding '0's to the left of the string that is going
  1309. X * to be printed.
  1310. X */
  1311. X#define FIX_PRECISION( adjust, precision, s, s_len )                \
  1312. X                    if ( adjust )                                                \
  1313. X                        while ( s_len < precision )                        \
  1314. X                        {                                                            \
  1315. X                            *--s = '0' ;                                        \
  1316. X                            s_len++ ;                                            \
  1317. X                        }
  1318. X
  1319. X/*
  1320. X * Macro that does padding. The padding is done by printing
  1321. X * the character ch.
  1322. X */
  1323. X#define PAD( width, len, ch )            do                                                        \
  1324. X                                                {                                                        \
  1325. X                                                    INS_CHAR( ch, sp, bep, odp, cc, fd ) ;    \
  1326. X                                                    width-- ;                                        \
  1327. X                                                }                                                        \
  1328. X                                                while ( width > len )
  1329. X
  1330. X/*
  1331. X * Prefix the character ch to the string str
  1332. X * Increase length
  1333. X * Set the has_prefix flag
  1334. X */
  1335. X#define PREFIX( str, length, ch )    *--str = ch ; length++ ; has_prefix = YES
  1336. X
  1337. X
  1338. X/*
  1339. X * Sprint is the equivalent of printf for SIO.
  1340. X * It returns the # of chars written
  1341. X * Assumptions:
  1342. X *     - all floating point arguments are passed as doubles
  1343. X */
  1344. X/* VARARGS2 */
  1345. Xint Sprint( fd, fmt, va_alist ) 
  1346. X    int fd ;
  1347. X    register char *fmt ;
  1348. X    va_dcl
  1349. X{
  1350. X    __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  1351. X    register __sio_od_t *odp = ODP( dp ) ;
  1352. X    register int cc ;
  1353. X    va_list ap ;
  1354. X
  1355. X    IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  1356. X
  1357. X    va_start( ap ) ;
  1358. X    cc = __sio_converter( odp, fd, fmt, ap ) ;
  1359. X    va_end( ap ) ;
  1360. X    return( cc ) ;
  1361. X}
  1362. X
  1363. X
  1364. X/*
  1365. X * This is the equivalent of vfprintf for SIO
  1366. X */
  1367. Xint Sprintv( fd, fmt, ap )
  1368. X    int fd ;
  1369. X    char *fmt ;
  1370. X    va_list ap ;
  1371. X{
  1372. X    __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  1373. X    register __sio_od_t *odp = ODP( dp ) ;
  1374. X
  1375. X    IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  1376. X    return( __sio_converter( odp, fd, fmt, ap ) ) ;
  1377. X}
  1378. X
  1379. X
  1380. X/*
  1381. X * Convert a floating point number to a string formats 'f', 'e' or 'E'.
  1382. X * The result is placed in buf, and len denotes the length of the string
  1383. X * The sign is returned in the is_negative argument (and is not placed
  1384. X * in buf).
  1385. X */
  1386. XPRIVATE char *conv_fp( format, num, add_dp, precision, is_negative, buf, len )
  1387. X    register char format ;
  1388. X    register double num ;
  1389. X    boolean_e add_dp ;            /* always add decimal point if YES */
  1390. X    int precision ;
  1391. X    bool_int *is_negative ;
  1392. X    char buf[] ;
  1393. X    int *len ;
  1394. X{
  1395. X    register char *s = buf ;
  1396. X    register char *p ;
  1397. X    int decimal_point ;
  1398. X    char *ecvt(), *fcvt() ;
  1399. X    char *conv_10() ;
  1400. X    char *strcpy() ;
  1401. X        
  1402. X    if ( format == 'f' )
  1403. X        p = fcvt( num, precision, &decimal_point, is_negative ) ;
  1404. X    else /* either e or E format */
  1405. X        p = ecvt( num, precision+1, &decimal_point, is_negative ) ;
  1406. X
  1407. X    /*
  1408. X     * Check for Infinity and NaN
  1409. X     */
  1410. X    if ( isalpha( *p ) )
  1411. X    {
  1412. X        *len = strlen( strcpy( buf, p ) ) ;
  1413. X        *is_negative = FALSE ;
  1414. X        return( buf ) ;
  1415. X    }
  1416. X    
  1417. X    if ( format == 'f' )
  1418. X        if ( decimal_point <= 0 )
  1419. X        {
  1420. X            *s++ = '0' ;
  1421. X            if ( precision > 0 )
  1422. X            {
  1423. X                *s++ = '.' ;
  1424. X                while ( decimal_point++ < 0 )
  1425. X                    *s++ = '0' ;
  1426. X            }
  1427. X            else if ( add_dp )
  1428. X                *s++ = '.' ;
  1429. X        }
  1430. X        else
  1431. X        {
  1432. X            while ( decimal_point-- > 0 )
  1433. X                *s++ = *p++ ;
  1434. X            if ( precision > 0 || add_dp ) *s++ = '.' ;
  1435. X        }
  1436. X    else
  1437. X    {
  1438. X        *s++ = *p++ ;
  1439. X        if ( precision > 0 || add_dp ) *s++ = '.' ;
  1440. X    }
  1441. X
  1442. X    /*
  1443. X     * copy the rest of p, the NUL is NOT copied
  1444. X     */
  1445. X    while ( *p ) *s++ = *p++ ;            
  1446. X    
  1447. X    if ( format != 'f' )
  1448. X    {
  1449. X        char temp[ EXPONENT_LENGTH ] ;                /* for exponent conversion */
  1450. X        int t_len ;
  1451. X        bool_int exponent_is_negative ;
  1452. X
  1453. X        *s++ = format ;        /* either e or E */
  1454. X        decimal_point-- ;
  1455. X        if ( decimal_point != 0 )
  1456. X        {
  1457. X            p = conv_10( (wide_int)decimal_point, FALSE, &exponent_is_negative,
  1458. X                                                &temp[ EXPONENT_LENGTH ], &t_len ) ;
  1459. X            *s++ = exponent_is_negative ? '-' : '+' ;
  1460. X            
  1461. X            /*
  1462. X             * Make sure the exponent has at least 2 digits
  1463. X             */
  1464. X            if ( t_len == 1 )
  1465. X                *s++ = '0' ;
  1466. X            while ( t_len-- ) *s++ = *p++ ;
  1467. X        }
  1468. X        else
  1469. X        {
  1470. X            *s++ = '+' ;
  1471. X            *s++ = '0' ;
  1472. X            *s++ = '0' ;
  1473. X        }
  1474. X    }
  1475. X
  1476. X    *len = s - buf ;
  1477. X    return( buf ) ;
  1478. X}
  1479. X
  1480. X
  1481. X/*
  1482. X * Convert num to a base X number where X is a power of 2. nbits determines X.
  1483. X * For example, if nbits is 3, we do base 8 conversion
  1484. X * Return value:
  1485. X *            a pointer to a string containing the number
  1486. X *
  1487. X * The caller provides a buffer for the string: that is the buf_end argument
  1488. X * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  1489. X * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  1490. X */
  1491. XPRIVATE char *conv_p2( num, nbits, format, buf_end, len )
  1492. X    register u_wide_int num ;
  1493. X    register int nbits ;
  1494. X    char format ;
  1495. X    char *buf_end ;
  1496. X    register int *len ;
  1497. X{
  1498. X    register int mask = ( 1 << nbits ) - 1 ;
  1499. X    register char *p = buf_end ;
  1500. X    static char low_digits[] = "0123456789abcdef" ;
  1501. X    static char upper_digits[] = "0123456789ABCDEF" ;
  1502. X    register char *digits = ( format == 'X' ) ? upper_digits : low_digits ;
  1503. X
  1504. X    do
  1505. X    {
  1506. X        *--p = digits[ num & mask ] ;
  1507. X        num >>= nbits ;
  1508. X    }
  1509. X    while( num ) ;
  1510. X
  1511. X    *len = buf_end - p ;
  1512. X    return( p ) ;
  1513. X}
  1514. X
  1515. X
  1516. X
  1517. X/*
  1518. X * Convert num to its decimal format.
  1519. X * Return value:
  1520. X *       - a pointer to a string containing the number (no sign)
  1521. X *            - len contains the length of the string
  1522. X *            - is_negative is set to TRUE or FALSE depending on the sign
  1523. X *              of the number (always set to FALSE if is_unsigned is TRUE)
  1524. X *
  1525. X * The caller provides a buffer for the string: that is the buf_end argument
  1526. X * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  1527. X * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  1528. X */
  1529. XPRIVATE char *conv_10( num, is_unsigned, is_negative, buf_end, len )
  1530. X    register wide_int num ; 
  1531. X    register bool_int is_unsigned ;
  1532. X    register bool_int *is_negative ;
  1533. X    char *buf_end ;
  1534. X    register int *len ;
  1535. X{
  1536. X    register char *p = buf_end ;
  1537. X    register u_wide_int magnitude ;
  1538. X
  1539. X    if ( is_unsigned )
  1540. X    {
  1541. X        magnitude = (u_wide_int) num ;
  1542. X        *is_negative = FALSE ;
  1543. X    }
  1544. X    else
  1545. X    {
  1546. X        *is_negative = ( num < 0 ) ;
  1547. X
  1548. X        /*
  1549. X         * On a 2's complement machine, negating the most negative integer 
  1550. X         * results in a number that cannot be represented as a signed integer.
  1551. X         * Here is what we do to obtain the number's magnitude:
  1552. X         *        a. add 1 to the number
  1553. X         *        b. negate it (becomes positive)
  1554. X         *        c. convert it to unsigned
  1555. X         *        d. add 1
  1556. X         */
  1557. X        if ( *is_negative )
  1558. X        {
  1559. X            wide_int t = num + 1 ;
  1560. X
  1561. X            magnitude = ( (u_wide_int) -t ) + 1 ;
  1562. X        }
  1563. X        else
  1564. X            magnitude = (u_wide_int) num ;
  1565. X    }
  1566. X
  1567. X    /*
  1568. X     * We use a do-while loop so that we write at least 1 digit 
  1569. X     */
  1570. X    do
  1571. X    {
  1572. X        register u_wide_int new_magnitude = magnitude / 10 ;
  1573. X
  1574. X        *--p = magnitude - new_magnitude*10 + '0' ;
  1575. X        magnitude = new_magnitude ;
  1576. X    }
  1577. X    while ( magnitude ) ;
  1578. X    
  1579. X    *len = buf_end - p ;
  1580. X    return( p ) ;
  1581. X}
  1582. X
  1583. X
  1584. X/*
  1585. X * Do format conversion placing the output in odp
  1586. X */
  1587. Xint __sio_converter( odp, fd, fmt, ap )
  1588. X    register __sio_od_t *odp ;
  1589. X    int fd ;
  1590. X    register char *fmt ;
  1591. X    va_list ap ;
  1592. X{
  1593. X    register char *sp ;
  1594. X    register char *bep ;
  1595. X    register int cc = 0 ;
  1596. X    register int i ;
  1597. X
  1598. X    register char *s ;
  1599. X    char *q ;
  1600. X    int s_len ;
  1601. X
  1602. X    register int min_width ;
  1603. X    int precision ;
  1604. X    enum { LEFT, RIGHT } adjust ;
  1605. X    char pad_char ;
  1606. X    char prefix_char ;
  1607. X
  1608. X    double fp_num ;
  1609. X    wide_int i_num ;
  1610. X    u_wide_int ui_num ;
  1611. X
  1612. X    char num_buf[ NUM_BUF_SIZE ] ;
  1613. X    char char_buf[ 2 ] ;        /* for printing %% and %<unknown> */
  1614. X
  1615. X    /*
  1616. X     * Flag variables
  1617. X     */
  1618. X    boolean_e is_long ;
  1619. X    boolean_e alternate_form ;
  1620. X    boolean_e print_sign ;
  1621. X    boolean_e print_blank ;
  1622. X    boolean_e adjust_precision ;
  1623. X    boolean_e adjust_width ;
  1624. X    bool_int is_negative ;
  1625. X
  1626. X    char *conv_10(), *conv_p2(), *conv_fp() ;
  1627. X    char *gcvt() ;
  1628. X    char *strchr() ;
  1629. X
  1630. X
  1631. X    sp = odp->nextb ;
  1632. X    bep = odp->buf_end ;
  1633. X
  1634. X    while ( *fmt )
  1635. X    {
  1636. X        if ( *fmt != '%' )
  1637. X        {
  1638. X            INS_CHAR( *fmt, sp, bep, odp, cc, fd ) ;
  1639. X        }
  1640. X        else
  1641. X        {
  1642. X            /*
  1643. X             * Default variable settings
  1644. X             */
  1645. X            adjust = RIGHT ;
  1646. X            alternate_form = print_sign = print_blank = NO ;
  1647. X            pad_char = ' ' ;
  1648. X            prefix_char = NUL ;
  1649. X
  1650. X            fmt++ ;
  1651. X
  1652. X            /*
  1653. X             * Try to avoid checking for flags, width or precision
  1654. X             */
  1655. X            if ( isascii( *fmt ) && ! islower( *fmt ) )
  1656. X            {
  1657. X                /*
  1658. X                 * Recognize flags: -, #, BLANK, +
  1659. X                 */
  1660. X                for ( ;; fmt++ )
  1661. X                {
  1662. X                    if ( *fmt == '-' )
  1663. X                        adjust = LEFT ;
  1664. X                    else if ( *fmt == '+' )
  1665. X                        print_sign = YES ;
  1666. X                    else if ( *fmt == '#' )
  1667. X                        alternate_form = YES ;
  1668. X                    else if ( *fmt == ' ' )
  1669. X                        print_blank = YES ;
  1670. X                    else if ( *fmt == '0' )
  1671. X                        pad_char = '0' ;
  1672. X                    else
  1673. X                        break ;
  1674. X                }
  1675. X
  1676. X                /*
  1677. X                 * Check if a width was specified
  1678. X                 */
  1679. X                if ( isdigit( *fmt ) )
  1680. X                {
  1681. X                    STR_TO_DEC( fmt, min_width ) ;
  1682. X                    adjust_width = YES ;
  1683. X                }
  1684. X                else if ( *fmt == '*' )
  1685. X                {
  1686. X                    min_width = va_arg( ap, int ) ;
  1687. X                    fmt++ ;
  1688. X                    adjust_width = YES ;
  1689. X                    if ( min_width < 0 )
  1690. X                    {
  1691. X                        adjust = LEFT ;
  1692. X                        min_width = -min_width ;
  1693. X                    }
  1694. X                }
  1695. X                else
  1696. X                    adjust_width = NO ;
  1697. X                
  1698. X                /*
  1699. X                 * Check if a precision was specified
  1700. X                 *
  1701. X                 * XXX: an unreasonable amount of precision may be specified
  1702. X                 *          resulting in overflow of num_buf. Currently we
  1703. X                 *          ignore this possibility.
  1704. X                 */
  1705. X                if ( *fmt == '.' )
  1706. X                {
  1707. X                    adjust_precision = YES ;
  1708. X                    fmt++ ;
  1709. X                    if ( isdigit( *fmt ) )
  1710. X                    {
  1711. X                        STR_TO_DEC( fmt, precision ) ;
  1712. X                    }
  1713. X                    else if ( *fmt == '*' )
  1714. X                    {
  1715. X                        precision = va_arg( ap, int ) ;
  1716. X                        fmt++ ;
  1717. X                        if ( precision < 0 )
  1718. X                            precision = 0 ;
  1719. X                    }
  1720. X                    else
  1721. X                        precision = 0 ;
  1722. X                }
  1723. X                else
  1724. X                    adjust_precision = NO ;
  1725. X            }
  1726. X            else
  1727. X                adjust_precision = adjust_width = NO ;
  1728. X
  1729. X            /*
  1730. X             * Modifier check
  1731. X             */
  1732. X            if ( *fmt == 'l' )
  1733. X            {
  1734. X                is_long = YES ;
  1735. X                fmt++ ;
  1736. X            }
  1737. X            else
  1738. X                is_long = NO ;
  1739. X
  1740. X            /*
  1741. X             * Argument extraction and printing.
  1742. X             * First we determine the argument type.
  1743. X             * Then, we convert the argument to a string.
  1744. X             * On exit from the switch, s points to the string that
  1745. X             * must be printed, s_len has the length of the string
  1746. X             * The precision requirements, if any, are reflected in s_len.
  1747. X             *
  1748. X             * NOTE: pad_char may be set to '0' because of the 0 flag.
  1749. X             *            It is reset to ' ' by non-numeric formats
  1750. X             */
  1751. X            switch( *fmt )
  1752. X            {
  1753. X                case 'd':
  1754. X                case 'i':
  1755. X                case 'u':
  1756. X                    if ( is_long )
  1757. X                        i_num = va_arg( ap, wide_int ) ;
  1758. X                    else
  1759. X                        i_num = (wide_int) va_arg( ap, int ) ;
  1760. X                    s = conv_10( i_num, (*fmt) == 'u', &is_negative,
  1761. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  1762. X                    FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  1763. X
  1764. X                    if ( *fmt != 'u' )
  1765. X                    {
  1766. X                        if ( is_negative )
  1767. X                            prefix_char = '-' ;
  1768. X                        else if ( print_sign )
  1769. X                            prefix_char = '+' ;
  1770. X                        else if ( print_blank )
  1771. X                            prefix_char = ' ' ;
  1772. X                    }
  1773. X                    break ;
  1774. X                
  1775. X
  1776. X                case 'o':
  1777. X                    if ( is_long )
  1778. X                        ui_num = va_arg( ap, u_wide_int ) ; 
  1779. X                    else
  1780. X                        ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
  1781. X                    s = conv_p2( ui_num, 3, *fmt, 
  1782. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  1783. X                    FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  1784. X                    if ( alternate_form && *s != '0' )
  1785. X                    {
  1786. X                        *--s = '0' ;
  1787. X                        s_len++ ;
  1788. X                    }
  1789. X                    break ;
  1790. X                
  1791. X
  1792. X                case 'x':
  1793. X                case 'X':
  1794. X                    if ( is_long )
  1795. X                        ui_num = (u_wide_int) va_arg( ap, u_wide_int ) ;
  1796. X                    else
  1797. X                        ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
  1798. X                    s = conv_p2( ui_num, 4, *fmt,
  1799. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  1800. X                    FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  1801. X                    if ( alternate_form && i_num != 0 )
  1802. X                    {
  1803. X                        *--s = *fmt ;            /* 'x' or 'X' */
  1804. X                        *--s = '0' ;
  1805. X                        s_len += 2 ;
  1806. X                    }
  1807. X                    break ;
  1808. X                
  1809. X
  1810. X                case 's':
  1811. X                    s = va_arg( ap, char * ) ;
  1812. X                    if ( s != NULL )
  1813. X                    {
  1814. X                        s_len = strlen( s ) ;
  1815. X                        if ( adjust_precision && precision < s_len )
  1816. X                            s_len = precision ;
  1817. X                    }
  1818. X                    else
  1819. X                    {
  1820. X                        s = S_NULL ;
  1821. X                        s_len = S_NULL_LEN ;
  1822. X                    }
  1823. X                    pad_char = ' ' ;
  1824. X                    break ;
  1825. X                
  1826. X
  1827. X                case 'f':
  1828. X                case 'e':
  1829. X                case 'E':
  1830. X                    fp_num = va_arg( ap, double ) ;
  1831. X
  1832. X                    s = conv_fp( *fmt, fp_num, alternate_form,
  1833. X                            ( adjust_precision == NO ) ? FLOAT_DIGITS : precision,
  1834. X                                                    &is_negative, &num_buf[ 1 ], &s_len ) ;
  1835. X                    if ( is_negative )
  1836. X                        prefix_char = '-' ;
  1837. X                    else if ( print_sign )
  1838. X                        prefix_char = '+' ;
  1839. X                    else if ( print_blank )
  1840. X                        prefix_char = ' ' ;
  1841. X                    break ;
  1842. X
  1843. X
  1844. X                case 'g':
  1845. X                case 'G':
  1846. X                    if ( adjust_precision == NO )
  1847. X                        precision = FLOAT_DIGITS ;
  1848. X                    else if ( precision == 0 )
  1849. X                        precision = 1 ;
  1850. X                    /*
  1851. X                     * We use &num_buf[ 1 ], so that we have room for the sign
  1852. X                     */
  1853. X                    s = gcvt( va_arg( ap, double ), precision, &num_buf[ 1 ] ) ;
  1854. X                    if ( *s == '-' )
  1855. X                        prefix_char = *s++ ;
  1856. X                    else if ( print_sign )
  1857. X                        prefix_char = '+' ;
  1858. X                    else if ( print_blank )
  1859. X                        prefix_char = ' ' ;
  1860. X
  1861. X                    s_len = strlen( s ) ;
  1862. X
  1863. X                    if ( alternate_form && ( q = strchr( s, '.' ) ) == NULL )
  1864. X                        s[ s_len++ ] = '.' ;
  1865. X                    if ( *fmt == 'G' && ( q = strchr( s, 'e' ) ) != NULL )
  1866. X                        *q = 'E' ;
  1867. X                    break ;
  1868. X
  1869. X
  1870. X                case 'c':
  1871. X                    char_buf[ 0 ] = (char) (va_arg( ap, int )) ;
  1872. X                    s = &char_buf[ 0 ] ;
  1873. X                    s_len = 1 ;
  1874. X                    pad_char = ' ' ;
  1875. X                    break ;
  1876. X
  1877. X
  1878. X                case '%':
  1879. X                    char_buf[ 0 ] = '%' ;
  1880. X                    s = &char_buf[ 0 ] ;
  1881. X                    s_len = 1 ;
  1882. X                    pad_char = ' ' ;
  1883. X                    break ;
  1884. X
  1885. X
  1886. X                case 'n':
  1887. X                    *(va_arg( ap, int * )) = cc ;
  1888. X                    break ;
  1889. X
  1890. X                /*
  1891. X                 * Always extract the argument as a "char *" pointer. We 
  1892. X                 * should be using "void *" but there are still machines 
  1893. X                 * that don't understand it.
  1894. X                 * If the pointer size is equal to the size of an unsigned
  1895. X                 * integer we convert the pointer to a hex number, otherwise 
  1896. X                 * we print "%p" to indicate that we don't handle "%p".
  1897. X                 */
  1898. X                case 'p':
  1899. X                    ui_num = (u_wide_int) va_arg( ap, char * ) ;
  1900. X
  1901. X                    if ( sizeof( char * ) <= sizeof( u_wide_int ) )
  1902. X                        s = conv_p2( ui_num, 4, 'x', 
  1903. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  1904. X                    else
  1905. X                    {
  1906. X                        s = "%p" ;
  1907. X                        s_len = 2 ;
  1908. X                    }
  1909. X                    pad_char = ' ' ;
  1910. X                    break ;
  1911. X                    
  1912. X
  1913. X                case NUL:
  1914. X                    /*
  1915. X                     * The last character of the format string was %.
  1916. X                     * We ignore it.
  1917. X                     */
  1918. X                    continue ;
  1919. X
  1920. X
  1921. X                    /*
  1922. X                      * The default case is for unrecognized %'s.
  1923. X                     * We print %<char> to help the user identify what
  1924. X                     * option is not understood.
  1925. X                     * This is also useful in case the user wants to pass
  1926. X                     * the output of __sio_converter to another function
  1927. X                     * that understands some other %<char> (like syslog).
  1928. X                     * Note that we can't point s inside fmt because the
  1929. X                     * unknown <char> could be preceded by width etc.
  1930. X                     */
  1931. X                default:
  1932. X                    char_buf[ 0 ] = '%' ;
  1933. X                    char_buf[ 1 ] = *fmt ;
  1934. X                    s = char_buf ;
  1935. X                    s_len = 2 ;
  1936. X                    pad_char = ' ' ;
  1937. X                    break ;
  1938. X            }
  1939. X
  1940. X            if ( prefix_char != NUL )
  1941. X            {
  1942. X                *--s = prefix_char ;
  1943. X                s_len++ ;
  1944. X            }
  1945. X
  1946. X            if ( adjust_width && adjust == RIGHT && min_width > s_len )
  1947. X            {
  1948. X                if ( pad_char == '0' && prefix_char != NUL )
  1949. X                {
  1950. X                    INS_CHAR( *s, sp, bep, odp, cc, fd )
  1951. X                    s++ ;
  1952. X                    s_len-- ;
  1953. X                    min_width-- ;
  1954. X                }
  1955. X                PAD( min_width, s_len, pad_char ) ;
  1956. X            }
  1957. X
  1958. X            /*
  1959. X             * Print the string s. 
  1960. X             */
  1961. X            for ( i = s_len ; i != 0 ; i-- )
  1962. X            {
  1963. X                INS_CHAR( *s, sp, bep, odp, cc, fd ) ;
  1964. X                s++ ;
  1965. X            }
  1966. X
  1967. X            if ( adjust_width && adjust == LEFT && min_width > s_len )
  1968. X                PAD( min_width, s_len, pad_char ) ;
  1969. X        }
  1970. X        fmt++ ;
  1971. X    }
  1972. X    odp->nextb = sp ;
  1973. X    return( cc ) ;
  1974. X}
  1975. X
  1976. END_OF_FILE
  1977.   if test 17542 -ne `wc -c <'libs/src/sio/sprint.c'`; then
  1978.     echo shar: \"'libs/src/sio/sprint.c'\" unpacked with wrong size!
  1979.   fi
  1980.   # end of 'libs/src/sio/sprint.c'
  1981. fi
  1982. if test ! -d 'libs/src/sio/suite' ; then
  1983.     echo shar: Creating directory \"'libs/src/sio/suite'\"
  1984.     mkdir 'libs/src/sio/suite'
  1985. fi
  1986. if test ! -d 'libs/src/str' ; then
  1987.     echo shar: Creating directory \"'libs/src/str'\"
  1988.     mkdir 'libs/src/str'
  1989. fi
  1990. if test ! -d 'pst' ; then
  1991.     echo shar: Creating directory \"'pst'\"
  1992.     mkdir 'pst'
  1993. fi
  1994. if test -f 'pst/common.c' -a "${1}" != "-c" ; then 
  1995.   echo shar: Will not clobber existing file \"'pst/common.c'\"
  1996. else
  1997.   echo shar: Extracting \"'pst/common.c'\" \(4850 characters\)
  1998.   sed "s/^X//" >'pst/common.c' <<'END_OF_FILE'
  1999. X/*
  2000. X * (c) Copyright 1993 by Panagiotis Tsirigotis
  2001. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  2002. X * and conditions for redistribution.
  2003. X */
  2004. X
  2005. Xstatic char RCSid[] = "$Id: common.c,v 1.4 1993/02/10 21:16:10 panos Exp $" ;
  2006. X
  2007. X#include <varargs.h>
  2008. X
  2009. Xvoid exit() ;
  2010. Xchar *malloc() ;
  2011. Xchar *realloc() ;
  2012. X
  2013. X#include "sio.h"
  2014. X
  2015. X#include "defs.h"
  2016. X
  2017. X/*
  2018. X * Skip all characters in the input until you find the character in 'c'
  2019. X */
  2020. Xvoid skip_until( fd, c )
  2021. X    int fd ;
  2022. X    int c ;
  2023. X{
  2024. X    int ic ;
  2025. X
  2026. X    for ( ;; )
  2027. X    {
  2028. X        NEXT_CHAR( fd, ic ) ;
  2029. X        if ( ic == SIO_EOF || ic == c )
  2030. X            return ;
  2031. X    }
  2032. X}
  2033. X
  2034. X
  2035. X/*
  2036. X * Skip procedure definition: we assume that a procedure starts with an
  2037. X * open curly bracket.
  2038. X */
  2039. Xvoid skip_bracket( fd, open_bracket, closed_bracket )
  2040. X    int fd ;
  2041. X    char open_bracket, closed_bracket ;
  2042. X{
  2043. X    int c ;
  2044. X    int bracket_level = 1 ;
  2045. X    int start_line = line_count ;
  2046. X
  2047. X    while ( bracket_level > 0 )
  2048. X    {
  2049. X        NEXT_CHAR( fd, c ) ;
  2050. X        if ( c == SIO_EOF )
  2051. X            error(
  2052. X                "Reached EOF while looking for '%c' (search started at line %d)\n",
  2053. X                    closed_bracket, start_line ) ;
  2054. X        if ( c == closed_bracket )
  2055. X            bracket_level-- ;
  2056. X        else if ( c == open_bracket )
  2057. X            bracket_level++ ;
  2058. X    }
  2059. X}
  2060. X
  2061. X
  2062. Xint next_char( fd )
  2063. X    int fd ;
  2064. X{
  2065. X    int c ;
  2066. X
  2067. X    NEXT_CHAR( fd, c ) ;
  2068. X    if ( c == SIO_EOF )
  2069. X        error( "Unexpected end of file\n" ) ;
  2070. X    return( c ) ;
  2071. X}
  2072. X
  2073. X
  2074. X#define BUF_INCREMENT                                1000
  2075. X
  2076. Xstatic char *outbuf ;
  2077. Xstatic int buflen ;
  2078. Xstatic int used ;
  2079. Xstatic int replace_space_with_newline ;
  2080. X
  2081. Xvoid printout( c )
  2082. X    int c ;
  2083. X{
  2084. X    if ( outbuf == NULL )
  2085. X    {
  2086. X        buflen = BUF_INCREMENT ;
  2087. X        outbuf = malloc( buflen ) ;
  2088. X        if ( outbuf == NULL )
  2089. X            error( "out of memory\n" ) ;
  2090. X        used = 0 ;
  2091. X    }
  2092. X
  2093. X    if ( c == NEWLINE )
  2094. X    {
  2095. X        if ( outbuf[ used-1 ] == '-' )
  2096. X        {
  2097. X            used-- ;                                        /* remove the '-' */
  2098. X            replace_space_with_newline = TRUE ;
  2099. X            return ;
  2100. X        }
  2101. X    }
  2102. X    else if ( c == SPACE && replace_space_with_newline )
  2103. X    {
  2104. X        c = NEWLINE ;
  2105. X        replace_space_with_newline = FALSE ;
  2106. X    }
  2107. X
  2108. X    /*
  2109. X     * We only output complete lines
  2110. X     */
  2111. X    if ( c != NEWLINE )
  2112. X    {
  2113. X        if ( used == buflen )
  2114. X        {
  2115. X            char *newbuf ;
  2116. X
  2117. X            buflen += BUF_INCREMENT ;
  2118. X            newbuf = realloc( outbuf, buflen ) ;
  2119. X            if ( newbuf == NULL )
  2120. X                error( "out of memory\n" ) ;
  2121. X            outbuf = newbuf ;
  2122. X        }
  2123. X        outbuf[ used++ ] = c ;
  2124. X    }
  2125. X    else
  2126. X    {
  2127. X        Swrite( 1, outbuf, used ) ;
  2128. X        Sputchar( 1, NEWLINE ) ;
  2129. X        used = 0 ;
  2130. X    }
  2131. X}
  2132. X
  2133. X
  2134. Xvoid printout_flush()
  2135. X{
  2136. X    if ( used )
  2137. X    {
  2138. X        Swrite( 1, outbuf, used ) ;
  2139. X        Sputchar( 1, NEWLINE ) ;
  2140. X        used = 0 ;
  2141. X    }
  2142. X}
  2143. X
  2144. X
  2145. Xvoid start_paragraph()
  2146. X{
  2147. X    printout_flush() ;
  2148. X    Sputchar( 1, NEWLINE ) ;
  2149. X}
  2150. X
  2151. X
  2152. Xvoid error( fmt, va_alist )
  2153. X    char *fmt ;
  2154. X    va_dcl
  2155. X{
  2156. X    va_list ap ;
  2157. X
  2158. X    va_start( ap ) ;
  2159. X    Sprint( 2, "Line %d: ", line_count ) ;
  2160. X    Sprintv( 2, fmt, ap ) ;
  2161. X    exit( 1 ) ;
  2162. X}
  2163. X
  2164. X
  2165. Xvoid decode_string( get_char, arg )
  2166. X    int (*get_char)() ;
  2167. X    void *arg ;
  2168. X{
  2169. X    int c ;
  2170. X    int skip_input = FALSE ;
  2171. X
  2172. X    for ( ;; )
  2173. X    {
  2174. X        if ( ! skip_input )
  2175. X            c = (*get_char)( arg ) ;
  2176. X        skip_input = FALSE ;
  2177. X
  2178. X        if ( c == CLOSE_PAREN )
  2179. X            return ;
  2180. X        
  2181. X        if ( c != BACKSLASH )
  2182. X        {
  2183. X            printout( c ) ;
  2184. X            continue ;
  2185. X        }
  2186. X
  2187. X        /*
  2188. X         * Interpret the character after the backslash
  2189. X         */
  2190. X        c = (*get_char) ( arg ) ;
  2191. X        if ( c == OPEN_PAREN || c == CLOSE_PAREN )
  2192. X            printout( c ) ;
  2193. X        else if ( c == 't' )
  2194. X            printout( TAB ) ;
  2195. X        else if ( c == 'n' )
  2196. X            printout( NEWLINE ) ;
  2197. X        else if ( c == BACKSLASH )
  2198. X            printout( BACKSLASH ) ;
  2199. X        else if ( isdigit( c ) )
  2200. X        {
  2201. X            int i ;
  2202. X            int num = NUM( c ) ;
  2203. X
  2204. X            /*
  2205. X             * We ignore numbers; Postscript allows up to 3 digits in \ddd
  2206. X             * and we have already consumed one.
  2207. X             */
  2208. X            for ( i = 0 ; i < 2 ; i++ )
  2209. X            {
  2210. X                c = (*get_char)( arg ) ;
  2211. X                if ( isdigit( c ) )
  2212. X                {
  2213. X                    num *= 8 ;
  2214. X                    num += NUM( c ) ;
  2215. X                }
  2216. X                else
  2217. X                {
  2218. X                    skip_input = TRUE ;
  2219. X                    break ;
  2220. X                }
  2221. X            }
  2222. X
  2223. X            if ( num == 013 )
  2224. X            {
  2225. X                printout( 'f' ) ;
  2226. X                printout( 'f' ) ;
  2227. X            }
  2228. X            else if ( num == 016 )
  2229. X            {
  2230. X                printout( 'f' ) ;
  2231. X                printout( 'f' ) ;
  2232. X                printout( 'i' ) ;
  2233. X            }
  2234. X            else if ( num == 0244 )
  2235. X                printout( '/' ) ;
  2236. X            else if ( num == 0251 || num == 0270 )
  2237. X                printout( '\'' ) ;
  2238. X            else if ( num == 0252 || num == 0271 || num == 0272 )
  2239. X                printout( '"' ) ;
  2240. X            else if ( num == 0253 )
  2241. X            {
  2242. X                printout( '<' ) ;
  2243. X                printout( '<' ) ;
  2244. X            }
  2245. X            else if ( num == 0254 )
  2246. X                printout( '<' ) ;
  2247. X            else if ( num == 0255 )
  2248. X                printout( '>' ) ;
  2249. X            else if ( num == 014 || num == 0256 )
  2250. X            {
  2251. X                printout( 'f' ) ;
  2252. X                printout( 'i' ) ;
  2253. X            }
  2254. X            else if ( num == 015 || num == 0257 )
  2255. X            {
  2256. X                printout( 'f' ) ;
  2257. X                printout( 'l' ) ;
  2258. X            }
  2259. X            else if ( num == 0261 )
  2260. X                printout( '-' ) ;
  2261. X            else if ( num == 0267 )        /* bullet point */
  2262. X                printout( '*' ) ;
  2263. X            else if ( num == 0273 )
  2264. X            {
  2265. X                printout( '>' ) ;
  2266. X                printout( '>' ) ;
  2267. X            }
  2268. X            else if ( num == 274 )
  2269. X            {
  2270. X                printout( '.' ) ;
  2271. X                printout( '.' ) ;
  2272. X                printout( '.' ) ;
  2273. X            }
  2274. X            else if ( num == 0303 )
  2275. X                printout( '^' ) ;
  2276. X            else if ( num == 0304 )
  2277. X                printout( '~' ) ;
  2278. X            else if ( isascii( num ) && isprint( num ) )
  2279. X                printout( num ) ;
  2280. X        }
  2281. X    }
  2282. X}
  2283. X
  2284. END_OF_FILE
  2285.   if test 4850 -ne `wc -c <'pst/common.c'`; then
  2286.     echo shar: \"'pst/common.c'\" unpacked with wrong size!
  2287.   fi
  2288.   # end of 'pst/common.c'
  2289. fi
  2290. echo shar: End of archive 1 \(of 6\).
  2291. cp /dev/null ark1isdone
  2292. MISSING=""
  2293. for I in 1 2 3 4 5 6 ; do
  2294.     if test ! -f ark${I}isdone ; then
  2295.     MISSING="${MISSING} ${I}"
  2296.     fi
  2297. done
  2298. if test "${MISSING}" = "" ; then
  2299.     echo You have unpacked all 6 archives.
  2300.     rm -f ark[1-9]isdone
  2301. else
  2302.     echo You still must unpack the following archives:
  2303.     echo "        " ${MISSING}
  2304. fi
  2305. exit 0
  2306. exit 0 # Just in case...
  2307.