/* PXDump (c)2000 Richard Odekerken */ #include #include #include #include "paradox.h" #define sec31120000to01011970 62135683200.0 double Time1970toParadox (long int lTime) { return (1000.0* ((double)lTime + sec31120000to01011970)); } long int TimeParadoxTo1970 (double fTime) { fTime /= 1000.0; fTime -= sec31120000to01011970; return ((long int)fTime); } int PrintDataType (PXBYTE iSize, PXBYTE iType, PXBYTE *pxData) { PXBYTE pxbTemp; PXLONGINT pxliTemp; PXBYTE pxachTemp[8]; PXINTEGER pxiTemp; double *dTemp = (double*)pxachTemp; int i; time_t tNow; struct tm *tmTemp; switch (iType) { case PXTYPE_ALPHA: pxbTemp = pxData[iSize]; pxData[iSize] = 0; printf ("%.*s", iSize, pxData); pxData[iSize] = pxbTemp; break; case PXTYPE_AUTOINC: case PXTYPE_LONGINT: pxliTemp = pxData[0] << 24; pxliTemp += pxData[1] << 16; pxliTemp += pxData[2]<< 8; pxliTemp += pxData[3]; printf ("%s%ld", (pxliTemp && 0x8000000) ? "" : "-", pxliTemp & 0x7fffffff); break; case PXTYPE_SHORTINT: pxiTemp = pxData[0] << 8; pxiTemp += pxData[1]; printf ("%s%d", (pxiTemp && 0x8000) ? "" : "-", pxiTemp & 0x7fff); break; case PXTYPE_TIME: pxliTemp = pxData[0] << 24; pxliTemp += pxData[1] << 16; pxliTemp += pxData[2]<< 8; pxliTemp += pxData[3]; pxliTemp &= 0x7fffffff; pxliTemp /= 1000; printf ("%02d:%02d:%02d", pxliTemp / 3600, (pxliTemp%3600) / 60, pxliTemp%60); break; case PXTYPE_DATE: pxliTemp = pxData[0] << 24; pxliTemp += pxData[1] << 16; pxliTemp += pxData[2]<< 8; pxliTemp += pxData[3]; pxliTemp &= 0x7fffffff; if (pxliTemp) { pxliTemp -= 719163; pxliTemp *= (24*3600); tmTemp = gmtime (&pxliTemp); printf ("%02d/%02d/%04d", tmTemp->tm_mday, tmTemp->tm_mon+1, tmTemp->tm_year + 1900); } else printf ("(null date)"); break; case PXTYPE_NUMBER: for (i=0; i<8;i++) pxachTemp[7-i] = pxData[i]; pxachTemp[7] &= 0x7f; printf ("%.2f", *dTemp); break; case PXTYPE_LOGICAL: printf ("%s", (pxData[0] && 0x80) ? "True" : "False"); break; case PXTYPE_TIMESTAMP: for (i=0; i<8;i++) pxachTemp[7-i] = pxData[i]; pxachTemp[7] &= 0x7f; pxliTemp = 0; if (*dTemp) pxliTemp = TimeParadoxTo1970(*dTemp); if (pxliTemp) { tmTemp = gmtime (&pxliTemp); if (tmTemp) printf ("%02d/%02d/%04d %02d:%02d:%02d", tmTemp->tm_mday,tmTemp->tm_mon+1, tmTemp->tm_year + 1900, tmTemp->tm_hour, tmTemp->tm_min, tmTemp->tm_sec); else printf ("(bogus timestamp)"); } else printf ("(null timestamp)"); break; default: printf ("Data type %c not supported", pcPxFldTypesShort[iType]); } return 0; } int DescribeTable (char *szFilename, int bContents, int bViewAddr) { PXHEADER *pPxHeader; PX4HEADER *pPx4Header; FILE *fp; unsigned long ulFileSize; PXBYTE *pvBuffer, *pvCurrent; PXFLDINFOREC *pvFieldInfoArray; PXBYTE *pvCreatedName; PXBYTE *pvFieldNames; PXBYTE *pc; PXBYTE *pcBlock; PXBLOCKHEADER *pBlkHdr; PXBYTE *pcField; PXINTEGER i, j, k, m; PXINTEGER iNumRecords; PXLONGINT lBlockSize; printf ("Description of file %s:\n\n", szFilename); fp = fopen (szFilename, "rb"); if (fp == NULL) { printf ("Could not open %s\n", szFilename); return 1; } fseek (fp, 0, SEEK_END); ulFileSize = ftell (fp); if (ulFileSize == 0) { printf ("Could not determine filesize of %s\n", szFilename); fclose (fp); return 2; } fseek (fp, 0, SEEK_SET); pvBuffer = malloc (ulFileSize); if (pvBuffer == NULL) { printf ("Could not allocate %ld bytes to read %s\n", ulFileSize, szFilename); fclose (fp); return 3; } pvCurrent = pvBuffer; fread (pvCurrent, sizeof (PXHEADER), 1, fp); pPxHeader = (PXHEADER*)pvCurrent; pvCurrent += sizeof (PXHEADER); ulFileSize -= sizeof (PXHEADER); if (pPxHeader->fileVersionID < 0x0d) printf ("This table is a Paradox version %s table\n", pcVersions[pPxHeader->fileVersionID]); else { printf ("Unknown Paradox version number!\n"); fclose (fp); return 4; } if (pPxHeader->fileVersionID >= 5) { fread (pvCurrent, sizeof (PX4HEADER), 1, fp); pPx4Header = (PX4HEADER*)pvCurrent; pvCurrent += sizeof (PX4HEADER); ulFileSize -= sizeof (PX4HEADER); } fread (pvCurrent, ulFileSize, 1, fp); fclose (fp); if ((pPxHeader->maxTableSize > 0) && (pPxHeader->maxTableSize < 5)) lBlockSize = pPxHeader->maxTableSize * 0x400; else { printf ("Max. table size contains bogus value\n"); return 5; } pvFieldInfoArray = (PXFLDINFOREC*)pvCurrent; pvCreatedName = pvCurrent + (6 * pPxHeader->numFields) + 4; printf ("Original table name: %s\n\n", pvCreatedName); pvFieldNames = pvCreatedName + 79; pc = pvFieldNames; printf ("Field name Size Type\n"); printf ("-------------------------------------------------\n"); for (i=0; i < pPxHeader->numFields; i++) { printf ("%-24s %4d %-20s\n", pc, pvFieldInfoArray[i].fSize, pcPxFldTypes[pvFieldInfoArray[i].fType]); pc += strlen (pc); pc++; } if (!bContents) return 0; printf ("-------------------------------------------------\n"); printf ("This table contains %d records:\n", pPxHeader->numRecords); pcBlock = pvBuffer + pPxHeader->headerSize; m=0; for (k=0; k < pPxHeader->fileBlocks; k++) { pcField = pcBlock + 6; pBlkHdr = (PXBLOCKHEADER*)pcBlock; iNumRecords= 1+(pBlkHdr->addDataSize / pPxHeader->recordSize); for (j=0; j < iNumRecords ; j++) { pc = pvFieldNames; printf ("\n-- Record %d\n", m++); for (i=0; i < pPxHeader->numFields; i++) { printf (" %-24s : ", pc); if (bViewAddr) printf ("(0x%04lx) : ", (pcField - pvBuffer)); PrintDataType (pvFieldInfoArray[i].fSize, pvFieldInfoArray[i].fType, pcField); pcField += pvFieldInfoArray[i].fSize; printf ("\n"); pc += strlen (pc); pc++; } } pcBlock += lBlockSize; } return 0; } int main (int argc, char **argv) { DescribeTable (argv[1], 1, 1); return 0; }