home *** CD-ROM | disk | FTP | other *** search
- _OB╩ LIBRAR┘ MANAGEMENT_
- b∙ Thoma≤ Siering
-
- [LISTING ONE]
-
- //****** svc.h -- Service functions *******
-
- #define NOFILE NULL // no error log file
- typedef enum {
- Message,
- Warning,
- Error
- } MESSAGETYPE;
-
- char *MakeASCIIZ(unsigned char *LString);
- void Output(MESSAGETYPE MsgType, FILE *Stream, char *OutputFormat, ...);
-
-
-
- [LISTING TWO]
- //****** svc.c -- Service functions *******
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdarg.h>
- #include "svc.h"
-
- // MakeASCIIZ - Take a string of 1-byte length/data format, and make it ASCIIZ.
- char *MakeASCIIZ(unsigned char *LString)
- {
- char *ASCIIZString;
- unsigned char StringLength;
-
- StringLength = *LString++;
- if ((ASCIIZString = malloc((int) StringLength + 1)) == NULL)
- return (NULL);
- strncpy(ASCIIZString, (signed char *) LString, StringLength);
- ASCIIZString[StringLength] = '\0';
- return (ASCIIZString);
- }
-
- // Output -- Write to the output stream. This function adds an exception-
- // handling layer to disk IO. It handles abnormal program termination, and
- // warnings to both stderr and output. Three types of message can be handled:
- // Message, simply printed to a file; Warning, print to file AND stderr;
- // Error, same as warning, but terminate with abnormal exit code.
- void Output(MESSAGETYPE MsgType, FILE *Stream, char *OutputFormat, ...)
- {
- char OutputBuffer[133];
- va_list VarArgP;
-
- va_start(VarArgP, OutputFormat);
- vsprintf(OutputBuffer, OutputFormat, VarArgP);
- // If this is (non-fatal) warning or (fatal) error, also send it to stderr
- if (MsgType != Message)è fprintf(stderr, "\a%s", OutputBuffer);
- // In any case: attempt to print message to output file. Exception check.
- if (Stream != NOFILE)
- if ((size_t) fprintf(Stream, OutputBuffer) != strlen(OutputBuffer)) {
- fprintf(stderr, "\aDisk Write Failure!\n");
- abort();
- }
- /* If this was (fatal) error message, abort on the spot */
- if (MsgType == Error) {
- flushall();
- fcloseall();
- abort();
- }
- va_end(VarArgP);
- }
-
-
-
- [LISTING THREE]
-
- //***** ole.h -- Global include info for Object Library Engine (ole.c) ******
-
- #define THEADR 0x80 // OMF module header
- #define COMENT 0x88 // OMF comment record
- #define MODEND 0x8A // OMF module end record
- #define LIBMOD 0xA3 // library module name comment class
- #define LIBHEADER 0xF0 // LIB file header
- #define MARKER_RECORD 0xF1 // marker between modules & dictionary
- #define NUMBUCKETS 37 // number of buckets/block
- #define DICTBLOCKSIZE 512 // bytes/symbol dictionary block
- #define DICTBLKFULL 0xFF // Symbol dictionary block full
-
- #define UNDEFINED -1 // to indicate non-initialized data
- #define STR_EQUAL 0 // string equality
-
- // These two macros will rotate word operand opw by nbits bits (0 - 16)
- #define WORDBITS 16
- #define ROL(opw, nbits) (((opw) << (nbits)) | ((opw) >> (WORDBITS - (nbits))))
- #define ROR(opw, nbits) (((opw) >> (nbits)) | ((opw) << (WORDBITS - (nbits))))
-
- typedef enum {
- false,
- true
- } bool;
-
- #pragma pack(1)
-
- typedef struct {
- unsigned char RecType;
- int RecLength;
- } OMFHEADER;
-
- typedef struct {
- unsigned char RecType;
- int RecLength;è unsigned char Attrib;
- unsigned char CommentClass;
- } COMENTHEADER;
-
- typedef struct { // Record Type F0h
- int PageSize; // Header length (excl. first 3 bytes)
- // == page size (module at page boundary)
- // page size == 2 ** n, 4 <= n <= 15
- long DictionaryOffset; // file offset of Symbol Dictionary
- int NumDictBlocks; // number of Symbol Dictionary blocks
- // <= 251 512-byte dictionary pages
- unsigned char Flags; // only valid flag: 01h => case-sensitive
- bool IsCaseSensitive;
- bool IsLIBMODFormat; // is MS extension type LIBMOD present?
- } LIBHDR;
-
- typedef struct {
- unsigned char MarkerType; // This's better be F1h
- int MarkerLength; // filler to dictionary's 512-byte alignment
- } DICTMARKER;
-
- typedef struct {
- int BlockNumber;
- int BucketNumber;
- unsigned char *SymbolP;
- long ModuleFilePos;
- bool IsFound;
- } DICTENTRY;
-
- typedef struct {
- int BlockHash;
- int BlockOvfl;
- int BucketHash;
- int BucketOvfl;
- } HashT;
-
- void GetLibHeader(LIBHDR *LibHeader, FILE *InLibFH);
- HashT Hash(char SymbolZ[], int NumHashBlocks);
- DICTENTRY FindSymbol(char *SymbolZ, LIBHDR *LibHeader, FILE *InLibFH);
- void GetSymDictBlock(int BlockNumber, LIBHDR *LibHeader,
- FILE *InLibFH);
- long FindModule(char *ModuleName, LIBHDR *LibHeader, FILE *InLibFH);
- DICTENTRY GetSymDictEntry(int BlockNumber, int BucketNumber,
- LIBHDR *LibHeader, FILE *InLibFH);
- char *GetModuleName(long ModuleFilePos, LIBHDR *LibHeader, FILE *InLibFH);
- bool FindLIBMOD(FILE *InLibFH);
- bool FindObjRecord(FILE *ObjFH, unsigned char RecType);
- bool ExtractModule(char *ModuleName, char *NewModuleName, LIBHDR *LibHeader,
- FILE *InLibFH);
- void CopyObjModule(FILE *NewObjFH, long FilePos, FILE *InLibFH);
-
-
-
- [LISTING FOUR]
- è//***** ole.c -- Object Library Engine ******
-
- #include <stdio.h>
- #include <io.h>
- #include <stdlib.h>
- #include <string.h>
- #include "ole.h"
- #include "svc.h"
-
- typedef struct {
- unsigned char SymbolDictBlock[DICTBLOCKSIZE]; // symbol dictionary block
- int FreeSpaceIdx; // cursor to next free symbol space slot
- bool IsFull; // is this sym. dict. block full?
- int BlockNumber; // current block number
- } DICTBLOCK;
-
- // The number of pages in the Symbol Dictionary has to be a prime <= 251.
- // NOTE: The smallest page number in MS LIB is 2, in Borland TLIB it's 1.
- static int Primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
- 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
- 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
- 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 };
- // Symbol Dictionary Block
- static DICTBLOCK DictBlock;
- // GetLibHeader -- Get header of an object module library. The library
- // header's ( record type F0) main purpose is to identify this data file as a
- // library, give page size, and size and location of Symbol Dictionary.
- void GetLibHeader(LIBHDR *LibHeader, FILE *InLibFH)
- {
- if (fgetc(InLibFH) != LIBHEADER)
- Output(Error, NOFILE, "Bogus Library Header\n");
- // NOTE: The LIBHDR data structure has been enlarged to include more
- // info than the actual LIB header contains. As a result, a few more bytes
- // are read in past the actual header when we take sizeof(LIBHDR). This
- // is no problem since there's plenty to read after the header, anyway!
- if (fread(LibHeader, sizeof(LIBHDR), 1, InLibFH) != 1)
- Output(Error, NOFILE, "Couldn't Read Library Header\n");
- // Add in Header length word & checksum byte
- LibHeader->PageSize += 3;
- // Determine if LIB includes Microsoft's LIBMOD extension
- // Find the first OBJ module in the LIB file
- if (fseek(InLibFH, (long) LibHeader->PageSize, SEEK_SET) != 0)
- Output(Error, NOFILE, "Seek for first object module failed\n");
- LibHeader->IsLIBMODFormat = FindLIBMOD(InLibFH);
- LibHeader->IsCaseSensitive = LibHeader->Flags == 0x01 ? true : false;
- // Make it clear that we haven't read Symbol Dictionary yet
- DictBlock.BlockNumber = UNDEFINED;
- }
- // FindModule -- Find a module in Symbol Dictionary and return its file
- // position. If not found, return -1L.
- long FindModule(char *ModuleName, LIBHDR *LibHeader, FILE *InLibFH)
- {
- char *ObjName;
- DICTENTRY DictEntry;
- char *ExtP;è // Allow extra space for terminating "!\0"
- if ((ObjName = malloc(strlen(ModuleName) + 2)) == NULL)
- Output(Error, NOFILE, "OBJ Name Memory Allocation Failed\n");
- strcpy(ObjName, ModuleName);
- // Allow search for module name xxx.obj
- if ((ExtP = strrchr(ObjName, '.')) != NULL)
- *ExtP = '\0';
- // NOTE: Module names are stored in LIB's with terminating '!'
- strcat(ObjName, "!");
- DictEntry = FindSymbol(ObjName, LibHeader, InLibFH);
-
- free(ObjName);
- return (DictEntry.IsFound == true ? DictEntry.ModuleFilePos : -1L);
- }
- // FindSymbol -- Find a symbol in Symbol Dictionary by (repeatedly, if
- // necessary) hashing the symbol and doing dictionary lookup.
- DICTENTRY FindSymbol(char *SymbolZ, LIBHDR *LibHeader, FILE *InLibFH)
- {
- DICTENTRY DictEntry;
- char *SymbolP;
- HashT HashVal;
- int MaxTries;
- int Block, Bucket;
-
- HashVal = Hash(SymbolZ, LibHeader->NumDictBlocks);
- Block = HashVal.BlockHash;
- Bucket = HashVal.BucketHash;
- MaxTries = LibHeader->NumDictBlocks * NUMBUCKETS;
- DictEntry.IsFound = false;
-
- while (MaxTries--) {
- DictEntry = GetSymDictEntry(Block, Bucket, LibHeader, InLibFH);
- // Three alternatives to check after Symbol Dictionary lookup:
- // 1. If the entry is zero, but the dictionary block is NOT full,
- // the symbol is not present:
- if (DictEntry.IsFound == false && DictBlock.IsFull == false)
- return (DictEntry);
- // 2. If the entry is zero, and the dictionary block is full, the
- // symbol may have been rehashed to another block; keep looking:
- // 3. If the entry is non-zero, we still have to verify the symbol.
- // If it's the wrong one (hash clash), keep looking:
- if (DictEntry.IsFound == true) {
- // Get the symbol name
- SymbolP = MakeASCIIZ(DictEntry.SymbolP);
- // Choose case-sensitive or insensitive comparison as appropriate
- if ((LibHeader->IsCaseSensitive == true ? strcmp(SymbolZ, SymbolP) :
- stricmp(SymbolZ, SymbolP)) == STR_EQUAL) {
- free(SymbolP);
- return (DictEntry);
- }
- free(SymbolP);
- }
- // Cases 2 and 3 (w/o a symbol match) require re-hash:
- Block += HashVal.BlockOvfl;
- Bucket += HashVal.BucketOvfl;è Block %= LibHeader->NumDictBlocks;
- Bucket %= NUMBUCKETS;
- }
- // We never found the entry!
- DictEntry.IsFound = false;
- return (DictEntry);
- }
- // Hash -- Hash a symbol for Symbol Dictionary entry
- // Inputs: SymbolZ - Symbol in ASCIIZ form; NumHashBlocks - current number of
- // Symbol Dictionary blocks (MS LIB max. 251 blocks)
- // Outputs: Hash data structure, containing: BlockHash, index of block
- // containing symbol; BlockOvfl, block index's rehash delta; BucketHash,
- // index of symbol's bucket (position) on page; BucketOvfl, bucket index's
- // rehash delta
- // Algorithm: Determine block index, i.e. page number in Symbol Dictionary
- // where the symbol is to reside, and the bucket index, i.e. the position
- // within that page (0-36). If this leads to collision, retry with bucket
- // delta until entire block has turned out to be full. Then, apply block
- // delta, and start over with original bucket index.
- HashT Hash(char SymbolZ[], int NumHashBlocks)
- {
- HashT SymHash; // the resulting aggregate hash values
- unsigned char *SymbolC; // symbol with prepended count
- int SymLength; // length of symbol to be hashed
- unsigned char *FwdP, *BwdP; // temp. pts's to string: forward/back.
- unsigned int FwdC, BwdC; // current char's at fwd/backw. pointers
- unsigned int BlockH, BlockD, BucketH, BucketD; // temporary values
- int i;
- SymLength = strlen(SymbolZ);
- // Make symbol string in Length byte/ASCII string format
- if ((SymbolC = malloc(SymLength + 2)) == NULL)
- Output(Error, NOFILE, "Memory Allocation Failed\n");
- SymbolC[0] = (unsigned char) SymLength;
- // copy w/o EOS
- strncpy((signed char *) &SymbolC[1], SymbolZ, SymLength + 1);
- FwdP = &SymbolC[0];
- BwdP = &SymbolC[SymLength];
- BlockH = BlockD = BucketH = BucketD = 0;
- for (i = 0; i < SymLength; i++) {
- // Hashing is done case-insensitive, incl. length byte
- FwdC = (unsigned int) *FwdP++ | 0x20;
- BwdC = (unsigned int) *BwdP-- | 0x20;
- // XOR the current character (moving forward or reverse, depending
- // on variable calculated) with the intermediate result rotated
- // by 2 bits (again, left or right, depending on variable).
- // Block Hash: traverse forward, rotate left
- BlockH = FwdC ^ ROL(BlockH, 2);
- // Block Overflow delta: traverse reverse, rotate left
- BlockD = BwdC ^ ROL(BlockD, 2);
- // Bucket Hash: traverse reverse, rotate right
- BucketH = BwdC ^ ROR(BucketH, 2);
- // Bucket Overflow delta: traverse forward, rotate right
- BucketD = FwdC ^ ROR(BucketD, 2);
- }
- // NOTE: Results are zero-basedè SymHash.BlockHash = BlockH % NumHashBlocks;
- SymHash.BucketHash = BucketH % NUMBUCKETS;
- // Obviously, hash deltas of 0 would be nonsense!
- SymHash.BlockOvfl = max(BlockD % NumHashBlocks, 1);
- SymHash.BucketOvfl = max(BucketD % NUMBUCKETS, 1);
-
- free(SymbolC);
- return (SymHash);
- }
- // GetSymDictBlock -- Read and pre-process a Symbol Dictionary block
- void GetSymDictBlock(int BlockNumber, LIBHDR *LibHeader, FILE *InLibFH)
- {
- // Find and read the whole Symbol Dictionary block
- if (fseek(InLibFH, LibHeader->DictionaryOffset + (long) BlockNumber *
- (long) DICTBLOCKSIZE, SEEK_SET) != 0)
- Output(Error, NOFILE, "Could Not Find Symbol Dictionary\n");
- if (fread(DictBlock.SymbolDictBlock, DICTBLOCKSIZE, 1, InLibFH) != 1)
- Output(Error, NOFILE, "Couldn't Read Library Header\n");
- // Is this block all used up?
- DictBlock.FreeSpaceIdx = DictBlock.SymbolDictBlock[NUMBUCKETS];
- DictBlock.IsFull = (DictBlock.FreeSpaceIdx == DICTBLKFULL) ? true : false;
- // For future reference, remember block number
- DictBlock.BlockNumber = BlockNumber;
- }
- // GetSymDictEntry -- Look up and process a Symbol Dictionary block entry
- DICTENTRY GetSymDictEntry(int BlockNumber, int BucketNumber,
- LIBHDR *LibHeader, FILE *InLibFH)
- {
- DICTENTRY DictEntry;
- unsigned char SymbolOffset;
- unsigned char SymbolLength;
- int PageNumber;
- // Remember entry's block/bucket and init. to no (NULL) entry
- DictEntry.BlockNumber = BlockNumber;
- DictEntry.BucketNumber = BucketNumber;
- DictEntry.SymbolP = NULL;
- DictEntry.IsFound = false;
- // Make sure the appropriate block was already read from obj. mod. library
- if (DictBlock.BlockNumber != BlockNumber)
- GetSymDictBlock(BlockNumber, LibHeader, InLibFH);
- // WORD offset of symbol in dictionary block: 0 means no entry
- SymbolOffset = DictBlock.SymbolDictBlock[BucketNumber];
- if (SymbolOffset != 0) {
- // Since it's word offset, need to multiply by two
- DictEntry.SymbolP = &DictBlock.SymbolDictBlock[SymbolOffset * 2];
- // Get the symbol's object module offset in LIB
- SymbolLength = *DictEntry.SymbolP;
- // Object module's LIB page number is right after symbol string
- PageNumber = *(int *) (DictEntry.SymbolP + SymbolLength + 1);
- DictEntry.ModuleFilePos = (long) PageNumber *
- (long) LibHeader->PageSize;
- DictEntry.IsFound = true;
- }
- return (DictEntry);
- }è// GetModuleName -- Read the OMF module header record (THEADR - 80h) or, if
- // present, MS's LIBMOD extension record type. NOTE: For Microsoft C,
- // THEADR reflects the source code name file at compilation time. OBJ name
- // may differ from this; the LIBMOD record will contain its name. For
- // Borland C++, THEADR is the only pertinent record and will contain OBJ
- // module's name rather than the source's.
- char *GetModuleName(long ModuleFilePos, LIBHDR *LibHeader, FILE *InLibFH)
- {
- int SymbolLength;
- char *ModuleName;
- OMFHEADER OmfHeader;
- // Position at beginning of pertinent object module
- if (fseek(InLibFH, ModuleFilePos, SEEK_SET) != 0)
- Output(Error, NOFILE, "Seek for object module at %lx failed\n",
- ModuleFilePos);
- if (LibHeader->IsLIBMODFormat == false) {
- if (fread(&OmfHeader, sizeof(OmfHeader), 1, InLibFH) != 1)
- Output(Error, NOFILE, "Couldn't Read THEADR at %lx\n",
- ModuleFilePos);
- if (OmfHeader.RecType != THEADR)
- Output(Error, NOFILE, "Bogus THEADR OMF record at %lx\n",
- ModuleFilePos);
- }
- else
- if (FindLIBMOD(InLibFH) == false) {
- Output(Warning, NOFILE, "No LIBMOD record found at %lx\n",
- ModuleFilePos);
- return (NULL);
- }
- SymbolLength = fgetc(InLibFH);
- if ((ModuleName = malloc(SymbolLength + 1)) == NULL)
- Output(Error, NOFILE, "Malloc failure Reading module name\n");
- if (fread(ModuleName, SymbolLength, 1, InLibFH) != 1)
- Output(Error, NOFILE, "Couldn't Read THEADR\n");
- ModuleName[SymbolLength] = '\0';
- return(ModuleName);
- }
- // FindLIBMOD -- Get a LIBMOD (A3) comment record, if present.
- // NOTE: This is a special OMF COMENT (88h) record comment class used by
- // Microsoft only. It provides the name of the object modules which may
- // differ from the source (contained in THEADR). This record is added when an
- // object module is put into library, and stripped out when it's extracted.
- // This routine will leave file pointer at the LIBMOD name field.
- bool FindLIBMOD(FILE *InLibFH)
- {
- COMENTHEADER CommentHdr;
- // Search (up to) all COMENT records in OBJ module
- while (FindObjRecord(InLibFH, COMENT) == true) {
- if (fread(&CommentHdr, sizeof(CommentHdr), 1, InLibFH) != 1)
- Output(Error, NOFILE, "Couldn't Read OBJ\n");
- if (CommentHdr.CommentClass == LIBMOD)
- return (true);
- else
- // if not found: forward to next record, and retry
- if (fseek(InLibFH, (long) CommentHdr.RecLength - è sizeof(CommentHdr) + sizeof(OMFHEADER), SEEK_CUR) != 0)
- Output(Error, NOFILE, "Seek retry for LIBMOD failed\n");
- }
- // We got here only if COMENT of class LIBMOD was never found
- return (false);
- }
- // FindObjRecord -- Find an object module record in one given module.
- // On call, file pointer must be set to an objec record. Search will
- // quit at the end of current module (or when record found).
- bool FindObjRecord(FILE *ObjFH, unsigned char RecType)
- {
- OMFHEADER ObjHeader;
- while (fread(&ObjHeader, sizeof(ObjHeader), 1, ObjFH) == 1) {
- // If it's the record type we're looking for, we're done
- if (ObjHeader.RecType == RecType) {
- // Return with obj module set to record requested
- if (fseek(ObjFH, -(long) sizeof(ObjHeader), SEEK_CUR) != 0)
- Output(Error, NOFILE, "Seek for Record Type %02x failed\n",
- RecType & 0xFF);
- return (true);
- }
- // End of object module, record type NEVER found
- if (ObjHeader.RecType == MODEND)
- return (false);
- // Forward file pointer to next object module record
- if (fseek(ObjFH, (long) ObjHeader.RecLength, SEEK_CUR) != 0)
- Output(Error, NOFILE, "Seek retry for Record Type %02x failed\n",
- RecType & 0xFF);
- }
- // If this quit due to I/O condition, it's either EOF or I/O error
- if (feof(ObjFH) == 0)
- Output(Error, NOFILE, "Couldn't Read OBJ\n");
- // we completed w/o error and w/o finding the record (should NEVER happen)
- return (false);
- }
- // ExtractModule -- Find an object module in a library and extract it into
- // "stand-alone" object file. Return true if ok, else false.
- // Optional: Can specify a new name for the module.
- bool ExtractModule(char *ModuleName, char *NewModuleName, LIBHDR *LibHeader,
- FILE *InLibFH)
- {
- long FilePos;
- char *NewObjP;
- char *NewObjName;
- FILE *NewObjFH;
- // Find the object module's position in the library file
- FilePos = FindModule(ModuleName, LibHeader, InLibFH);
- if (FilePos == -1L)
- return (false);
- // Determine name for new .obj, and set it up
- NewObjP = NewModuleName != NULL ? NewModuleName : ModuleName;
- if ((NewObjName = malloc(strlen(NewObjP) + 5)) == NULL)
- Output(Error, NOFILE, "Malloc failure Making module name %s\n",
- NewObjP);
- strcpy(NewObjName, NewObjP);è // Open the new .obj file, and pass everything off to low-level routine
- if ((NewObjFH = fopen(NewObjName, "wb")) == NULL)
- Output(Error, NOFILE, "Open failure new module %s\n", NewObjName);
- CopyObjModule(NewObjFH, FilePos, InLibFH);
- fclose(NewObjFH);
- free(NewObjName);
- return (true);
- }
- // CopyObjModule -- Low-level copy of LIB member to OBJ file.
- void CopyObjModule(FILE *NewObjFH, long FilePos, FILE *InLibFH)
- {
- OMFHEADER RecHdr;
- // Get to the object module in LIB
- if (fseek(InLibFH, FilePos, SEEK_SET) != 0)
- Output(Error, NOFILE, "Seek failure to file position %ld\n", FilePos);
- // Write module from LIB to separate obj file
- do {
- // Read OMF header record, this will give record type and length
- if (fread(&RecHdr, sizeof(RecHdr), 1, InLibFH) != 1)
- Output(Error, NOFILE, "Couldn't Read OBJ\n");
- // Need to check every COMENT record to make sure to strip LIBMOD out
- if (RecHdr.RecType == COMENT) {
- // Throw away next byte (Attrib COMENT byte) for now
- fgetc(InLibFH);
- // Check COMENT's Comment Class
- // If it's a LIBMOD, set file pointer ro next record and continue
- if (fgetc(InLibFH) == LIBMOD) {
- if (fseek(InLibFH, (long) RecHdr.RecLength - 2L, SEEK_CUR) != 0)
- Output(Error, NOFILE, "Seek error on COMENT\n");
- continue;
- }
- else
- // Wasn't a LIBMOD: reset file pointer to continue normally
- if (fseek(InLibFH, -2L, SEEK_CUR) != 0)
- Output(Error, NOFILE, "Seek error on COMENT\n");
- }
- if (fwrite(&RecHdr, sizeof(RecHdr), 1, NewObjFH) != 1)
- Output(Error, NOFILE, "Couldn't Write new OBJ\n");
- while (RecHdr.RecLength--)
- fputc(fgetc(InLibFH), NewObjFH);
- } while (RecHdr.RecType != MODEND);
- }
-
-
-
- [LISTING FIVE]
-
- //***** olu1.c -- Object Library Utility, Sample Application 1. *****
- // This utility performs a linear scan and dump of an object module library's
- // Symbol Dictionary. NOTE: Due to Borland TLIB bug, this utility may NOT work
- // with libraries generated with versions 3.01 or less.
- //*****************************************************************************
- #include <stdio.h>
- #include <stdlib.h>
- #include "ole.h"è#include "svc.h"
-
- static void DumpSymbolDictionary(LIBHDR *LibHeader, FILE *InLibFH);
- void main(int argc, char *argv[]);
-
- // main -- Surprise!
- void main(int argc, char *argv[])
- {
- FILE *InLibFH;
- LIBHDR LibHeader;
- long ModFilePos;
- if (argc != 2)
- Output(Error, NOFILE, "Usage: %s file.lib\n", argv[0]);
- if ((InLibFH = fopen(argv[1], "rb")) == NULL)
- Output(Error, NOFILE, "Couldn't Open %s\n", argv[1]);
- GetLibHeader(&LibHeader, InLibFH);
- DumpSymbolDictionary(&LibHeader, InLibFH);
- }
- // DumpSymbolDictionary -- Print out an entire Symbol Dictionary
- static void DumpSymbolDictionary(LIBHDR *LibHeader, FILE *InLibFH)
- {
- int BlockIdx, BucketIdx;
- DICTENTRY DictEntry;
- char *ModuleName;
- char *SymbolP;
- for (BlockIdx = 0; BlockIdx < LibHeader->NumDictBlocks; BlockIdx++)
- for (BucketIdx = 0; BucketIdx < NUMBUCKETS; BucketIdx++) {
- DictEntry = GetSymDictEntry(BlockIdx, BucketIdx, LibHeader,
- InLibFH);
- if (DictEntry.IsFound == false)
- continue;
- // Get the symbol name
- SymbolP = MakeASCIIZ(DictEntry.SymbolP);
- // Get to the corresponding module name record (THEADR or LIBMOD)
- ModuleName = GetModuleName(DictEntry.ModuleFilePos, LibHeader,
- InLibFH);
- printf("%s -- Module %s (%08lxh)\n", SymbolP,
- ModuleName, DictEntry.ModuleFilePos);
- printf("Hash: Block %d , Bucket %d\n", BlockIdx, BucketIdx);
- free(SymbolP);
- free(ModuleName);
- }
- }
-
-
- [LISTING SIX]
-
- //***** olu2.c -- Object Library Utility, Sample Application 2. *****
- // This utility explodes an object module library, i.e. move all its members
- // out into .obj form. This functionality is absent from popular library
- // managers; useful for libraries the user is unfamiliar with. Optionally,
- // named single members can be copied, as well. NOTE: Modules can be
- // extracted in sequence efficiently, but we're showing off functions!
- #include <stdio.h>
- #include <stdlib.h>è#include <string.h>
- #include "ole.h"
- #include "svc.h"
-
- static void ExplodeLibrary(LIBHDR *LibHeader, FILE *InLibFH);
- void main(int argc, char *argv[]);
-
- // main -- Surprise!
- void main(int argc, char *argv[])
- {
- FILE *InLibFH;
- LIBHDR LibHeader;
-
- if (argc != 2 && argc!= 3)
- Output(Error, NOFILE, "Usage: %s file.lib [file.obj]\n", argv[0]);
- if ((InLibFH = fopen(argv[1], "rb")) == NULL)
- Output(Error, NOFILE, "Couldn't Open %s\n", argv[1]);
- GetLibHeader(&LibHeader, InLibFH);
- if (argc == 3) {
- if (ExtractModule(argv[2], NULL, &LibHeader, InLibFH) == false)
- Output(Error, NOFILE, "Extraction of Module %s failed\n",
- argv[2]);
- }
- else
- ExplodeLibrary(&LibHeader, InLibFH);
- }
- // Explode Library -- Extract all (or one specific) library member(s).
- // NOTE: This is done in a contrived way just to show off some of functions.
- // We go through entire Symbol Dict., determine if a symbol is a module name
- // by comparing its entry to the module name that entry is leading to, and
- // then extract the module.
- static void ExplodeLibrary(LIBHDR *LibHeader, FILE *InLibFH)
- {
- int BlockIdx, BucketIdx;
- DICTENTRY DictEntry;
- char *ModuleName;
- char *SymbolP;
- char *ModuleFN;
- for (BlockIdx = 0; BlockIdx < LibHeader->NumDictBlocks; BlockIdx++)
- for (BucketIdx = 0; BucketIdx < NUMBUCKETS; BucketIdx++) {
- DictEntry = GetSymDictEntry(BlockIdx, BucketIdx, LibHeader,
- InLibFH);
- if (DictEntry.IsFound == false)
- continue;
- // Get the symbol name
- SymbolP = MakeASCIIZ(DictEntry.SymbolP);
- ModuleName = GetModuleName(DictEntry.ModuleFilePos, LibHeader,
- InLibFH);
- // If it compares, it's a module name
- if (strnicmp(SymbolP, ModuleName, strlen(ModuleName)) ==
- STR_EQUAL) {
- if ((ModuleFN = malloc(strlen(ModuleName) + 4)) == NULL)
- Output(Error, NOFILE, "Couldn't malloc file name %s\n",
- ModuleName);
- strcpy(ModuleFN, ModuleName);è strcat(ModuleFN, ".obj");
- if (ExtractModule(ModuleFN, NULL, LibHeader, InLibFH) ==
- false)
- Output(Error, NOFILE, "Extraction of Module %s failed\n",
- ModuleFN);
- free(ModuleFN);
- }
- free(SymbolP);
- free(ModuleName);
- }
- }