fork download
  1. /*
  2.  
  3. ax_printf - public domain
  4. Last update: 2015-02-27 Aaron Miller
  5.  
  6.  
  7. TODO
  8.  
  9. - Convert to proper single-source header form (like STB)
  10. - Add proper %g and %e support.
  11. - Test %f more, and add support for #INF, #NAN, etc.
  12.  
  13.  
  14. LICENSE
  15.  
  16. This software is in the public domain. Where that dedication is not
  17. recognized, you are granted a perpetual, irrevocable license to copy
  18. and modify this file as you see fit.
  19.  
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24.  
  25. /* -------------------------------------------------------------------------- */
  26. /* axpf() (printf) implementation */
  27.  
  28. #include <errno.h>
  29. #include <assert.h>
  30. #include <stdarg.h>
  31. #include <stddef.h>
  32. #include <string.h>
  33.  
  34. #ifdef _MSC_VER
  35. typedef signed __int8 int8;
  36. typedef signed __int16 int16;
  37. typedef signed __int32 int32;
  38. typedef signed __int64 int64;
  39. typedef unsigned __int8 uint8;
  40. typedef unsigned __int16 uint16;
  41. typedef unsigned __int32 uint32;
  42. typedef unsigned __int64 uint64;
  43. #else
  44. # include <stdint.h>
  45. typedef int8_t int8;
  46. typedef int16_t int16;
  47. typedef int32_t int32;
  48. typedef int64_t int64;
  49. typedef uint8_t uint8;
  50. typedef uint16_t uint16;
  51. typedef uint32_t uint32;
  52. typedef uint64_t uint64;
  53. #endif
  54.  
  55. /*
  56.  
  57. See: http://w...content-available-to-author-only...s.com/reference/cstdio/printf/
  58. See: http://w...content-available-to-author-only...x.com/man-page/FreeBSD/9/printf/
  59. See: http://w...content-available-to-author-only...x.com/man-page/freebsd/3/syslog/
  60.  
  61. */
  62.  
  63. typedef ptrdiff_t( *axpf_write_fn_t )( void *, const char *, const char * );
  64.  
  65. struct axpf__write_mem_data_
  66. {
  67. char *p;
  68. size_t i;
  69. size_t n;
  70. };
  71.  
  72. static ptrdiff_t axpf__write_mem_f( void *data, const char *s, const char *e )
  73. {
  74. struct axpf__write_mem_data_ *md;
  75. size_t n;
  76.  
  77. md = ( struct axpf__write_mem_data_ * )data;
  78.  
  79. n = ( size_t )( e - s );
  80. if( !n ) {
  81. return 0;
  82. }
  83.  
  84. if( md->i + n > md->n ) {
  85. n = md->n - md->i;
  86. }
  87.  
  88. memcpy( ( void * )&md->p[ md->i ], ( const void * )s, n );
  89. return n;
  90. }
  91. static ptrdiff_t axpf__write_fp_f( void *data, const char *s, const char *e )
  92. {
  93. if( !fwrite( ( const void * )s, ( size_t )( e - s ), 1, ( FILE * )data ) ) {
  94. return ( ptrdiff_t )-1;
  95. }
  96.  
  97. return ( ptrdiff_t )( e - s );
  98. }
  99.  
  100. enum
  101. {
  102. /* "-" Left-justify within the given field width */
  103. kPF_Left = 1<<0,
  104. /* "+" Result will be preceeded by either a - or + */
  105. kPF_Sign = 1<<1,
  106. /* " " Result will be preceeded by either a - or a space */
  107. kPF_Space = 1<<2,
  108. /* "#" Insert an appropriate radix (0, 0x, 0X) */
  109. kPF_Radix = 1<<3,
  110. /* "0" Left-pad the number with zeroes instead of spaces */
  111. kPF_Zero = 1<<4,
  112. /* "'" Use a digit separator */
  113. kPF_Group = 1<<5,
  114.  
  115. /* [Internal] Printing an array */
  116. kPF_Array = 1<<11,
  117. /* [Internal] Uppercase */
  118. kPF_Upper = 1<<12,
  119. /* [Internal] Width directive was specified */
  120. kPF_Width = 1<<13,
  121. /* [Internal] Precision directive was specified */
  122. kPF_Precision = 1<<14,
  123. /* [Internal] Use a lower-case radix (for pointer printing) */
  124. kPF_Pointer = 1<<15
  125. };
  126. typedef enum
  127. {
  128. kLS_None,
  129. kLS_hh,
  130. kLS_h,
  131. kLS_l,
  132. kLS_ll,
  133. kLS_j,
  134. kLS_z,
  135. kLS_t,
  136. kLS_L,
  137.  
  138. kLS_I,
  139. kLS_I32,
  140. kLS_I64
  141. } axpf__lengthSpecifier_t;
  142.  
  143. #define AXPF__MAX_ARRAY_PRINT 4
  144. struct axpf__state_
  145. {
  146. axpf_write_fn_t pfn_write;
  147. void *write_data;
  148. size_t num_written;
  149. int diderror;
  150.  
  151. unsigned repeats;
  152. size_t arraysize;
  153. char arrayprint[ AXPF__MAX_ARRAY_PRINT ];
  154. unsigned flags;
  155. int width;
  156. int precision;
  157. axpf__lengthSpecifier_t lenspec;
  158. unsigned radix;
  159. va_list args;
  160. const char *s;
  161. const char *e;
  162. const char *p;
  163. };
  164.  
  165. static char axpf__read( struct axpf__state_ *s )
  166. {
  167. return s->p < s->e ? *s->p++ : '\0';
  168. }
  169. static char axpf__look( struct axpf__state_ *s )
  170. {
  171. return s->p < s->e ? *s->p : '\0';
  172. }
  173. static void axpf__skip( struct axpf__state_ *s )
  174. {
  175. if( s->p < s->e ) {
  176. s->p++;
  177. }
  178. }
  179.  
  180. static int axpf__check( struct axpf__state_ *s, int ch )
  181. {
  182. if( s->p < s->e && *s->p == ch ) {
  183. ++s->p;
  184. return 1;
  185. }
  186.  
  187. return 0;
  188. }
  189. static int axpf__checks( struct axpf__state_ *s, const char *p )
  190. {
  191. if( s->p < s->e && *s->p == *p ) {
  192. const char *q;
  193.  
  194. q = s->p + 1;
  195. while( *q++ == *++p ) {
  196. if( !*p ) {
  197. break;
  198. }
  199. }
  200. if( !*p ) {
  201. s->p = q;
  202. return 1;
  203. }
  204. }
  205.  
  206. return 0;
  207. }
  208.  
  209. static int axpf__write( struct axpf__state_ *s, const char *p, const char *e )
  210. {
  211. ptrdiff_t r;
  212.  
  213. r = s->pfn_write( s->write_data, p, e );
  214. if( r == -1 ) {
  215. s->diderror = 1;
  216. return 0;
  217. }
  218.  
  219. if( s->num_written + ( size_t )r >= s->num_written ) {
  220. s->num_written += ( size_t )r;
  221. } else {
  222. s->num_written = ( ~( size_t )0 ) - 1;
  223. }
  224.  
  225. return 1;
  226. }
  227. static int axpf__writech( struct axpf__state_ *s, char ch )
  228. {
  229. char txt[ 2 ];
  230.  
  231. txt[ 0 ] = ch;
  232. txt[ 1 ] = '\0';
  233.  
  234. return axpf__write( s, &txt[ 0 ], &txt[ 1 ] );
  235. }
  236.  
  237. static char *axpf__utoa( char *end, uintmax_t i, unsigned radix, int flags )
  238. {
  239. static const char *lower = "0123456789abcdefghijklmnopqrstuvwxyz";
  240. static const char *upper = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  241.  
  242. const char *digits;
  243. unsigned groupingdist, groupingbase;
  244. char groupingchar;
  245. char *p;
  246.  
  247. if( radix < 2 ) { radix = 2; }
  248. if( radix > 36 ) { radix = 36; }
  249.  
  250. digits = ( flags & 1 ) ? upper : lower;
  251.  
  252. /* TODO: Grab information from locale */
  253. groupingbase = ( flags & 4 ) ? 3 : 9999;
  254. groupingdist = groupingbase + 1;
  255. groupingchar = ',';
  256.  
  257. p = end - 1;
  258.  
  259. *p = '\0';
  260.  
  261. while( i > 0 ) {
  262. if( !--groupingdist ) {
  263. groupingdist = groupingbase;
  264. *--p = groupingchar;
  265. }
  266. *--p = digits[ i%radix ];
  267. i /= radix;
  268. }
  269. if( *p == '\0' && ( ~flags & 2 ) ) {
  270. *--p = '0';
  271. }
  272.  
  273. return p;
  274. }
  275. static int axpf__dtoax( char *buf, char *outsign, double f, int usescinot,
  276. unsigned maxdigits, unsigned radix )
  277. {
  278. /*
  279. ORIGINAL: http://w...content-available-to-author-only...d.com/thread5585.html (by cb30)
  280. */
  281. union {
  282. int64 i;
  283. double f;
  284. } x;
  285. int64 mantissa, whole, fract;
  286. int16 exp2;
  287.  
  288. ( void )usescinot;
  289.  
  290. if( !f ) {
  291. *buf++ = '0';
  292. *buf++ = '.';
  293. *buf++ = '0';
  294. *buf = '\0';
  295.  
  296. return 0;
  297. }
  298.  
  299. x.f = f;
  300. if( x.i < 0 ) {
  301. x.i &= ~( 1ULL<<63 );
  302. *outsign = '-';
  303. } else {
  304. *outsign = '+';
  305. }
  306.  
  307. exp2 = ( ( int16 )( ( x.i>>52 ) & 0x7FF ) ) - 1023;
  308. mantissa = ( x.i & 0x1FFFFFFFFFFFFF ) | 0x10000000000000;
  309. whole = 0;
  310. fract = 0;
  311.  
  312. if( exp2 >= 63 ) {
  313. *buf = '\0';
  314. return 1;
  315. }
  316.  
  317. if( exp2 < -52 ) {
  318. *buf = '\0';
  319. return -1;
  320. }
  321.  
  322. if( exp2 >= 52 ) {
  323. whole = mantissa << ( exp2 - 52 );
  324. } else if( exp2 >= 0 ) {
  325. whole = mantissa >> ( 52 - exp2 );
  326. fract = ( mantissa << ( exp2 + 1 ) ) & 0x1FFFFFFFFFFFFF;
  327. } else {
  328. fract = ( mantissa & 0x1FFFFFFFFFFFFF ) >> -( exp2 + 1 );
  329. }
  330.  
  331. if( !whole ) {
  332. *buf++ = '0';
  333. } else {
  334. char tmp[ 32 ];
  335. char *p;
  336.  
  337. p = axpf__utoa( &tmp[ sizeof( tmp ) - 1 ], whole, radix, 0 );
  338. while( *p != '\0' ) {
  339. *buf++ = *p++;
  340. }
  341. }
  342.  
  343. *buf++ = '.';
  344.  
  345. if( !fract ) {
  346. *buf++ = '0';
  347. } else {
  348. unsigned numdigits = 0;
  349.  
  350. if( maxdigits > 32 ) {
  351. maxdigits = 32;
  352. }
  353.  
  354. for( numdigits = 0; numdigits < maxdigits; ++numdigits ) {
  355. fract *= 10;
  356. *buf++ = ( fract >> 53 ) + '0';
  357. fract &= 0x1FFFFFFFFFFFFF;
  358. }
  359. }
  360.  
  361. *buf = '\0';
  362. return 0;
  363. }
  364.  
  365. static int axpf__pad( struct axpf__state_ *s, unsigned num, char ch )
  366. {
  367. static const char spaces[] = " ";
  368. static const char zeroes[] = "0000000000000000";
  369. const char *p;
  370.  
  371. p = ( ch == ' ' ? &spaces[0] : ( ch == '0' ? &zeroes[0] : NULL ) );
  372.  
  373. if( !p ) {
  374. while( num-- > 0 ) {
  375. if( !axpf__writech( s, ch ) ) {
  376. return 0;
  377. }
  378. }
  379.  
  380. return 1;
  381. }
  382.  
  383. while( num > 0 ) {
  384. unsigned n = num;
  385.  
  386. if( n > sizeof( spaces ) - 1 ) {
  387. n = sizeof( spaces ) - 1;
  388. }
  389.  
  390. if( !axpf__write( s, p, p + n ) ) {
  391. return 0;
  392. }
  393.  
  394. num -= n;
  395. }
  396.  
  397. return 1;
  398. }
  399. static int axpf__write_uintx( struct axpf__state_ *s, uintmax_t i, char sign )
  400. {
  401. const char *prefix;
  402. unsigned prefixlen;
  403. unsigned numberlen, numbersignlen;
  404. unsigned numpadzeroes;
  405. unsigned numpadspaces;
  406. unsigned padinfringe;
  407. char buf[ 128 ];
  408. char *p;
  409. int f;
  410.  
  411. f = 0;
  412. if( s->flags & kPF_Upper ) { f |= 1; }
  413. if( ( s->flags & kPF_Precision ) && s->precision == 0 ) { f |= 2; }
  414. if( s->flags & kPF_Group ) { f |= 4; }
  415.  
  416. p = axpf__utoa( &buf[ sizeof( buf ) ], i, s->radix, f );
  417.  
  418. prefix = NULL;
  419. prefixlen = 0;
  420. if( s->flags & ( kPF_Radix | kPF_Pointer ) ) {
  421. int useupper;
  422.  
  423. if( ( s->flags & kPF_Pointer ) || ( ~s->flags & kPF_Upper ) ) {
  424. useupper = 0;
  425. } else {
  426. useupper = 1;
  427. }
  428.  
  429. switch( s->radix ) {
  430. case 2:
  431. prefixlen = 2;
  432. prefix = useupper ? "0B" : "0b";
  433. break;
  434. case 8:
  435. prefixlen = 1;
  436. prefix = "0";
  437. break;
  438. case 16:
  439. prefixlen = 2;
  440. prefix = useupper ? "0X" : "0x";
  441. break;
  442. default:
  443. break;
  444. }
  445. }
  446. numberlen = ( unsigned )( size_t )( &buf[ sizeof( buf ) - 1 ] - p );
  447.  
  448. if( !sign ) {
  449. if( s->flags & kPF_Sign ) {
  450. sign = '+';
  451. } else if( s->flags & kPF_Space ) {
  452. sign = ' ';
  453. }
  454. }
  455. numbersignlen = numberlen + +( sign != '\0' );
  456.  
  457. numpadzeroes = 0;
  458. if( ( s->flags & kPF_Precision ) &&
  459. ( unsigned )s->precision > numbersignlen ) {
  460. numpadzeroes = s->precision - numbersignlen;
  461. }
  462.  
  463. numpadspaces = 0;
  464. padinfringe = numbersignlen + prefixlen + numpadzeroes;
  465. if( ( s->flags & kPF_Width ) && ( unsigned )s->width > padinfringe ) {
  466. if( s->flags & kPF_Zero ) {
  467. numpadzeroes += s->width - padinfringe;
  468. } else {
  469. numpadspaces += s->width - padinfringe;
  470. }
  471. }
  472.  
  473. #if 0 /* debugging */
  474. printf( "\n[numpadspaces=%u;numpadzeroes=%u;;%s(%i)%s(%i)::%u;%s]\n",
  475. numpadspaces, numpadzeroes,
  476. ( s->flags & kPF_Width ) ? "w" : "_", s->width,
  477. ( s->flags & kPF_Precision ) ? "p" : "_", s->precision,
  478. prefixlen, prefix != NULL ? prefix : "(null)" );
  479. #endif
  480.  
  481. if( ~s->flags & kPF_Left ) {
  482. if( !axpf__pad( s, numpadspaces, ' ' ) ) {
  483. return 0;
  484. }
  485. }
  486.  
  487. if( sign ) {
  488. if( !axpf__writech( s, sign ) ) {
  489. return 0;
  490. }
  491. }
  492.  
  493. if( prefix != NULL && prefixlen > 0 ) {
  494. if( !axpf__write( s, prefix, prefix + prefixlen ) ) {
  495. return 0;
  496. }
  497. }
  498. axpf__pad( s, numpadzeroes, '0' );
  499.  
  500. if( !axpf__write( s, p, &buf[ sizeof( buf ) - 1 ] ) ) {
  501. return 0;
  502. }
  503.  
  504. if( s->flags & kPF_Left ) {
  505. if( !axpf__pad( s, numpadspaces, ' ' ) ) {
  506. return 0;
  507. }
  508. }
  509.  
  510. return 1;
  511. }
  512. static int axpf__write_int( struct axpf__state_ *s, intmax_t i )
  513. {
  514. while( s->repeats-- > 0 ) {
  515. if( i < 0 ) {
  516. if( !axpf__write_uintx( s, ( uintmax_t )-i, '-' ) ) {
  517. return 0;
  518. }
  519. } else if( !axpf__write_uintx( s, ( uintmax_t )i, '\0' ) ) {
  520. return 0;
  521. }
  522. }
  523.  
  524. return 1;
  525. }
  526. static int axpf__write_uint( struct axpf__state_ *s, uintmax_t i )
  527. {
  528. while( s->repeats-- > 0 ) {
  529. if( !axpf__write_uintx( s, i, '\0' ) ) {
  530. return 0;
  531. }
  532. }
  533.  
  534. return 1;
  535. }
  536.  
  537. static int axpf__write_floatd( struct axpf__state_ *s, double f, char spec )
  538. {
  539. unsigned maxdigits;
  540. char buf[ 128 ], *p, *end, *dec;
  541. char sign;
  542. int r;
  543.  
  544. maxdigits = ( s->flags & kPF_Precision ) ? s->precision : 6;
  545. sign = '\0';
  546. p = &buf[ sizeof( buf )/2 ];
  547. r = axpf__dtoax( p, &sign, ( double )f, 0, maxdigits, s->radix );
  548. if( r < 0 ) {
  549. buf[ 0 ] = '#'; buf[ 1 ] = 'S'; buf[ 2 ] = '\0';
  550. p = &buf[ 0 ];
  551. } else if( r > 0 ) {
  552. buf[ 0 ] = '#'; buf[ 1 ] = 'L'; buf[ 2 ] = '\0';
  553. p = &buf[ 0 ];
  554. }
  555.  
  556. if( sign != '-' && ( ~s->flags & kPF_Sign ) ) {
  557. sign = '\0';
  558. }
  559.  
  560. end = strchr( p, '\0' );
  561.  
  562. if( spec == 'g' ) {
  563. while( end > &buf[ 0 ] && *( end - 1 ) == '0' ) {
  564. *--end = '\0';
  565. }
  566.  
  567. if( end > &buf[ 0 ] && *( end - 1 ) == '.' ) {
  568. *--end = '\0';
  569. }
  570. }
  571.  
  572. dec = strchr( p, '.' );
  573. if( !dec ) {
  574. dec = end;
  575. }
  576.  
  577. if( ( s->flags & kPF_Precision ) && s->precision > 0 && r == 0 ) {
  578. unsigned numdigits;
  579.  
  580. if( *dec != '.' ) {
  581. dec[ 0 ] = '.';
  582. dec[ 1 ] = '\0';
  583. end = &dec[ 1 ];
  584. }
  585.  
  586. numdigits = ( unsigned )( size_t )( end - dec ) - 1;
  587. while( ( int )numdigits < s->precision && numdigits < 32 ) {
  588. *end++ = '0';
  589. }
  590.  
  591. *end = '\0';
  592. }
  593.  
  594. if( ( s->flags & kPF_Width ) && s->width > 0 && r == 0 ) {
  595. unsigned numwidth;
  596. char ch;
  597.  
  598. ch = ( s->flags & kPF_Zero ) ? '0' : ' ';
  599.  
  600. numwidth = ( unsigned )( size_t )( dec - p );
  601. if( ch != '0' && sign != '\0' ) {
  602. *--p = sign;
  603. sign = '\0';
  604. ++numwidth;
  605. }
  606.  
  607. while( ( int )numwidth < s->width && numwidth < 32 ) {
  608. *--p = ch;
  609. ++numwidth;
  610. }
  611. }
  612.  
  613. if( sign != '\0' ) {
  614. *--p = sign;
  615. }
  616.  
  617. while( s->repeats-- > 0 ) {
  618. if( !axpf__write( s, p, end ) ) {
  619. return 0;
  620. }
  621. }
  622.  
  623. return 1;
  624. }
  625.  
  626. static int axpf__write_char( struct axpf__state_ *s, int ch )
  627. {
  628. while( s->repeats-- > 0 ) {
  629. if( !axpf__writech( s, ch ) ) {
  630. return 0;
  631. }
  632. }
  633.  
  634. return 1;
  635. }
  636. static int axpf__writewch( struct axpf__state_ *s, wchar_t ch )
  637. {
  638. ( void )s;
  639. ( void )ch;
  640.  
  641. return 0;
  642. }
  643. static int axpf__write_wchar( struct axpf__state_ *s, wchar_t ch )
  644. {
  645. while( s->repeats-- > 0 ) {
  646. if( !axpf__writewch( s, ch ) ) {
  647. return 0;
  648. }
  649. }
  650.  
  651. return 1;
  652. }
  653.  
  654. static int axpf__write_str( struct axpf__state_ *s, const char *p )
  655. {
  656. const char *e;
  657.  
  658. if( !p ) {
  659. p = "(null)";
  660. e = p + 6;
  661. } else if( s->flags & kPF_Precision ) {
  662. e = &p[ s->precision ];
  663. } else {
  664. e = strchr( p, '\0' );
  665. }
  666.  
  667. while( s->repeats-- > 0 ) {
  668. if( !axpf__write( s, p, e ) ) {
  669. return 0;
  670. }
  671. }
  672.  
  673. return 1;
  674. }
  675. static int axpf__write_wstr( struct axpf__state_ *s, const wchar_t *p )
  676. {
  677. const wchar_t *e;
  678.  
  679. if( !p ) {
  680. p = L"(null)";
  681. e = p + 6;
  682. } else if( s->flags & kPF_Precision ) {
  683. e = &p[ s->precision ];
  684. } else {
  685. e = wcschr( p, L'\0' );
  686. }
  687.  
  688. while( s->repeats-- > 0 ) {
  689. while( p < e ) {
  690. if( !axpf__writewch( s, *p++ ) ) {
  691. return 0;
  692. }
  693. }
  694. }
  695.  
  696. return 1;
  697. }
  698.  
  699. static int axpf__write_syserr( struct axpf__state_ *s, int err )
  700. {
  701. char errbuf[ 128 ];
  702.  
  703. #if defined( _MSC_VER ) && defined( __STDC_WANT_SECURE_LIB__ )
  704. if( strerror_s( errbuf, sizeof( errbuf ), err ) != 0 ) {
  705. errbuf[ 0 ] = '('; errbuf[ 1 ] = 'n'; errbuf[ 2 ] = 'u';
  706. errbuf[ 3 ] = 'l'; errbuf[ 4 ] = 'l'; errbuf[ 5 ] = ')';
  707. errbuf[ 6 ] = '\0';
  708. }
  709. #else
  710. strncpy( errbuf, strerror( err ), sizeof( errbuf ) - 1 );
  711. #endif
  712. errbuf[ sizeof( errbuf ) - 1 ] = '\0';
  713.  
  714. while( s->repeats-- > 0 ) {
  715. if( !axpf__write( s, errbuf, strchr( errbuf, '\0' ) ) ) {
  716. return 0;
  717. }
  718. }
  719.  
  720. return 1;
  721. }
  722. static int axpf__write_bitfield( struct axpf__state_ *s, int bits,
  723. const char *names )
  724. {
  725. int needcomma;
  726.  
  727. if( !names || !*names ) {
  728. return 0;
  729. }
  730.  
  731. if( !s->repeats ) {
  732. return 1;
  733. }
  734.  
  735. s->radix = *( const unsigned char * )names;
  736. if( s->radix == 1 ) {
  737. s->radix = 10;
  738. }
  739.  
  740. ++names;
  741.  
  742. if( !axpf__write_uint( s, ( unsigned )bits ) ) {
  743. return 0;
  744. }
  745.  
  746. if( !axpf__writech( s, ' ' ) || !axpf__writech( s, '<' ) ) {
  747. return 0;
  748. }
  749.  
  750. needcomma = 0;
  751. while( *names && bits ) {
  752. unsigned bit;
  753.  
  754. bit = ( ( unsigned )*names++ ) - 1;
  755. if( bits & ( 1<<bit ) ) {
  756. const char *p;
  757.  
  758. bits &= ~( 1<<bit );
  759.  
  760. if( needcomma ) {
  761. axpf__writech( s, ',' );
  762. }
  763.  
  764. p = names;
  765. while( *names > ' ' ) {
  766. ++names;
  767. }
  768.  
  769. if( !axpf__write( s, p, names ) ) {
  770. return 0;
  771. }
  772.  
  773. needcomma = 1;
  774. }
  775. }
  776.  
  777. if( !axpf__writech( s, '>' ) ) {
  778. return 0;
  779. }
  780.  
  781. return 1;
  782. }
  783. static int axpf__write_hex_dump( struct axpf__state_ *s, const unsigned char *p,
  784. const char *delimiter )
  785. {
  786. const char *delimend;
  787. unsigned count = 16;
  788. unsigned n;
  789. unsigned i;
  790.  
  791. if( !s->repeats ) {
  792. return 1;
  793. }
  794.  
  795. if( !delimiter || !*delimiter ) {
  796. delimiter = " ";
  797. }
  798.  
  799. delimend = strchr( delimiter, '\0' );
  800. n = ( unsigned )( size_t )( delimend - delimiter );
  801.  
  802. s->radix = 16;
  803.  
  804. if( ( s->flags & kPF_Width ) && s->width > 0 ) {
  805. count = s->width;
  806. }
  807.  
  808. s->flags = kPF_Precision;
  809. s->precision = 2;
  810. for( i = 0; i < count; ++i ) {
  811. if( i > 0 && !axpf__writech( s, delimiter[ ( i - 1 )%n ] ) ) {
  812. return 0;
  813. }
  814.  
  815. if( !axpf__write_uintx( s, p[ i ], '\0' ) ) {
  816. return 0;
  817. }
  818. }
  819.  
  820. return 1;
  821. }
  822.  
  823. static int axpf__find( struct axpf__state_ *s, int ch, int doflush )
  824. {
  825. const char *p;
  826. size_t n;
  827.  
  828. n = ( size_t )( s->e - s->p );
  829. if( !n ) {
  830. return 0;
  831. }
  832.  
  833. p = ( const char * )memchr( ( const void * )s->p, ch, n );
  834. if( !p ) {
  835. return 0;
  836. }
  837.  
  838. if( doflush && s->p != p ) {
  839. if( !axpf__write( s, s->p, p ) ) {
  840. return 0;
  841. }
  842. }
  843.  
  844. s->p = p;
  845. return 1;
  846. }
  847.  
  848. static int axpf__getdigit( int ch, unsigned radix )
  849. {
  850. unsigned rlo, rhi;
  851. unsigned c;
  852.  
  853. rlo = radix < 10 ? radix : 10;
  854. rhi = radix > 10 ? radix - 10 : 0;
  855.  
  856. c = ( unsigned )ch;
  857. if( c >= '0' && c < '0' + rlo ) {
  858. return ch - '0';
  859. }
  860.  
  861. if( c >= 'a' && c < 'a' + rhi ) {
  862. return ch - 'a' + 10;
  863. }
  864. if( c >= 'A' && c < 'A' + rhi ) {
  865. return ch - 'A' + 10;
  866. }
  867.  
  868. return -1;
  869. }
  870.  
  871. static unsigned axpf__step_uint( struct axpf__state_ *s )
  872. {
  873. unsigned r = 0;
  874.  
  875. for(;;) {
  876. int n;
  877.  
  878. n = axpf__getdigit( axpf__look( s ), 10 );
  879. if( n < 0 ) {
  880. break;
  881. }
  882.  
  883. if( r < ( 1L<<( sizeof( int )*8 - 2 ) ) ) {
  884. r *= 10;
  885. r += n;
  886. }
  887. axpf__skip( s );
  888. }
  889.  
  890. return r;
  891. }
  892. static int axpf__step_int( struct axpf__state_ *s )
  893. {
  894. int m = 1;
  895.  
  896. if( axpf__check( s, '-' ) ) {
  897. m = -1;
  898. }
  899.  
  900. return m*( int )axpf__step_uint( s );
  901. }
  902. static int axpf__step( struct axpf__state_ *s )
  903. {
  904. char spec;
  905.  
  906. if( !axpf__find( s, '%', 1 ) ) {
  907. axpf__write( s, s->p, s->e );
  908. return 0;
  909. }
  910.  
  911. axpf__skip( s );
  912.  
  913. if( axpf__check( s, '%' ) ) {
  914. axpf__writech( s, '%' );
  915. return 1;
  916. }
  917.  
  918. s->repeats = 1;
  919. s->arraysize = 0;
  920. s->arrayprint[ 0 ] = '{';
  921. s->arrayprint[ 1 ] = ',';
  922. s->arrayprint[ 2 ] = ' ';
  923. s->arrayprint[ 3 ] = '}';
  924. s->flags = 0;
  925. s->width = 0;
  926. s->precision = 0;
  927. s->lenspec = kLS_None;
  928. s->radix = 10;
  929.  
  930. /* repeats */
  931. if( axpf__check( s, '{' ) ) {
  932. if( axpf__check( s, '*' ) ) {
  933. s->repeats = va_arg( s->args, unsigned );
  934. } else {
  935. s->repeats = axpf__step_uint( s );
  936. }
  937.  
  938. ( void )axpf__check( s, '}' );
  939. }
  940.  
  941. /* array */
  942. if( axpf__check( s, '[' ) ) {
  943. unsigned n = 0;
  944.  
  945. if( axpf__check( s, '*' ) ) {
  946. s->arraysize = va_arg( s->args, size_t );
  947. } else {
  948. s->arraysize = axpf__step_uint( s );
  949. }
  950. s->flags |= kPF_Array;
  951.  
  952. while( n < AXPF__MAX_ARRAY_PRINT ) {
  953. if( axpf__check( s, ']' ) ) {
  954. break;
  955. }
  956.  
  957. s->arrayprint[ n++ ] = axpf__read( s );
  958. }
  959.  
  960. if( n == AXPF__MAX_ARRAY_PRINT ) {
  961. ( void )axpf__check( s, ']' );
  962. } else if( n > 0 ) {
  963. /* the last character specified is the closing value */
  964. s->arrayprint[ AXPF__MAX_ARRAY_PRINT - 1 ] = s->arrayprint[ n - 1 ];
  965.  
  966. /* if a space was omitted then don't space elements out */
  967. if( n < 4 ) {
  968. s->arrayprint[ 2 ] = '\0';
  969. }
  970.  
  971. /* if a delimiter was omitted then assume a comma */
  972. if( n < 3 ) {
  973. s->arrayprint[ 1 ] = ',';
  974. }
  975. }
  976. }
  977.  
  978. /* flags */
  979. unsigned fcount;
  980. do {
  981. fcount = 0;
  982.  
  983. if( axpf__check( s, '-' ) ) {
  984. s->flags |= kPF_Left;
  985. ++fcount;
  986. }
  987. if( axpf__check( s, '+' ) ) {
  988. s->flags |= kPF_Sign;
  989. ++fcount;
  990. }
  991. if( axpf__check( s, ' ' ) ) {
  992. s->flags |= kPF_Space;
  993. ++fcount;
  994. }
  995. if( axpf__check( s, '#' ) ) {
  996. s->flags |= kPF_Radix;
  997. ++fcount;
  998. }
  999. if( axpf__check( s, '0' ) ) {
  1000. s->flags |= kPF_Zero;
  1001. ++fcount;
  1002. }
  1003. if( axpf__check( s, '\'' ) ) {
  1004. s->flags |= kPF_Group;
  1005. ++fcount;
  1006. }
  1007. } while( fcount > 0 );
  1008.  
  1009. /* width */
  1010. if( axpf__check( s, '*' ) ) {
  1011. s->width = va_arg( s->args, int );
  1012. s->flags |= kPF_Width;
  1013. } else if( axpf__getdigit( axpf__look( s ), 10 ) >= 0 ) {
  1014. s->width = axpf__step_int( s );
  1015. s->flags |= kPF_Width;
  1016. }
  1017.  
  1018. /* precision */
  1019. if( axpf__check( s, '.' ) ) {
  1020. if( axpf__check( s, '*' ) ) {
  1021. s->precision = va_arg( s->args, int );
  1022. s->flags |= kPF_Precision;
  1023. } else if( axpf__getdigit( axpf__look( s ), 10 ) >= 0 ) {
  1024. s->precision = axpf__step_int( s );
  1025. s->flags |= kPF_Precision;
  1026. }
  1027. }
  1028.  
  1029. /* length specifier */
  1030. if( axpf__check( s, 'h' ) ) {
  1031. if( axpf__check( s, 'h' ) ) {
  1032. s->lenspec = kLS_hh;
  1033. } else {
  1034. s->lenspec = kLS_h;
  1035. }
  1036. } else if( axpf__check( s, 'l' ) ) {
  1037. if( axpf__check( s, 'l' ) ) {
  1038. s->lenspec = kLS_ll;
  1039. } else {
  1040. s->lenspec = kLS_l;
  1041. }
  1042. } else if( axpf__check( s, 'j' ) ) {
  1043. s->lenspec = kLS_j;
  1044. } else if( axpf__check( s, 'z' ) ) {
  1045. s->lenspec = kLS_z;
  1046. } else if( axpf__check( s, 't' ) ) {
  1047. s->lenspec = kLS_t;
  1048. } else if( axpf__check( s, 'L' ) ) {
  1049. s->lenspec = kLS_L;
  1050. } else if( axpf__check( s, 'q' ) ) {
  1051. s->lenspec = kLS_I64;
  1052. } else if( axpf__check( s, 'w' ) ) {
  1053. s->lenspec = kLS_l;
  1054. } else if( axpf__check( s, 'I' ) ) {
  1055. if( axpf__checks( s, "32" ) ) {
  1056. s->lenspec = kLS_I32;
  1057. } else if( axpf__checks( s, "64" ) ) {
  1058. s->lenspec = kLS_I64;
  1059. } else {
  1060. s->lenspec = kLS_I;
  1061. }
  1062. }
  1063.  
  1064. spec = axpf__read( s );
  1065. if( spec >= 'A' && spec <= 'Z' && spec!='C' && spec!='D' && spec!='S' ) {
  1066. s->flags |= kPF_Upper;
  1067. spec = spec - 'A' + 'a';
  1068. }
  1069.  
  1070. /* arrays require special handling */
  1071. if( s->flags & kPF_Array ) {
  1072. const void *ptrbase;
  1073. unsigned repeats;
  1074.  
  1075. if( spec == 'r' ) {
  1076. s->radix = va_arg( s->args, unsigned int );
  1077. }
  1078. ptrbase = va_arg( s->args, const void * );
  1079.  
  1080. if( spec == 'a' ) {
  1081. spec = 'f';
  1082. s->radix = 16;
  1083. }
  1084.  
  1085. repeats = s->repeats;
  1086. while( repeats-- > 0 ) {
  1087. union {
  1088. const void *p;
  1089. const int *i; const unsigned int *u;
  1090. const signed char *sc; const unsigned char *usc;
  1091. const short int *si; const unsigned short int *usi;
  1092. const long int *li; const unsigned long int *uli;
  1093. #ifdef _MSC_VER
  1094. const __int64 *lli; const unsigned __int64 *ulli;
  1095. #else
  1096. const long long int *lli; const unsigned long long int *ulli;
  1097. #endif
  1098. const intmax_t *im; const uintmax_t *uim;
  1099. const size_t *sz;
  1100. const ptrdiff_t *pd;
  1101. const int32 *i32; const uint32 *ui32;
  1102. const int64 *i64; const uint64 *ui64;
  1103. const float *f;
  1104. const double *d;
  1105. const long double *ld;
  1106. const char *c;
  1107. const wchar_t *wc;
  1108. const char *const *s;
  1109. const wchar_t *const *ws;
  1110. } x;
  1111. size_t i;
  1112.  
  1113. if( !ptrbase ) {
  1114. const char buf[] = "(null)";
  1115. axpf__write( s, buf, buf + sizeof(buf) - 1 );
  1116. continue;
  1117. }
  1118.  
  1119. axpf__writech( s, s->arrayprint[ 0 ] );
  1120.  
  1121. x.p = ptrbase;
  1122. for( i = 0; i < s->arraysize; ++i ) {
  1123. if( i > 0 ) {
  1124. axpf__writech( s, s->arrayprint[ 1 ] );
  1125. }
  1126. if( s->arrayprint[ 2 ] == ' ' ) {
  1127. axpf__writech( s, ' ' );
  1128. }
  1129.  
  1130. s->repeats = 1;
  1131. switch( spec ) {
  1132. case 'd':
  1133. case 'i':
  1134. switch( s->lenspec ) {
  1135. #define P_(F_) axpf__write_int( s, x.F_[i] ); break
  1136. case kLS_None: P_( i );
  1137. case kLS_hh: P_( sc );
  1138. case kLS_h: P_( si );
  1139. case kLS_l:
  1140. case kLS_L: P_( li );
  1141. case kLS_ll: P_( lli );
  1142. case kLS_j: P_( im );
  1143. case kLS_z: P_( sz );
  1144. case kLS_I:
  1145. case kLS_t: P_( pd );
  1146. case kLS_I32: P_( i32 );
  1147. case kLS_I64: P_( i64 );
  1148. #undef P_
  1149. }
  1150. break;
  1151.  
  1152. case 'u':
  1153. case 'o':
  1154. case 'x':
  1155. case 'r':
  1156. if( spec == 'o' ) {
  1157. s->radix = 8;
  1158. } else if( spec == 'x' ) {
  1159. s->radix = 16;
  1160. } else if( spec == 'r' ) {
  1161. s->radix = va_arg( s->args, unsigned int );
  1162. }
  1163.  
  1164. switch( s->lenspec ) {
  1165. #define P_(F_) axpf__write_uint( s, x.F_[i] ); break
  1166. case kLS_None: P_( u );
  1167. case kLS_hh: P_( usc );
  1168. case kLS_h: P_( usi );
  1169. case kLS_l:
  1170. case kLS_L: P_( uli );
  1171. case kLS_ll: P_( ulli );
  1172. case kLS_j: P_( uim );
  1173. case kLS_I:
  1174. case kLS_z: P_( sz );
  1175. case kLS_t: P_( pd );
  1176. case kLS_I32: P_( ui32 );
  1177. case kLS_I64: P_( ui64 );
  1178. #undef P_
  1179. }
  1180. break;
  1181.  
  1182. case 'f':
  1183. case 'e':
  1184. case 'g':
  1185. if( s->lenspec == kLS_None ) {
  1186. axpf__write_floatd( s, ( double )x.f[ i ], spec );
  1187. } else if( s->lenspec == kLS_l ) {
  1188. axpf__write_floatd( s, x.d[ i ], spec );
  1189. } else if( s->lenspec == kLS_L ) {
  1190. axpf__write_floatd( s, ( double )x.ld[ i ], spec );
  1191. }
  1192. break;
  1193.  
  1194. case 'c':
  1195. case 'C':
  1196. if( s->lenspec == kLS_None && spec != 'C' ) {
  1197. axpf__write_char( s, x.c[ i ] );
  1198. } else if( s->lenspec == kLS_l || spec == 'C' ) {
  1199. axpf__write_wchar( s, x.wc[ i ] );
  1200. }
  1201. break;
  1202.  
  1203. case 's':
  1204. case 'S':
  1205. if( s->lenspec == kLS_None && spec != 'S' ) {
  1206. axpf__write_str( s, x.s[ i ] );
  1207. } else if( s->lenspec == kLS_l || spec == 'S' ) {
  1208. axpf__write_wstr( s, x.ws[ i ] );
  1209. }
  1210. break;
  1211.  
  1212. case 'p':
  1213. s->radix = 16;
  1214. s->flags |= kPF_Radix | kPF_Pointer | kPF_Precision;
  1215. s->precision = sizeof( void * )*2;
  1216. axpf__write_uint( s, x.sz[ i ] );
  1217. break;
  1218. }
  1219. }
  1220.  
  1221. if( s->arrayprint[ 2 ] == ' ' ) {
  1222. axpf__writech( s, ' ' );
  1223. }
  1224.  
  1225. axpf__writech( s, s->arrayprint[ 3 ] );
  1226. }
  1227.  
  1228. return !s->diderror;
  1229. }
  1230.  
  1231. /* check the specifier */
  1232. switch( spec ) {
  1233. case 'd':
  1234. case 'i':
  1235. if( s->lenspec == kLS_l ) {
  1236. axpf__write_int( s, va_arg( s->args, long int ) );
  1237. } else if( s->lenspec == kLS_ll || s->lenspec == kLS_L ) {
  1238. #ifdef _MSC_VER
  1239. axpf__write_int( s, va_arg( s->args, __int64 ) );
  1240. #else
  1241. axpf__write_int( s, va_arg( s->args, long long int ) );
  1242. #endif
  1243. } else if( s->lenspec == kLS_t || s->lenspec == kLS_I ) {
  1244. axpf__write_int( s, va_arg( s->args, ptrdiff_t ) );
  1245. } else if( s->lenspec == kLS_z ) {
  1246. axpf__write_int( s, va_arg( s->args, size_t ) );
  1247. } else if( s->lenspec == kLS_j ) {
  1248. axpf__write_int( s, va_arg( s->args, intmax_t ) );
  1249. } else if( s->lenspec == kLS_I32 ) {
  1250. axpf__write_int( s, va_arg( s->args, int32 ) );
  1251. } else if( s->lenspec == kLS_I64 ) {
  1252. axpf__write_int( s, va_arg( s->args, int64 ) );
  1253. } else {
  1254. axpf__write_int( s, va_arg( s->args, int ) );
  1255. }
  1256. break;
  1257.  
  1258. case 'u':
  1259. case 'o':
  1260. case 'x':
  1261. case 'r':
  1262. if( spec == 'o' ) {
  1263. s->radix = 8;
  1264. } else if( spec == 'x' ) {
  1265. s->radix = 16;
  1266. } else if( spec == 'r' ) {
  1267. s->radix = va_arg( s->args, unsigned int );
  1268. }
  1269.  
  1270. if( s->lenspec == kLS_l ) {
  1271. axpf__write_uint( s, va_arg( s->args, unsigned long int ) );
  1272. } else if( s->lenspec == kLS_ll || s->lenspec == kLS_L ) {
  1273. #ifdef _MSC_VER
  1274. axpf__write_uint( s, va_arg( s->args, unsigned __int64 ) );
  1275. #else
  1276. axpf__write_uint( s, va_arg( s->args, unsigned long long int ) );
  1277. #endif
  1278. } else if( s->lenspec == kLS_t ) {
  1279. axpf__write_uint( s, va_arg( s->args, ptrdiff_t ) );
  1280. } else if( s->lenspec == kLS_z || s->lenspec == kLS_I ) {
  1281. axpf__write_uint( s, va_arg( s->args, size_t ) );
  1282. } else if( s->lenspec == kLS_j ) {
  1283. axpf__write_uint( s, va_arg( s->args, uintmax_t ) );
  1284. } else if( s->lenspec == kLS_I32 ) {
  1285. axpf__write_uint( s, va_arg( s->args, uint32 ) );
  1286. } else if( s->lenspec == kLS_I64 ) {
  1287. axpf__write_uint( s, va_arg( s->args, uint64 ) );
  1288. } else {
  1289. axpf__write_uint( s, va_arg( s->args, unsigned int ) );
  1290. }
  1291. break;
  1292.  
  1293. case 'f':
  1294. case 'e':
  1295. case 'g':
  1296. case 'a':
  1297. if( spec == 'a' ) {
  1298. spec = 'f';
  1299. s->radix = 16;
  1300. }
  1301.  
  1302. if( s->lenspec == kLS_None ) {
  1303. axpf__write_floatd( s, va_arg( s->args, double ), spec );
  1304. } else if( s->lenspec == kLS_l || s->lenspec == kLS_L ) {
  1305. axpf__write_floatd( s, ( double )va_arg( s->args, long double ),
  1306. spec );
  1307. }
  1308. break;
  1309.  
  1310. case 'c':
  1311. case 'C':
  1312. if( s->lenspec == kLS_None && spec != 'C' ) {
  1313. axpf__write_char( s, va_arg( s->args, int ) );
  1314. } else if( s->lenspec == kLS_l || spec == 'C' ) {
  1315. axpf__write_wchar( s, va_arg( s->args, int/*wint_t*/ ) );
  1316. }
  1317. break;
  1318.  
  1319. case 's':
  1320. case 'S':
  1321. if( s->lenspec == kLS_None && spec != 'S' ) {
  1322. axpf__write_str( s, va_arg( s->args, const char * ) );
  1323. } else if( s->lenspec == kLS_l || spec == 'S' ) {
  1324. axpf__write_wstr( s, va_arg( s->args, const wchar_t * ) );
  1325. }
  1326. break;
  1327.  
  1328. case 'p':
  1329. s->radix = 16;
  1330. s->flags |= kPF_Radix | kPF_Pointer | kPF_Precision;
  1331. s->precision = sizeof( void * )*2;
  1332. axpf__write_uint( s, va_arg( s->args, size_t ) );
  1333. break;
  1334.  
  1335. case 'n':
  1336. switch( s->lenspec ) {
  1337. #define P_(Ty_) *va_arg( s->args, Ty_ * ) = ( Ty_ )s->num_written; break
  1338. case kLS_None: P_( int );
  1339. case kLS_hh: P_( signed char );
  1340. case kLS_h: P_( short int );
  1341. case kLS_l:
  1342. case kLS_L: P_( long int );
  1343. #ifdef _MSC_VER
  1344. case kLS_ll: P_( __int64 );
  1345. #else
  1346. case kLS_ll: P_( long long int );
  1347. #endif
  1348. case kLS_j: P_( intmax_t );
  1349. case kLS_z: P_( size_t );
  1350. case kLS_I:
  1351. case kLS_t: P_( ptrdiff_t );
  1352. case kLS_I32: P_( int32 );
  1353. case kLS_I64: P_( int64 );
  1354. #undef P_
  1355. }
  1356. break;
  1357.  
  1358. case 'm':
  1359. axpf__write_syserr( s, s->width != 0 ? s->width : ( int )errno );
  1360. break;
  1361.  
  1362. case 'b':
  1363. {
  1364. int bits;
  1365. const char *names;
  1366.  
  1367. bits = va_arg( s->args, int );
  1368. names = va_arg( s->args, const char * );
  1369.  
  1370. axpf__write_bitfield( s, bits, names );
  1371. }
  1372. break;
  1373. case 'D':
  1374. {
  1375. const unsigned char *data;
  1376. const char *delm;
  1377.  
  1378. data = va_arg( s->args, const unsigned char * );
  1379. delm = va_arg( s->args, const char * );
  1380.  
  1381. axpf__write_hex_dump( s, data, delm );
  1382. }
  1383. break;
  1384. }
  1385.  
  1386. return !s->diderror;
  1387. }
  1388. static ptrdiff_t axpf__main( struct axpf__state_ *s, const char *fmt,
  1389. const char *fmte, va_list args )
  1390. {
  1391. s->s = fmt;
  1392. s->p = fmt;
  1393. s->e = !fmte ? strchr( fmt, '\0' ) : fmte;
  1394.  
  1395. s->num_written = 0;
  1396. s->args = args;
  1397.  
  1398. s->diderror = 0;
  1399.  
  1400. while( axpf__step( s ) ) {
  1401. }
  1402.  
  1403. if( s->diderror ) {
  1404. return -1;
  1405. }
  1406.  
  1407. return ( ptrdiff_t )s->num_written;
  1408. }
  1409.  
  1410. ptrdiff_t axfpfev( FILE *fp, const char *fmt, const char *fmte, va_list args )
  1411. {
  1412. struct axpf__state_ s;
  1413.  
  1414. s.pfn_write = &axpf__write_fp_f;
  1415. s.write_data = ( void * )fp;
  1416.  
  1417. return axpf__main( &s, fmt, fmte, args );
  1418. }
  1419. ptrdiff_t axfpfv( FILE *fp, const char *fmt, va_list args )
  1420. {
  1421. struct axpf__state_ s;
  1422.  
  1423. s.pfn_write = &axpf__write_fp_f;
  1424. s.write_data = ( void * )fp;
  1425.  
  1426. return axpf__main( &s, fmt, ( const char * )0, args );
  1427. }
  1428. ptrdiff_t axfpfe( FILE *fp, const char *fmt, const char *fmte, ... )
  1429. {
  1430. struct axpf__state_ s;
  1431. ptrdiff_t r;
  1432. va_list args;
  1433.  
  1434. s.pfn_write = &axpf__write_fp_f;
  1435. s.write_data = ( void * )fp;
  1436.  
  1437. va_start( args, fmte );
  1438. r = axpf__main( &s, fmt, fmte, args );
  1439. va_end( args );
  1440.  
  1441. return r;
  1442. }
  1443. ptrdiff_t axfpf( FILE *fp, const char *fmt, ... )
  1444. {
  1445. struct axpf__state_ s;
  1446. ptrdiff_t r;
  1447. va_list args;
  1448.  
  1449. s.pfn_write = &axpf__write_fp_f;
  1450. s.write_data = ( void * )fp;
  1451.  
  1452. va_start( args, fmt );
  1453. r = axpf__main( &s, fmt, ( const char * )0, args );
  1454. va_end( args );
  1455.  
  1456. return r;
  1457. }
  1458.  
  1459. ptrdiff_t axerrfev( const char *fmt, const char *fmte, va_list args )
  1460. {
  1461. struct axpf__state_ s;
  1462.  
  1463. s.pfn_write = &axpf__write_fp_f;
  1464. s.write_data = ( void * )stderr;
  1465.  
  1466. return axpf__main( &s, fmt, fmte, args );
  1467. }
  1468. ptrdiff_t axerrfv( const char *fmt, va_list args )
  1469. {
  1470. struct axpf__state_ s;
  1471.  
  1472. s.pfn_write = &axpf__write_fp_f;
  1473. s.write_data = ( void * )stderr;
  1474.  
  1475. return axpf__main( &s, fmt, ( const char * )0, args );
  1476. }
  1477. ptrdiff_t axerrfe( const char *fmt, const char *fmte, ... )
  1478. {
  1479. struct axpf__state_ s;
  1480. ptrdiff_t r;
  1481. va_list args;
  1482.  
  1483. s.pfn_write = &axpf__write_fp_f;
  1484. s.write_data = ( void * )stderr;
  1485.  
  1486. va_start( args, fmte );
  1487. r = axpf__main( &s, fmt, fmte, args );
  1488. va_end( args );
  1489.  
  1490. return r;
  1491. }
  1492. ptrdiff_t axerrf( const char *fmt, ... )
  1493. {
  1494. struct axpf__state_ s;
  1495. ptrdiff_t r;
  1496. va_list args;
  1497.  
  1498. s.pfn_write = &axpf__write_fp_f;
  1499. s.write_data = ( void * )stderr;
  1500.  
  1501. va_start( args, fmt );
  1502. r = axpf__main( &s, fmt, ( const char * )0, args );
  1503. va_end( args );
  1504.  
  1505. return r;
  1506. }
  1507.  
  1508. ptrdiff_t axpfev( const char *fmt, const char *fmte, va_list args )
  1509. {
  1510. struct axpf__state_ s;
  1511.  
  1512. s.pfn_write = &axpf__write_fp_f;
  1513. s.write_data = ( void * )stdout;
  1514.  
  1515. return axpf__main( &s, fmt, fmte, args );
  1516. }
  1517. ptrdiff_t axpfv( const char *fmt, va_list args )
  1518. {
  1519. struct axpf__state_ s;
  1520.  
  1521. s.pfn_write = &axpf__write_fp_f;
  1522. s.write_data = ( void * )stdout;
  1523.  
  1524. return axpf__main( &s, fmt, ( const char * )0, args );
  1525. }
  1526. ptrdiff_t axpfe( const char *fmt, const char *fmte, ... )
  1527. {
  1528. struct axpf__state_ s;
  1529. ptrdiff_t r;
  1530. va_list args;
  1531.  
  1532. s.pfn_write = &axpf__write_fp_f;
  1533. s.write_data = ( void * )stdout;
  1534.  
  1535. va_start( args, fmte );
  1536. r = axpf__main( &s, fmt, fmte, args );
  1537. va_end( args );
  1538.  
  1539. return r;
  1540. }
  1541. ptrdiff_t axpf( const char *fmt, ... )
  1542. {
  1543. struct axpf__state_ s;
  1544. ptrdiff_t r;
  1545. va_list args;
  1546.  
  1547. s.pfn_write = &axpf__write_fp_f;
  1548. s.write_data = ( void * )stdout;
  1549.  
  1550. va_start( args, fmt );
  1551. r = axpf__main( &s, fmt, ( const char * )0, args );
  1552. va_end( args );
  1553.  
  1554. return r;
  1555. }
  1556.  
  1557. ptrdiff_t axspfev( char *buf, size_t nbuf, const char *fmt, const char *fmte,
  1558. va_list args )
  1559. {
  1560. struct axpf__write_mem_data_ m;
  1561. struct axpf__state_ s;
  1562. ptrdiff_t r;
  1563.  
  1564. m.p = buf;
  1565. m.i = 0;
  1566. m.n = nbuf;
  1567.  
  1568. s.pfn_write = &axpf__write_mem_f;
  1569. s.write_data = ( void * )&m;
  1570.  
  1571. r = axpf__main( &s, fmt, fmte, args );
  1572. if( m.n > 0 ) {
  1573. m.p[ m.i < m.n ? m.i : m.n - 1 ] = '\0';
  1574. }
  1575.  
  1576. return r;
  1577. }
  1578. ptrdiff_t axspfv( char *buf, size_t nbuf, const char *fmt, va_list args )
  1579. {
  1580. return axspfev( buf, nbuf, fmt, ( const char * )0, args );
  1581. }
  1582. ptrdiff_t axspfe( char *buf, size_t nbuf, const char *fmt, const char *fmte,
  1583. ... )
  1584. {
  1585. ptrdiff_t r;
  1586. va_list args;
  1587.  
  1588. va_start( args, fmte );
  1589. r = axspfev( buf, nbuf, fmt, fmte, args );
  1590. va_end( args );
  1591.  
  1592. return r;
  1593. }
  1594. ptrdiff_t axspf( char *buf, size_t nbuf, const char *fmt, ... )
  1595. {
  1596. ptrdiff_t r;
  1597. va_list args;
  1598.  
  1599. va_start( args, fmt );
  1600. r = axspfev( buf, nbuf, fmt, ( const char * )0, args );
  1601. va_end( args );
  1602.  
  1603. return r;
  1604. }
  1605.  
  1606. #ifdef __cplusplus
  1607. template< size_t tMaxBuf >
  1608. ptrdiff_t axspfev( char( &buf )[ tMaxBuf ], const char *fmt, const char *fmte,
  1609. va_list args )
  1610. {
  1611. return axspfev( buf, tMaxBuf, fmt, fmte, args );
  1612. }
  1613. template< size_t tMaxBuf >
  1614. ptrdiff_t axspfv( char( &buf )[ tMaxBuf ], const char *fmt, va_list args )
  1615. {
  1616. return axspfev( buf, tMaxBuf, fmt, ( const char * )0, args );
  1617. }
  1618. template< size_t tMaxBuf >
  1619. ptrdiff_t axspfe( char( &buf )[ tMaxBuf ], const char *fmt, const char *fmte,
  1620. ... )
  1621. {
  1622. ptrdiff_t r;
  1623. va_list args;
  1624.  
  1625. va_start( args, fmte );
  1626. r = axspfev( buf, tMaxBuf, fmt, fmte, args );
  1627. va_end( args );
  1628.  
  1629. return r;
  1630. }
  1631. template< size_t tMaxBuf >
  1632. ptrdiff_t axspf( char( &buf )[ tMaxBuf ], const char *fmt, ... )
  1633. {
  1634. ptrdiff_t r;
  1635. va_list args;
  1636.  
  1637. va_start( args, fmt );
  1638. r = axspfev( buf, tMaxBuf, fmt, ( const char * )0, args );
  1639. va_end( args );
  1640.  
  1641. return r;
  1642. }
  1643. #endif
  1644.  
  1645. /* -------------------------------------------------------------------------- */
  1646.  
  1647. int main()
  1648. {
  1649. float arr_f[ 4 ];
  1650. int arr_i[ 4 ];
  1651.  
  1652. arr_i[ 0 ] = 1;
  1653. arr_i[ 1 ] = 2;
  1654. arr_i[ 2 ] = 3;
  1655. arr_i[ 3 ] = 4;
  1656.  
  1657. axpf( "Hello, world!\n" );
  1658. axpf( "Test string: \"%s\"\n", "This is a test" );
  1659. axpf( "Test integer: %d\n", 100 );
  1660. axpf( "Test signed integer: %d\n", -123 );
  1661. axpf( "Test hex: %X\n", 0xFACE );
  1662. axpf( "Test hex two: %#X\n", 0xFACE );
  1663. axpf( "Test pointer: %p\n", ( const void * )"Yo" );
  1664. axpf( "Hex: %4D\n", "ABCD", ":" );
  1665. axpf( "Bits: %b\n", 3, "\20\3Three\2Two\1One" );
  1666. axpf( "String: %.*s\n", 4, "Hey!XXXXXXXX" );
  1667. axpf( "String: %.2s\n", "YoXXXXX" );
  1668. axpf( "Errno: %2m\n" ); /* No such file or directory */
  1669. axpf( "Grouping: %'d ;; %'d ;; %'d ;; %'d\n", 12345, 1234, 123, 1234567 );
  1670. axpf( "Binary: %r\n", 2, 10 );
  1671. axpf( "Binary-pre: %#r\n", 2, 127 );
  1672. axpf( "Repeat: %{5}s\n", "A" );
  1673. axpf( "Repeat: %{*}sYo\n", 4, " " );
  1674. axpf( "Repeat: %{1}i\n", 1234 );
  1675. axpf( "Repeat: %{0}i\n", 1234 );
  1676. axpf( "Array: %[3]d\n", &arr_i[0] );
  1677. axpf( "Array: %[*]d\n", 4, arr_i );
  1678. axpf( "Repeat-array: %{3}[2]d\n", arr_i );
  1679.  
  1680. arr_i[ 0 ] = 1234;
  1681. arr_i[ 1 ] = 5678;
  1682. arr_i[ 2 ] = 1593;
  1683. axpf( "Custom-array: %[3<;>]'d\n", arr_i );
  1684.  
  1685. axpf( "Float: %f\n", 3.1415926535 );
  1686.  
  1687. arr_f[ 0 ] = -1.5f;
  1688. arr_f[ 1 ] = 95.235f;
  1689. arr_f[ 2 ] = -127.127f;
  1690.  
  1691. axpf( "Float-array: %[3].2f\n", arr_f );
  1692.  
  1693. return EXIT_SUCCESS;
  1694. }
  1695.  
Success #stdin #stdout 0s 2064KB
stdin
Standard input is empty
stdout
Hello, world!
Test string: "This is a test"
Test integer: 100
Test signed integer: -123
Test hex: FACE
Test hex two: 0XFACE
Test pointer: 0x0804af5e
Hex: 41:42:43:44
Bits: 3 <Two,One>
String: Hey!
String: Yo
Errno: No such file or directory
Grouping: 12,345 ;; 1,234 ;; 123 ;; 1,234,567
Binary: 1010
Binary-pre: 0b1111111
Repeat: AAAAA
Repeat:     Yo
Repeat: 1234
Repeat: 
Array: { 1, 2, 3 }
Array: { 1, 2, 3, 4 }
Repeat-array: { 1, 2 }{ 1, 2 }{ 1, 2 }
Custom-array: <1,234;5,678;1,593>
Float: 3.141592
Float-array: { -1.50, 95.23, -127.12 }