]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/antiword/datalist.c
change icanhasvmx to report extra info only with -v
[plan9front.git] / sys / src / cmd / aux / antiword / datalist.c
1 /*
2  * datalist.c
3  * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
4  *
5  * Description:
6  * Build, read and destroy a list of Word data blocks
7  */
8
9 #include <stdlib.h>
10 #include <errno.h>
11 #include "antiword.h"
12
13 #if defined(__riscos)
14 #define EIO             42
15 #endif /* __riscos */
16
17
18 /*
19  * Private structure to hide the way the information
20  * is stored from the rest of the program
21  */
22 typedef struct data_mem_tag {
23         data_block_type         tInfo;
24         struct data_mem_tag     *pNext;
25 } data_mem_type;
26
27 /* Variable to describe the start of the data block list */
28 static data_mem_type    *pAnchor = NULL;
29 /* Variable needed to read the data block list */
30 static data_mem_type    *pBlockLast = NULL;
31 /* Variable needed to read the data block list */
32 static data_mem_type    *pBlockCurrent = NULL;
33 static ULONG    ulBlockOffset = 0;
34 static size_t   tByteNext = 0;
35 /* Last block read */
36 static UCHAR    aucBlock[BIG_BLOCK_SIZE];
37
38
39 /*
40  * vDestroyDataBlockList - destroy the data block list
41  */
42 void
43 vDestroyDataBlockList(void)
44 {
45         data_mem_type   *pCurr, *pNext;
46
47         DBG_MSG("vDestroyDataBlockList");
48
49         pCurr = pAnchor;
50         while (pCurr != NULL) {
51                 pNext = pCurr->pNext;
52                 pCurr = xfree(pCurr);
53                 pCurr = pNext;
54         }
55         pAnchor = NULL;
56         /* Reset all the control variables */
57         pBlockLast = NULL;
58         pBlockCurrent = NULL;
59         ulBlockOffset = 0;
60         tByteNext = 0;
61 } /* end of vDestroyDataBlockList */
62
63 /*
64  * bAdd2DataBlockList - add an element to the data block list
65  *
66  * Returns TRUE when successful, otherwise FALSE
67  */
68 BOOL
69 bAdd2DataBlockList(const data_block_type *pDataBlock)
70 {
71         data_mem_type   *pListMember;
72
73         fail(pDataBlock == NULL);
74         fail(pDataBlock->ulFileOffset == FC_INVALID);
75         fail(pDataBlock->ulDataPos == CP_INVALID);
76         fail(pDataBlock->ulLength == 0);
77
78         NO_DBG_MSG("bAdd2DataBlockList");
79         NO_DBG_HEX(pDataBlock->ulFileOffset);
80         NO_DBG_HEX(pDataBlock->ulDataPos);
81         NO_DBG_HEX(pDataBlock->ulLength);
82
83         if (pDataBlock->ulFileOffset == FC_INVALID ||
84             pDataBlock->ulDataPos == CP_INVALID ||
85             pDataBlock->ulLength == 0) {
86                 werr(0, "Software (datablock) error");
87                 return FALSE;
88         }
89         /* Check for continuous blocks */
90         if (pBlockLast != NULL &&
91             pBlockLast->tInfo.ulFileOffset +
92              pBlockLast->tInfo.ulLength == pDataBlock->ulFileOffset &&
93             pBlockLast->tInfo.ulDataPos +
94              pBlockLast->tInfo.ulLength == pDataBlock->ulDataPos) {
95                 /* These are continous blocks */
96                 pBlockLast->tInfo.ulLength += pDataBlock->ulLength;
97                 return TRUE;
98         }
99         /* Make a new block */
100         pListMember = xmalloc(sizeof(data_mem_type));
101         /* Add the block to the data list */
102         pListMember->tInfo = *pDataBlock;
103         pListMember->pNext = NULL;
104         if (pAnchor == NULL) {
105                 pAnchor = pListMember;
106         } else {
107                 fail(pBlockLast == NULL);
108                 pBlockLast->pNext = pListMember;
109         }
110         pBlockLast = pListMember;
111         return TRUE;
112 } /* end of bAdd2DataBlockList */
113
114 /*
115  * ulGetDataOffset - get the offset in the data block list
116  *
117  * Get the fileoffset the current position in the data block list
118  */
119 ULONG
120 ulGetDataOffset(FILE *pFile)
121 {
122         return pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset + tByteNext;
123 } /* end of ulGetDataOffset */
124
125 /*
126  * bSetDataOffset - set the offset in the data block list
127  *
128  * Make the given fileoffset the current position in the data block list
129  */
130 BOOL
131 bSetDataOffset(FILE *pFile, ULONG ulFileOffset)
132 {
133         data_mem_type   *pCurr;
134         size_t  tReadLen;
135
136         DBG_HEX(ulFileOffset);
137
138         for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
139                 if (ulFileOffset < pCurr->tInfo.ulFileOffset ||
140                     ulFileOffset >= pCurr->tInfo.ulFileOffset +
141                      pCurr->tInfo.ulLength) {
142                         /* The file offset is not in this block */
143                         continue;
144                 }
145                 /* Compute the maximum number of bytes to read */
146                 tReadLen = (size_t)(pCurr->tInfo.ulFileOffset +
147                                 pCurr->tInfo.ulLength -
148                                 ulFileOffset);
149                 /* Compute the real number of bytes to read */
150                 if (tReadLen > sizeof(aucBlock)) {
151                         tReadLen = sizeof(aucBlock);
152                 }
153                 /* Read the bytes */
154                 if (!bReadBytes(aucBlock, tReadLen, ulFileOffset, pFile)) {
155                         return FALSE;
156                 }
157                 /* Set the control variables */
158                 pBlockCurrent = pCurr;
159                 ulBlockOffset = ulFileOffset - pCurr->tInfo.ulFileOffset;
160                 tByteNext = 0;
161                 return TRUE;
162         }
163         return FALSE;
164 } /* end of bSetDataOffset */
165
166 /*
167  * iNextByte - get the next byte from the data block list
168  */
169 int
170 iNextByte(FILE *pFile)
171 {
172         ULONG   ulReadOff;
173         size_t  tReadLen;
174
175         fail(pBlockCurrent == NULL);
176
177         if (tByteNext >= sizeof(aucBlock) ||
178             ulBlockOffset + tByteNext >= pBlockCurrent->tInfo.ulLength) {
179                 if (ulBlockOffset + sizeof(aucBlock) <
180                                         pBlockCurrent->tInfo.ulLength) {
181                         /* Same block, next part */
182                         ulBlockOffset += sizeof(aucBlock);
183                 } else {
184                         /* Next block, first part */
185                         pBlockCurrent = pBlockCurrent->pNext;
186                         ulBlockOffset = 0;
187                 }
188                 if (pBlockCurrent == NULL) {
189                         /* Past the last part of the last block */
190                         errno = EIO;
191                         return EOF;
192                 }
193                 tReadLen = (size_t)
194                                 (pBlockCurrent->tInfo.ulLength - ulBlockOffset);
195                 if (tReadLen > sizeof(aucBlock)) {
196                         tReadLen = sizeof(aucBlock);
197                 }
198                 ulReadOff = pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset;
199                 if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
200                         errno = EIO;
201                         return EOF;
202                 }
203                 tByteNext = 0;
204         }
205         return (int)aucBlock[tByteNext++];
206 } /* end of iNextByte */
207
208 /*
209  * usNextWord - get the next word from the data block list
210  *
211  * Read a two byte value in Little Endian order, that means MSB last
212  *
213  * All return values can be valid so errno is set in case of error
214  */
215 USHORT
216 usNextWord(FILE *pFile)
217 {
218         USHORT  usLSB, usMSB;
219
220         usLSB = (USHORT)iNextByte(pFile);
221         if (usLSB == (USHORT)EOF) {
222                 errno = EIO;
223                 return (USHORT)EOF;
224         }
225         usMSB = (USHORT)iNextByte(pFile);
226         if (usMSB == (USHORT)EOF) {
227                 DBG_MSG("usNextWord: Unexpected EOF");
228                 errno = EIO;
229                 return (USHORT)EOF;
230         }
231         return (usMSB << 8) | usLSB;
232 } /* end of usNextWord */
233
234 /*
235  * ulNextLong - get the next long from the data block list
236  *
237  * Read a four byte value in Little Endian order, that means MSW last
238  *
239  * All return values can be valid so errno is set in case of error
240  */
241 ULONG
242 ulNextLong(FILE *pFile)
243 {
244         ULONG   ulLSW, ulMSW;
245
246         ulLSW = (ULONG)usNextWord(pFile);
247         if (ulLSW == (ULONG)EOF) {
248                 errno = EIO;
249                 return (ULONG)EOF;
250         }
251         ulMSW = (ULONG)usNextWord(pFile);
252         if (ulMSW == (ULONG)EOF) {
253                 DBG_MSG("ulNextLong: Unexpected EOF");
254                 errno = EIO;
255                 return (ULONG)EOF;
256         }
257         return (ulMSW << 16) | ulLSW;
258 } /* end of ulNextLong */
259
260 /*
261  * usNextWordBE - get the next two byte value
262  *
263  * Read a two byte value in Big Endian order, that means MSB first
264  *
265  * All return values can be valid so errno is set in case of error
266  */
267 USHORT
268 usNextWordBE(FILE *pFile)
269 {
270         USHORT usLSB, usMSB;
271
272         usMSB = (USHORT)iNextByte(pFile);
273         if (usMSB == (USHORT)EOF) {
274                 errno = EIO;
275                 return (USHORT)EOF;
276         }
277         usLSB = (USHORT)iNextByte(pFile);
278         if (usLSB == (USHORT)EOF) {
279                 DBG_MSG("usNextWordBE: Unexpected EOF");
280                 errno = EIO;
281                 return (USHORT)EOF;
282         }
283         return (usMSB << 8) | usLSB;
284 } /* end of usNextWordBE */
285
286 /*
287  * ulNextLongBE - get the next four byte value
288  *
289  * Read a four byte value in Big Endian order, that means MSW first
290  *
291  * All return values can be valid so errno is set in case of error
292  */
293 ULONG
294 ulNextLongBE(FILE *pFile)
295 {
296         ULONG   ulLSW, ulMSW;
297
298         ulMSW = (ULONG)usNextWordBE(pFile);
299         if (ulMSW == (ULONG)EOF) {
300                 errno = EIO;
301                 return (ULONG)EOF;
302         }
303         ulLSW = (ULONG)usNextWordBE(pFile);
304         if (ulLSW == (ULONG)EOF) {
305                 DBG_MSG("ulNextLongBE: Unexpected EOF");
306                 errno = EIO;
307                 return (ULONG)EOF;
308         }
309         return (ulMSW << 16) | ulLSW;
310 } /* end of ulNextLongBE */
311
312 /*
313  * tSkipBytes - skip over the given number of bytes
314  *
315  * Returns the number of skipped bytes
316  */
317 size_t
318 tSkipBytes(FILE *pFile, size_t tToSkip)
319 {
320         size_t  tToGo, tMaxMove, tMove;
321
322         fail(pFile == NULL);
323         fail(pBlockCurrent == NULL);
324
325         tToGo = tToSkip;
326         while (tToGo != 0) {
327                 /* Goto the end of the current block */
328                 tMaxMove = min(sizeof(aucBlock) - tByteNext,
329                                 (size_t)(pBlockCurrent->tInfo.ulLength -
330                                 ulBlockOffset - tByteNext));
331                 tMove = min(tMaxMove, tToGo);
332                 tByteNext += tMove;
333                 tToGo -= tMove;
334                 if (tToGo != 0) {
335                         /* Goto the next block */
336                         if (iNextByte(pFile) == EOF) {
337                                 return tToSkip - tToGo;
338                         }
339                         tToGo--;
340                 }
341         }
342         return tToSkip;
343 } /* end of tSkipBytes */
344
345 /*
346  * Translate  a data position to an offset in the file.
347  * Logical to physical offset.
348  *
349  * Returns:     FC_INVALID: in case of error
350  *              otherwise: the computed file offset
351  */
352 ULONG
353 ulDataPos2FileOffset(ULONG ulDataPos)
354 {
355         data_mem_type   *pCurr;
356
357         fail(ulDataPos == CP_INVALID);
358
359         for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
360                 if (ulDataPos < pCurr->tInfo.ulDataPos ||
361                     ulDataPos >= pCurr->tInfo.ulDataPos +
362                      pCurr->tInfo.ulLength) {
363                         /* The data offset is not in this block, try the next */
364                         continue;
365                 }
366                 /* The data offset is in the current block */
367                 return pCurr->tInfo.ulFileOffset +
368                                 ulDataPos -
369                                 pCurr->tInfo.ulDataPos;
370         }
371         /* Passed beyond the end of the list */
372         DBG_HEX_C(ulDataPos != 0, ulDataPos);
373         return FC_INVALID;
374 } /* end of ulDataPos2FileOffset */