summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/antiword/datalist.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/aux/antiword/datalist.c374
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 */