123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- /*
- * datalist.c
- * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
- *
- * Description:
- * Build, read and destroy a list of Word data blocks
- */
- #include <stdlib.h>
- #include <errno.h>
- #include "antiword.h"
- #if defined(__riscos)
- #define EIO 42
- #endif /* __riscos */
- /*
- * Private structure to hide the way the information
- * is stored from the rest of the program
- */
- typedef struct data_mem_tag {
- data_block_type tInfo;
- struct data_mem_tag *pNext;
- } data_mem_type;
- /* Variable to describe the start of the data block list */
- static data_mem_type *pAnchor = NULL;
- /* Variable needed to read the data block list */
- static data_mem_type *pBlockLast = NULL;
- /* Variable needed to read the data block list */
- static data_mem_type *pBlockCurrent = NULL;
- static ULONG ulBlockOffset = 0;
- static size_t tByteNext = 0;
- /* Last block read */
- static UCHAR aucBlock[BIG_BLOCK_SIZE];
- /*
- * vDestroyDataBlockList - destroy the data block list
- */
- void
- vDestroyDataBlockList(void)
- {
- data_mem_type *pCurr, *pNext;
- DBG_MSG("vDestroyDataBlockList");
- pCurr = pAnchor;
- while (pCurr != NULL) {
- pNext = pCurr->pNext;
- pCurr = xfree(pCurr);
- pCurr = pNext;
- }
- pAnchor = NULL;
- /* Reset all the control variables */
- pBlockLast = NULL;
- pBlockCurrent = NULL;
- ulBlockOffset = 0;
- tByteNext = 0;
- } /* end of vDestroyDataBlockList */
- /*
- * bAdd2DataBlockList - add an element to the data block list
- *
- * Returns TRUE when successful, otherwise FALSE
- */
- BOOL
- bAdd2DataBlockList(const data_block_type *pDataBlock)
- {
- data_mem_type *pListMember;
- fail(pDataBlock == NULL);
- fail(pDataBlock->ulFileOffset == FC_INVALID);
- fail(pDataBlock->ulDataPos == CP_INVALID);
- fail(pDataBlock->ulLength == 0);
- NO_DBG_MSG("bAdd2DataBlockList");
- NO_DBG_HEX(pDataBlock->ulFileOffset);
- NO_DBG_HEX(pDataBlock->ulDataPos);
- NO_DBG_HEX(pDataBlock->ulLength);
- if (pDataBlock->ulFileOffset == FC_INVALID ||
- pDataBlock->ulDataPos == CP_INVALID ||
- pDataBlock->ulLength == 0) {
- werr(0, "Software (datablock) error");
- return FALSE;
- }
- /* Check for continuous blocks */
- if (pBlockLast != NULL &&
- pBlockLast->tInfo.ulFileOffset +
- pBlockLast->tInfo.ulLength == pDataBlock->ulFileOffset &&
- pBlockLast->tInfo.ulDataPos +
- pBlockLast->tInfo.ulLength == pDataBlock->ulDataPos) {
- /* These are continous blocks */
- pBlockLast->tInfo.ulLength += pDataBlock->ulLength;
- return TRUE;
- }
- /* Make a new block */
- pListMember = xmalloc(sizeof(data_mem_type));
- /* Add the block to the data list */
- pListMember->tInfo = *pDataBlock;
- pListMember->pNext = NULL;
- if (pAnchor == NULL) {
- pAnchor = pListMember;
- } else {
- fail(pBlockLast == NULL);
- pBlockLast->pNext = pListMember;
- }
- pBlockLast = pListMember;
- return TRUE;
- } /* end of bAdd2DataBlockList */
- /*
- * ulGetDataOffset - get the offset in the data block list
- *
- * Get the fileoffset the current position in the data block list
- */
- ULONG
- ulGetDataOffset(FILE *pFile)
- {
- return pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset + tByteNext;
- } /* end of ulGetDataOffset */
- /*
- * bSetDataOffset - set the offset in the data block list
- *
- * Make the given fileoffset the current position in the data block list
- */
- BOOL
- bSetDataOffset(FILE *pFile, ULONG ulFileOffset)
- {
- data_mem_type *pCurr;
- size_t tReadLen;
- DBG_HEX(ulFileOffset);
- for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
- if (ulFileOffset < pCurr->tInfo.ulFileOffset ||
- ulFileOffset >= pCurr->tInfo.ulFileOffset +
- pCurr->tInfo.ulLength) {
- /* The file offset is not in this block */
- continue;
- }
- /* Compute the maximum number of bytes to read */
- tReadLen = (size_t)(pCurr->tInfo.ulFileOffset +
- pCurr->tInfo.ulLength -
- ulFileOffset);
- /* Compute the real number of bytes to read */
- if (tReadLen > sizeof(aucBlock)) {
- tReadLen = sizeof(aucBlock);
- }
- /* Read the bytes */
- if (!bReadBytes(aucBlock, tReadLen, ulFileOffset, pFile)) {
- return FALSE;
- }
- /* Set the control variables */
- pBlockCurrent = pCurr;
- ulBlockOffset = ulFileOffset - pCurr->tInfo.ulFileOffset;
- tByteNext = 0;
- return TRUE;
- }
- return FALSE;
- } /* end of bSetDataOffset */
- /*
- * iNextByte - get the next byte from the data block list
- */
- int
- iNextByte(FILE *pFile)
- {
- ULONG ulReadOff;
- size_t tReadLen;
- fail(pBlockCurrent == NULL);
- if (tByteNext >= sizeof(aucBlock) ||
- ulBlockOffset + tByteNext >= pBlockCurrent->tInfo.ulLength) {
- if (ulBlockOffset + sizeof(aucBlock) <
- pBlockCurrent->tInfo.ulLength) {
- /* Same block, next part */
- ulBlockOffset += sizeof(aucBlock);
- } else {
- /* Next block, first part */
- pBlockCurrent = pBlockCurrent->pNext;
- ulBlockOffset = 0;
- }
- if (pBlockCurrent == NULL) {
- /* Past the last part of the last block */
- errno = EIO;
- return EOF;
- }
- tReadLen = (size_t)
- (pBlockCurrent->tInfo.ulLength - ulBlockOffset);
- if (tReadLen > sizeof(aucBlock)) {
- tReadLen = sizeof(aucBlock);
- }
- ulReadOff = pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset;
- if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
- errno = EIO;
- return EOF;
- }
- tByteNext = 0;
- }
- return (int)aucBlock[tByteNext++];
- } /* end of iNextByte */
- /*
- * usNextWord - get the next word from the data block list
- *
- * Read a two byte value in Little Endian order, that means MSB last
- *
- * All return values can be valid so errno is set in case of error
- */
- USHORT
- usNextWord(FILE *pFile)
- {
- USHORT usLSB, usMSB;
- usLSB = (USHORT)iNextByte(pFile);
- if (usLSB == (USHORT)EOF) {
- errno = EIO;
- return (USHORT)EOF;
- }
- usMSB = (USHORT)iNextByte(pFile);
- if (usMSB == (USHORT)EOF) {
- DBG_MSG("usNextWord: Unexpected EOF");
- errno = EIO;
- return (USHORT)EOF;
- }
- return (usMSB << 8) | usLSB;
- } /* end of usNextWord */
- /*
- * ulNextLong - get the next long from the data block list
- *
- * Read a four byte value in Little Endian order, that means MSW last
- *
- * All return values can be valid so errno is set in case of error
- */
- ULONG
- ulNextLong(FILE *pFile)
- {
- ULONG ulLSW, ulMSW;
- ulLSW = (ULONG)usNextWord(pFile);
- if (ulLSW == (ULONG)EOF) {
- errno = EIO;
- return (ULONG)EOF;
- }
- ulMSW = (ULONG)usNextWord(pFile);
- if (ulMSW == (ULONG)EOF) {
- DBG_MSG("ulNextLong: Unexpected EOF");
- errno = EIO;
- return (ULONG)EOF;
- }
- return (ulMSW << 16) | ulLSW;
- } /* end of ulNextLong */
- /*
- * usNextWordBE - get the next two byte value
- *
- * Read a two byte value in Big Endian order, that means MSB first
- *
- * All return values can be valid so errno is set in case of error
- */
- USHORT
- usNextWordBE(FILE *pFile)
- {
- USHORT usLSB, usMSB;
- usMSB = (USHORT)iNextByte(pFile);
- if (usMSB == (USHORT)EOF) {
- errno = EIO;
- return (USHORT)EOF;
- }
- usLSB = (USHORT)iNextByte(pFile);
- if (usLSB == (USHORT)EOF) {
- DBG_MSG("usNextWordBE: Unexpected EOF");
- errno = EIO;
- return (USHORT)EOF;
- }
- return (usMSB << 8) | usLSB;
- } /* end of usNextWordBE */
- /*
- * ulNextLongBE - get the next four byte value
- *
- * Read a four byte value in Big Endian order, that means MSW first
- *
- * All return values can be valid so errno is set in case of error
- */
- ULONG
- ulNextLongBE(FILE *pFile)
- {
- ULONG ulLSW, ulMSW;
- ulMSW = (ULONG)usNextWordBE(pFile);
- if (ulMSW == (ULONG)EOF) {
- errno = EIO;
- return (ULONG)EOF;
- }
- ulLSW = (ULONG)usNextWordBE(pFile);
- if (ulLSW == (ULONG)EOF) {
- DBG_MSG("ulNextLongBE: Unexpected EOF");
- errno = EIO;
- return (ULONG)EOF;
- }
- return (ulMSW << 16) | ulLSW;
- } /* end of ulNextLongBE */
- /*
- * tSkipBytes - skip over the given number of bytes
- *
- * Returns the number of skipped bytes
- */
- size_t
- tSkipBytes(FILE *pFile, size_t tToSkip)
- {
- size_t tToGo, tMaxMove, tMove;
- fail(pFile == NULL);
- fail(pBlockCurrent == NULL);
- tToGo = tToSkip;
- while (tToGo != 0) {
- /* Goto the end of the current block */
- tMaxMove = min(sizeof(aucBlock) - tByteNext,
- (size_t)(pBlockCurrent->tInfo.ulLength -
- ulBlockOffset - tByteNext));
- tMove = min(tMaxMove, tToGo);
- tByteNext += tMove;
- tToGo -= tMove;
- if (tToGo != 0) {
- /* Goto the next block */
- if (iNextByte(pFile) == EOF) {
- return tToSkip - tToGo;
- }
- tToGo--;
- }
- }
- return tToSkip;
- } /* end of tSkipBytes */
- /*
- * Translate a data position to an offset in the file.
- * Logical to physical offset.
- *
- * Returns: FC_INVALID: in case of error
- * otherwise: the computed file offset
- */
- ULONG
- ulDataPos2FileOffset(ULONG ulDataPos)
- {
- data_mem_type *pCurr;
- fail(ulDataPos == CP_INVALID);
- for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
- if (ulDataPos < pCurr->tInfo.ulDataPos ||
- ulDataPos >= pCurr->tInfo.ulDataPos +
- pCurr->tInfo.ulLength) {
- /* The data offset is not in this block, try the next */
- continue;
- }
- /* The data offset is in the current block */
- return pCurr->tInfo.ulFileOffset +
- ulDataPos -
- pCurr->tInfo.ulDataPos;
- }
- /* Passed beyond the end of the list */
- DBG_HEX_C(ulDataPos != 0, ulDataPos);
- return FC_INVALID;
- } /* end of ulDataPos2FileOffset */
|