home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / CDROM / ATAPI / PRINTF.C < prev   
Encoding:
C/C++ Source or Header  |  1995-04-14  |  10.6 KB  |  510 lines

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