home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / xinetd21 / part29 < prev    next >
Encoding:
Text File  |  1993-06-26  |  19.7 KB  |  811 lines

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