home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / audiopdd.zip / myprintf.c < prev    next >
C/C++ Source or Header  |  1999-02-24  |  11KB  |  390 lines

  1. //
  2. // myprintf()
  3. // 25-Jan-99
  4. //
  5. // see ras40's stuff for perhaps a more recent version
  6. //
  7. // Note: if "%s" then string pointer in the ,... section must be a FAR POINTER! in the , ...
  8. //       part of the string:  ddprintf(dest,"%s","a string"); will fail because compiler
  9. //       only passes near pointer for "a string" -- either pass a far pointer, or use
  10. //       ddprintf(dest,"%s",(char __far *)"a string"), or don't use strings in the arg list,
  11. //       but instead actual (far) pointers
  12. //
  13. // static VOID PrintCom(USHORT basePort, UCHAR byte);
  14. // static VOID ddputstring (char far *St);
  15. // static char far *ddprintf_DecWordToASCII(char far *StrPtr, WORD wDecVal, WORD Option);
  16. // static char far *ddprintf_DecLongToASCII(char far *StrPtr, DWORD lDecVal,WORD Option);
  17. // static char far *ddprintf_HexWordToASCII(char far *StrPtr, WORD wHexVal, WORD Option);
  18. // static char far *ddprintf_HexLongToASCII(char far *StrPtr, DWORD wHexVal, WORD Option);
  19. // VOID __cdecl ddprintf (char far *DbgStr , ...);
  20. //
  21. // writes to com port 2 a ddprintf() string (up to MAX_STR_SIZE bytes)
  22. // (or could write to screen at init (DosPutMessage) or basedev (devhelp save_message)
  23. //
  24. // 16-bit version, so %u limited to word-size data (use %lh for 32-bit data (%lx, too)
  25. // though %p always goes after seg:off so expects 32-bit data
  26. //
  27. // should only include in debug builds (probably, or at least move data and code to INIT segment)
  28.  
  29. //#define DRV_16 (can only find it used in a PAS16 mixer thing)
  30.  
  31. //#define FAST_OUT  // only output strings starting with ~ if defined
  32.  
  33. #include "cs40.h"
  34.  
  35. #pragma code_seg ("_TEXT");
  36. #pragma data_seg ("_DATA","DATA");
  37.  
  38. #define MAX_STR_SIZE 260
  39.  
  40. #define LEADING_ZEROES          0x8000
  41. #define SIGNIFICANT_FIELD       0x0007
  42.  
  43. static char ddhextab[]="0123456789ABCDEF";
  44. static char dd_BuildString[MAX_STR_SIZE];
  45.  
  46. // Following declarations are need for string display from basedev
  47. //#define MSG_REPLACEMENT_STRING 1178   /* replacement string */
  48. //UCHAR szStringOut [CCHMAXPATH];
  49. //static MSGTABLE StringOutMsg = {MSG_REPLACEMENT_STRING, 1, NULL};
  50.  
  51. // dx+5 is LSR register
  52. // dx is baseport (also data register)
  53.  
  54. VOID PrintCom(USHORT basePort, UCHAR byte);  // aux asm macro
  55. #pragma aux PrintCom =\
  56.         "add dx,5"    \
  57. "wait4:  in al,dx"    \
  58.         "test al,20h" \
  59.         "jz wait4"    \
  60.         "sub dx,5"    \
  61.         "mov al,ah"   \
  62.         "out dx,al"   \
  63.  parm caller nomemory [dx] [ah]  \
  64.  modify exact [ax dx];
  65.  
  66.  
  67. static VOID ddputstring (char far *St) {
  68.  
  69. // putmessage
  70.    //int      iMsgLength;
  71.    //char far *TempSt;
  72.    //
  73.    //TempSt = St;
  74.    //iMsgLength = 0;
  75.    //while (*TempSt != '\0')
  76.    //   {
  77.    //   TempSt++;
  78.    //   iMsgLength++;
  79.    //   }               // Should strcat a \r\n to the string.
  80.    //DosPutMessage (1, iMsgLength, St);         // For ring-3 initialization
  81.  
  82. // savemessage
  83.    //chhTrace_Save_Message (St);
  84.    //chhStringOutMsg.MsgStrings[0] = St;
  85.    //chhDevHelp_Save_Message ((NPBYTE)&StringOutMsg);
  86.  
  87.    //dd_strcpy (szStringOut, (NPBYTE)St);      // For ring-0 initialization
  88.    //szStringOut [CCHMAXPATH-1] = '\0';
  89.  
  90.  
  91. // added this to write to com2 (25-Jan-99)
  92. // commessage
  93.    char al = 0;
  94.    while (*St) {
  95.       al = *St++;
  96.       PrintCom(0x2F8,al);
  97.    }
  98. //   if (al) {
  99. //      PrintCom(0x2F8,13);
  100. //      PrintCom(0x2F8,10);
  101. //   }
  102. }
  103.  
  104. static char far *ddprintf_DecWordToASCII(char far *StrPtr, WORD wDecVal, WORD Option) {
  105.  
  106.   BOOL fNonZero=FALSE;
  107.   WORD Digit;
  108.   WORD Power=10000;
  109.  
  110.   while (Power)
  111.      {
  112.      Digit=0;
  113.      while (wDecVal >=Power)                   //Digit=wDecVal/Power;
  114.         {
  115.         Digit++;
  116.         wDecVal-=Power;
  117.         }
  118.  
  119.      if (Digit)
  120.         fNonZero=TRUE;
  121.  
  122.      if (Digit ||
  123.          fNonZero ||
  124.          (Option & LEADING_ZEROES) ||
  125.          ((Power==1) && (fNonZero==FALSE)))
  126.          {
  127.          *StrPtr=(char)('0'+Digit);
  128.          StrPtr++;
  129.          }
  130.  
  131.      if (Power==10000)
  132.         Power=1000;
  133.      else if (Power==1000)
  134.         Power=100;
  135.      else if (Power==100)
  136.         Power=10;
  137.      else if (Power==10)
  138.         Power=1;
  139.      else
  140.         Power=0;
  141.      } // end while
  142.  
  143.   return (StrPtr);
  144. }
  145.  
  146.  
  147. static char far *ddprintf_DecLongToASCII(char far *StrPtr, DWORD lDecVal,WORD Option) {
  148.  
  149.    BOOL  fNonZero=FALSE;
  150.    DWORD Digit;
  151.    DWORD Power=1000000000;                      // 1 billion
  152.  
  153.    while (Power)
  154.       {
  155.       Digit=0;                                                                        // Digit=lDecVal/Power
  156.       while (lDecVal >=Power)                   // replaced with while loop
  157.          {
  158.          Digit++;
  159.          lDecVal-=Power;
  160.          }
  161.  
  162.       if (Digit)
  163.          fNonZero=TRUE;
  164.  
  165.       if (Digit ||
  166.           fNonZero ||
  167.           (Option & LEADING_ZEROES) ||
  168.           ((Power==1) && (fNonZero==FALSE)))
  169.          {
  170.          *StrPtr=(char)('0'+Digit);
  171.          StrPtr++;
  172.          }
  173.  
  174.       if (Power==1000000000)                    // 1 billion
  175.          Power=100000000;
  176.       else if (Power==100000000)
  177.          Power=10000000;
  178.       else if (Power==10000000)
  179.          Power=1000000;
  180.       else if (Power==1000000)
  181.          Power=100000;
  182.       else if (Power==100000)
  183.          Power=10000;
  184.       else if (Power==10000)
  185.          Power=1000;
  186.       else if (Power==1000)
  187.          Power=100;
  188.       else if (Power==100)
  189.          Power=10;
  190.       else if (Power==10)
  191.          Power=1;
  192.       else
  193.          Power=0;
  194.       }
  195.    return (StrPtr);
  196. }
  197.  
  198.  
  199. static char far *ddprintf_HexWordToASCII(char far *StrPtr, WORD wHexVal, WORD Option) {
  200.  
  201.    BOOL fNonZero=FALSE;
  202.    WORD Digit;
  203.    WORD Power=0xF000;
  204.    WORD ShiftVal=12;
  205.  
  206.    while (Power)
  207.       {
  208.       Digit=(wHexVal & Power)>>ShiftVal;
  209.       if (Digit)
  210.          fNonZero=TRUE;
  211.  
  212.       if (Digit ||
  213.           fNonZero ||
  214.           (Option & LEADING_ZEROES) ||
  215.           ((Power==0x0F) && (fNonZero==FALSE)))
  216.          //*StrPtr++=(char)('0'+Digit);
  217.          *StrPtr++=ddhextab[Digit];
  218.  
  219.       Power>>=4;
  220.       ShiftVal-=4;
  221.       } // end while
  222.  
  223.    return (StrPtr);
  224. }
  225.  
  226.  
  227. static char far *ddprintf_HexLongToASCII(char far *StrPtr, DWORD wHexVal, WORD Option) {
  228.  
  229.    BOOL  fNonZero=FALSE;
  230.    DWORD Digit;
  231.    DWORD Power=0xF0000000;
  232.    DWORD ShiftVal=28;
  233.  
  234.    while (Power)
  235.       {
  236.       Digit=(wHexVal & Power)>>ShiftVal;
  237.       if (Digit)
  238.          fNonZero=TRUE;
  239.  
  240.       if (Digit ||
  241.           fNonZero ||
  242.           (Option & LEADING_ZEROES) ||
  243.           ((Power==0x0F) && (fNonZero==FALSE)))
  244.           *StrPtr++=ddhextab[Digit];
  245.  
  246.       if (Power==0xF0000000)                  // 1 billion
  247.          Power=0xF000000;
  248.       else if (Power==0xF000000)
  249.          Power=0xF00000;
  250.       else if (Power==0xF00000)
  251.          Power=0xF0000;
  252.       else if (Power==0xF0000)
  253.          Power=0xF000;
  254.       else if (Power==0xF000)
  255.          Power=0xF00;
  256.       else if (Power==0xF00)
  257.          Power=0xF0;
  258.       else if (Power==0xF0)
  259.          Power=0xF;
  260.       else Power=0;
  261.  
  262.       ShiftVal-=4;
  263.       } // end while
  264.  
  265.    return (StrPtr);
  266. }
  267.  
  268. // saveregs is not saving all regs! so have to do it myself to be sure all are really saved
  269. // esp. es:bx (can't use pusha/popa since need bp)
  270. // diff between __saveregs and not is just es (probably all that's called for for __cdecl)
  271. // si/di is already saved
  272.  
  273. VOID __cdecl ddprintf (char far *DbgStr , ...) {
  274.  
  275.    char far *BuildPtr; //=dd_BuildString;
  276.    char far *pStr;     //=(char far *) DbgStr;
  277.    char far *SubStr;
  278.    union {
  279.     VOID    far *VoidPtr;
  280.     WORD    far *WordPtr;
  281.     DWORD   far *LongPtr;
  282.     DWORD far *StringPtr;
  283.    } Parm;
  284.    WORD wBuildOption;
  285.  
  286. // !!!
  287. // fast out
  288.  
  289. #ifdef FAST_OUT
  290.  if (*DbgStr != '~') return;  // only let strings starting with ~ through
  291. #endif
  292.  
  293.    BuildPtr = dd_BuildString;
  294.    pStr = DbgStr;
  295.  
  296.    Parm.VoidPtr=(VOID far *) &DbgStr;
  297.    Parm.StringPtr++;                            // skip size of string pointer
  298.  
  299.    while (*pStr) {
  300.       
  301.       if (BuildPtr >= (char far *) &dd_BuildString[MAX_STR_SIZE-2]) break; // don't overflow target
  302.  
  303.       switch (*pStr)
  304.       {
  305.          case '%':
  306.             wBuildOption=0;
  307.             pStr++;
  308.             if (*pStr=='0')
  309.                {
  310.                wBuildOption|=LEADING_ZEROES;
  311.                pStr++;
  312.                }
  313.  
  314.             //if (*pStr=='u')    // always unsigned
  315.             //   pStr++;        // this means %u won't work!  buggy crap
  316.  
  317.             switch(*pStr)
  318.                {
  319.                case 'x':
  320.                case 'X':
  321.                   BuildPtr=ddprintf_HexWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
  322.                   pStr++;
  323.                   continue;
  324.  
  325.                case 'u':
  326.                case 'd':
  327.                   BuildPtr=ddprintf_DecWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
  328.                   pStr++;
  329.                   continue;
  330.  
  331.                case 's':
  332.                   SubStr=(char far *)*Parm.StringPtr;
  333.                   while (*BuildPtr++ = *SubStr++);
  334.                   Parm.StringPtr++;
  335.                   BuildPtr--;  // remove the \0
  336.                   pStr++;
  337.                   continue;
  338.  
  339.                case 'p':
  340.                   BuildPtr=ddprintf_HexLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
  341.                   pStr++;
  342.                   continue;
  343.  
  344.                case 'l':
  345.                   pStr++;
  346.                   switch (*pStr)
  347.                   {
  348.                   case 'x':
  349.                   case 'X':
  350.                      BuildPtr=ddprintf_HexLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
  351.                      pStr++;
  352.                      continue;
  353.  
  354.                   case 'u':
  355.                   case 'd':
  356.                      BuildPtr=ddprintf_DecLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
  357.                      pStr++;
  358.                      continue;
  359.  
  360.                   } // end switch
  361.                   continue;    // dunno what he wants
  362.  
  363.                case 0:
  364.                   continue;
  365.                } // end switch
  366.             break;
  367.  
  368.          case '\\':   // that means a literal '\' is in the stream, not just a '\n' (binary 10)
  369.          case '\r':   // CR, already is literal (assumed "msg\n" only stores a binary 10)
  370.             break;
  371.  
  372.          case '\n':
  373.             *BuildPtr++=13;
  374.             *BuildPtr++=10;
  375.             pStr++;
  376.             continue;
  377.  
  378.       } // end switch
  379.  
  380.       *BuildPtr++=*pStr++;
  381.    } // end while
  382.  
  383.    *BuildPtr=0;                                 // cauterize the string
  384.    ddputstring((char far *) dd_BuildString);    // display
  385.  
  386.    return;
  387. }
  388.  
  389.  
  390.