windows-nt/Source/XPSP1/NT/base/busdrv/acpi/asl/binfmt.c
2020-09-26 16:20:57 +08:00

560 lines
16 KiB
C

/*** binfmt.c - Binary Data Format services
*
* This module contains format services for converting binary data into format
* text strings according to the format record.
*
* Copyright (c) 1995,1996 Microsoft Corporation
* Author: Michael Tsang (MikeTs)
* Created 11/06/95
*
* MODIFICATION HISTORY
*/
#ifdef __UNASM
#pragma warning (disable: 4001)
#include "basedef.h"
#define USE_CRUNTIME
#include "binfmt.h"
typedef int (*PFNFMT)(char *, PFMTHDR, BYTE *, DWORD *);
//Local function prototypes
int FormatNum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
int FormatEnum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
int FormatBits(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
int FormatString(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
int GetData(BYTE bUnitSize, BYTE *pb, DWORD dwOffset, DWORD *pdwData);
int PrintData(char *pszBuffer, BYTE bUnitSize, DWORD dwData, BOOL fPadSpace);
char szDefSep[] = SZ_SEP_SPACE;
char szDefOffsetFmt[] = SZ_FMT_WORDOFFSET;
PFNFMT FmtFuncTable[] =
{
FormatNum, //0: FMT_NUMBER
FormatEnum, //1: FMT_ENUM
FormatBits, //2: FMT_BITS
FormatString, //3: FMT_STRING
};
#define NUM_FMT_FUNCS (sizeof(FmtFuncTable)/sizeof(PFNFMT))
#ifdef FPRINTF
/***EP BinFPrintf - Binary fprintf
*
* ENTRY
* pfile -> output file
* pszBuffer -> buffer to hold the formatted string
* (if NULL, use internal buffer)
* pfmt -> format record array
* pb -> binary data buffer
* pdwOffset -> offset to binary data buffer (if NULL, use internal)
* pszOffsetFormat -> offset format string (can be NULL)
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int BinFPrintf(FILE *pfile, char *pszBuffer, PFMT pfmt, BYTE *pb,
DWORD *pdwOffset, char *pszOffsetFormat)
{
TRACENAME("BINFPRINTF")
int rc = FERR_NONE;
DWORD dwOffset = 0, dwOldOffset;
DWORD dwData;
char szBuff[256];
char *psz = pszBuffer? pszBuffer: szBuff;
DWORD *pdw = pdwOffset? pdwOffset: &dwOffset;
ENTER(4, ("BinFPrintf(pszBuff=%lx,pfmt=%lx,pdwOffset=%lx,Offset=%lx)\n",
pszBuffer, pfmt, pdwOffset, pdwOffset? *pdwOffset: 0));
if (pfmt != NULL)
{
BYTE i, j;
for (i = 0; pfmt[i].pfmtType != NULL; ++i)
{
if (pfmt[i].pszLabel != NULL)
{
if (pszOffsetFormat != NULL)
{
FPRINTF(pfile, pszOffsetFormat,
*pdw, pfmt[i].pfmtType->bUnitSize);
if (pfmt[i].pfmtType->dwfFormat & FMTF_NO_RAW_DATA)
{
FPRINTF(pfile, " ");
}
else
{
if (GetData(pfmt[i].pfmtType->bUnitSize, pb, *pdw,
&dwData) == FERR_NONE)
{
PrintData(psz, pfmt[i].pfmtType->bUnitSize, dwData,
TRUE);
FPRINTF(pfile, psz);
}
for (j = 1; j < pfmt[i].pfmtType->bUnitCnt; ++j)
{
if (GetData(pfmt[i].pfmtType->bUnitSize, pb,
*pdw + j*pfmt[i].pfmtType->bUnitSize,
&dwData) == FERR_NONE)
{
FPRINTF(pfile, ",");
PrintData(psz, pfmt[i].pfmtType->bUnitSize,
dwData, FALSE);
FPRINTF(pfile, psz);
}
}
}
}
if (pfmt[i].pszLabel[0] != '\0')
FPRINTF(pfile, ";%s", pfmt[i].pszLabel);
else
FPRINTF(pfile, "\n");
}
dwOldOffset = *pdw;
if ((pfmt[i].pszLabel != NULL) && (pfmt[i].pszLabel[0] == '\0'))
{
*pdw += pfmt[i].pfmtType->bUnitCnt*pfmt[i].pfmtType->bUnitSize;
}
else
{
if (pfmt[i].pszLabel == NULL)
FPRINTF(pfile, ",");
rc = BinSprintf(psz, pfmt[i].pfmtType, pb, pdw);
if (rc == FERR_NONE)
{
char *psz1, *psz2;
BOOL fSpace = FALSE, fInQuote = FALSE, fInString = FALSE;
for (psz1 = psz2 = psz; *psz2 != '\0'; ++psz2)
{
if (*psz2 == '"')
{
fSpace = FALSE;
fInString = ~fInString;
*psz1 = *psz2;
psz1++;
}
else if (*psz2 == '\'')
{
fSpace = FALSE;
fInQuote = ~fInQuote;
*psz1 = *psz2;
psz1++;
}
else if (*psz2 == ' ')
{
if (!fSpace && !fInString && !fInQuote &&
(psz1 != psz))
{
*psz1 = ',';
psz1++;
}
else if (fInString || fInQuote)
{
*psz1 = *psz2;
psz1++;
}
fSpace = TRUE;
}
else
{
fSpace = FALSE;
*psz1 = *psz2;
psz1++;
}
}
if ((psz1 > psz) && (*(psz1 - 1) == ','))
*(psz1 - 1) = '\0';
else if ((psz1 > psz) && (*(psz1 - 1) == '\n') &&
(*(psz1 - 2) == ','))
{
*(psz1 - 2) = '\n';
*(psz1 - 1) = '\0';
}
else
*psz1 = '\0';
FPRINTF(pfile, psz);
}
}
if (pfmt[i].lpfn != NULL)
(*pfmt[i].lpfn)(pfile, pb, dwOldOffset);
}
}
EXIT(4, ("BinFPrintf=%d (Offset=%lx,Buff=%s)\n",
rc, *pdwOffset, pszBuffer));
return rc;
} //BinFPrintf
#endif //ifdef FPRINTF
/***EP BinSprintf - Binary sprintf
*
* ENTRY
* pszBuffer -> buffer to hold the formatted string
* pfmt -> format record
* pb -> binary data buffer
* pdwOffset -> offset to binary data buffer
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int BinSprintf(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
{
TRACENAME("BINSPRINTF")
int rc = FERR_NONE;
ENTER(4, ("BinSprintf(fmt=%d,Offset=%lx)\n", pfmt->bFmtType, *pdwOffset));
if (pfmt->bFmtType >= NUM_FMT_FUNCS)
rc = FERR_INVALID_FORMAT;
else
{
int i;
BYTE j;
DWORD dwData;
*pszBuffer = '\0';
for (i = 0; (rc == FERR_NONE) && (i < pfmt->iRepeatCnt); ++i)
{
if (pfmt->dwfFormat & FMTF_PRINT_OFFSET)
{
SPRINTF(pszBuffer,
pfmt->pszOffsetFmt? pfmt->pszOffsetFmt: szDefOffsetFmt,
*pdwOffset);
}
if (!(pfmt->dwfFormat & FMTF_NO_PRINT_DATA) &&
(GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData) ==
FERR_NONE))
{
PrintData(pszBuffer, pfmt->bUnitSize, dwData, FALSE);
STRCAT(pszBuffer, ";");
}
if (pfmt->pszLabel)
STRCAT(pszBuffer, pfmt->pszLabel);
for (j = 0; (rc == FERR_NONE) && (j < pfmt->bUnitCnt); ++j)
{
rc = (*FmtFuncTable[pfmt->bFmtType])
(&pszBuffer[STRLEN(pszBuffer)], pfmt, pb, pdwOffset);
if (rc == FERR_NONE)
{
if (!(pfmt->dwfFormat & FMTF_NO_SEP))
{
STRCAT(pszBuffer,
pfmt->pszFieldSep? pfmt->pszFieldSep: szDefSep);
}
if (!(pfmt->dwfFormat & FMTF_NO_INC_OFFSET))
*pdwOffset += pfmt->bUnitSize;
}
}
if ((rc == FERR_NONE) && !(pfmt->dwfFormat & FMTF_NO_EOL))
{
STRCAT(pszBuffer, "\n");
}
}
}
EXIT(4, ("BinSprintf=%d (Offset=%lx,Buff=%s)\n",
rc, *pdwOffset, pszBuffer));
return rc;
} //BinSprintf
/***LP FormatNum - Format numbers
*
* ENTRY
* pszBuffer -> buffer to hold formatted string
* pfmt -> format record
* pb -> binary data buffer
* pdwOffset -> offset to binary data buffer
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int FormatNum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
{
TRACENAME("FORMATNUM")
int rc;
PFMTNUM pfmtNum = (PFMTNUM)pfmt;
DWORD dwData;
ENTER(5, ("FormatNum(Offset=%lx)\n", *pdwOffset));
if ((rc = GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData)) == FERR_NONE)
{
dwData &= pfmtNum->dwMask;
dwData >>= pfmtNum->bShiftCnt;
SPRINTF(&pszBuffer[STRLEN(pszBuffer)], pfmtNum->pszNumFmt, dwData);
}
EXIT(5, ("FormatNum=%d (Offset=%lx,Buff=%s)\n",
rc, *pdwOffset, pszBuffer));
return rc;
} //FormatNum
/***LP FormatEnum - Format enumerated values
*
* ENTRY
* pszBuffer -> buffer to hold formatted string
* pfmt -> format record
* pb -> binary data buffer
* pdwOffset -> offset to binary data buffer
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int FormatEnum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
{
TRACENAME("FORMATENUM")
int rc = FERR_NONE;
PFMTENUM pfmtEnum = (PFMTENUM)pfmt;
DWORD dwData;
ENTER(5, ("FormatEnum(Offset=%lx)\n", *pdwOffset));
if ((rc = GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData)) == FERR_NONE)
{
dwData &= pfmtEnum->dwMask;
dwData >>= pfmtEnum->bShiftCnt;
if ((dwData < pfmtEnum->dwStartEnum) || (dwData > pfmtEnum->dwEndEnum))
STRCAT(pszBuffer, pfmtEnum->pszOutOfRange);
else
{
dwData -= pfmtEnum->dwStartEnum;
STRCAT(pszBuffer, pfmtEnum->ppszEnumNames[dwData]);
}
}
EXIT(5, ("FormatEnum=%d (Offset=%lx,Buff=%s)\n",
rc, *pdwOffset, pszBuffer));
return rc;
} //FormatEnum
/***LP FormatBits - Format bit values
*
* ENTRY
* pszBuffer -> buffer to hold formatted string
* pfmt -> format record
* pb -> binary data buffer
* pdwOffset -> offset to binary data buffer
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int FormatBits(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
{
TRACENAME("FORMATBITS")
int rc = FERR_NONE;
PFMTBITS pfmtBits = (PFMTBITS)pfmt;
DWORD dwData;
ENTER(5, ("FormatBits(Offset=%lx)\n", *pdwOffset));
if ((rc = GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData)) == FERR_NONE)
{
int i, j;
DWORD dw;
for (i = 31, j = 0; i >= 0; --i)
{
dw = 1L << i;
if (pfmtBits->dwMask & dw)
{
if (dwData & dw)
{
if ((pfmtBits->ppszOnNames != NULL) &&
(pfmtBits->ppszOnNames[j] != NULL))
{
STRCAT(pszBuffer, pfmtBits->ppszOnNames[j]);
}
}
else
{
if ((pfmtBits->ppszOffNames != NULL) &&
(pfmtBits->ppszOffNames[j] != NULL))
{
STRCAT(pszBuffer, pfmtBits->ppszOffNames[j]);
}
}
if (!(pfmt->dwfFormat & FMTF_NO_SEP))
{
STRCAT(pszBuffer,
pfmt->pszFieldSep? pfmt->pszFieldSep: szDefSep);
}
j++;
}
}
}
EXIT(5, ("FormatBits=%d (Offset=%lx,Buff=%s)\n",
rc, *pdwOffset, pszBuffer));
return rc;
} //FormatBits
/***LP FormatString - Format string data
*
* ENTRY
* pszBuffer -> buffer to hold formatted string
* pfmt -> format record
* pb -> binary data buffer
* pdwOffset -> offset to binary data buffer
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int FormatString(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
{
TRACENAME("FORMATSTRING")
int rc = FERR_NONE;
ENTER(5, ("FormatString(Offset=%lx)\n", *pdwOffset));
pb += *pdwOffset;
if (pfmt->dwfFormat & FMTF_STR_ASCIIZ)
{
pszBuffer[0] = '"';
STRCPY(pszBuffer + 1, (char *)pb);
pszBuffer[STRLEN(pszBuffer)] = '"';
if ((pfmt->bUnitSize == 0) && !(pfmt->dwfFormat & FMTF_NO_INC_OFFSET))
*pdwOffset += STRLEN((char *)pb) + 3;
}
else if (pfmt->bUnitSize != 0)
{
if (isalnum(*pb) || (*pb == ' '))
{
pszBuffer[0] = '\'';
STRCPYN(pszBuffer + 1, (char *)pb, pfmt->bUnitSize);
pszBuffer[pfmt->bUnitSize + 1] = '\'';
pszBuffer[pfmt->bUnitSize + 2] = '\0';
}
else
{
rc = PrintData(pszBuffer, pfmt->bUnitSize, *((PDWORD)pb), FALSE);
}
}
EXIT(5, ("FormatString=%d (Offset=%lx,Buff=%s)\n",
rc, *pdwOffset, pszBuffer));
return rc;
} //FormatString
/***LP GetData - Get data of appropriate size from the binary buffer
*
* ENTRY
* bUnitSize - size of data unit
* pb -> data buffer
* dwOffset - offset into data buffer
* pdwData -> to hold data
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int GetData(BYTE bUnitSize, BYTE *pb, DWORD dwOffset, DWORD *pdwData)
{
TRACENAME("GETDATA")
int rc = FERR_NONE;
ENTER(6, ("GetData(UnitSize=%d,Data=%lx,Offset=%lx)\n",
bUnitSize, *(DWORD *)pb, dwOffset));
pb += dwOffset;
switch (bUnitSize)
{
case UNIT_BYTE:
*pdwData = (DWORD)(*pb);
break;
case UNIT_WORD:
*pdwData = (DWORD)(*((WORD *)pb));
break;
case UNIT_DWORD:
*pdwData = *(DWORD *)pb;
break;
default:
rc = FERR_INVALID_UNITSIZE;
}
EXIT(6, ("GetData=%d (Data=%lx)\n", rc, *pdwData));
return rc;
} //GetData
/***LP PrintData - Print data value according to its size
*
* ENTRY
* pszBuffer -> buffer to hold formatted string
* bUnitSize - size of data unit
* dwData - number
* fPadSpace - if TRUE pad space to 8 chars
*
* EXIT-SUCCESS
* returns FERR_NONE
* EXIT-FAILURE
* returns negative error code
*/
int PrintData(char *pszBuffer, BYTE bUnitSize, DWORD dwData, BOOL fPadSpace)
{
TRACENAME("PRINTDATA")
int rc = FERR_NONE;
ENTER(6, ("PrintData(UnitSize=%d,Data=%lx)\n", bUnitSize, dwData));
switch (bUnitSize)
{
case UNIT_BYTE:
SPRINTF(pszBuffer, "%02x", (BYTE)dwData);
if (fPadSpace)
STRCAT(pszBuffer, " ");
break;
case UNIT_WORD:
SPRINTF(pszBuffer, "%04x", (WORD)dwData);
if (fPadSpace)
STRCAT(pszBuffer, " ");
break;
case UNIT_DWORD:
SPRINTF(pszBuffer, "%08lx", dwData);
break;
default:
rc = FERR_INVALID_UNITSIZE;
}
EXIT(6, ("PrintData=%d (Buff=%s)\n", rc, pszBuffer));
return rc;
} //PrintData
#endif //ifdef __UNASM