home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
audiopdd.zip
/
myprintf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-02-24
|
11KB
|
390 lines
//
// myprintf()
// 25-Jan-99
//
// see ras40's stuff for perhaps a more recent version
//
// Note: if "%s" then string pointer in the ,... section must be a FAR POINTER! in the , ...
// part of the string: ddprintf(dest,"%s","a string"); will fail because compiler
// only passes near pointer for "a string" -- either pass a far pointer, or use
// ddprintf(dest,"%s",(char __far *)"a string"), or don't use strings in the arg list,
// but instead actual (far) pointers
//
// static VOID PrintCom(USHORT basePort, UCHAR byte);
// static VOID ddputstring (char far *St);
// static char far *ddprintf_DecWordToASCII(char far *StrPtr, WORD wDecVal, WORD Option);
// static char far *ddprintf_DecLongToASCII(char far *StrPtr, DWORD lDecVal,WORD Option);
// static char far *ddprintf_HexWordToASCII(char far *StrPtr, WORD wHexVal, WORD Option);
// static char far *ddprintf_HexLongToASCII(char far *StrPtr, DWORD wHexVal, WORD Option);
// VOID __cdecl ddprintf (char far *DbgStr , ...);
//
// writes to com port 2 a ddprintf() string (up to MAX_STR_SIZE bytes)
// (or could write to screen at init (DosPutMessage) or basedev (devhelp save_message)
//
// 16-bit version, so %u limited to word-size data (use %lh for 32-bit data (%lx, too)
// though %p always goes after seg:off so expects 32-bit data
//
// should only include in debug builds (probably, or at least move data and code to INIT segment)
//#define DRV_16 (can only find it used in a PAS16 mixer thing)
//#define FAST_OUT // only output strings starting with ~ if defined
#include "cs40.h"
#pragma code_seg ("_TEXT");
#pragma data_seg ("_DATA","DATA");
#define MAX_STR_SIZE 260
#define LEADING_ZEROES 0x8000
#define SIGNIFICANT_FIELD 0x0007
static char ddhextab[]="0123456789ABCDEF";
static char dd_BuildString[MAX_STR_SIZE];
// Following declarations are need for string display from basedev
//#define MSG_REPLACEMENT_STRING 1178 /* replacement string */
//UCHAR szStringOut [CCHMAXPATH];
//static MSGTABLE StringOutMsg = {MSG_REPLACEMENT_STRING, 1, NULL};
// dx+5 is LSR register
// dx is baseport (also data register)
VOID PrintCom(USHORT basePort, UCHAR byte); // aux asm macro
#pragma aux PrintCom =\
"add dx,5" \
"wait4: in al,dx" \
"test al,20h" \
"jz wait4" \
"sub dx,5" \
"mov al,ah" \
"out dx,al" \
parm caller nomemory [dx] [ah] \
modify exact [ax dx];
static VOID ddputstring (char far *St) {
// putmessage
//int iMsgLength;
//char far *TempSt;
//
//TempSt = St;
//iMsgLength = 0;
//while (*TempSt != '\0')
// {
// TempSt++;
// iMsgLength++;
// } // Should strcat a \r\n to the string.
//DosPutMessage (1, iMsgLength, St); // For ring-3 initialization
// savemessage
//chhTrace_Save_Message (St);
//chhStringOutMsg.MsgStrings[0] = St;
//chhDevHelp_Save_Message ((NPBYTE)&StringOutMsg);
//dd_strcpy (szStringOut, (NPBYTE)St); // For ring-0 initialization
//szStringOut [CCHMAXPATH-1] = '\0';
// added this to write to com2 (25-Jan-99)
// commessage
char al = 0;
while (*St) {
al = *St++;
PrintCom(0x2F8,al);
}
// if (al) {
// PrintCom(0x2F8,13);
// PrintCom(0x2F8,10);
// }
}
static char far *ddprintf_DecWordToASCII(char far *StrPtr, WORD wDecVal, WORD Option) {
BOOL fNonZero=FALSE;
WORD Digit;
WORD Power=10000;
while (Power)
{
Digit=0;
while (wDecVal >=Power) //Digit=wDecVal/Power;
{
Digit++;
wDecVal-=Power;
}
if (Digit)
fNonZero=TRUE;
if (Digit ||
fNonZero ||
(Option & LEADING_ZEROES) ||
((Power==1) && (fNonZero==FALSE)))
{
*StrPtr=(char)('0'+Digit);
StrPtr++;
}
if (Power==10000)
Power=1000;
else if (Power==1000)
Power=100;
else if (Power==100)
Power=10;
else if (Power==10)
Power=1;
else
Power=0;
} // end while
return (StrPtr);
}
static char far *ddprintf_DecLongToASCII(char far *StrPtr, DWORD lDecVal,WORD Option) {
BOOL fNonZero=FALSE;
DWORD Digit;
DWORD Power=1000000000; // 1 billion
while (Power)
{
Digit=0; // Digit=lDecVal/Power
while (lDecVal >=Power) // replaced with while loop
{
Digit++;
lDecVal-=Power;
}
if (Digit)
fNonZero=TRUE;
if (Digit ||
fNonZero ||
(Option & LEADING_ZEROES) ||
((Power==1) && (fNonZero==FALSE)))
{
*StrPtr=(char)('0'+Digit);
StrPtr++;
}
if (Power==1000000000) // 1 billion
Power=100000000;
else if (Power==100000000)
Power=10000000;
else if (Power==10000000)
Power=1000000;
else if (Power==1000000)
Power=100000;
else if (Power==100000)
Power=10000;
else if (Power==10000)
Power=1000;
else if (Power==1000)
Power=100;
else if (Power==100)
Power=10;
else if (Power==10)
Power=1;
else
Power=0;
}
return (StrPtr);
}
static char far *ddprintf_HexWordToASCII(char far *StrPtr, WORD wHexVal, WORD Option) {
BOOL fNonZero=FALSE;
WORD Digit;
WORD Power=0xF000;
WORD ShiftVal=12;
while (Power)
{
Digit=(wHexVal & Power)>>ShiftVal;
if (Digit)
fNonZero=TRUE;
if (Digit ||
fNonZero ||
(Option & LEADING_ZEROES) ||
((Power==0x0F) && (fNonZero==FALSE)))
//*StrPtr++=(char)('0'+Digit);
*StrPtr++=ddhextab[Digit];
Power>>=4;
ShiftVal-=4;
} // end while
return (StrPtr);
}
static char far *ddprintf_HexLongToASCII(char far *StrPtr, DWORD wHexVal, WORD Option) {
BOOL fNonZero=FALSE;
DWORD Digit;
DWORD Power=0xF0000000;
DWORD ShiftVal=28;
while (Power)
{
Digit=(wHexVal & Power)>>ShiftVal;
if (Digit)
fNonZero=TRUE;
if (Digit ||
fNonZero ||
(Option & LEADING_ZEROES) ||
((Power==0x0F) && (fNonZero==FALSE)))
*StrPtr++=ddhextab[Digit];
if (Power==0xF0000000) // 1 billion
Power=0xF000000;
else if (Power==0xF000000)
Power=0xF00000;
else if (Power==0xF00000)
Power=0xF0000;
else if (Power==0xF0000)
Power=0xF000;
else if (Power==0xF000)
Power=0xF00;
else if (Power==0xF00)
Power=0xF0;
else if (Power==0xF0)
Power=0xF;
else Power=0;
ShiftVal-=4;
} // end while
return (StrPtr);
}
// saveregs is not saving all regs! so have to do it myself to be sure all are really saved
// esp. es:bx (can't use pusha/popa since need bp)
// diff between __saveregs and not is just es (probably all that's called for for __cdecl)
// si/di is already saved
VOID __cdecl ddprintf (char far *DbgStr , ...) {
char far *BuildPtr; //=dd_BuildString;
char far *pStr; //=(char far *) DbgStr;
char far *SubStr;
union {
VOID far *VoidPtr;
WORD far *WordPtr;
DWORD far *LongPtr;
DWORD far *StringPtr;
} Parm;
WORD wBuildOption;
// !!!
// fast out
#ifdef FAST_OUT
if (*DbgStr != '~') return; // only let strings starting with ~ through
#endif
BuildPtr = dd_BuildString;
pStr = DbgStr;
Parm.VoidPtr=(VOID far *) &DbgStr;
Parm.StringPtr++; // skip size of string pointer
while (*pStr) {
if (BuildPtr >= (char far *) &dd_BuildString[MAX_STR_SIZE-2]) break; // don't overflow target
switch (*pStr)
{
case '%':
wBuildOption=0;
pStr++;
if (*pStr=='0')
{
wBuildOption|=LEADING_ZEROES;
pStr++;
}
//if (*pStr=='u') // always unsigned
// pStr++; // this means %u won't work! buggy crap
switch(*pStr)
{
case 'x':
case 'X':
BuildPtr=ddprintf_HexWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
pStr++;
continue;
case 'u':
case 'd':
BuildPtr=ddprintf_DecWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
pStr++;
continue;
case 's':
SubStr=(char far *)*Parm.StringPtr;
while (*BuildPtr++ = *SubStr++);
Parm.StringPtr++;
BuildPtr--; // remove the \0
pStr++;
continue;
case 'p':
BuildPtr=ddprintf_HexLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
pStr++;
continue;
case 'l':
pStr++;
switch (*pStr)
{
case 'x':
case 'X':
BuildPtr=ddprintf_HexLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
pStr++;
continue;
case 'u':
case 'd':
BuildPtr=ddprintf_DecLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
pStr++;
continue;
} // end switch
continue; // dunno what he wants
case 0:
continue;
} // end switch
break;
case '\\': // that means a literal '\' is in the stream, not just a '\n' (binary 10)
case '\r': // CR, already is literal (assumed "msg\n" only stores a binary 10)
break;
case '\n':
*BuildPtr++=13;
*BuildPtr++=10;
pStr++;
continue;
} // end switch
*BuildPtr++=*pStr++;
} // end while
*BuildPtr=0; // cauterize the string
ddputstring((char far *) dd_BuildString); // display
return;
}