504 lines
15 KiB
C
504 lines
15 KiB
C
//////////////////////////////////////////////////////////////////////////////
|
|
// ppm2pps
|
|
//
|
|
// Copyright (c) 1996-1999 Microsoft Corporation
|
|
//
|
|
// Dump contents of ppm file
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <imagehlp.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "gen.h"
|
|
|
|
// string to put in front of all error messages so that BUILD can find them.
|
|
const char *ErrMsgPrefix = "NMAKE : U8603: 'PPM2PPS' ";
|
|
|
|
//
|
|
// global variables
|
|
BOOL fDebug; // global debug flag
|
|
BOOL fDumpCCheck; // when set build ppswind.h for checking sizes/offsets
|
|
HANDLE hFile;
|
|
HANDLE hMapFile = NULL;
|
|
|
|
PRBTREE pFunctions = NULL;
|
|
PRBTREE pStructures = NULL;
|
|
PRBTREE pTypedefs = NULL;
|
|
PKNOWNTYPES NIL = NULL;
|
|
|
|
// function prototypes
|
|
void __cdecl ErrMsg(char *pch, ...);
|
|
void __cdecl ExitErrMsg(BOOL bSysError, char *pch, ...);
|
|
BOOL DumpTypedefs(FILE *filePpsfile, // file to write output
|
|
BOOL fDumpNamedOnly, // when set don't do unnamed
|
|
PRBTREE pHead); // known types function list
|
|
BOOL DumpStructures(FILE *filePpsfile, // file to write output
|
|
BOOL fDumpNamedOnly, // when set don't do unnamed
|
|
PRBTREE pHead); // known types function list
|
|
BOOL DumpFunctions(FILE *filePpsfile, // file to write output
|
|
BOOL fDumpNamedOnly, // when set don't do unnamed
|
|
PRBTREE pHead); // known types function list
|
|
void Usage(char *s);
|
|
BOOL ParseArguments(int argc, char *argv[], char *sPpmfile, char *sPpsfile,
|
|
BOOL *pfDumpNamedOnly, BOOL *pfDebug,
|
|
BOOL *pfDumpCCheck);
|
|
BOOL DumpCCheckHeader(PRBTREE pTypedefs, // typedef lsit
|
|
PRBTREE pStructs); // structs sit
|
|
|
|
|
|
int __cdecl main(int argc, char *argv[])
|
|
{
|
|
void *pvPpmData = NULL;
|
|
BOOL fDumpNamedOnly;
|
|
char sPpmfile[MAX_PATH];
|
|
char sPpsfile[MAX_PATH];
|
|
FILE *pfilePpsfile;
|
|
|
|
try {
|
|
|
|
if (! ParseArguments(argc, argv, sPpmfile, sPpsfile,
|
|
&fDumpNamedOnly, &fDebug, &fDumpCCheck))
|
|
{
|
|
Usage(argv[0]);
|
|
return(-1);
|
|
}
|
|
|
|
if (*sPpmfile)
|
|
{
|
|
PCVMHEAPHEADER pHeader;
|
|
|
|
pvPpmData = MapPpmFile(sPpmfile, TRUE);
|
|
|
|
pHeader = (PCVMHEAPHEADER)pvPpmData;
|
|
|
|
pFunctions = &pHeader->FuncsList;
|
|
pTypedefs = &pHeader->TypeDefsList;
|
|
pStructures =&pHeader->StructsList;
|
|
NIL =&pHeader->NIL;
|
|
|
|
pfilePpsfile = fopen(sPpsfile, "w");
|
|
if (pfilePpsfile == 0)
|
|
{
|
|
ErrMsg("ERROR - Could not open output file %s\n", sPpsfile);
|
|
CloseHandle(hFile);
|
|
CloseHandle(hMapFile);
|
|
return(-1);
|
|
}
|
|
|
|
if (DumpFunctions(pfilePpsfile, fDumpNamedOnly,
|
|
pFunctions))
|
|
{
|
|
if (DumpStructures(pfilePpsfile, fDumpNamedOnly,
|
|
pStructures))
|
|
{
|
|
DumpTypedefs(pfilePpsfile,fDumpNamedOnly, pTypedefs);
|
|
}
|
|
}
|
|
fclose(pfilePpsfile);
|
|
}
|
|
|
|
if (fDumpCCheck && pTypedefs && pStructures)
|
|
{
|
|
DumpCCheckHeader(pTypedefs, pStructures);
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
CloseHandle(hMapFile);
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
ExitErrMsg(FALSE,
|
|
"ExceptionCode=%x\n",
|
|
GetExceptionCode()
|
|
);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
void
|
|
DumpFuncinfo(FILE *pfilePpsfile, PFUNCINFO pf)
|
|
{
|
|
while (pf) {
|
|
int i;
|
|
|
|
fprintf(pfilePpsfile,
|
|
"%s %s%s %s %s %s",
|
|
TokenString[pf->tkDirection],
|
|
(pf->fIsPtr64) ? "__ptr64 " : "",
|
|
TokenString[pf->tkPreMod],
|
|
TokenString[pf->tkSUE],
|
|
pf->sType,
|
|
TokenString[pf->tkPrePostMod]
|
|
);
|
|
i = pf->IndLevel;
|
|
while (i--) {
|
|
fprintf(pfilePpsfile, "*");
|
|
}
|
|
fprintf(pfilePpsfile,
|
|
"%s %s",
|
|
TokenString[pf->tkPostMod],
|
|
(pf->sName) ? pf->sName : ""
|
|
);
|
|
|
|
pf = pf->pfuncinfoNext;
|
|
if (pf) {
|
|
fprintf(pfilePpsfile, ", ");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DumpCCheckHeader
|
|
//
|
|
// dump header file that can be used to check sizes in ppm file against
|
|
// those that are generated by C
|
|
//
|
|
// returns TRUE on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL DumpCCheckHeader(PRBTREE pTypedefs, // typedef lsit
|
|
PRBTREE pStructs) // structs lsit
|
|
|
|
{
|
|
PKNOWNTYPES pknwntyp, pknwntypBasic;
|
|
FILE *pfile;
|
|
|
|
pfile = fopen("ppswind.h", "w");
|
|
if (pfile == NULL)
|
|
{
|
|
ErrMsg("Error opening ppwind.h for output\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
fprintf(pfile, "CCHECKSIZE cchecksize[] = {\n");
|
|
|
|
//
|
|
// typedefs
|
|
pknwntyp = pTypedefs->pLastNodeInserted;
|
|
|
|
while (pknwntyp) {
|
|
if ((! isdigit(*pknwntyp->TypeName)) &&
|
|
(strcmp(pknwntyp->TypeName,"...")) &&
|
|
(strcmp(pknwntyp->TypeName,"()")) &&
|
|
(strcmp(pknwntyp->BasicType, szFUNC)) &&
|
|
(pknwntyp->Size > 0) &&
|
|
(pknwntyp->dwScopeLevel == 0)) {
|
|
|
|
pknwntypBasic = GetBasicType(pknwntyp->TypeName,
|
|
pTypedefs, pStructs);
|
|
|
|
if (! ( (pknwntypBasic == NULL) ||
|
|
( (! strcmp(pknwntypBasic->BaseName, szVOID)) &&
|
|
(pknwntypBasic->pmeminfo == NULL)))) {
|
|
|
|
fprintf(pfile, " { %4d, sizeof(%s), \"%s\"}, \n",
|
|
pknwntyp->Size,
|
|
pknwntyp->TypeName,
|
|
pknwntyp->TypeName);
|
|
}
|
|
}
|
|
pknwntyp = pknwntyp->Next;
|
|
}
|
|
|
|
|
|
//
|
|
// structs
|
|
pknwntyp = pStructs->pLastNodeInserted;
|
|
|
|
while (pknwntyp) {
|
|
if ((! isdigit(*pknwntyp->TypeName) &&
|
|
(pknwntyp->pmeminfo)))
|
|
{
|
|
if (!(pknwntyp->Flags & BTI_ANONYMOUS) && (pknwntyp->Size > 0) && (pknwntyp->dwScopeLevel == 0)) {
|
|
fprintf(pfile, " { %4d, sizeof(%s %s), \"%s %s\" }, \n",
|
|
pknwntyp->Size,
|
|
pknwntyp->BaseName,
|
|
pknwntyp->TypeName,
|
|
pknwntyp->BaseName,
|
|
pknwntyp->TypeName);
|
|
}
|
|
}
|
|
pknwntyp = pknwntyp->Next;
|
|
}
|
|
|
|
fprintf(pfile, " {0xffffffff, 0xffffffff, \"\"}\n");
|
|
fprintf(pfile,"\n};\n");
|
|
|
|
//
|
|
// structs fields
|
|
fprintf(pfile, "CCHECKOFFSET ccheckoffset[] = {\n");
|
|
|
|
pknwntyp = pStructs->pLastNodeInserted;
|
|
|
|
while (pknwntyp) {
|
|
if (! isdigit(*pknwntyp->TypeName))
|
|
{
|
|
if (!(pknwntyp->Flags & BTI_ANONYMOUS) && !(pknwntyp->Flags & BTI_VIRTUALONLY) && (pknwntyp->Size > 0) && (pknwntyp->dwScopeLevel == 0)) {
|
|
PMEMBERINFO pmeminfo = pknwntyp->pmeminfo;
|
|
while (pmeminfo != NULL) {
|
|
if ((pmeminfo->sName != NULL) && (*pmeminfo->sName != 0) && !(pmeminfo->bIsBitfield))
|
|
{
|
|
fprintf(pfile, " { %4d, (long) (& (((%s %s *)0)->%s)), \"%s\", \"%s\" },\n",
|
|
pmeminfo->dwOffset,
|
|
pknwntyp->BaseName,
|
|
pknwntyp->TypeName,
|
|
pmeminfo->sName,
|
|
pknwntyp->TypeName,
|
|
pmeminfo->sName);
|
|
}
|
|
pmeminfo = pmeminfo->pmeminfoNext;
|
|
}
|
|
|
|
}
|
|
}
|
|
pknwntyp = pknwntyp->Next;
|
|
}
|
|
|
|
fprintf(pfile, " {0xffffffff, 0xffffffff, \"\", \"\"}\n");
|
|
fprintf(pfile,"\n};\n");
|
|
fclose(pfile);
|
|
return(TRUE);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DumpTypedefs
|
|
//
|
|
// dump structures from ppm file to output file
|
|
//
|
|
// returns TRUE on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL DumpTypedefs(FILE *pfilePpsfile, // file to write output
|
|
BOOL fDumpNamedOnly, // when set don't do unnamed
|
|
PRBTREE pHead) // known types function list
|
|
{
|
|
KNOWNTYPES *pknwntyp;
|
|
|
|
pknwntyp = pHead->pLastNodeInserted;
|
|
|
|
fprintf(pfilePpsfile,"[Typedefs]\n\n");
|
|
while (pknwntyp) {
|
|
fprintf(pfilePpsfile,
|
|
"%2.1x|%2.1x|%2.1x|%s|%s|%s|%s|%s|",
|
|
pknwntyp->Flags,
|
|
pknwntyp->IndLevel,
|
|
pknwntyp->Size,
|
|
pknwntyp->BasicType,
|
|
pknwntyp->BaseName ? pknwntyp->BaseName : szNULL,
|
|
pknwntyp->FuncRet ? pknwntyp->FuncRet : szNULL,
|
|
pknwntyp->FuncMod ? pknwntyp->FuncMod : szNULL,
|
|
pknwntyp->TypeName
|
|
);
|
|
DumpFuncinfo(pfilePpsfile, pknwntyp->pfuncinfo);
|
|
fprintf(pfilePpsfile, "|\n");
|
|
|
|
pknwntyp = pknwntyp->Next;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DumpStructures
|
|
//
|
|
// dump structures from ppm file to output file
|
|
//
|
|
// returns TRUE on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL DumpStructures(FILE *pfilePpsfile, // file to write output
|
|
BOOL fDumpNamedOnly, // when set don't do unnamed
|
|
PRBTREE pHead) // known types function list
|
|
{
|
|
KNOWNTYPES *pknwntyp;
|
|
DWORD dw;
|
|
PMEMBERINFO pmeminfo;
|
|
|
|
pknwntyp = pHead->pLastNodeInserted;
|
|
|
|
fprintf(pfilePpsfile,"[Structures]\n\n");
|
|
while (pknwntyp) {
|
|
if (! fDumpNamedOnly || ! isdigit(*pknwntyp->TypeName)) {
|
|
fprintf(pfilePpsfile,
|
|
"%2.1x|%2.1x|%2.1x|%s|%s|%s|%s|%s|",
|
|
pknwntyp->Flags,
|
|
pknwntyp->IndLevel,
|
|
pknwntyp->Size,
|
|
pknwntyp->BasicType,
|
|
pknwntyp->BaseName ? pknwntyp->BaseName : szNULL,
|
|
pknwntyp->FuncRet ? pknwntyp->FuncRet : szNULL,
|
|
pknwntyp->FuncMod ? pknwntyp->FuncMod : szNULL,
|
|
pknwntyp->TypeName);
|
|
|
|
// dump out the structure member info, if present
|
|
pmeminfo = pknwntyp->pmeminfo;
|
|
while (pmeminfo) {
|
|
int i;
|
|
|
|
fprintf(pfilePpsfile, "%s", pmeminfo->sType);
|
|
i = pmeminfo->IndLevel;
|
|
if (i) {
|
|
fprintf(pfilePpsfile, " ");
|
|
while (i--) {
|
|
fprintf(pfilePpsfile, "*");
|
|
}
|
|
}
|
|
if (pmeminfo->sName) {
|
|
fprintf(pfilePpsfile, " %s", pmeminfo->sName);
|
|
}
|
|
fprintf(pfilePpsfile, " @ %d|", pmeminfo->dwOffset);
|
|
pmeminfo = pmeminfo->pmeminfoNext;
|
|
}
|
|
|
|
// dump out the function info, if present
|
|
DumpFuncinfo(pfilePpsfile, pknwntyp->pfuncinfo);
|
|
|
|
fprintf(pfilePpsfile, "\n");
|
|
}
|
|
|
|
pknwntyp = pknwntyp->Next;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DumpFunctions
|
|
//
|
|
// dump fucntion prototypes from ppm file to output file
|
|
//
|
|
// returns TRUE on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL DumpFunctions(FILE *pfilePpsfile, // file to write output
|
|
BOOL fDumpNamedOnly, // when set don't do unnamed
|
|
PRBTREE pHead) // known types function list
|
|
{
|
|
KNOWNTYPES *pknwntyp;
|
|
PFUNCINFO pf;
|
|
|
|
pknwntyp = pHead->pLastNodeInserted;
|
|
|
|
fprintf(pfilePpsfile,"[Functions]\n\n");
|
|
while (pknwntyp) {
|
|
fprintf(pfilePpsfile,
|
|
"%s|%s|%s|%s|",
|
|
(pknwntyp->Flags & BTI_DLLEXPORT) ? "dllexport" : "",
|
|
pknwntyp->FuncRet,
|
|
pknwntyp->FuncMod ? pknwntyp->FuncMod : szNULL,
|
|
pknwntyp->TypeName
|
|
);
|
|
DumpFuncinfo(pfilePpsfile, pknwntyp->pfuncinfo);
|
|
fprintf(pfilePpsfile, "|\n");
|
|
pknwntyp = pknwntyp->Next;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Usgae
|
|
//
|
|
// tells how to use
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Usage(char *s) // name of command invoked
|
|
{
|
|
printf("Usage:\n");
|
|
printf(" %s -d -n -x <ppm file> <pps output file>\n", s);
|
|
printf(" -d set debug flag\n");
|
|
printf(" -n dumps only named structs/enums/unions\n");
|
|
printf(" -x creates ppswind.h for size/offset checking\n");
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ParseArgumaners
|
|
//
|
|
// parse arguments
|
|
//
|
|
// returnms FALSE on syntax error
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL ParseArguments(int argc, char *argv[], char *sPpmfile, char *sPpsfile,
|
|
BOOL *pfDumpNamedOnly, BOOL *pfDebug,
|
|
BOOL *pfDumpCCheck)
|
|
{
|
|
int i;
|
|
|
|
*sPpmfile = 0;
|
|
*sPpsfile = 0;
|
|
*pfDumpNamedOnly = FALSE;
|
|
*pfDebug = FALSE;
|
|
*pfDumpCCheck = FALSE;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (*argv[i] == '-')
|
|
{
|
|
switch(tolower(argv[i][1]))
|
|
{
|
|
case 'd':
|
|
{
|
|
*pfDebug = TRUE;
|
|
break;
|
|
}
|
|
|
|
case 'n':
|
|
{
|
|
*pfDumpNamedOnly = TRUE;
|
|
break;
|
|
}
|
|
|
|
case 'x':
|
|
{
|
|
*pfDumpCCheck = TRUE;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
} else {
|
|
if (lstrlenA(argv[i]) >= MAX_PATH)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
if (*sPpmfile == 0)
|
|
{
|
|
strcpy(sPpmfile, argv[i]);
|
|
} else if (*sPpsfile == 0)
|
|
{
|
|
strcpy(sPpsfile, argv[i]);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
return( *pfDumpCCheck || ((*sPpmfile != 0) && (*sPpsfile != 0)));
|
|
}
|
|
|
|
void
|
|
HandlePreprocessorDirective(
|
|
char *p
|
|
)
|
|
{
|
|
ExitErrMsg(FALSE, "Preprocessor directives not allowed by ppm2pps\n");
|
|
}
|