700 lines
18 KiB
C
700 lines
18 KiB
C
|
|
/*
|
|
* Module Name: WSPDUMP.C
|
|
*
|
|
* Program: WSPDUMP
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
* Dumps the contents of a WSP file.
|
|
*
|
|
* Contitional compilation notes:
|
|
*
|
|
* Modification History:
|
|
*
|
|
* 6-12-92: Adapted OS/2 version of wspdump for NT marklea
|
|
* 6-17-92: Modified wspDumpBits to dump in correct order marklea
|
|
* 6-18-92: Added page useage information marklea
|
|
* 8-31-92: Made single exe from wspdump, wsreduce and wstune marklea
|
|
* 4-13-98: QFE DerrickG (mdg):
|
|
* - new WSP file format for large symbol counts (ULONG vs. USHORT)
|
|
* - support for long file names (LFN) of input/output files
|
|
* - removed buggy reference to WSDIR env. variable
|
|
* - based .TMI file name exclusively on .WSP name for consistency
|
|
* - removed limit on symbol name lengths - return allocated name from WsTMIReadRec()
|
|
* - removed unused static declarations
|
|
*
|
|
*/
|
|
|
|
#include "wstune.h"
|
|
|
|
/*
|
|
* Global variable declaration and initialization.
|
|
*/
|
|
|
|
typedef struct fxn_t{
|
|
CHAR *pszFxnName;
|
|
ULONG cbFxn;
|
|
ULONG ulTmiIndex;
|
|
ULONG ulOrigIndex;
|
|
}FXN;
|
|
typedef FXN *PFXN;
|
|
|
|
/*
|
|
* Function prototypes.
|
|
*/
|
|
|
|
static VOID wspDumpSetup( VOID );
|
|
static VOID wspDumpRandom( VOID );
|
|
static UINT wspDumpBits( VOID );
|
|
static VOID wspDumpExit( UINT, USHORT, UINT, ULONG, PSZ );
|
|
static void wspDumpCleanup( void );
|
|
static VOID wspDumpSeq(VOID);
|
|
static int __cdecl wspCompare(const void *fxn1, const void *fxn2);
|
|
|
|
|
|
|
|
static CHAR *szFileWSP = NULL; // WSP file name
|
|
static CHAR *szFileTMI = NULL; // TMI file name
|
|
static CHAR *szFileWSR = NULL; // WSR file name
|
|
static CHAR *szDatFile = NULL; // DAT file name
|
|
|
|
|
|
static ULONG rc = NO_ERROR; // Return code
|
|
static ULONG ulTmp; // Temp variable for Dos API returns
|
|
static ULONG ulFxnIndex; // Original index in symbol table
|
|
static FILE *hFileWSP; // Input WSP file handle
|
|
static FILE *hFileTMI; // Input TMI file handle
|
|
static FILE *hFileDAT; // Data file for dump
|
|
static wsphdr_t WspHdr; // Input WSP file header
|
|
static BOOL fRandom = FALSE; // Flag for random mode
|
|
static BOOL fVerbose = FALSE; // Flag for verbose mode
|
|
static ULONG ulFxnTot = 0; // Total number of functions
|
|
static ULONG clVarTot = 0; // Total number of dwords in bitstr
|
|
static ULONG *pulFxnBitstring; // Function bitstring
|
|
static ULONG ulSetSym = 0; // Number of symbols set // mdg 4/98
|
|
static BOOL fDatFile = FALSE;
|
|
|
|
/*
|
|
* Procedure wspDumpMain
|
|
*
|
|
*
|
|
***
|
|
* Effects:
|
|
*
|
|
* Constructs .WSP and .TMI input names from input basefile name. If szDatExt is
|
|
* not NULL, appends it to szBaseFile to create output data file name. If fRandom,
|
|
* constructs a .WSR output file. If fVerbose, adds extra output to data file.
|
|
*
|
|
* Processes the input files and displays the function reference data
|
|
* for each function in the specified module WSP file.
|
|
*
|
|
*/
|
|
BOOL wspDumpMain( CHAR *szBaseFile, CHAR *szDatExt, BOOL fRndm, BOOL fVbose )
|
|
{
|
|
size_t c;
|
|
char * pSlash;
|
|
|
|
fRandom = fRndm;
|
|
fVerbose = fVbose;
|
|
// mdg 98/4 Allocate space for filenames - don't use static buffers
|
|
c = 5 + strlen( szBaseFile ); // Length to allocate for filenames
|
|
szFileWSP = malloc( c );
|
|
if (szFileWSP) {
|
|
strcat( strcpy( szFileWSP, szBaseFile ), ".WSP" );
|
|
} else {
|
|
return (1);
|
|
}
|
|
szFileTMI = malloc( c );
|
|
if (szFileTMI) {
|
|
strcat( strcpy( szFileTMI, szBaseFile ), ".TMI" );
|
|
} else {
|
|
free(szFileWSP);
|
|
return (1);
|
|
}
|
|
|
|
// Create output file in current directory
|
|
if (NULL != (pSlash = strrchr( szBaseFile, '\\' ))
|
|
|| NULL != (pSlash = strrchr( szBaseFile, '/' ))
|
|
|| NULL != (pSlash = strrchr( szBaseFile, ':' )))
|
|
{
|
|
c = strlen( ++pSlash ) + 5;
|
|
} else
|
|
pSlash = szBaseFile;
|
|
|
|
if (fRandom) {
|
|
szFileWSR = malloc( c );
|
|
if (szFileWSR) {
|
|
strcat( strcpy( szFileWSR, pSlash ), ".WSR" );
|
|
} else {
|
|
free(szFileTMI);
|
|
free(szFileWSP);
|
|
return (1);
|
|
}
|
|
}
|
|
if (szDatExt != NULL) {
|
|
fDatFile = TRUE;
|
|
szDatFile = malloc( c - 4 + strlen( szDatExt ) );
|
|
if (szDatFile) {
|
|
strcat( strcpy( szDatFile, pSlash ), szDatExt );
|
|
} else {
|
|
free(szFileWSR);
|
|
free(szFileTMI);
|
|
free(szFileWSP);
|
|
return (1);
|
|
}
|
|
} else {
|
|
fDatFile = FALSE;
|
|
szDatFile = "";
|
|
}
|
|
|
|
// Setup input files for dump processing.
|
|
wspDumpSetup();
|
|
|
|
/* Print the WSP file info, either randomly (based on WSR file
|
|
* input) or sequentially (the default).
|
|
*/
|
|
if (fRandom == TRUE)
|
|
wspDumpRandom();
|
|
else
|
|
wspDumpSeq();
|
|
|
|
wspDumpCleanup();
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
/*
|
|
*
|
|
***LP wspDumpSetup
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
* Opens the module's WSP and TMI input files, seeks to the start of the
|
|
* first function's bitstring data in the WSP file, and allocates memory
|
|
* to hold one function's bitstring.
|
|
*
|
|
* Returns:
|
|
*
|
|
* Void. If an error is encountered, exits through wspDumpExit()
|
|
* with ERROR.
|
|
*
|
|
*/
|
|
|
|
VOID
|
|
wspDumpSetup()
|
|
{
|
|
CHAR szLineTMI[MAXLINE]; // Line from TMI file
|
|
|
|
if(fDatFile){
|
|
hFileDAT = fopen (szDatFile, "wt");
|
|
if (hFileDAT == NULL) {
|
|
printf("Error creating file %s, will send output to stdout.\n",
|
|
szDatFile);
|
|
hFileDAT = stdout;
|
|
}
|
|
}
|
|
else hFileDAT = stdout;
|
|
|
|
/* Open input WSP file. Read and validate WSP file header.*/
|
|
|
|
rc = WsWSPOpen(szFileWSP, &hFileWSP,(PFN)wspDumpExit,&WspHdr,ERROR,PRINT_MSG);
|
|
ulSetSym = WspHdr.wsphdr_dtqo.dtqo_SymCnt;
|
|
clVarTot = WspHdr.wsphdr_ulSnaps;
|
|
fprintf(stdout, "\n%s: Set symbol count=%lu - Segment size=%ld\n", // mdg 4/98
|
|
szDatFile, WspHdr.wsphdr_dtqo.dtqo_SymCnt,
|
|
WspHdr.wsphdr_dtqo.dtqo_clSegSize);
|
|
|
|
|
|
/* Open TMI file (contains function names, obj:offset, size, etc.).
|
|
* Verify that the TMI file identifier matches the module
|
|
* identifier from the WSP file.
|
|
*/
|
|
ulFxnTot = WsTMIOpen(szFileTMI, &hFileTMI, (PFN) wspDumpExit,
|
|
0, (PCHAR)0);
|
|
|
|
|
|
if (!fseek(hFileTMI, 0L, SEEK_SET)) {
|
|
return;
|
|
}
|
|
fgets(szLineTMI, MAXLINE, hFileTMI);
|
|
|
|
/* Print module header information for output file */
|
|
szLineTMI[strlen(szLineTMI)-1] = '\0';
|
|
|
|
fprintf(hFileDAT,"\nDUMP OF FUNCTION REFERENCES FOR '%s':\n\n",szLineTMI);
|
|
|
|
fclose (hFileTMI);
|
|
ulFxnTot = WsTMIOpen(szFileTMI, &hFileTMI, (PFN) wspDumpExit,
|
|
0, (PCHAR)0);
|
|
|
|
/* Allocate memory to hold one function's entire bitstring. */
|
|
|
|
pulFxnBitstring = (ULONG *) malloc(clVarTot * sizeof(ULONG));
|
|
if (pulFxnBitstring == NULL)
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_NO_MEM,
|
|
clVarTot * sizeof(ULONG), "pulFxnBitstring[]");
|
|
}
|
|
|
|
/*
|
|
*
|
|
***LP wspDumpSeq
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
* For each function, prints the bitstring in ASCII form.
|
|
*
|
|
* Returns:
|
|
*
|
|
* Void. If an error is encountered, exits through wspDumpExit()
|
|
* with ERROR.
|
|
*
|
|
*/
|
|
|
|
VOID wspDumpSeq(VOID)
|
|
{
|
|
UINT uiFxn = 0; // Function number
|
|
UINT cTouched=0; // Count of touched pages
|
|
BOOL fTouched=0; // Flag to indicate page is touched. // mdg 4/98
|
|
UINT i=0; // Generic counter
|
|
ULONG cbFxnCum =0; // Cumulative function sizes
|
|
PFXN Fxn; // pointer to array of fxn name ptrs
|
|
FILE *fpFileWSR = NULL; // WSR file pointer
|
|
ULONG cbFBits = 0; // Count of bytes in bitstring
|
|
UINT uiPageCount=0; // Pages touched.
|
|
ULONG ulMaxBytes=0; // Bytes of touched pages.
|
|
|
|
|
|
/* Allocate memory for function names. */
|
|
Fxn = (PFXN) malloc(ulFxnTot * sizeof(FXN));
|
|
if (Fxn == NULL)
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_NO_MEM,
|
|
ulFxnTot * sizeof(FXN), "Fxn[]");
|
|
|
|
WsIndicator( WSINDF_NEW, "Load Functions", ulFxnTot );
|
|
/* Read function names from TMI file. */
|
|
for (uiFxn = 0; uiFxn < ulFxnTot; uiFxn++)
|
|
{
|
|
WsIndicator( WSINDF_PROGRESS, NULL, uiFxn );
|
|
Fxn[uiFxn].cbFxn = WsTMIReadRec(&Fxn[uiFxn].pszFxnName, &ulFxnIndex, &ulTmp, hFileTMI,
|
|
(PFN) wspDumpExit, (PCHAR)0);
|
|
Fxn[uiFxn].ulOrigIndex = ulFxnIndex;
|
|
Fxn[uiFxn].ulTmiIndex = (ULONG)uiFxn;
|
|
|
|
}
|
|
|
|
qsort(Fxn, ulFxnTot, sizeof(FXN), wspCompare);
|
|
WsIndicator( WSINDF_FINISH, NULL, 0 );
|
|
|
|
cbFBits = clVarTot * sizeof(ULONG);
|
|
|
|
WsIndicator( WSINDF_NEW, "Write Data Out", ulFxnTot );
|
|
for (uiFxn = 0; uiFxn < ulFxnTot; uiFxn++)
|
|
{
|
|
|
|
WsIndicator( WSINDF_PROGRESS, NULL, uiFxn );
|
|
/* Seek to function's bitstring in WSP file. */
|
|
if ((rc = fseek(hFileWSP,(WspHdr.wsphdr_ulOffBits+(Fxn[uiFxn].ulTmiIndex*cbFBits)),SEEK_SET))!=NO_ERROR)
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_FILE_OFFSET,
|
|
rc, szFileWSP);
|
|
|
|
fprintf(hFileDAT,"Fxn '%s' (#%d):\n\t", Fxn[uiFxn].pszFxnName, Fxn[uiFxn].ulOrigIndex);
|
|
free(Fxn[uiFxn].pszFxnName); // mdg 98/4: Free allocated name string
|
|
Fxn[uiFxn].pszFxnName = NULL;
|
|
// Print this function's reference bitstring.
|
|
// and if it has had a bit set, set touched flag to true
|
|
|
|
if(wspDumpBits()){
|
|
fTouched |=1;
|
|
ulMaxBytes += Fxn[uiFxn].cbFxn;
|
|
}
|
|
|
|
|
|
fprintf(hFileDAT,"%-28s %10ld bytes.\n","Function size:", Fxn[uiFxn].cbFxn);
|
|
cbFxnCum += Fxn[uiFxn].cbFxn;
|
|
fprintf(hFileDAT,"%-28s %10ld bytes.\n\n","Cumulative function sizes:",
|
|
cbFxnCum);
|
|
|
|
//Checck to see if a 4k page boundry has been reached
|
|
|
|
if(cbFxnCum >= (4096+(4096 * uiPageCount))){
|
|
for(i=0; i < 60; i++){
|
|
fprintf(hFileDAT, "*");
|
|
}
|
|
|
|
fprintf(hFileDAT,"\n\nTotal function sizes has reached or exceeds %d bytes.\n\n",
|
|
(4096+(4096*uiPageCount)));
|
|
++uiPageCount;
|
|
|
|
//Check to see of the page has been touched.
|
|
|
|
if(fTouched){
|
|
fprintf(hFileDAT,"This page has been touched.\n");
|
|
++cTouched;
|
|
}
|
|
else{
|
|
fprintf(hFileDAT,"This page has not been touched.\n");
|
|
}
|
|
fTouched = 0;
|
|
|
|
|
|
for(i=0; i < 60; i++){
|
|
fprintf(hFileDAT, "*");
|
|
}
|
|
fprintf(hFileDAT, "\n\n");
|
|
}
|
|
|
|
}
|
|
++uiPageCount;
|
|
if(fTouched){
|
|
fprintf(hFileDAT,"\n\n");
|
|
for(i=0; i < 70; i++){
|
|
fprintf(hFileDAT, "=");
|
|
}
|
|
++cTouched;
|
|
fprintf(hFileDAT,"\n\nThis page has been touched.");
|
|
}
|
|
fprintf(hFileDAT,"\n\n");
|
|
for(i=0; i < 70; i++){
|
|
fprintf(hFileDAT, "=");
|
|
}
|
|
|
|
fprintf(hFileDAT,"\n\n%-28s %10ld bytes\n\n","Cumulative function size:", cbFxnCum);
|
|
fprintf(hFileDAT,"%-28s %10d bytes\n\n", "Size of functions touched:", ulMaxBytes);
|
|
fprintf(hFileDAT,"%-28s %10d\n\n", "Total page count:", uiPageCount);
|
|
fprintf(hFileDAT,"%-28s %10d\n\n", "Total pages touched:", cTouched);
|
|
|
|
WsIndicator( WSINDF_FINISH, NULL, 0 );
|
|
}
|
|
|
|
/*
|
|
*
|
|
***LP wspDumpBits
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
* Prints a function's reference bitstring (verbose mode only), followed
|
|
* by the sum of the "on" bits.
|
|
*
|
|
* Returns:
|
|
*
|
|
* Void. If an error is encountered, exits through wspDumpExit()
|
|
* with ERROR.
|
|
*
|
|
*/
|
|
|
|
UINT
|
|
wspDumpBits()
|
|
{
|
|
ULONG clVar = 0; // Current dword of bitstring
|
|
UINT uiBit = 0; // Result of bit test (1 or 0)
|
|
UINT cBitsOn; // Count of "on" bits
|
|
ULONG *pulBits; // Pointer to ULONG packets of bits
|
|
CHAR szTmp[33];
|
|
CHAR szBits[33];
|
|
|
|
cBitsOn = 0;
|
|
pulBits = pulFxnBitstring;
|
|
|
|
/* Read next dword of function's bitstring. */
|
|
|
|
szBits[0] = '\0';
|
|
szTmp[0] = '\0';
|
|
for (clVar = 0; clVar < clVarTot; clVar++, pulBits++)
|
|
{
|
|
rc = fread((PVOID)pulBits,
|
|
(ULONG) sizeof(ULONG),1, hFileWSP);
|
|
if(rc == 1)
|
|
rc = NO_ERROR;
|
|
else
|
|
rc = 2;
|
|
|
|
|
|
if (rc != NO_ERROR)
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_FILE_READ,
|
|
rc, szFileWSP);
|
|
|
|
if (*pulBits == 0)
|
|
{
|
|
if (fVerbose == TRUE)
|
|
fprintf(hFileDAT,"00000000000000000000000000000000");
|
|
}
|
|
else
|
|
for (uiBit = 0; uiBit < NUM_VAR_BITS; uiBit++)
|
|
{
|
|
|
|
if (*pulBits & 1)
|
|
{
|
|
cBitsOn++;
|
|
if (fVerbose == TRUE){
|
|
strcpy(szTmp,szBits);
|
|
strcpy(szBits,"1");
|
|
strcat(szBits,szTmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fVerbose == TRUE){
|
|
strcpy(szTmp,szBits);
|
|
strcpy(szBits,"0");
|
|
strcat(szBits,szTmp);
|
|
}
|
|
}
|
|
|
|
*pulBits = *pulBits >> 1;
|
|
}
|
|
if (fVerbose == TRUE)
|
|
{
|
|
if ((clVar % 2) != 0){
|
|
fprintf(hFileDAT,"%s",szBits);
|
|
szBits[0]='\0';
|
|
fprintf(hFileDAT,"\n\t");
|
|
}
|
|
else{
|
|
fprintf(hFileDAT,"%s",szBits);
|
|
szBits[0]='\0';
|
|
fprintf(hFileDAT," ");
|
|
}
|
|
}
|
|
}
|
|
fprintf(hFileDAT,"\n\t*** Sum of '1' bits = %ld\n\n", cBitsOn);
|
|
|
|
return(cBitsOn);
|
|
}
|
|
|
|
/*
|
|
*
|
|
***LP wspDumpRandom
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
* For each function ordinal specified in the WSR file, prints the
|
|
* corresponding function's reference bitstring in ASCII form (verbose
|
|
* mode only), followed by a sum of the "on" bits..
|
|
*
|
|
* Returns:
|
|
*
|
|
* Void. If an error is encountered, exits through wspDumpExit()
|
|
* with ERROR.
|
|
*/
|
|
|
|
VOID
|
|
wspDumpRandom()
|
|
{
|
|
UINT uiFxn = 0; // Function number
|
|
UINT cTouched=0; // Count of touched pages
|
|
BOOL fTouched=0; // Flag to indicate page is touched. // mdg 4/98
|
|
UINT i=0; // Generic counter
|
|
ULONG cbFxnCum =0; // Cumulative function sizes
|
|
PFXN Fxn; // pointer to array of fxn name ptrs
|
|
ULONG ulFxnOrd; // function number within module
|
|
FILE *fpFileWSR = NULL; // WSR file pointer
|
|
ULONG cbFBits = 0; // Count of bytes in bitstring
|
|
UINT uiPageCount=0; // Pages touched.
|
|
ULONG ulMaxBytes=0; // Bytes of touched pages.
|
|
|
|
/* Open WSR file (contains function ordinal numbers in ASCII). */
|
|
|
|
if ((fpFileWSR = fopen(szFileWSR, "r")) == NULL)
|
|
{
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_FILE_OPEN, rc, szFileWSR);
|
|
}
|
|
|
|
/* Allocate memory for function names. */
|
|
Fxn = (PFXN) malloc(ulFxnTot * sizeof(FXN));
|
|
if (Fxn == NULL)
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_NO_MEM,
|
|
ulFxnTot * sizeof(FXN), "Fxn[]");
|
|
|
|
WsIndicator( WSINDF_NEW, "Load Functions", ulFxnTot );
|
|
/* Read function names from TMI file. */
|
|
for (uiFxn = 0; uiFxn < ulFxnTot; uiFxn++)
|
|
{
|
|
WsIndicator( WSINDF_PROGRESS, NULL, uiFxn );
|
|
Fxn[uiFxn].cbFxn = WsTMIReadRec(&Fxn[uiFxn].pszFxnName, &ulFxnIndex, &ulTmp, hFileTMI,
|
|
(PFN) wspDumpExit, (PCHAR)0);
|
|
|
|
}
|
|
WsIndicator( WSINDF_FINISH, NULL, 0 );
|
|
|
|
cbFBits = clVarTot * sizeof(ULONG);
|
|
|
|
WsIndicator( WSINDF_NEW, "Write Data Out", ulFxnTot );
|
|
for (uiFxn = 0; uiFxn < ulFxnTot; uiFxn++)
|
|
{
|
|
WsIndicator( WSINDF_PROGRESS, NULL, uiFxn );
|
|
/* Read function number from WSR file. */
|
|
rc = fscanf(fpFileWSR, "%ld\n", &ulFxnOrd);
|
|
if (rc != 1)
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_FILE_READ,
|
|
rc, szFileWSR);
|
|
|
|
/* Seek to function's bitstring in WSP file. */
|
|
if ((rc = fseek(hFileWSP,(WspHdr.wsphdr_ulOffBits+(ulFxnOrd*cbFBits)),SEEK_SET))!=NO_ERROR)
|
|
wspDumpExit(ERROR, PRINT_MSG, MSG_FILE_OFFSET,
|
|
rc, szFileWSP);
|
|
|
|
fprintf(hFileDAT,"Fxn '%s' (#%d):\n\t", Fxn[ulFxnOrd].pszFxnName, ulFxnOrd);
|
|
free(Fxn[ulFxnOrd].pszFxnName); // mdg 98/4: Free allocated name string
|
|
Fxn[ulFxnOrd].pszFxnName = NULL;
|
|
|
|
// Print this function's reference bitstring.
|
|
// and if it has had a bit set, set touched flag to true
|
|
|
|
if(uiFxn < ulSetSym){ // mdg 4/98
|
|
if(wspDumpBits()){
|
|
fTouched |= 1;
|
|
ulMaxBytes += Fxn[ulFxnOrd].cbFxn;
|
|
}
|
|
}
|
|
else{
|
|
fprintf(hFileDAT,"\n\t*** Sum of '1' bits = %ld\n\n", 0L);
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(hFileDAT,"%-28s %10ld bytes.\n","Function size:", Fxn[ulFxnOrd].cbFxn);
|
|
cbFxnCum += Fxn[ulFxnOrd].cbFxn;
|
|
fprintf(hFileDAT,"%-28s %10ld bytes.\n\n","Cumulative function sizes:",
|
|
cbFxnCum);
|
|
|
|
//Check to see if a 4k page boundry has been reached
|
|
|
|
if(cbFxnCum >= (4096+(4096 * uiPageCount))){
|
|
for(i=0; i < 60; i++){
|
|
fprintf(hFileDAT, "*");
|
|
}
|
|
|
|
fprintf(hFileDAT,"\n\nTotal function sizes has reached or exceeds %d bytes.\n\n",
|
|
(4096+(4096*uiPageCount)));
|
|
++uiPageCount;
|
|
|
|
//Check to see of the page has been touched.
|
|
|
|
if(fTouched){
|
|
fprintf(hFileDAT,"This page has been touched.\n");
|
|
++cTouched;
|
|
}
|
|
else{
|
|
fprintf(hFileDAT,"This page has not been touched.\n");
|
|
}
|
|
fTouched = 0;
|
|
|
|
|
|
for(i=0; i < 60; i++){
|
|
fprintf(hFileDAT, "*");
|
|
}
|
|
fprintf(hFileDAT, "\n\n");
|
|
}
|
|
|
|
}
|
|
++uiPageCount;
|
|
if(fTouched){
|
|
fprintf(hFileDAT,"\n\n");
|
|
for(i=0; i < 70; i++){
|
|
fprintf(hFileDAT, "=");
|
|
}
|
|
++cTouched;
|
|
fprintf(hFileDAT,"\n\nThis page has been touched.");
|
|
}
|
|
fprintf(hFileDAT,"\n\n");
|
|
for(i=0; i < 70; i++){
|
|
fprintf(hFileDAT, "=");
|
|
}
|
|
|
|
fprintf(hFileDAT,"\n\n%-28s %10ld bytes\n\n","Cumulative function size:", cbFxnCum);
|
|
fprintf(hFileDAT,"%-28s %10d bytes\n\n", "Size of functions touched:", ulMaxBytes);
|
|
fprintf(hFileDAT,"%-28s %10d\n\n", "Total page count:", uiPageCount);
|
|
fprintf(hFileDAT,"%-28s %10d\n\n", "Total pages touched:", cTouched);
|
|
WsIndicator( WSINDF_FINISH, NULL, 0 );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
***LP wspDumpExit
|
|
*
|
|
*
|
|
***
|
|
*
|
|
* Effects:
|
|
*
|
|
* Frees up resources (as necessary). Exits with the specified
|
|
* exit code, or returns void if exit code is NOEXIT.
|
|
*
|
|
***
|
|
* Returns:
|
|
*
|
|
* Void, else exits.
|
|
*/
|
|
|
|
VOID
|
|
wspDumpExit(uiExitCode, fPrintMsg, uiMsgCode, ulParam1, pszParam2)
|
|
UINT uiExitCode;
|
|
USHORT fPrintMsg;
|
|
UINT uiMsgCode;
|
|
ULONG ulParam1;
|
|
PSZ pszParam2;
|
|
{
|
|
|
|
|
|
/* Print message, if necessary. */
|
|
if (fPrintMsg == TRUE)
|
|
{
|
|
printf(pchMsg[uiMsgCode], szProgName, pszVersion, ulParam1, pszParam2);
|
|
}
|
|
|
|
// Special case: do NOT exit if called with NOEXIT.
|
|
if (uiExitCode == NOEXIT)
|
|
return;
|
|
|
|
wspDumpCleanup();
|
|
exit(uiExitCode);
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
***LP wspDumpCleanup
|
|
*
|
|
*
|
|
***
|
|
*
|
|
* Effects:
|
|
*
|
|
* Frees up resources (as necessary).
|
|
*
|
|
***
|
|
* Returns:
|
|
*
|
|
* Void.
|
|
*/
|
|
void
|
|
wspDumpCleanup( void )
|
|
{
|
|
_fcloseall();
|
|
|
|
free( szFileWSP );
|
|
free( szFileTMI );
|
|
if (fRandom)
|
|
free( szFileWSR );
|
|
if (fDatFile)
|
|
free( szDatFile );
|
|
}
|
|
|
|
|
|
|
|
int __cdecl wspCompare(const void *fxn1, const void *fxn2)
|
|
{
|
|
return (((PFXN)fxn1)->ulOrigIndex < ((PFXN)fxn2)->ulOrigIndex ? -1:
|
|
((PFXN)fxn1)->ulOrigIndex == ((PFXN)fxn2)->ulOrigIndex ? 0:
|
|
1);
|
|
}
|