/*++ Copyright (c) 1992-2000 Microsoft Corporation Purpose: Formatting functions. --*/ #include "precomp.hxx" #pragma hdrstop #define MAXNESTING (50) static TCHAR rgchOpenQuote[] = { _T('\"'), _T('\''), _T('('), _T('{'), _T('[') }; static TCHAR rgchCloseQuote[] = { _T('\"'), _T('\''), _T(')'), _T('}'), _T(']') }; #define MAXQUOTE (_tsizeof(rgchOpenQuote) / _tsizeof(rgchOpenQuote[0])) static TCHAR rgchDelim[] = { _T(' '), _T('\t'), _T(',') }; #define MAXDELIM (_tsizeof(rgchDelim) / _tsizeof(rgchDelim[0])) //extern LPSHF Lpshf; int CPCopyString( PTSTR * lplps, PTSTR lpT, TCHAR chEscape, BOOL fQuote ) /*++ Routine Description: Scan and copy an optionally quoted C-style string. If the first character is a quote, a matching quote will terminate the string, otherwise the scanning will stop at the first whitespace encountered. The target string will be null terminated if any characters are copied. Arguments: lplps - Supplies a pointer to a pointer to the source string lpt - Supplies a pointer to the target string chEscape - Supplies the escape character (typically '\\') fQuote - Supplies a flag indicating whether the first character is a quote Return Value: The number of characters copied into lpt[]. If an error occurs, -1 is returned. --*/ { PTSTR lps = *lplps; PTSTR lpt = lpT; int i; int n; int err = 0; TCHAR cQuote = _T('\0'); if (fQuote) { if (*lps) { cQuote = *lps++; } } while (!err) { if (*lps == 0) { if (fQuote) { err = 1; } else { *lpt = _T('\0'); } break; } else if (fQuote && *lps == cQuote) { *lpt = _T('\0'); // eat the quote lps++; break; } else if (!fQuote && (!*lps || *lps == _T(' ') || *lps == _T('\t') || *lps == _T('\r') || *lps == _T('\n'))) { *lpt = _T('\0'); break; } else if (*lps != chEscape) { *lpt++ = *lps++; } else { switch (*++lps) { case 0: err = 1; --lps; break; default: // any char - usually escape or quote *lpt++ = *lps; break; case _T('b'): // backspace *lpt++ = _T('\b'); break; case _T('f'): // formfeed *lpt++ = _T('\f'); break; case _T('n'): // newline *lpt++ = _T('\n'); break; case _T('r'): // return *lpt++ = _T('\r'); break; case _T('s'): // space *lpt++ = _T(' '); break; case _T('t'): // tab *lpt++ = _T('\t'); break; case _T('0'): // octal escape for (n = 0, i = 0; i < 3; i++) { ++lps; if (*lps < _T('0') || *lps > _T('7')) { --lps; break; } n = (n<<3) + *lps - _T('0'); } *lpt++ = (UCHAR)(n & 0xff); break; } lps++; // skip char from switch } } // while if (err) { return -1; } else { *lplps = lps; return (int) (lpt - lpT); } } BOOL CPFormatMemory( LPCH lpchTarget, DWORD cchTarget, LPBYTE lpbSource, DWORD cBits, FMTTYPE fmtType, DWORD radix ) /*++ Routine Description: CPFormatMemory. formats a value by template Arguments: lpchTarget - Destination buffer. cchTarget - Size of destination buffer. lpbSource - Data to be formatted. cBits - Number of bits in the data. fmtType - Determines how the data will be treated?? UINT, float, real, ... radix - Radix to use when formatting. Return Value: TRUE - Success FALSE - Bad things happened --*/ { LONG64 l; long cb; ULONG64 ul = 0; TCHAR rgch[512] = {0}; Assert (radix == 8 || radix == 10 || radix == 16 || (fmtType & fmtBasis) == fmtAscii || (fmtType & fmtBasis) == fmtUnicode); Assert (cBits != 0); Assert (cchTarget <= _tsizeof(rgch)); switch (fmtType & fmtBasis) { // // Format from memory bytes into an integer format number // case fmtInt: if (radix == 10) { switch( (cBits + 7)/8 ) { case 1: l = *(signed char *)lpbSource; if (fmtType & fmtZeroPad) { _stprintf(rgch, _T("%0*I64d"), cchTarget-1, l); } else if (fmtType & fmtSpacePad) { _stprintf(rgch, _T("% *I64d"), cchTarget-1, l); } else { _stprintf(rgch, _T("% I64d"), l); } break; case 2: l = *(short *)lpbSource; if (fmtType & fmtZeroPad) { _stprintf(rgch, _T("%0*I64d"), cchTarget-1, l); } else if (fmtType & fmtSpacePad) { _stprintf(rgch, _T("% *I64d"), cchTarget-1, l); } else { _stprintf(rgch, _T("% I64d"), l); } break; case 4: l = *(long *)lpbSource; if (fmtType & fmtZeroPad) { _stprintf(rgch, _T("%0*I64d"), cchTarget-1, l); } else if (fmtType & fmtSpacePad) { _stprintf(rgch, _T("% *I64d"), cchTarget-1, l); } else { _stprintf(rgch, _T("% I64d"), l); } break; case 8: l = *(LONG64 *)lpbSource; if (fmtType & fmtZeroPad) { _stprintf(rgch, _T("%0*I64d"), cchTarget-1, l); } else if (fmtType & fmtSpacePad) { _stprintf(rgch, _T("% *I64d"), cchTarget-1, l); } else { _stprintf(rgch, _T("% I64d"), l); } break; default: return FALSE; // Bad format } if (_tcslen(rgch) >= cchTarget) { return FALSE; // Overrun } _tcscpy(lpchTarget, rgch); break; } // // then we should handle this as UInt // case fmtUInt: cb = (cBits + 7)/8; switch( cb ) { case 1: ul = *(BYTE *) lpbSource; break; case 2: ul = *(USHORT *) lpbSource; break; case 4: ul = *(ULONG *) lpbSource; break; // // MBH - bugbug - CENTAUR bug; // putting contents of instead of address of structure // for return value in a0. // case 8: ul = *(ULONG64 *) lpbSource; break; default: if (radix != 16 || (fmtType & fmtZeroPad) == 0) { return FALSE; // Bad format } } if (fmtType & fmtZeroPad) { switch (radix) { case 8: _stprintf(rgch, _T("%0*.*I64o"), cchTarget-1, cchTarget-1, ul); break; case 10: _stprintf(rgch, _T("%0*.*I64u"), cchTarget-1, cchTarget-1, ul); break; case 16: if (cb <= 8) { _stprintf(rgch, _T("%0*.*I64x"), cchTarget-1, cchTarget-1, ul); } else { // handle any size: // NOTENOTE a-kentf this is dependent on byte order for (l = 0; l < cb; l++) { _stprintf(rgch+l+l, _T("%02.2x"), lpbSource[cb - l - 1]); } //_stprintf(rgch, _T("%0*.*x"), cchTarget-1, cchTarget-1, ul); } break; } } else if (fmtType & fmtSpacePad) { switch (radix) { case 8: _stprintf(rgch, _T("% *.*I64o"), cchTarget-1, cchTarget-1, ul); break; case 10: _stprintf(rgch, _T("% *.*I64u"), cchTarget-1, cchTarget-1, ul); break; case 16: if (cb <= 8) { _stprintf(rgch, _T("% *.*I64x"), cchTarget-1, cchTarget-1, ul); } else { // handle any size: // NOTENOTE a-kentf this is dependent on byte order /*for (l = 0; l < cb; l++) { _stprintf(rgch+l+l, _T("% 2.2x"), lpbSource[cb - l - 1]); }*/ _stprintf(rgch, _T("% *.*I64x"), cchTarget-1, cchTarget-1, ul); } break; } } else { switch (radix) { case 8: _stprintf(rgch, _T("%I64o"), ul); break; case 10: _stprintf(rgch, _T("%I64u"), ul); break; case 16: _stprintf(rgch, _T("%I64x"), ul); break; } } if (_tcslen(rgch) >= cchTarget) { return FALSE; // Overrun } _tcscpy(lpchTarget, rgch); break; case fmtAscii: if ( cBits != 8 ) { return FALSE; // Bad format } lpchTarget[0] = *(BYTE *) lpbSource; if ((lpchTarget[0] < _T(' ')) || (lpchTarget[0] > 0x7e)) { lpchTarget[0] = _T('.'); } lpchTarget[1] = 0; return TRUE; // success case fmtUnicode: if (cBits != 16) { return FALSE; // Bad format } Assert((DWORD)MB_CUR_MAX <= cchTarget); if ((wctomb(lpchTarget, *(LPWCH)lpbSource) == -1) || (lpchTarget[0] < _T(' ')) || (lpchTarget[0] > 0x7e)) { lpchTarget[0] = _T('.'); } lpchTarget[1] = 0; return TRUE; // success case fmtFloat: switch ( cBits ) { case 4*8: _stprintf(rgch, _T("% 12.6e"),*((float *) lpbSource)); break; case 8*8: // _stprintf(rgch, _T("% 17.11le"), *((double *) lpbSource)); _stprintf(rgch, _T("% 21.14le"), *((double *) lpbSource)); break; case 10*8: if (_uldtoa((_ULDOUBLE *)lpbSource, 25, rgch) == NULL) { return FALSE; // Bad format } break; case 16*8: // v-vadimp this is an IA64 float - may have to rethink the format here // what we are getting here is really FLOAT128 if (_uldtoa((_ULDOUBLE *)(lpbSource), 30, rgch) == NULL) { return FALSE; // Bad format } break; default: return FALSE; // Bad format } if (_tcslen(rgch) >= cchTarget) { return FALSE; // Overrun } _tcsncpy(lpchTarget, rgch, cchTarget-1); lpchTarget[cchTarget-1] = 0; return TRUE; // success case fmtBit: { WORD i,j,shift=0; //shift will allow for a blank after each 8 bits for (i=0;i>j) & 0x1) { rgch[i*8+j+shift]=_T('1'); } else { rgch[i*8+j+shift]=_T('0'); } } rgch[(i+1)*8+shift]=_T(' '); shift++; } rgch[cBits+shift-1]=_T('\0'); _tcscpy(lpchTarget,rgch); } return TRUE; // success default: return FALSE; // Bad format } return TRUE; // success } /* CPFormatMemory() */