home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume27 / clc / part19 < prev    next >
Encoding:
Text File  |  1993-11-28  |  19.7 KB  |  812 lines

  1. Newsgroups: comp.sources.unix
  2. From: panos@anchor.cs.colorado.edu (Panos Tsirigotis)
  3. Subject: v27i125: clc - C Libraries Collection, Part19/20
  4. References: <1.754527080.23891@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: panos@anchor.cs.colorado.edu (Panos Tsirigotis)
  9. Posting-Number: Volume 27, Issue 125
  10. Archive-Name: clc/part19
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 19 (of 20)."
  19. # Contents:  libs/src/sio/sprint.c
  20. # Wrapped by panos@eclipse on Sun Nov 28 14:48:17 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'libs/src/sio/sprint.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'libs/src/sio/sprint.c'\"
  24. else
  25. echo shar: Extracting \"'libs/src/sio/sprint.c'\" \(17542 characters\)
  26. sed "s/^X//" >'libs/src/sio/sprint.c' <<'END_OF_FILE'
  27. X/*
  28. X * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  29. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  30. X * and conditions for redistribution.
  31. X */
  32. X
  33. X
  34. Xstatic char RCSid[] = "$Id: sprint.c,v 8.3 1993/03/30 21:33:44 panos Exp $" ;
  35. X
  36. X#include <ctype.h>
  37. X
  38. X#include "sio.h"
  39. X#include "impl.h"
  40. X
  41. X#ifndef WIDE_INT
  42. X#define WIDE_INT                            long
  43. X#endif
  44. X
  45. Xtypedef WIDE_INT                             wide_int ;
  46. Xtypedef unsigned WIDE_INT                 u_wide_int ;
  47. Xtypedef int                                 bool_int ;
  48. X
  49. X#define S_NULL                                "(null)"
  50. X#define S_NULL_LEN                        6
  51. X
  52. X#define FLOAT_DIGITS                        6
  53. X#define EXPONENT_LENGTH                    10
  54. X
  55. X/*
  56. X * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
  57. X *
  58. X * XXX: this is a magic number; do not decrease it
  59. X */
  60. X#define NUM_BUF_SIZE                        512
  61. X
  62. X/*
  63. X * The INS_CHAR macro inserts a character in the buffer and writes
  64. X * the buffer back to disk if necessary
  65. X * It uses the char pointers sp and bep:
  66. X *     sp points to the next available character in the buffer
  67. X *     bep points to the end-of-buffer+1
  68. X * While using this macro, note that the nextb pointer is NOT updated.
  69. X *
  70. X * No I/O is performed if fd is not positive. Negative fd values imply
  71. X * conversion with the output directed to a string. Excess characters
  72. X * are discarded if the string overflows.
  73. X *
  74. X * NOTE: Evaluation of the c argument should not have any side-effects
  75. X */
  76. X#define INS_CHAR( c, sp, bep, odp, cc, fd )                                            \
  77. X            {                                                                                        \
  78. X                if ( sp < bep )                                                                \
  79. X                {                                                                                    \
  80. X                    *sp++ = c ;                                                                    \
  81. X                    cc++ ;                                                                        \
  82. X                }                                                                                    \
  83. X                else                                                                                \
  84. X                {                                                                                    \
  85. X                    if ( fd >= 0 )                                                                \
  86. X                    {                                                                                \
  87. X                        odp->nextb = sp ;                                                        \
  88. X                        if ( __sio_writef( odp, fd ) != bep - odp->start )            \
  89. X                            return( ( cc != 0 ) ? cc : SIO_ERR ) ;                        \
  90. X                        sp = odp->nextb ;                                                        \
  91. X                        *sp++ = c ;                                                                \
  92. X                        cc++ ;                                                                    \
  93. X                    }                                                                                \
  94. X                }                                                                                    \
  95. X                if ( __SIO_MUST_FLUSH( *odp, c ) && fd >= 0 )                         \
  96. X                {                                                                                    \
  97. X                    int b_in_buffer = sp - odp->start ;                                    \
  98. X                                                                                                    \
  99. X                    odp->nextb = sp ;                                                            \
  100. X                    if ( __sio_writef( odp, fd ) != b_in_buffer )                    \
  101. X                        return( cc ) ;                                                            \
  102. X                    sp = odp->nextb ;                                                            \
  103. X                }                                                                                    \
  104. X            }
  105. X
  106. X
  107. X
  108. X#define NUM( c )            ( c - '0' )
  109. X
  110. X#define STR_TO_DEC( str, num )                                    \
  111. X                                    num = NUM( *str++ ) ;            \
  112. X                                    while ( isdigit( *str ) )        \
  113. X                                    {                                        \
  114. X                                        num *= 10 ;                        \
  115. X                                        num += NUM( *str++ ) ;        \
  116. X                                    }
  117. X
  118. X/*
  119. X * This macro does zero padding so that the precision
  120. X * requirement is satisfied. The padding is done by
  121. X * adding '0's to the left of the string that is going
  122. X * to be printed.
  123. X */
  124. X#define FIX_PRECISION( adjust, precision, s, s_len )                \
  125. X                    if ( adjust )                                                \
  126. X                        while ( s_len < precision )                        \
  127. X                        {                                                            \
  128. X                            *--s = '0' ;                                        \
  129. X                            s_len++ ;                                            \
  130. X                        }
  131. X
  132. X/*
  133. X * Macro that does padding. The padding is done by printing
  134. X * the character ch.
  135. X */
  136. X#define PAD( width, len, ch )            do                                                        \
  137. X                                                {                                                        \
  138. X                                                    INS_CHAR( ch, sp, bep, odp, cc, fd ) ;    \
  139. X                                                    width-- ;                                        \
  140. X                                                }                                                        \
  141. X                                                while ( width > len )
  142. X
  143. X/*
  144. X * Prefix the character ch to the string str
  145. X * Increase length
  146. X * Set the has_prefix flag
  147. X */
  148. X#define PREFIX( str, length, ch )    *--str = ch ; length++ ; has_prefix = YES
  149. X
  150. X
  151. X/*
  152. X * Sprint is the equivalent of printf for SIO.
  153. X * It returns the # of chars written
  154. X * Assumptions:
  155. X *     - all floating point arguments are passed as doubles
  156. X */
  157. X/* VARARGS2 */
  158. Xint Sprint( fd, fmt, va_alist ) 
  159. X    int fd ;
  160. X    register char *fmt ;
  161. X    va_dcl
  162. X{
  163. X    __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  164. X    register __sio_od_t *odp = ODP( dp ) ;
  165. X    register int cc ;
  166. X    va_list ap ;
  167. X
  168. X    IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  169. X
  170. X    va_start( ap ) ;
  171. X    cc = __sio_converter( odp, fd, fmt, ap ) ;
  172. X    va_end( ap ) ;
  173. X    return( cc ) ;
  174. X}
  175. X
  176. X
  177. X/*
  178. X * This is the equivalent of vfprintf for SIO
  179. X */
  180. Xint Sprintv( fd, fmt, ap )
  181. X    int fd ;
  182. X    char *fmt ;
  183. X    va_list ap ;
  184. X{
  185. X    __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  186. X    register __sio_od_t *odp = ODP( dp ) ;
  187. X
  188. X    IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  189. X    return( __sio_converter( odp, fd, fmt, ap ) ) ;
  190. X}
  191. X
  192. X
  193. X/*
  194. X * Convert a floating point number to a string formats 'f', 'e' or 'E'.
  195. X * The result is placed in buf, and len denotes the length of the string
  196. X * The sign is returned in the is_negative argument (and is not placed
  197. X * in buf).
  198. X */
  199. XPRIVATE char *conv_fp( format, num, add_dp, precision, is_negative, buf, len )
  200. X    register char format ;
  201. X    register double num ;
  202. X    boolean_e add_dp ;            /* always add decimal point if YES */
  203. X    int precision ;
  204. X    bool_int *is_negative ;
  205. X    char buf[] ;
  206. X    int *len ;
  207. X{
  208. X    register char *s = buf ;
  209. X    register char *p ;
  210. X    int decimal_point ;
  211. X    char *ecvt(), *fcvt() ;
  212. X    char *conv_10() ;
  213. X    char *strcpy() ;
  214. X        
  215. X    if ( format == 'f' )
  216. X        p = fcvt( num, precision, &decimal_point, is_negative ) ;
  217. X    else /* either e or E format */
  218. X        p = ecvt( num, precision+1, &decimal_point, is_negative ) ;
  219. X
  220. X    /*
  221. X     * Check for Infinity and NaN
  222. X     */
  223. X    if ( isalpha( *p ) )
  224. X    {
  225. X        *len = strlen( strcpy( buf, p ) ) ;
  226. X        *is_negative = FALSE ;
  227. X        return( buf ) ;
  228. X    }
  229. X    
  230. X    if ( format == 'f' )
  231. X        if ( decimal_point <= 0 )
  232. X        {
  233. X            *s++ = '0' ;
  234. X            if ( precision > 0 )
  235. X            {
  236. X                *s++ = '.' ;
  237. X                while ( decimal_point++ < 0 )
  238. X                    *s++ = '0' ;
  239. X            }
  240. X            else if ( add_dp )
  241. X                *s++ = '.' ;
  242. X        }
  243. X        else
  244. X        {
  245. X            while ( decimal_point-- > 0 )
  246. X                *s++ = *p++ ;
  247. X            if ( precision > 0 || add_dp ) *s++ = '.' ;
  248. X        }
  249. X    else
  250. X    {
  251. X        *s++ = *p++ ;
  252. X        if ( precision > 0 || add_dp ) *s++ = '.' ;
  253. X    }
  254. X
  255. X    /*
  256. X     * copy the rest of p, the NUL is NOT copied
  257. X     */
  258. X    while ( *p ) *s++ = *p++ ;            
  259. X    
  260. X    if ( format != 'f' )
  261. X    {
  262. X        char temp[ EXPONENT_LENGTH ] ;                /* for exponent conversion */
  263. X        int t_len ;
  264. X        bool_int exponent_is_negative ;
  265. X
  266. X        *s++ = format ;        /* either e or E */
  267. X        decimal_point-- ;
  268. X        if ( decimal_point != 0 )
  269. X        {
  270. X            p = conv_10( (wide_int)decimal_point, FALSE, &exponent_is_negative,
  271. X                                                &temp[ EXPONENT_LENGTH ], &t_len ) ;
  272. X            *s++ = exponent_is_negative ? '-' : '+' ;
  273. X            
  274. X            /*
  275. X             * Make sure the exponent has at least 2 digits
  276. X             */
  277. X            if ( t_len == 1 )
  278. X                *s++ = '0' ;
  279. X            while ( t_len-- ) *s++ = *p++ ;
  280. X        }
  281. X        else
  282. X        {
  283. X            *s++ = '+' ;
  284. X            *s++ = '0' ;
  285. X            *s++ = '0' ;
  286. X        }
  287. X    }
  288. X
  289. X    *len = s - buf ;
  290. X    return( buf ) ;
  291. X}
  292. X
  293. X
  294. X/*
  295. X * Convert num to a base X number where X is a power of 2. nbits determines X.
  296. X * For example, if nbits is 3, we do base 8 conversion
  297. X * Return value:
  298. X *            a pointer to a string containing the number
  299. X *
  300. X * The caller provides a buffer for the string: that is the buf_end argument
  301. X * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  302. X * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  303. X */
  304. XPRIVATE char *conv_p2( num, nbits, format, buf_end, len )
  305. X    register u_wide_int num ;
  306. X    register int nbits ;
  307. X    char format ;
  308. X    char *buf_end ;
  309. X    register int *len ;
  310. X{
  311. X    register int mask = ( 1 << nbits ) - 1 ;
  312. X    register char *p = buf_end ;
  313. X    static char low_digits[] = "0123456789abcdef" ;
  314. X    static char upper_digits[] = "0123456789ABCDEF" ;
  315. X    register char *digits = ( format == 'X' ) ? upper_digits : low_digits ;
  316. X
  317. X    do
  318. X    {
  319. X        *--p = digits[ num & mask ] ;
  320. X        num >>= nbits ;
  321. X    }
  322. X    while( num ) ;
  323. X
  324. X    *len = buf_end - p ;
  325. X    return( p ) ;
  326. X}
  327. X
  328. X
  329. X
  330. X/*
  331. X * Convert num to its decimal format.
  332. X * Return value:
  333. X *       - a pointer to a string containing the number (no sign)
  334. X *            - len contains the length of the string
  335. X *            - is_negative is set to TRUE or FALSE depending on the sign
  336. X *              of the number (always set to FALSE if is_unsigned is TRUE)
  337. X *
  338. X * The caller provides a buffer for the string: that is the buf_end argument
  339. X * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  340. X * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  341. X */
  342. XPRIVATE char *conv_10( num, is_unsigned, is_negative, buf_end, len )
  343. X    register wide_int num ; 
  344. X    register bool_int is_unsigned ;
  345. X    register bool_int *is_negative ;
  346. X    char *buf_end ;
  347. X    register int *len ;
  348. X{
  349. X    register char *p = buf_end ;
  350. X    register u_wide_int magnitude ;
  351. X
  352. X    if ( is_unsigned )
  353. X    {
  354. X        magnitude = (u_wide_int) num ;
  355. X        *is_negative = FALSE ;
  356. X    }
  357. X    else
  358. X    {
  359. X        *is_negative = ( num < 0 ) ;
  360. X
  361. X        /*
  362. X         * On a 2's complement machine, negating the most negative integer 
  363. X         * results in a number that cannot be represented as a signed integer.
  364. X         * Here is what we do to obtain the number's magnitude:
  365. X         *        a. add 1 to the number
  366. X         *        b. negate it (becomes positive)
  367. X         *        c. convert it to unsigned
  368. X         *        d. add 1
  369. X         */
  370. X        if ( *is_negative )
  371. X        {
  372. X            wide_int t = num + 1 ;
  373. X
  374. X            magnitude = ( (u_wide_int) -t ) + 1 ;
  375. X        }
  376. X        else
  377. X            magnitude = (u_wide_int) num ;
  378. X    }
  379. X
  380. X    /*
  381. X     * We use a do-while loop so that we write at least 1 digit 
  382. X     */
  383. X    do
  384. X    {
  385. X        register u_wide_int new_magnitude = magnitude / 10 ;
  386. X
  387. X        *--p = magnitude - new_magnitude*10 + '0' ;
  388. X        magnitude = new_magnitude ;
  389. X    }
  390. X    while ( magnitude ) ;
  391. X    
  392. X    *len = buf_end - p ;
  393. X    return( p ) ;
  394. X}
  395. X
  396. X
  397. X/*
  398. X * Do format conversion placing the output in odp
  399. X */
  400. Xint __sio_converter( odp, fd, fmt, ap )
  401. X    register __sio_od_t *odp ;
  402. X    int fd ;
  403. X    register char *fmt ;
  404. X    va_list ap ;
  405. X{
  406. X    register char *sp ;
  407. X    register char *bep ;
  408. X    register int cc = 0 ;
  409. X    register int i ;
  410. X
  411. X    register char *s ;
  412. X    char *q ;
  413. X    int s_len ;
  414. X
  415. X    register int min_width ;
  416. X    int precision ;
  417. X    enum { LEFT, RIGHT } adjust ;
  418. X    char pad_char ;
  419. X    char prefix_char ;
  420. X
  421. X    double fp_num ;
  422. X    wide_int i_num ;
  423. X    u_wide_int ui_num ;
  424. X
  425. X    char num_buf[ NUM_BUF_SIZE ] ;
  426. X    char char_buf[ 2 ] ;        /* for printing %% and %<unknown> */
  427. X
  428. X    /*
  429. X     * Flag variables
  430. X     */
  431. X    boolean_e is_long ;
  432. X    boolean_e alternate_form ;
  433. X    boolean_e print_sign ;
  434. X    boolean_e print_blank ;
  435. X    boolean_e adjust_precision ;
  436. X    boolean_e adjust_width ;
  437. X    bool_int is_negative ;
  438. X
  439. X    char *conv_10(), *conv_p2(), *conv_fp() ;
  440. X    char *gcvt() ;
  441. X    char *strchr() ;
  442. X
  443. X
  444. X    sp = odp->nextb ;
  445. X    bep = odp->buf_end ;
  446. X
  447. X    while ( *fmt )
  448. X    {
  449. X        if ( *fmt != '%' )
  450. X        {
  451. X            INS_CHAR( *fmt, sp, bep, odp, cc, fd ) ;
  452. X        }
  453. X        else
  454. X        {
  455. X            /*
  456. X             * Default variable settings
  457. X             */
  458. X            adjust = RIGHT ;
  459. X            alternate_form = print_sign = print_blank = NO ;
  460. X            pad_char = ' ' ;
  461. X            prefix_char = NUL ;
  462. X
  463. X            fmt++ ;
  464. X
  465. X            /*
  466. X             * Try to avoid checking for flags, width or precision
  467. X             */
  468. X            if ( isascii( *fmt ) && ! islower( *fmt ) )
  469. X            {
  470. X                /*
  471. X                 * Recognize flags: -, #, BLANK, +
  472. X                 */
  473. X                for ( ;; fmt++ )
  474. X                {
  475. X                    if ( *fmt == '-' )
  476. X                        adjust = LEFT ;
  477. X                    else if ( *fmt == '+' )
  478. X                        print_sign = YES ;
  479. X                    else if ( *fmt == '#' )
  480. X                        alternate_form = YES ;
  481. X                    else if ( *fmt == ' ' )
  482. X                        print_blank = YES ;
  483. X                    else if ( *fmt == '0' )
  484. X                        pad_char = '0' ;
  485. X                    else
  486. X                        break ;
  487. X                }
  488. X
  489. X                /*
  490. X                 * Check if a width was specified
  491. X                 */
  492. X                if ( isdigit( *fmt ) )
  493. X                {
  494. X                    STR_TO_DEC( fmt, min_width ) ;
  495. X                    adjust_width = YES ;
  496. X                }
  497. X                else if ( *fmt == '*' )
  498. X                {
  499. X                    min_width = va_arg( ap, int ) ;
  500. X                    fmt++ ;
  501. X                    adjust_width = YES ;
  502. X                    if ( min_width < 0 )
  503. X                    {
  504. X                        adjust = LEFT ;
  505. X                        min_width = -min_width ;
  506. X                    }
  507. X                }
  508. X                else
  509. X                    adjust_width = NO ;
  510. X                
  511. X                /*
  512. X                 * Check if a precision was specified
  513. X                 *
  514. X                 * XXX: an unreasonable amount of precision may be specified
  515. X                 *          resulting in overflow of num_buf. Currently we
  516. X                 *          ignore this possibility.
  517. X                 */
  518. X                if ( *fmt == '.' )
  519. X                {
  520. X                    adjust_precision = YES ;
  521. X                    fmt++ ;
  522. X                    if ( isdigit( *fmt ) )
  523. X                    {
  524. X                        STR_TO_DEC( fmt, precision ) ;
  525. X                    }
  526. X                    else if ( *fmt == '*' )
  527. X                    {
  528. X                        precision = va_arg( ap, int ) ;
  529. X                        fmt++ ;
  530. X                        if ( precision < 0 )
  531. X                            precision = 0 ;
  532. X                    }
  533. X                    else
  534. X                        precision = 0 ;
  535. X                }
  536. X                else
  537. X                    adjust_precision = NO ;
  538. X            }
  539. X            else
  540. X                adjust_precision = adjust_width = NO ;
  541. X
  542. X            /*
  543. X             * Modifier check
  544. X             */
  545. X            if ( *fmt == 'l' )
  546. X            {
  547. X                is_long = YES ;
  548. X                fmt++ ;
  549. X            }
  550. X            else
  551. X                is_long = NO ;
  552. X
  553. X            /*
  554. X             * Argument extraction and printing.
  555. X             * First we determine the argument type.
  556. X             * Then, we convert the argument to a string.
  557. X             * On exit from the switch, s points to the string that
  558. X             * must be printed, s_len has the length of the string
  559. X             * The precision requirements, if any, are reflected in s_len.
  560. X             *
  561. X             * NOTE: pad_char may be set to '0' because of the 0 flag.
  562. X             *            It is reset to ' ' by non-numeric formats
  563. X             */
  564. X            switch( *fmt )
  565. X            {
  566. X                case 'd':
  567. X                case 'i':
  568. X                case 'u':
  569. X                    if ( is_long )
  570. X                        i_num = va_arg( ap, wide_int ) ;
  571. X                    else
  572. X                        i_num = (wide_int) va_arg( ap, int ) ;
  573. X                    s = conv_10( i_num, (*fmt) == 'u', &is_negative,
  574. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  575. X                    FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  576. X
  577. X                    if ( *fmt != 'u' )
  578. X                    {
  579. X                        if ( is_negative )
  580. X                            prefix_char = '-' ;
  581. X                        else if ( print_sign )
  582. X                            prefix_char = '+' ;
  583. X                        else if ( print_blank )
  584. X                            prefix_char = ' ' ;
  585. X                    }
  586. X                    break ;
  587. X                
  588. X
  589. X                case 'o':
  590. X                    if ( is_long )
  591. X                        ui_num = va_arg( ap, u_wide_int ) ; 
  592. X                    else
  593. X                        ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
  594. X                    s = conv_p2( ui_num, 3, *fmt, 
  595. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  596. X                    FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  597. X                    if ( alternate_form && *s != '0' )
  598. X                    {
  599. X                        *--s = '0' ;
  600. X                        s_len++ ;
  601. X                    }
  602. X                    break ;
  603. X                
  604. X
  605. X                case 'x':
  606. X                case 'X':
  607. X                    if ( is_long )
  608. X                        ui_num = (u_wide_int) va_arg( ap, u_wide_int ) ;
  609. X                    else
  610. X                        ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
  611. X                    s = conv_p2( ui_num, 4, *fmt,
  612. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  613. X                    FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  614. X                    if ( alternate_form && i_num != 0 )
  615. X                    {
  616. X                        *--s = *fmt ;            /* 'x' or 'X' */
  617. X                        *--s = '0' ;
  618. X                        s_len += 2 ;
  619. X                    }
  620. X                    break ;
  621. X                
  622. X
  623. X                case 's':
  624. X                    s = va_arg( ap, char * ) ;
  625. X                    if ( s != NULL )
  626. X                    {
  627. X                        s_len = strlen( s ) ;
  628. X                        if ( adjust_precision && precision < s_len )
  629. X                            s_len = precision ;
  630. X                    }
  631. X                    else
  632. X                    {
  633. X                        s = S_NULL ;
  634. X                        s_len = S_NULL_LEN ;
  635. X                    }
  636. X                    pad_char = ' ' ;
  637. X                    break ;
  638. X                
  639. X
  640. X                case 'f':
  641. X                case 'e':
  642. X                case 'E':
  643. X                    fp_num = va_arg( ap, double ) ;
  644. X
  645. X                    s = conv_fp( *fmt, fp_num, alternate_form,
  646. X                            ( adjust_precision == NO ) ? FLOAT_DIGITS : precision,
  647. X                                                    &is_negative, &num_buf[ 1 ], &s_len ) ;
  648. X                    if ( is_negative )
  649. X                        prefix_char = '-' ;
  650. X                    else if ( print_sign )
  651. X                        prefix_char = '+' ;
  652. X                    else if ( print_blank )
  653. X                        prefix_char = ' ' ;
  654. X                    break ;
  655. X
  656. X
  657. X                case 'g':
  658. X                case 'G':
  659. X                    if ( adjust_precision == NO )
  660. X                        precision = FLOAT_DIGITS ;
  661. X                    else if ( precision == 0 )
  662. X                        precision = 1 ;
  663. X                    /*
  664. X                     * We use &num_buf[ 1 ], so that we have room for the sign
  665. X                     */
  666. X                    s = gcvt( va_arg( ap, double ), precision, &num_buf[ 1 ] ) ;
  667. X                    if ( *s == '-' )
  668. X                        prefix_char = *s++ ;
  669. X                    else if ( print_sign )
  670. X                        prefix_char = '+' ;
  671. X                    else if ( print_blank )
  672. X                        prefix_char = ' ' ;
  673. X
  674. X                    s_len = strlen( s ) ;
  675. X
  676. X                    if ( alternate_form && ( q = strchr( s, '.' ) ) == NULL )
  677. X                        s[ s_len++ ] = '.' ;
  678. X                    if ( *fmt == 'G' && ( q = strchr( s, 'e' ) ) != NULL )
  679. X                        *q = 'E' ;
  680. X                    break ;
  681. X
  682. X
  683. X                case 'c':
  684. X                    char_buf[ 0 ] = (char) (va_arg( ap, int )) ;
  685. X                    s = &char_buf[ 0 ] ;
  686. X                    s_len = 1 ;
  687. X                    pad_char = ' ' ;
  688. X                    break ;
  689. X
  690. X
  691. X                case '%':
  692. X                    char_buf[ 0 ] = '%' ;
  693. X                    s = &char_buf[ 0 ] ;
  694. X                    s_len = 1 ;
  695. X                    pad_char = ' ' ;
  696. X                    break ;
  697. X
  698. X
  699. X                case 'n':
  700. X                    *(va_arg( ap, int * )) = cc ;
  701. X                    break ;
  702. X
  703. X                /*
  704. X                 * Always extract the argument as a "char *" pointer. We 
  705. X                 * should be using "void *" but there are still machines 
  706. X                 * that don't understand it.
  707. X                 * If the pointer size is equal to the size of an unsigned
  708. X                 * integer we convert the pointer to a hex number, otherwise 
  709. X                 * we print "%p" to indicate that we don't handle "%p".
  710. X                 */
  711. X                case 'p':
  712. X                    ui_num = (u_wide_int) va_arg( ap, char * ) ;
  713. X
  714. X                    if ( sizeof( char * ) <= sizeof( u_wide_int ) )
  715. X                        s = conv_p2( ui_num, 4, 'x', 
  716. X                                                &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  717. X                    else
  718. X                    {
  719. X                        s = "%p" ;
  720. X                        s_len = 2 ;
  721. X                    }
  722. X                    pad_char = ' ' ;
  723. X                    break ;
  724. X                    
  725. X
  726. X                case NUL:
  727. X                    /*
  728. X                     * The last character of the format string was %.
  729. X                     * We ignore it.
  730. X                     */
  731. X                    continue ;
  732. X
  733. X
  734. X                    /*
  735. X                      * The default case is for unrecognized %'s.
  736. X                     * We print %<char> to help the user identify what
  737. X                     * option is not understood.
  738. X                     * This is also useful in case the user wants to pass
  739. X                     * the output of __sio_converter to another function
  740. X                     * that understands some other %<char> (like syslog).
  741. X                     * Note that we can't point s inside fmt because the
  742. X                     * unknown <char> could be preceded by width etc.
  743. X                     */
  744. X                default:
  745. X                    char_buf[ 0 ] = '%' ;
  746. X                    char_buf[ 1 ] = *fmt ;
  747. X                    s = char_buf ;
  748. X                    s_len = 2 ;
  749. X                    pad_char = ' ' ;
  750. X                    break ;
  751. X            }
  752. X
  753. X            if ( prefix_char != NUL )
  754. X            {
  755. X                *--s = prefix_char ;
  756. X                s_len++ ;
  757. X            }
  758. X
  759. X            if ( adjust_width && adjust == RIGHT && min_width > s_len )
  760. X            {
  761. X                if ( pad_char == '0' && prefix_char != NUL )
  762. X                {
  763. X                    INS_CHAR( *s, sp, bep, odp, cc, fd )
  764. X                    s++ ;
  765. X                    s_len-- ;
  766. X                    min_width-- ;
  767. X                }
  768. X                PAD( min_width, s_len, pad_char ) ;
  769. X            }
  770. X
  771. X            /*
  772. X             * Print the string s. 
  773. X             */
  774. X            for ( i = s_len ; i != 0 ; i-- )
  775. X            {
  776. X                INS_CHAR( *s, sp, bep, odp, cc, fd ) ;
  777. X                s++ ;
  778. X            }
  779. X
  780. X            if ( adjust_width && adjust == LEFT && min_width > s_len )
  781. X                PAD( min_width, s_len, pad_char ) ;
  782. X        }
  783. X        fmt++ ;
  784. X    }
  785. X    odp->nextb = sp ;
  786. X    return( cc ) ;
  787. X}
  788. X
  789. END_OF_FILE
  790. if test 17542 -ne `wc -c <'libs/src/sio/sprint.c'`; then
  791.     echo shar: \"'libs/src/sio/sprint.c'\" unpacked with wrong size!
  792. fi
  793. # end of 'libs/src/sio/sprint.c'
  794. fi
  795. echo shar: End of archive 19 \(of 20\).
  796. cp /dev/null ark19isdone
  797. MISSING=""
  798. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
  799.     if test ! -f ark${I}isdone ; then
  800.     MISSING="${MISSING} ${I}"
  801.     fi
  802. done
  803. if test "${MISSING}" = "" ; then
  804.     echo You have unpacked all 20 archives.
  805.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  806. else
  807.     echo You still need to unpack the following archives:
  808.     echo "        " ${MISSING}
  809. fi
  810. ##  End of shell archive.
  811. exit 0
  812.