home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdrom.zip / DDK / BASE / SRC / DEV / DASD / CDROM / ATAPI / printf.c < prev   
Encoding:
C/C++ Source or Header  |  1998-04-10  |  9.7 KB  |  499 lines

  1. /**************************************************************************
  2.  * DESCRIPTION : C SPRINTF Routine
  3.  ***************************************************************************/
  4.  
  5.  
  6.  
  7.  #define INCL_NOBASEAPI
  8.  #define INCL_NOPMAPI
  9.  #define INCL_NO_SCB
  10.  #define INCL_INITRP_ONLY
  11.  #include "os2.h"
  12.  #include "dos.h"
  13.  
  14. #define va_start(ap,v) ap = (PUCHAR) &v + sizeof(v)
  15. #define va_arg(ap,t)   ((t FAR *)(ap += sizeof(t)))[-1]
  16. #define va_end(ap)     ap = NULL
  17.  
  18. struct _FMTPARMS
  19.   {
  20.     USHORT      type;
  21. #define         TYPE_END         0
  22. #define         TYPE_INVALID     1
  23. #define         TYPE_STRING      2
  24. #define         TYPE_CHAR        3
  25. #define         TYPE_DECIMAL     4
  26. #define         TYPE_UNSIGNED    5
  27. #define         TYPE_HEX         6
  28. #define         TYPE_PCT         7
  29.  
  30.     USHORT      flags;
  31. #define         FS_NEGLEN        0x8000
  32. #define         FS_LEN           0x4000
  33. #define         FS_PRC           0x2000
  34. #define         FS_LONG          0x1000
  35.  
  36.     UINT        len;
  37.     USHORT      prc;
  38.     UCHAR       pad;
  39.  
  40.     PUCHAR      buf;
  41.     USHORT      off;
  42.  
  43.     PUCHAR      fmtstrt,
  44.                 fmtptr;
  45.  
  46.   };
  47.  
  48. typedef struct _FMTPARMS  FMTPARMS;
  49.  
  50. typedef FMTPARMS FAR *LPFMTPARMS;
  51.  
  52. #define MIN(a,b)        ((a) < (b) ? (a) : (b))
  53. #define MAX(a,b)        ((a) > (b) ? (a) : (b))
  54.  
  55.  
  56.  
  57.  
  58. VOID NEAR sprintf ( PSZ buf, PSZ fmt, ... );
  59.  
  60. static prntf(   PSZ buf, PSZ fmt, PUCHAR arg_ptr );
  61.  
  62. static process_format( LPFMTPARMS fs );
  63.  
  64. static put_field( LPFMTPARMS fs, PSZ buf );
  65. static cvtld (    PSZ buf, LONG n   );
  66. static cvtlu (    PSZ buf, ULONG n  );
  67. static cvtlx(     PSZ s,   ULONG n  );
  68. static reverse(   PSZ s );
  69. static strlen(    PSZ s );
  70. static strncpy(   PSZ d, PSZ s,  USHORT n );
  71. static strnovl(   PSZ d, PSZ s,  USHORT n );
  72. static chrdup(    PSZ d, UCHAR c,USHORT n );
  73.  
  74.  
  75.  
  76.  
  77. /******************************/
  78. /* Format to Buffer (USER EP) */
  79. /******************************/
  80.  
  81. VOID NEAR sprintf ( PSZ buf, PSZ fmt, ... )
  82. {
  83.   PUCHAR  arg_ptr;
  84.  
  85.   va_start(arg_ptr, fmt);
  86.   prntf(buf, fmt, arg_ptr);
  87.   va_end(arg_ptr);
  88. }
  89.  
  90.  
  91.  
  92. /******************/
  93. /* Format string  */
  94. /******************/
  95.  
  96. static prntf( PSZ buf, PSZ fmt, PUCHAR arg_ptr )
  97. {
  98.  
  99.    FMTPARMS fs;
  100.    UCHAR    sbuf[20];
  101.    PCHAR    sptr;
  102.  
  103.    LONG     lval;
  104.    ULONG    uval;
  105.  
  106.   fs.buf    = buf;
  107.   fs.off    = 0;
  108.   fs.fmtptr = fmt;
  109.  
  110.   while (  process_format( (LPFMTPARMS) &fs ) != TYPE_END )
  111.     {
  112.       switch( fs.type )
  113.         {
  114.           case TYPE_STRING:
  115.             sptr = va_arg( arg_ptr, PUCHAR );
  116.             put_field( (LPFMTPARMS) &fs, sptr);
  117.             break;
  118.  
  119.          case TYPE_CHAR:
  120.            *((short *)(fs.buf+fs.off)) = va_arg( arg_ptr, USHORT );
  121.            fs.off++;
  122.            break;
  123.  
  124.          case TYPE_PCT:
  125.            *(short *)(fs.buf+fs.off) = '%';
  126.            fs.off++;
  127.            break;
  128.  
  129.          case TYPE_DECIMAL:
  130.            lval = (fs.flags & FS_LONG) ? va_arg( arg_ptr, LONG )
  131.                                        : va_arg( arg_ptr, INT  );
  132.            cvtld(sbuf, lval);
  133.  
  134.            put_field( &fs, sbuf );
  135.            break;
  136.  
  137.          case TYPE_UNSIGNED:
  138.          case TYPE_HEX:
  139.            uval = (fs.flags & FS_LONG) ? va_arg( arg_ptr, ULONG )
  140.                                        : va_arg( arg_ptr, USHORT  );
  141.            if ( fs.type == TYPE_HEX )
  142.              cvtlx( sbuf, uval );
  143.            else
  144.              cvtlu( sbuf, uval );
  145.  
  146.            put_field( &fs, sbuf );
  147.            break;
  148.  
  149.          case TYPE_INVALID:
  150.            strncpy( fs.buf+fs.off, fs.fmtstrt, fs.fmtptr-fs.fmtstrt );
  151.            fs.off += fs.fmtptr - fs.fmtstrt;
  152.            break;
  153.         }
  154.     }
  155.  
  156.   return ( 0 );
  157. }
  158.  
  159.  
  160. /****************************/
  161. /* Process Next Format Spec */
  162. /****************************/
  163.  
  164. static process_format( LPFMTPARMS fs )
  165. {
  166.   PUCHAR fp;
  167.   UCHAR c;
  168.  
  169.   fs->len = fs->prc = fs->flags = 0;
  170.   fs->pad   = ' ';
  171.  
  172.   fp = fs->fmtstrt = fs->fmtptr;
  173.   c = *fp;
  174.  
  175.   /**********************/
  176.   /* Ouput Literal Data */
  177.   /**********************/
  178.  
  179.   while ( c && c != '%'  )
  180.     {
  181.       *(fs->buf+fs->off) = c;
  182.       fs->off++;
  183.       c = *++fp;
  184.     }
  185.  
  186.   *(fs->buf+fs->off) = 0;
  187.  
  188.   /**********************************/
  189.   /* Check for End of Format String */
  190.   /**********************************/
  191.  
  192.   if ( !c )
  193.     {
  194.       fs->type = TYPE_END;
  195.       goto fmt_done;
  196.     }
  197.  
  198.   fs->fmtstrt = fp;
  199.  
  200.   c = *++fp;
  201.  
  202.   /******************************/
  203.   /* Check for %% Format String */
  204.   /******************************/
  205.  
  206.   if ( c == '%' )
  207.     {
  208.       fs->type = TYPE_PCT;
  209.       fp++;
  210.       goto fmt_done;
  211.     }
  212.  
  213.   /***********************/
  214.   /* Check for Leading - */
  215.   /***********************/
  216.  
  217.   if ( c == '-' )
  218.     {
  219.       fs->flags |= FS_NEGLEN;
  220.       c = *++fp;
  221.     }
  222.  
  223.   /**************************/
  224.   /* Check for Zero Padding */
  225.   /**************************/
  226.  
  227.   if ( c == '0' )
  228.     {
  229.       fs->pad = '0';
  230.       c = *++fp;
  231.     }
  232.  
  233.   /******************************/
  234.   /* Check for Min Field Length */
  235.   /******************************/
  236.  
  237.   while ( c >= '0' && c <= '9' )
  238.     {
  239.       fs->flags |= FS_LEN;
  240.       fs->len    = fs->len * 10 + c - '0';
  241.       c = *++fp;
  242.     }
  243.  
  244.   /******************************/
  245.   /* Check for Max Field Length */
  246.   /******************************/
  247.  
  248.   if (c == '.')
  249.     {
  250.       c = *++fp;
  251.  
  252.       while ( c >= '0' && c <= '9' )
  253.         {
  254.           fs->flags |= FS_PRC;
  255.           fs->prc    = fs->prc * 10 + c - '0';
  256.           c = *++fp;
  257.         }
  258.     }
  259.  
  260.   /****************************/
  261.   /* Check for Long Parameter */
  262.   /****************************/
  263.  
  264.   if ( c == 'l' || c == 'L')
  265.     {
  266.       fs->flags |= FS_LONG;
  267.       c = *++fp;
  268.     }
  269.  
  270.   /***************************/
  271.   /* Check Valid Format Type */
  272.   /***************************/
  273.  
  274.   switch ( c )
  275.     {
  276.       case 's' :
  277.       case 'S' :
  278.         fs->type = TYPE_STRING;
  279.         break;
  280.       case 'd' :
  281.       case 'D' :
  282.         fs->type = TYPE_DECIMAL;
  283.         break;
  284.       case 'u' :
  285.       case 'U' :
  286.         fs->type = TYPE_UNSIGNED;
  287.         break;
  288.       case 'x' :
  289.       case 'X' :
  290.         fs->type = TYPE_HEX;
  291.         break;
  292.       case 'c' :
  293.       case 'C' :
  294.         fs->type = TYPE_CHAR;
  295.         break;
  296.       default:
  297.         fs->type = TYPE_INVALID;
  298.     }
  299.  
  300.   fp++;
  301.  
  302.   fmt_done: fs->fmtptr = fp;
  303.  
  304.   return ( fs->type );
  305.  
  306. }
  307.  
  308.  
  309. /********************************************/
  310. /* Transfer Formatted Data to Output Buffer */
  311. /********************************************/
  312.  
  313. static put_field( LPFMTPARMS fs, PSZ buf )
  314. {
  315.   USHORT dlen,
  316.          flen,
  317.          slen;
  318.  
  319.   INT   boff;
  320.  
  321.  
  322.   /*************************/
  323.   /* Calculate Data Length */
  324.   /*************************/
  325.  
  326.   slen = strlen( buf );
  327.   dlen = (fs->flags & FS_PRC) ? MIN( fs->prc, slen ) : slen;
  328.  
  329.   /**************************/
  330.   /* Calculate Field Length */
  331.   /**************************/
  332.  
  333.   flen = (fs->flags & FS_LEN) ? fs->len : dlen;
  334.  
  335.   /**********************************/
  336.   /* Calculate Data Offset in Field */
  337.   /**********************************/
  338.  
  339.   boff = ((fs->flags & FS_LEN) && !(fs->flags & FS_NEGLEN) ) ? flen - dlen : 0;
  340.   if (boff < 0 ) boff = 0;
  341.  
  342.   /****************************/
  343.   /* Fill Field with Pad Char */
  344.   /****************************/
  345.  
  346.   chrdup( fs->buf+fs->off, fs->pad, MAX(flen, dlen) );
  347.  
  348.   /**********************/
  349.   /* Copy Data to Field */
  350.   /**********************/
  351.  
  352.   strnovl( fs->buf+fs->off+boff, buf, dlen );
  353.   fs->off += MAX( flen, dlen ) ;
  354.  
  355.   return( 0 );
  356. }
  357.  
  358. /*******************************/
  359. /* Convert LONG INT to CHAR    */
  360. /*******************************/
  361.  
  362. static cvtld ( PSZ buf, LONG n )
  363. {
  364.   SHORT i=0,
  365.         nz = 0;
  366.   LONG  j,
  367.         d;
  368.  
  369.   if ( n < 0 )
  370.     {
  371.       buf[i++] = '-';
  372.       n = -n;
  373.     }
  374.  
  375.   cvtlu( buf+i, n );
  376. }
  377.  
  378. /*******************************/
  379. /* Convert ULONG INT to CHAR   */
  380. /*******************************/
  381.  
  382. static cvtlu ( PSZ buf, ULONG n )
  383. {
  384.   SHORT i=0,
  385.         nz = 0;
  386.   ULONG j,
  387.         d;
  388.  
  389.   if (n == 0)
  390.     buf[i++] = '0';
  391.   else
  392.   {
  393.  
  394.     for ( j=1000000000L; j > 0; j /= 10 )
  395.       {
  396.         d =  n / j;
  397.         n =  n % j;
  398.  
  399.         if ( nz = (nz || d ) )
  400.             buf[i++] = d + '0';
  401.        }
  402.   }
  403.   buf[i] = 0;
  404.   return( 0 );
  405. }
  406.  
  407.  
  408. /*******************************/
  409. /* convert ULONG to hex string */
  410. /*******************************/
  411.  
  412. static cvtlx( PSZ s, ULONG n)
  413. {
  414.   SHORT i, sign;
  415.   //static CHAR table[] = "0123456789ABCDEF";
  416.  
  417.   i = 0;
  418.   do {
  419.     //s[i++] = table[ n & 0x000F ];
  420.     s[i++] = (( n & 0x000F ) > 0x0009 ?
  421.                                (n & 0x000F)-0xA +'A' : (n & 0x000F) +'0');
  422.   } while ((n >>= 4) > 0);
  423.  
  424.   s[i] = '\0';
  425.   reverse(s);
  426.  
  427.  return( 0 );
  428. }
  429.  
  430. /*******************************/
  431. /* reverse string s in place   */
  432. /*******************************/
  433.  
  434. static reverse(PSZ s)
  435. {
  436.   SHORT i, j;
  437.   CHAR  c;
  438.  
  439.   for (i = 0, j = strlen(s)-1; i < j; i++, j-- ){
  440.     c = s[i];
  441.     s[i] = s[j];
  442.     s[j] = c;
  443.   } /* endfor */
  444.  
  445.   return ( 0 );
  446. }
  447.  
  448.  
  449. /*****************/
  450. /* String Length */
  451. /*****************/
  452.  
  453. static strlen( PSZ s )
  454. {
  455.   INT   i = 0;
  456.  
  457.   while( *s++ ) i++;
  458.  
  459.   return ( i );
  460. }
  461.  
  462. /*****************/
  463. /* String N Copy */
  464. /*****************/
  465.  
  466. static strncpy( PSZ d, PSZ s, USHORT n )
  467. {
  468.   while( *s && n-- ) *d++ = *s++;
  469.   *d = 0;
  470.  
  471.   return ( 0 );
  472. }
  473.  
  474. /********************/
  475. /* String N Overlay */
  476. /********************/
  477.  
  478. static strnovl( PSZ d, PSZ s, USHORT n )
  479. {
  480.   while( *s && n-- ) *d++ = *s++;
  481.   return ( 0 );
  482. }
  483.  
  484.  
  485. /******************/
  486. /* Char Duplicate */
  487. /******************/
  488.  
  489. static chrdup( PSZ d, UCHAR c, USHORT n )
  490. {
  491.   USHORT   i;
  492.  
  493.   while( n-- ) *d++ = c;
  494.   *d = 0;
  495.  
  496.   return ( 0 );
  497. }
  498.  
  499.