diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/antiword/datalist.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/antiword/datalist.c')
-rwxr-xr-x | sys/src/cmd/aux/antiword/datalist.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/antiword/datalist.c b/sys/src/cmd/aux/antiword/datalist.c new file mode 100755 index 000000000..564f46980 --- /dev/null +++ b/sys/src/cmd/aux/antiword/datalist.c @@ -0,0 +1,374 @@ +/* + * 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 */ |