/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1994 **/ /**********************************************************************/ /* debug.c This module contains debug support routines. FILE HISTORY: KeithMo 20-Sep-1993 Created. */ #include #include #ifdef DEBUG // // Private constants. // #define MAX_PRINTF_OUTPUT 512 // characters #define OUTPUT_LABEL "DHCP" #define IS_DIGIT(ch) (((ch) >= '0') && ((ch) <= '9')) // // Private types. // // // Private globals. // // // Private prototypes. // int VxdVsprintf( char * pszStr, char * pszFmt, char * ArgPtr ); // // Public functions. // /******************************************************************* NAME: VxdAssert SYNOPSIS: Called if an assertion fails. Displays the failed assertion, file name, and line number. Gives the user the opportunity to ignore the assertion or break into the debugger. ENTRY: pAssertion - The text of the failed expression. pFileName - The containing source file. nLineNumber - The guilty line number. HISTORY: KeithMo 20-Sep-1993 Created. ********************************************************************/ void VxdAssert( void * pAssertion, void * pFileName, unsigned long nLineNumber ) { VxdPrintf( "\n" "*** Assertion failed: %s\n" "*** Source file %s, line %lu\n\n", pAssertion, pFileName, nLineNumber ); DEBUG_BREAK; } // VxdAssert /******************************************************************* NAME: VxdPrintf SYNOPSIS: Customized debug output routine. ENTRY: Usual printf-style parameters. HISTORY: KeithMo 20-Sep-1993 Created. ********************************************************************/ void VxdPrintf( char * pszFormat, ... ) { char szOutput[MAX_PRINTF_OUTPUT]; va_list ArgList; int cch; cch = VxdSprintf( szOutput, "%s: ", OUTPUT_LABEL ); va_start( ArgList, pszFormat ); VxdVsprintf( szOutput + cch, pszFormat, ArgList ); va_end( ArgList ); VxdSprintf( szOutput, "%s\r\n", szOutput ) ; ASSERT( (strlen( szOutput ) + 1) < MAX_PRINTF_OUTPUT ); CTEMemCopy( DBOut+iCurPos, szOutput, strlen( szOutput ) + 1 ) ; NbtDebugOut( DBOut+iCurPos ) ; } // VxdPrintf // // Private functions. // /******************************************************************* NAME: VxdVsprintf SYNOPSIS: Half-baked vsprintf() clone for VxD environment. ENTRY: pszStr - Will receive the formatted string. pszFmt - The format, with field specifiers. ArgPtr - Points to the actual printf() arguments. RETURNS: int - Number of characters stored in *pszStr. HISTORY: KeithMo 20-Sep-1993 Created. ********************************************************************/ int VxdVsprintf( char * pszStr, char * pszFmt, char * ArgPtr ) { char ch; char * pszStrStart; int fZeroPad; int cchWidth; // // Remember start of output, so we can calc length. // pszStrStart = pszStr; while( ( ch = *pszFmt++ ) != '\0' ) { // // Scan for format specifiers. // if( ch != '%' ) { *pszStr++ = ch; continue; } // // Got one. // ch = *pszFmt++; // // Initialize attributes for this item. // fZeroPad = 0; cchWidth = 0; // // Interpret the field specifiers. // if( ch == '-' ) { // // Left justification not supported. // ch = *pszFmt++; } if( ch == '0' ) { // // Zero padding. // fZeroPad = 1; ch = *pszFmt++; } if( ch == '*' ) { // // Retrieve width from next argument. // cchWidth = va_arg( ArgPtr, int ); ch = *pszFmt++; } else { // // Calculate width. // while( IS_DIGIT(ch) ) { cchWidth = ( cchWidth * 10 ) + ( ch - '0' ); ch = *pszFmt++; } } // // Note that we don't support the precision specifiers, // but we do honor the syntax. // if( ch == '.' ) { ch = *pszFmt++; if( ch == '*' ) { (void)va_arg( ArgPtr, int ); ch = *pszFmt++; } else { while( IS_DIGIT(ch) ) { ch = *pszFmt++; } } } // // All numbers are longs. // if( ch == 'l' ) { ch = *pszFmt++; } // // Decipher the format specifier. // if( ( ch == 'd' ) || ( ch == 'u' ) || ( ch == 'x' ) || ( ch == 'X' ) ) { unsigned long ul; unsigned long radix; char xbase; char * pszTmp; char * pszEnd; int cchNum; int fNegative; // // Numeric. Retrieve the value. // ul = va_arg( ArgPtr, unsigned long ); // // If this is a negative number, remember and negate. // if( ( ch == 'd' ) && ( (long)ul < 0 ) ) { fNegative = 1; ul = (unsigned long)(-(long)ul); } else { fNegative = 0; } // // Remember start of digits. // pszTmp = pszStr; cchNum = 0; // // Special goodies for hex conversion. // radix = ( ( ch == 'x' ) || ( ch == 'X' ) ) ? 16 : 10; xbase = ( ch == 'x' ) ? 'a' : 'A'; // // Loop until we're out of digits. // do { unsigned int digit; digit = (unsigned int)( ul % radix ); ul /= radix; if( digit > 9 ) { *pszTmp++ = (char)( digit - 10 + xbase ); } else { *pszTmp++ = (char)( digit + '0' ); } cchNum++; } while( ul > 0 ); // // Add the negative sign if necessary. // if( fNegative ) { *pszTmp++ = '-'; cchNum++; } // // Add any necessary padding. // while( cchNum < cchWidth ) { *pszTmp++ = fZeroPad ? '0' : ' '; cchNum++; } // // Now reverse the digits. // pszEnd = pszTmp--; do { char tmp; tmp = *pszTmp; *pszTmp = *pszStr; *pszStr = tmp; pszTmp--; pszStr++; } while( pszTmp > pszStr ); pszStr = pszEnd; } else if( ch == 's' ) { char * pszTmp; // // Copy the string. // pszTmp = va_arg( ArgPtr, char * ); while( *pszTmp ) { *pszStr++ = *pszTmp++; } } else if( ch == 'c' ) { // // A single character. // *pszStr++ = (char)va_arg( ArgPtr, int ); } else { // // Unknown. Ideally we should copy the entire // format specifier, including any width & precision // values, but who really cares? // *pszStr++ = ch; } } // // Terminate it properly. // *pszStr = '\0'; // // Return the length of the generated string. // return pszStr - pszStrStart; } // VxdVsprintf /******************************************************************* NAME: VxdSprintf SYNOPSIS: Half-baked sprintf() clone for VxD environment. ENTRY: pszStr - Will receive the formatted string. pszFmt - The format, with field specifiers. ... - Usual printf()-like parameters. RETURNS: int - Number of characters stored in *pszStr. HISTORY: KeithMo 20-Sep-1993 Created. ********************************************************************/ int VxdSprintf( char * pszStr, char * pszFmt, ... ) { int cch; va_list ArgPtr; va_start( ArgPtr, pszFmt ); cch = VxdVsprintf( pszStr, pszFmt, ArgPtr ); va_end( ArgPtr ); return( cch ); } // VxdSprintf #endif // DEBUG