summaryrefslogtreecommitdiff
authorerik <erik>2007-01-26 20:24:07 (UTC)
committer erik <erik>2007-01-26 20:24:07 (UTC)
commitcc5b326a212414a612838b0041e6077477ebbc70 (patch) (unidiff)
treefd69c302a511c3bc715ff0e160181b9ad1cbf82d
parent53d630c9c4813142ee13e6843c30476a5db26e78 (diff)
downloadopie-cc5b326a212414a612838b0041e6077477ebbc70.zip
opie-cc5b326a212414a612838b0041e6077477ebbc70.tar.gz
opie-cc5b326a212414a612838b0041e6077477ebbc70.tar.bz2
A couple of places where a string is overrun. This fixes both of them.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-reader/chm_lib.c5
-rw-r--r--noncore/settings/sysinfo/contrib/dhry.c4
2 files changed, 5 insertions, 4 deletions
diff --git a/noncore/apps/opie-reader/chm_lib.c b/noncore/apps/opie-reader/chm_lib.c
index ecf8278..7acd1d2 100644
--- a/noncore/apps/opie-reader/chm_lib.c
+++ b/noncore/apps/opie-reader/chm_lib.c
@@ -1,1876 +1,1877 @@
1/* $Id$ */ 1/* $Id$ */
2/*************************************************************************** 2/***************************************************************************
3 * chm_lib.c - CHM archive manipulation routines * 3 * chm_lib.c - CHM archive manipulation routines *
4 * ------------------- * 4 * ------------------- *
5 * * 5 * *
6 * author: Jed Wing <jedwin@ugcs.caltech.edu> * 6 * author: Jed Wing <jedwin@ugcs.caltech.edu> *
7 * version: 0.3 * 7 * version: 0.3 *
8 * notes: These routines are meant for the manipulation of microsoft * 8 * notes: These routines are meant for the manipulation of microsoft *
9 * .chm (compiled html help) files, but may likely be used * 9 * .chm (compiled html help) files, but may likely be used *
10 * for the manipulation of any ITSS archive, if ever ITSS * 10 * for the manipulation of any ITSS archive, if ever ITSS *
11 * archives are used for any other purpose. * 11 * archives are used for any other purpose. *
12 * * 12 * *
13 * Note also that the section names are statically handled. * 13 * Note also that the section names are statically handled. *
14 * To be entirely correct, the section names should be read * 14 * To be entirely correct, the section names should be read *
15 * from the section names meta-file, and then the various * 15 * from the section names meta-file, and then the various *
16 * content sections and the "transforms" to apply to the data * 16 * content sections and the "transforms" to apply to the data *
17 * they contain should be inferred from the section name and * 17 * they contain should be inferred from the section name and *
18 * the meta-files referenced using that name; however, all of * 18 * the meta-files referenced using that name; however, all of *
19 * the files I've been able to get my hands on appear to have * 19 * the files I've been able to get my hands on appear to have *
20 * only two sections: Uncompressed and MSCompressed. * 20 * only two sections: Uncompressed and MSCompressed. *
21 * Additionally, the ITSS.DLL file included with Windows does * 21 * Additionally, the ITSS.DLL file included with Windows does *
22 * not appear to handle any different transforms than the * 22 * not appear to handle any different transforms than the *
23 * simple LZX-transform. Furthermore, the list of transforms * 23 * simple LZX-transform. Furthermore, the list of transforms *
24 * to apply is broken, in that only half the required space * 24 * to apply is broken, in that only half the required space *
25 * is allocated for the list. (It appears as though the * 25 * is allocated for the list. (It appears as though the *
26 * space is allocated for ASCII strings, but the strings are * 26 * space is allocated for ASCII strings, but the strings are *
27 * written as unicode. As a result, only the first half of * 27 * written as unicode. As a result, only the first half of *
28 * the string appears.) So this is probably not too big of * 28 * the string appears.) So this is probably not too big of *
29 * a deal, at least until CHM v4 (MS .lit files), which also * 29 * a deal, at least until CHM v4 (MS .lit files), which also *
30 * incorporate encryption, of some description. * 30 * incorporate encryption, of some description. *
31 * * 31 * *
32 * switches: CHM_MT: compile library with thread-safety * 32 * switches: CHM_MT: compile library with thread-safety *
33 * * 33 * *
34 * switches (Linux only): * 34 * switches (Linux only): *
35 * CHM_USE_PREAD: compile library to use pread instead of * 35 * CHM_USE_PREAD: compile library to use pread instead of *
36 * lseek/read * 36 * lseek/read *
37 * CHM_USE_IO64: compile library to support full 64-bit I/O * 37 * CHM_USE_IO64: compile library to support full 64-bit I/O *
38 * as is needed to properly deal with the * 38 * as is needed to properly deal with the *
39 * 64-bit file offsets. * 39 * 64-bit file offsets. *
40 ***************************************************************************/ 40 ***************************************************************************/
41 41
42/*************************************************************************** 42/***************************************************************************
43 * * 43 * *
44 * This program is free software; you can redistribute it and/or modify * 44 * This program is free software; you can redistribute it and/or modify *
45 * it under the terms of the GNU Lesser General Public License as * 45 * it under the terms of the GNU Lesser General Public License as *
46 * published by the Free Software Foundation; either version 2.1 of the * 46 * published by the Free Software Foundation; either version 2.1 of the *
47 * License, or (at your option) any later version. * 47 * License, or (at your option) any later version. *
48 * * 48 * *
49 ***************************************************************************/ 49 ***************************************************************************/
50 50
51#include "chm_lib.h" 51#include "chm_lib.h"
52 52
53#ifdef CHM_MT 53#ifdef CHM_MT
54#define _REENTRANT 54#define _REENTRANT
55#endif 55#endif
56 56
57#include "lzx.h" 57#include "lzx.h"
58 58
59#include <stdlib.h> 59#include <stdlib.h>
60#include <string.h> 60#include <string.h>
61 61
62#if __sun || __sgi 62#if __sun || __sgi
63#include <strings.h> 63#include <strings.h>
64#endif 64#endif
65 65
66#ifdef WIN32 66#ifdef WIN32
67#include <windows.h> 67#include <windows.h>
68#include <malloc.h> 68#include <malloc.h>
69#else 69#else
70/* basic Linux system includes */ 70/* basic Linux system includes */
71#define _XOPEN_SOURCE 500 71#define _XOPEN_SOURCE 500
72#include <unistd.h> 72#include <unistd.h>
73#include <sys/types.h> 73#include <sys/types.h>
74#include <sys/stat.h> 74#include <sys/stat.h>
75#include <fcntl.h> 75#include <fcntl.h>
76#include <malloc.h> 76#include <malloc.h>
77#endif 77#endif
78 78
79/* includes/defines for threading, if using them */ 79/* includes/defines for threading, if using them */
80#ifdef CHM_MT 80#ifdef CHM_MT
81#ifdef WIN32 81#ifdef WIN32
82#define CHM_ACQUIRE_LOCK(a) do { \ 82#define CHM_ACQUIRE_LOCK(a) do { \
83 EnterCriticalSection(&(a)); \ 83 EnterCriticalSection(&(a)); \
84 } while(0) 84 } while(0)
85#define CHM_RELEASE_LOCK(a) do { \ 85#define CHM_RELEASE_LOCK(a) do { \
86 EnterCriticalSection(&(a)); \ 86 EnterCriticalSection(&(a)); \
87 } while(0) 87 } while(0)
88 88
89#else 89#else
90#include <pthread.h> 90#include <pthread.h>
91 91
92#define CHM_ACQUIRE_LOCK(a) do { \ 92#define CHM_ACQUIRE_LOCK(a) do { \
93 pthread_mutex_lock(&(a)); \ 93 pthread_mutex_lock(&(a)); \
94 } while(0) 94 } while(0)
95#define CHM_RELEASE_LOCK(a) do { \ 95#define CHM_RELEASE_LOCK(a) do { \
96 pthread_mutex_unlock(&(a)); \ 96 pthread_mutex_unlock(&(a)); \
97 } while(0) 97 } while(0)
98 98
99#endif 99#endif
100#else 100#else
101#define CHM_ACQUIRE_LOCK(a) /* do nothing */ 101#define CHM_ACQUIRE_LOCK(a) /* do nothing */
102#define CHM_RELEASE_LOCK(a) /* do nothing */ 102#define CHM_RELEASE_LOCK(a) /* do nothing */
103#endif 103#endif
104 104
105#ifdef WIN32 105#ifdef WIN32
106#define CHM_NULL_FD (INVALID_HANDLE_VALUE) 106#define CHM_NULL_FD (INVALID_HANDLE_VALUE)
107#define CHM_USE_WIN32IO 1 107#define CHM_USE_WIN32IO 1
108#define CHM_CLOSE_FILE(fd) CloseHandle((fd)) 108#define CHM_CLOSE_FILE(fd) CloseHandle((fd))
109#else 109#else
110#define CHM_NULL_FD (-1) 110#define CHM_NULL_FD (-1)
111#define CHM_CLOSE_FILE(fd) close((fd)) 111#define CHM_CLOSE_FILE(fd) close((fd))
112#endif 112#endif
113 113
114/* 114/*
115 * defines related to tuning 115 * defines related to tuning
116 */ 116 */
117#ifndef CHM_MAX_BLOCKS_CACHED 117#ifndef CHM_MAX_BLOCKS_CACHED
118#define CHM_MAX_BLOCKS_CACHED 5 118#define CHM_MAX_BLOCKS_CACHED 5
119#endif 119#endif
120 120
121/* 121/*
122 * architecture specific defines 122 * architecture specific defines
123 * 123 *
124 * Note: as soon as C99 is more widespread, the below defines should 124 * Note: as soon as C99 is more widespread, the below defines should
125 * probably just use the C99 sized-int types. 125 * probably just use the C99 sized-int types.
126 * 126 *
127 * The following settings will probably work for many platforms. The sizes 127 * The following settings will probably work for many platforms. The sizes
128 * don't have to be exactly correct, but the types must accommodate at least as 128 * don't have to be exactly correct, but the types must accommodate at least as
129 * many bits as they specify. 129 * many bits as they specify.
130 */ 130 */
131 131
132/* i386, 32-bit, Windows */ 132/* i386, 32-bit, Windows */
133#ifdef WIN32 133#ifdef WIN32
134typedef unsigned char UChar; 134typedef unsigned char UChar;
135typedef __int16 Int16; 135typedef __int16 Int16;
136typedef unsigned __int16 UInt16; 136typedef unsigned __int16 UInt16;
137typedef __int32 Int32; 137typedef __int32 Int32;
138typedef unsigned __int32 UInt32; 138typedef unsigned __int32 UInt32;
139typedef __int64 Int64; 139typedef __int64 Int64;
140typedef unsigned __int64 UInt64; 140typedef unsigned __int64 UInt64;
141 141
142/* I386, 32-bit, non-Windows */ 142/* I386, 32-bit, non-Windows */
143/* Sparc */ 143/* Sparc */
144/* MIPS */ 144/* MIPS */
145#else 145#else
146typedef unsigned char UChar; 146typedef unsigned char UChar;
147typedef short Int16; 147typedef short Int16;
148typedef unsigned short UInt16; 148typedef unsigned short UInt16;
149typedef long Int32; 149typedef long Int32;
150typedef unsigned long UInt32; 150typedef unsigned long UInt32;
151typedef long long Int64; 151typedef long long Int64;
152typedef unsigned long long UInt64; 152typedef unsigned long long UInt64;
153#endif 153#endif
154 154
155/* GCC */ 155/* GCC */
156#ifdef __GNUC__ 156#ifdef __GNUC__
157#define memcmp __builtin_memcmp 157#define memcmp __builtin_memcmp
158#define memcpy __builtin_memcpy 158#define memcpy __builtin_memcpy
159#define strlen __builtin_strlen 159#define strlen __builtin_strlen
160 160
161#elif defined(WIN32) 161#elif defined(WIN32)
162static int ffs(unsigned int val) 162static int ffs(unsigned int val)
163{ 163{
164 int bit=1, idx=1; 164 int bit=1, idx=1;
165 while (bit != 0 && (val & bit) == 0) 165 while (bit != 0 && (val & bit) == 0)
166 { 166 {
167 bit <<= 1; 167 bit <<= 1;
168 ++idx; 168 ++idx;
169 } 169 }
170 if (bit == 0) 170 if (bit == 0)
171 return 0; 171 return 0;
172 else 172 else
173 return idx; 173 return idx;
174} 174}
175 175
176#endif 176#endif
177 177
178/* utilities for unmarshalling data */ 178/* utilities for unmarshalling data */
179static int _unmarshal_char_array(unsigned char **pData, 179static int _unmarshal_char_array(unsigned char **pData,
180 unsigned long *pLenRemain, 180 unsigned long *pLenRemain,
181 char *dest, 181 char *dest,
182 int count) 182 int count)
183{ 183{
184 if (count <= 0 || (unsigned int)count > *pLenRemain) 184 if (count <= 0 || (unsigned int)count > *pLenRemain)
185 return 0; 185 return 0;
186 memcpy(dest, (*pData), count); 186 memcpy(dest, (*pData), count);
187 *pData += count; 187 *pData += count;
188 *pLenRemain -= count; 188 *pLenRemain -= count;
189 return 1; 189 return 1;
190} 190}
191 191
192static int _unmarshal_uchar_array(unsigned char **pData, 192static int _unmarshal_uchar_array(unsigned char **pData,
193 unsigned long *pLenRemain, 193 unsigned long *pLenRemain,
194 unsigned char *dest, 194 unsigned char *dest,
195 int count) 195 int count)
196{ 196{
197 if (count <= 0 || (unsigned int)count > *pLenRemain) 197 if (count <= 0 || (unsigned int)count > *pLenRemain)
198 return 0; 198 return 0;
199 memcpy(dest, (*pData), count); 199 memcpy(dest, (*pData), count);
200 *pData += count; 200 *pData += count;
201 *pLenRemain -= count; 201 *pLenRemain -= count;
202 return 1; 202 return 1;
203} 203}
204 204
205static int _unmarshal_int16(unsigned char **pData, 205static int _unmarshal_int16(unsigned char **pData,
206 unsigned long *pLenRemain, 206 unsigned long *pLenRemain,
207 Int16 *dest) 207 Int16 *dest)
208{ 208{
209 if (2 > *pLenRemain) 209 if (2 > *pLenRemain)
210 return 0; 210 return 0;
211 *dest = (*pData)[0] | (*pData)[1]<<8; 211 *dest = (*pData)[0] | (*pData)[1]<<8;
212 *pData += 2; 212 *pData += 2;
213 *pLenRemain -= 2; 213 *pLenRemain -= 2;
214 return 1; 214 return 1;
215} 215}
216 216
217static int _unmarshal_uint16(unsigned char **pData, 217static int _unmarshal_uint16(unsigned char **pData,
218 unsigned long *pLenRemain, 218 unsigned long *pLenRemain,
219 UInt16 *dest) 219 UInt16 *dest)
220{ 220{
221 if (2 > *pLenRemain) 221 if (2 > *pLenRemain)
222 return 0; 222 return 0;
223 *dest = (*pData)[0] | (*pData)[1]<<8; 223 *dest = (*pData)[0] | (*pData)[1]<<8;
224 *pData += 2; 224 *pData += 2;
225 *pLenRemain -= 2; 225 *pLenRemain -= 2;
226 return 1; 226 return 1;
227} 227}
228 228
229static int _unmarshal_int32(unsigned char **pData, 229static int _unmarshal_int32(unsigned char **pData,
230 unsigned long *pLenRemain, 230 unsigned long *pLenRemain,
231 Int32 *dest) 231 Int32 *dest)
232{ 232{
233 if (4 > *pLenRemain) 233 if (4 > *pLenRemain)
234 return 0; 234 return 0;
235 *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24; 235 *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24;
236 *pData += 4; 236 *pData += 4;
237 *pLenRemain -= 4; 237 *pLenRemain -= 4;
238 return 1; 238 return 1;
239} 239}
240 240
241static int _unmarshal_uint32(unsigned char **pData, 241static int _unmarshal_uint32(unsigned char **pData,
242 unsigned long *pLenRemain, 242 unsigned long *pLenRemain,
243 UInt32 *dest) 243 UInt32 *dest)
244{ 244{
245 if (4 > *pLenRemain) 245 if (4 > *pLenRemain)
246 return 0; 246 return 0;
247 *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24; 247 *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24;
248 *pData += 4; 248 *pData += 4;
249 *pLenRemain -= 4; 249 *pLenRemain -= 4;
250 return 1; 250 return 1;
251} 251}
252 252
253static int _unmarshal_int64(unsigned char **pData, 253static int _unmarshal_int64(unsigned char **pData,
254 unsigned long *pLenRemain, 254 unsigned long *pLenRemain,
255 Int64 *dest) 255 Int64 *dest)
256{ 256{
257 Int64 temp; 257 Int64 temp;
258 int i; 258 int i;
259 if (8 > *pLenRemain) 259 if (8 > *pLenRemain)
260 return 0; 260 return 0;
261 temp=0; 261 temp=0;
262 for(i=8; i>0; i--) 262 for(i=8; i>0; i--)
263 { 263 {
264 temp <<= 8; 264 temp <<= 8;
265 temp |= (*pData)[i-1]; 265 temp |= (*pData)[i-1];
266 } 266 }
267 *dest = temp; 267 *dest = temp;
268 *pData += 8; 268 *pData += 8;
269 *pLenRemain -= 8; 269 *pLenRemain -= 8;
270 return 1; 270 return 1;
271} 271}
272 272
273static int _unmarshal_uint64(unsigned char **pData, 273static int _unmarshal_uint64(unsigned char **pData,
274 unsigned long *pLenRemain, 274 unsigned long *pLenRemain,
275 UInt64 *dest) 275 UInt64 *dest)
276{ 276{
277 UInt64 temp; 277 UInt64 temp;
278 int i; 278 int i;
279 if (8 > *pLenRemain) 279 if (8 > *pLenRemain)
280 return 0; 280 return 0;
281 temp=0; 281 temp=0;
282 for(i=8; i>0; i--) 282 for(i=8; i>0; i--)
283 { 283 {
284 temp <<= 8; 284 temp <<= 8;
285 temp |= (*pData)[i-1]; 285 temp |= (*pData)[i-1];
286 } 286 }
287 *dest = temp; 287 *dest = temp;
288 *pData += 8; 288 *pData += 8;
289 *pLenRemain -= 8; 289 *pLenRemain -= 8;
290 return 1; 290 return 1;
291} 291}
292 292
293static int _unmarshal_uuid(unsigned char **pData, 293static int _unmarshal_uuid(unsigned char **pData,
294 unsigned long *pDataLen, 294 unsigned long *pDataLen,
295 unsigned char *dest) 295 unsigned char *dest)
296{ 296{
297 return _unmarshal_uchar_array(pData, pDataLen, dest, 16); 297 return _unmarshal_uchar_array(pData, pDataLen, dest, 16);
298} 298}
299 299
300/* names of sections essential to decompression */ 300/* names of sections essential to decompression */
301static const char _CHMU_RESET_TABLE[] = 301static const char _CHMU_RESET_TABLE[] =
302 "::DataSpace/Storage/MSCompressed/Transform/" 302 "::DataSpace/Storage/MSCompressed/Transform/"
303 "{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/" 303 "{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/"
304 "InstanceData/ResetTable"; 304 "InstanceData/ResetTable";
305static const char _CHMU_LZXC_CONTROLDATA[] = 305static const char _CHMU_LZXC_CONTROLDATA[] =
306 "::DataSpace/Storage/MSCompressed/ControlData"; 306 "::DataSpace/Storage/MSCompressed/ControlData";
307static const char _CHMU_CONTENT[] = 307static const char _CHMU_CONTENT[] =
308 "::DataSpace/Storage/MSCompressed/Content"; 308 "::DataSpace/Storage/MSCompressed/Content";
309static const char _CHMU_SPANINFO[] = 309static const char _CHMU_SPANINFO[] =
310 "::DataSpace/Storage/MSCompressed/SpanInfo"; 310 "::DataSpace/Storage/MSCompressed/SpanInfo";
311 311
312/* 312/*
313 * structures local to this module 313 * structures local to this module
314 */ 314 */
315 315
316/* structure of ITSF headers */ 316/* structure of ITSF headers */
317#define _CHM_ITSF_V2_LEN (0x58) 317#define _CHM_ITSF_V2_LEN (0x58)
318#define _CHM_ITSF_V3_LEN (0x60) 318#define _CHM_ITSF_V3_LEN (0x60)
319struct chmItsfHeader 319struct chmItsfHeader
320{ 320{
321 char signature[4]; /* 0 (ITSF) */ 321 char signature[4]; /* 0 (ITSF) */
322 Int32 version; /* 4 */ 322 Int32 version; /* 4 */
323 Int32 header_len; /* 8 */ 323 Int32 header_len; /* 8 */
324 Int32 unknown_000c; /* c */ 324 Int32 unknown_000c; /* c */
325 UInt32 last_modified; /* 10 */ 325 UInt32 last_modified; /* 10 */
326 UInt32 lang_id; /* 14 */ 326 UInt32 lang_id; /* 14 */
327 UChar dir_uuid[16]; /* 18 */ 327 UChar dir_uuid[16]; /* 18 */
328 UChar stream_uuid[16]; /* 28 */ 328 UChar stream_uuid[16]; /* 28 */
329 UInt64 unknown_offset; /* 38 */ 329 UInt64 unknown_offset; /* 38 */
330 UInt64 unknown_len; /* 40 */ 330 UInt64 unknown_len; /* 40 */
331 UInt64 dir_offset; /* 48 */ 331 UInt64 dir_offset; /* 48 */
332 UInt64 dir_len; /* 50 */ 332 UInt64 dir_len; /* 50 */
333 UInt64 data_offset; /* 58 (Not present before V3) */ 333 UInt64 data_offset; /* 58 (Not present before V3) */
334}; /* __attribute__ ((aligned (1))); */ 334}; /* __attribute__ ((aligned (1))); */
335 335
336static int _unmarshal_itsf_header(unsigned char **pData, 336static int _unmarshal_itsf_header(unsigned char **pData,
337 unsigned long *pDataLen, 337 unsigned long *pDataLen,
338 struct chmItsfHeader *dest) 338 struct chmItsfHeader *dest)
339{ 339{
340 /* we only know how to deal with the 0x58 and 0x60 byte structures */ 340 /* we only know how to deal with the 0x58 and 0x60 byte structures */
341 if (*pDataLen != _CHM_ITSF_V2_LEN && *pDataLen != _CHM_ITSF_V3_LEN) 341 if (*pDataLen != _CHM_ITSF_V2_LEN && *pDataLen != _CHM_ITSF_V3_LEN)
342 return 0; 342 return 0;
343 343
344 /* unmarshal common fields */ 344 /* unmarshal common fields */
345 _unmarshal_char_array(pData, pDataLen, dest->signature, 4); 345 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
346 _unmarshal_int32 (pData, pDataLen, &dest->version); 346 _unmarshal_int32 (pData, pDataLen, &dest->version);
347 _unmarshal_int32 (pData, pDataLen, &dest->header_len); 347 _unmarshal_int32 (pData, pDataLen, &dest->header_len);
348 _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c); 348 _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c);
349 _unmarshal_uint32 (pData, pDataLen, &dest->last_modified); 349 _unmarshal_uint32 (pData, pDataLen, &dest->last_modified);
350 _unmarshal_uint32 (pData, pDataLen, &dest->lang_id); 350 _unmarshal_uint32 (pData, pDataLen, &dest->lang_id);
351 _unmarshal_uuid (pData, pDataLen, dest->dir_uuid); 351 _unmarshal_uuid (pData, pDataLen, dest->dir_uuid);
352 _unmarshal_uuid (pData, pDataLen, dest->stream_uuid); 352 _unmarshal_uuid (pData, pDataLen, dest->stream_uuid);
353 _unmarshal_uint64 (pData, pDataLen, &dest->unknown_offset); 353 _unmarshal_uint64 (pData, pDataLen, &dest->unknown_offset);
354 _unmarshal_uint64 (pData, pDataLen, &dest->unknown_len); 354 _unmarshal_uint64 (pData, pDataLen, &dest->unknown_len);
355 _unmarshal_uint64 (pData, pDataLen, &dest->dir_offset); 355 _unmarshal_uint64 (pData, pDataLen, &dest->dir_offset);
356 _unmarshal_uint64 (pData, pDataLen, &dest->dir_len); 356 _unmarshal_uint64 (pData, pDataLen, &dest->dir_len);
357 357
358 /* error check the data */ 358 /* error check the data */
359 /* XXX: should also check UUIDs, probably, though with a version 3 file, 359 /* XXX: should also check UUIDs, probably, though with a version 3 file,
360 * current MS tools do not seem to use them. 360 * current MS tools do not seem to use them.
361 */ 361 */
362 if (memcmp(dest->signature, "ITSF", 4) != 0) 362 if (memcmp(dest->signature, "ITSF", 4) != 0)
363 return 0; 363 return 0;
364 if (dest->version == 2) 364 if (dest->version == 2)
365 { 365 {
366 if (dest->header_len < _CHM_ITSF_V2_LEN) 366 if (dest->header_len < _CHM_ITSF_V2_LEN)
367 return 0; 367 return 0;
368 } 368 }
369 else if (dest->version == 3) 369 else if (dest->version == 3)
370 { 370 {
371 if (dest->header_len < _CHM_ITSF_V3_LEN) 371 if (dest->header_len < _CHM_ITSF_V3_LEN)
372 return 0; 372 return 0;
373 } 373 }
374 else 374 else
375 return 0; 375 return 0;
376 376
377 /* now, if we have a V3 structure, unmarshal the rest. 377 /* now, if we have a V3 structure, unmarshal the rest.
378 * otherwise, compute it 378 * otherwise, compute it
379 */ 379 */
380 if (dest->version == 3) 380 if (dest->version == 3)
381 { 381 {
382 if (*pDataLen != 0) 382 if (*pDataLen != 0)
383 _unmarshal_uint64(pData, pDataLen, &dest->data_offset); 383 _unmarshal_uint64(pData, pDataLen, &dest->data_offset);
384 else 384 else
385 return 0; 385 return 0;
386 } 386 }
387 else 387 else
388 dest->data_offset = dest->dir_offset + dest->dir_len; 388 dest->data_offset = dest->dir_offset + dest->dir_len;
389 389
390 return 1; 390 return 1;
391} 391}
392 392
393/* structure of ITSP headers */ 393/* structure of ITSP headers */
394#define _CHM_ITSP_V1_LEN (0x54) 394#define _CHM_ITSP_V1_LEN (0x54)
395struct chmItspHeader 395struct chmItspHeader
396{ 396{
397 char signature[4]; /* 0 (ITSP) */ 397 char signature[4]; /* 0 (ITSP) */
398 Int32 version; /* 4 */ 398 Int32 version; /* 4 */
399 Int32 header_len; /* 8 */ 399 Int32 header_len; /* 8 */
400 Int32 unknown_000c; /* c */ 400 Int32 unknown_000c; /* c */
401 UInt32 block_len; /* 10 */ 401 UInt32 block_len; /* 10 */
402 Int32 blockidx_intvl; /* 14 */ 402 Int32 blockidx_intvl; /* 14 */
403 Int32 index_depth; /* 18 */ 403 Int32 index_depth; /* 18 */
404 Int32 index_root; /* 1c */ 404 Int32 index_root; /* 1c */
405 Int32 index_head; /* 20 */ 405 Int32 index_head; /* 20 */
406 Int32 unknown_0024; /* 24 */ 406 Int32 unknown_0024; /* 24 */
407 UInt32 num_blocks; /* 28 */ 407 UInt32 num_blocks; /* 28 */
408 Int32 unknown_002c; /* 2c */ 408 Int32 unknown_002c; /* 2c */
409 UInt32 lang_id; /* 30 */ 409 UInt32 lang_id; /* 30 */
410 UChar system_uuid[16]; /* 34 */ 410 UChar system_uuid[16]; /* 34 */
411 UChar unknown_0044[16]; /* 44 */ 411 UChar unknown_0044[16]; /* 44 */
412}; /* __attribute__ ((aligned (1))); */ 412}; /* __attribute__ ((aligned (1))); */
413 413
414static int _unmarshal_itsp_header(unsigned char **pData, 414static int _unmarshal_itsp_header(unsigned char **pData,
415 unsigned long *pDataLen, 415 unsigned long *pDataLen,
416 struct chmItspHeader *dest) 416 struct chmItspHeader *dest)
417{ 417{
418 /* we only know how to deal with a 0x54 byte structures */ 418 /* we only know how to deal with a 0x54 byte structures */
419 if (*pDataLen != _CHM_ITSP_V1_LEN) 419 if (*pDataLen != _CHM_ITSP_V1_LEN)
420 return 0; 420 return 0;
421 421
422 /* unmarshal fields */ 422 /* unmarshal fields */
423 _unmarshal_char_array(pData, pDataLen, dest->signature, 4); 423 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
424 _unmarshal_int32 (pData, pDataLen, &dest->version); 424 _unmarshal_int32 (pData, pDataLen, &dest->version);
425 _unmarshal_int32 (pData, pDataLen, &dest->header_len); 425 _unmarshal_int32 (pData, pDataLen, &dest->header_len);
426 _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c); 426 _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c);
427 _unmarshal_uint32 (pData, pDataLen, &dest->block_len); 427 _unmarshal_uint32 (pData, pDataLen, &dest->block_len);
428 _unmarshal_int32 (pData, pDataLen, &dest->blockidx_intvl); 428 _unmarshal_int32 (pData, pDataLen, &dest->blockidx_intvl);
429 _unmarshal_int32 (pData, pDataLen, &dest->index_depth); 429 _unmarshal_int32 (pData, pDataLen, &dest->index_depth);
430 _unmarshal_int32 (pData, pDataLen, &dest->index_root); 430 _unmarshal_int32 (pData, pDataLen, &dest->index_root);
431 _unmarshal_int32 (pData, pDataLen, &dest->index_head); 431 _unmarshal_int32 (pData, pDataLen, &dest->index_head);
432 _unmarshal_int32 (pData, pDataLen, &dest->unknown_0024); 432 _unmarshal_int32 (pData, pDataLen, &dest->unknown_0024);
433 _unmarshal_uint32 (pData, pDataLen, &dest->num_blocks); 433 _unmarshal_uint32 (pData, pDataLen, &dest->num_blocks);
434 _unmarshal_int32 (pData, pDataLen, &dest->unknown_002c); 434 _unmarshal_int32 (pData, pDataLen, &dest->unknown_002c);
435 _unmarshal_uint32 (pData, pDataLen, &dest->lang_id); 435 _unmarshal_uint32 (pData, pDataLen, &dest->lang_id);
436 _unmarshal_uuid (pData, pDataLen, dest->system_uuid); 436 _unmarshal_uuid (pData, pDataLen, dest->system_uuid);
437 _unmarshal_uchar_array(pData, pDataLen, dest->unknown_0044, 16); 437 _unmarshal_uchar_array(pData, pDataLen, dest->unknown_0044, 16);
438 438
439 /* error check the data */ 439 /* error check the data */
440 if (memcmp(dest->signature, "ITSP", 4) != 0) 440 if (memcmp(dest->signature, "ITSP", 4) != 0)
441 return 0; 441 return 0;
442 if (dest->version != 1) 442 if (dest->version != 1)
443 return 0; 443 return 0;
444 if (dest->header_len != _CHM_ITSP_V1_LEN) 444 if (dest->header_len != _CHM_ITSP_V1_LEN)
445 return 0; 445 return 0;
446 446
447 return 1; 447 return 1;
448} 448}
449 449
450/* structure of PMGL headers */ 450/* structure of PMGL headers */
451static const char _chm_pmgl_marker[4] = "PMGL"; 451static const char _chm_pmgl_marker[4] = "PMGL";
452#define _CHM_PMGL_LEN (0x14) 452#define _CHM_PMGL_LEN (0x14)
453struct chmPmglHeader 453struct chmPmglHeader
454{ 454{
455 char signature[4]; /* 0 (PMGL) */ 455 char signature[4]; /* 0 (PMGL) */
456 UInt32 free_space; /* 4 */ 456 UInt32 free_space; /* 4 */
457 UInt32 unknown_0008; /* 8 */ 457 UInt32 unknown_0008; /* 8 */
458 Int32 block_prev; /* c */ 458 Int32 block_prev; /* c */
459 Int32 block_next; /* 10 */ 459 Int32 block_next; /* 10 */
460}; /* __attribute__ ((aligned (1))); */ 460}; /* __attribute__ ((aligned (1))); */
461 461
462static int _unmarshal_pmgl_header(unsigned char **pData, 462static int _unmarshal_pmgl_header(unsigned char **pData,
463 unsigned long *pDataLen, 463 unsigned long *pDataLen,
464 struct chmPmglHeader *dest) 464 struct chmPmglHeader *dest)
465{ 465{
466 /* we only know how to deal with a 0x14 byte structures */ 466 /* we only know how to deal with a 0x14 byte structures */
467 if (*pDataLen != _CHM_PMGL_LEN) 467 if (*pDataLen != _CHM_PMGL_LEN)
468 return 0; 468 return 0;
469 469
470 /* unmarshal fields */ 470 /* unmarshal fields */
471 _unmarshal_char_array(pData, pDataLen, dest->signature, 4); 471 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
472 _unmarshal_uint32 (pData, pDataLen, &dest->free_space); 472 _unmarshal_uint32 (pData, pDataLen, &dest->free_space);
473 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_0008); 473 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_0008);
474 _unmarshal_int32 (pData, pDataLen, &dest->block_prev); 474 _unmarshal_int32 (pData, pDataLen, &dest->block_prev);
475 _unmarshal_int32 (pData, pDataLen, &dest->block_next); 475 _unmarshal_int32 (pData, pDataLen, &dest->block_next);
476 476
477 /* check structure */ 477 /* check structure */
478 if (memcmp(dest->signature, _chm_pmgl_marker, 4) != 0) 478 if (memcmp(dest->signature, _chm_pmgl_marker, 4) != 0)
479 return 0; 479 return 0;
480 480
481 return 1; 481 return 1;
482} 482}
483 483
484/* structure of PMGI headers */ 484/* structure of PMGI headers */
485static const char _chm_pmgi_marker[4] = "PMGI"; 485static const char _chm_pmgi_marker[4] = "PMGI";
486#define _CHM_PMGI_LEN (0x08) 486#define _CHM_PMGI_LEN (0x08)
487struct chmPmgiHeader 487struct chmPmgiHeader
488{ 488{
489 char signature[4]; /* 0 (PMGI) */ 489 char signature[4]; /* 0 (PMGI) */
490 UInt32 free_space; /* 4 */ 490 UInt32 free_space; /* 4 */
491}; /* __attribute__ ((aligned (1))); */ 491}; /* __attribute__ ((aligned (1))); */
492 492
493static int _unmarshal_pmgi_header(unsigned char **pData, 493static int _unmarshal_pmgi_header(unsigned char **pData,
494 unsigned long *pDataLen, 494 unsigned long *pDataLen,
495 struct chmPmgiHeader *dest) 495 struct chmPmgiHeader *dest)
496{ 496{
497 /* we only know how to deal with a 0x8 byte structures */ 497 /* we only know how to deal with a 0x8 byte structures */
498 if (*pDataLen != _CHM_PMGI_LEN) 498 if (*pDataLen != _CHM_PMGI_LEN)
499 return 0; 499 return 0;
500 500
501 /* unmarshal fields */ 501 /* unmarshal fields */
502 _unmarshal_char_array(pData, pDataLen, dest->signature, 4); 502 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
503 _unmarshal_uint32 (pData, pDataLen, &dest->free_space); 503 _unmarshal_uint32 (pData, pDataLen, &dest->free_space);
504 504
505 /* check structure */ 505 /* check structure */
506 if (memcmp(dest->signature, _chm_pmgi_marker, 4) != 0) 506 if (memcmp(dest->signature, _chm_pmgi_marker, 4) != 0)
507 return 0; 507 return 0;
508 508
509 return 1; 509 return 1;
510} 510}
511 511
512/* structure of LZXC reset table */ 512/* structure of LZXC reset table */
513#define _CHM_LZXC_RESETTABLE_V1_LEN (0x28) 513#define _CHM_LZXC_RESETTABLE_V1_LEN (0x28)
514struct chmLzxcResetTable 514struct chmLzxcResetTable
515{ 515{
516 UInt32 version; 516 UInt32 version;
517 UInt32 block_count; 517 UInt32 block_count;
518 UInt32 unknown; 518 UInt32 unknown;
519 UInt32 table_offset; 519 UInt32 table_offset;
520 UInt64 uncompressed_len; 520 UInt64 uncompressed_len;
521 UInt64 compressed_len; 521 UInt64 compressed_len;
522 UInt64 block_len; 522 UInt64 block_len;
523}; /* __attribute__ ((aligned (1))); */ 523}; /* __attribute__ ((aligned (1))); */
524 524
525static int _unmarshal_lzxc_reset_table(unsigned char **pData, 525static int _unmarshal_lzxc_reset_table(unsigned char **pData,
526 unsigned long *pDataLen, 526 unsigned long *pDataLen,
527 struct chmLzxcResetTable *dest) 527 struct chmLzxcResetTable *dest)
528{ 528{
529 /* we only know how to deal with a 0x28 byte structures */ 529 /* we only know how to deal with a 0x28 byte structures */
530 if (*pDataLen != _CHM_LZXC_RESETTABLE_V1_LEN) 530 if (*pDataLen != _CHM_LZXC_RESETTABLE_V1_LEN)
531 return 0; 531 return 0;
532 532
533 /* unmarshal fields */ 533 /* unmarshal fields */
534 _unmarshal_uint32 (pData, pDataLen, &dest->version); 534 _unmarshal_uint32 (pData, pDataLen, &dest->version);
535 _unmarshal_uint32 (pData, pDataLen, &dest->block_count); 535 _unmarshal_uint32 (pData, pDataLen, &dest->block_count);
536 _unmarshal_uint32 (pData, pDataLen, &dest->unknown); 536 _unmarshal_uint32 (pData, pDataLen, &dest->unknown);
537 _unmarshal_uint32 (pData, pDataLen, &dest->table_offset); 537 _unmarshal_uint32 (pData, pDataLen, &dest->table_offset);
538 _unmarshal_uint64 (pData, pDataLen, &dest->uncompressed_len); 538 _unmarshal_uint64 (pData, pDataLen, &dest->uncompressed_len);
539 _unmarshal_uint64 (pData, pDataLen, &dest->compressed_len); 539 _unmarshal_uint64 (pData, pDataLen, &dest->compressed_len);
540 _unmarshal_uint64 (pData, pDataLen, &dest->block_len); 540 _unmarshal_uint64 (pData, pDataLen, &dest->block_len);
541 541
542 /* check structure */ 542 /* check structure */
543 if (dest->version != 2) 543 if (dest->version != 2)
544 return 0; 544 return 0;
545 545
546 return 1; 546 return 1;
547} 547}
548 548
549/* structure of LZXC control data block */ 549/* structure of LZXC control data block */
550#define _CHM_LZXC_MIN_LEN (0x18) 550#define _CHM_LZXC_MIN_LEN (0x18)
551#define _CHM_LZXC_V2_LEN (0x1c) 551#define _CHM_LZXC_V2_LEN (0x1c)
552struct chmLzxcControlData 552struct chmLzxcControlData
553{ 553{
554 UInt32 size; /* 0 */ 554 UInt32 size; /* 0 */
555 char signature[4]; /* 4 (LZXC) */ 555 char signature[4]; /* 4 (LZXC) */
556 UInt32 version; /* 8 */ 556 UInt32 version; /* 8 */
557 UInt32 resetInterval; /* c */ 557 UInt32 resetInterval; /* c */
558 UInt32 windowSize; /* 10 */ 558 UInt32 windowSize; /* 10 */
559 UInt32 unknown_14; /* 14 */ 559 UInt32 unknown_14; /* 14 */
560 UInt32 unknown_18; /* 18 */ 560 UInt32 unknown_18; /* 18 */
561}; 561};
562 562
563static int _unmarshal_lzxc_control_data(unsigned char **pData, 563static int _unmarshal_lzxc_control_data(unsigned char **pData,
564 unsigned long *pDataLen, 564 unsigned long *pDataLen,
565 struct chmLzxcControlData *dest) 565 struct chmLzxcControlData *dest)
566{ 566{
567 /* we want at least 0x18 bytes */ 567 /* we want at least 0x18 bytes */
568 if (*pDataLen < _CHM_LZXC_MIN_LEN) 568 if (*pDataLen < _CHM_LZXC_MIN_LEN)
569 return 0; 569 return 0;
570 570
571 /* unmarshal fields */ 571 /* unmarshal fields */
572 _unmarshal_uint32 (pData, pDataLen, &dest->size); 572 _unmarshal_uint32 (pData, pDataLen, &dest->size);
573 _unmarshal_char_array(pData, pDataLen, dest->signature, 4); 573 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
574 _unmarshal_uint32 (pData, pDataLen, &dest->version); 574 _unmarshal_uint32 (pData, pDataLen, &dest->version);
575 _unmarshal_uint32 (pData, pDataLen, &dest->resetInterval); 575 _unmarshal_uint32 (pData, pDataLen, &dest->resetInterval);
576 _unmarshal_uint32 (pData, pDataLen, &dest->windowSize); 576 _unmarshal_uint32 (pData, pDataLen, &dest->windowSize);
577 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_14); 577 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_14);
578 578
579 if (*pDataLen >= _CHM_LZXC_V2_LEN) 579 if (*pDataLen >= _CHM_LZXC_V2_LEN)
580 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_18); 580 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_18);
581 else 581 else
582 dest->unknown_18 = 0; 582 dest->unknown_18 = 0;
583 583
584 if (dest->version == 2) 584 if (dest->version == 2)
585 { 585 {
586 dest->resetInterval *= 0x8000; 586 dest->resetInterval *= 0x8000;
587 dest->windowSize *= 0x8000; 587 dest->windowSize *= 0x8000;
588 dest->unknown_14 *= 0x8000; 588 dest->unknown_14 *= 0x8000;
589 } 589 }
590 if (dest->windowSize == 0 || dest->resetInterval == 0) 590 if (dest->windowSize == 0 || dest->resetInterval == 0)
591 return 0; 591 return 0;
592 592
593 /* for now, only support resetInterval a multiple of windowSize/2 */ 593 /* for now, only support resetInterval a multiple of windowSize/2 */
594 if (dest->windowSize == 1) 594 if (dest->windowSize == 1)
595 return 0; 595 return 0;
596 if ((dest->resetInterval % (dest->windowSize/2)) != 0) 596 if ((dest->resetInterval % (dest->windowSize/2)) != 0)
597 return 0; 597 return 0;
598 598
599 /* check structure */ 599 /* check structure */
600 if (memcmp(dest->signature, "LZXC", 4) != 0) 600 if (memcmp(dest->signature, "LZXC", 4) != 0)
601 return 0; 601 return 0;
602 602
603 return 1; 603 return 1;
604} 604}
605 605
606/* the structure used for chm file handles */ 606/* the structure used for chm file handles */
607struct chmFile 607struct chmFile
608{ 608{
609#ifdef WIN32 609#ifdef WIN32
610 HANDLE fd; 610 HANDLE fd;
611#else 611#else
612 int fd; 612 int fd;
613#endif 613#endif
614 614
615#ifdef CHM_MT 615#ifdef CHM_MT
616#ifdef WIN32 616#ifdef WIN32
617 CRITICAL_SECTION mutex; 617 CRITICAL_SECTION mutex;
618 CRITICAL_SECTION lzx_mutex; 618 CRITICAL_SECTION lzx_mutex;
619 CRITICAL_SECTION cache_mutex; 619 CRITICAL_SECTION cache_mutex;
620#else 620#else
621 pthread_mutex_t mutex; 621 pthread_mutex_t mutex;
622 pthread_mutex_t lzx_mutex; 622 pthread_mutex_t lzx_mutex;
623 pthread_mutex_t cache_mutex; 623 pthread_mutex_t cache_mutex;
624#endif 624#endif
625#endif 625#endif
626 626
627 UInt64 dir_offset; 627 UInt64 dir_offset;
628 UInt64 dir_len; 628 UInt64 dir_len;
629 UInt64 data_offset; 629 UInt64 data_offset;
630 Int32 index_root; 630 Int32 index_root;
631 Int32 index_head; 631 Int32 index_head;
632 UInt32 block_len; 632 UInt32 block_len;
633 633
634 UInt64 span; 634 UInt64 span;
635 struct chmUnitInfo rt_unit; 635 struct chmUnitInfo rt_unit;
636 struct chmUnitInfo cn_unit; 636 struct chmUnitInfo cn_unit;
637 struct chmLzxcResetTable reset_table; 637 struct chmLzxcResetTable reset_table;
638 638
639 /* LZX control data */ 639 /* LZX control data */
640 UInt32 window_size; 640 UInt32 window_size;
641 UInt32 reset_interval; 641 UInt32 reset_interval;
642 UInt32 reset_blkcount; 642 UInt32 reset_blkcount;
643 643
644 /* decompressor state */ 644 /* decompressor state */
645 struct LZXstate *lzx_state; 645 struct LZXstate *lzx_state;
646 int lzx_last_block; 646 int lzx_last_block;
647 647
648 /* cache for decompressed blocks */ 648 /* cache for decompressed blocks */
649 UChar **cache_blocks; 649 UChar **cache_blocks;
650 Int64 *cache_block_indices; 650 Int64 *cache_block_indices;
651 Int32 cache_num_blocks; 651 Int32 cache_num_blocks;
652}; 652};
653 653
654/* 654/*
655 * utility functions local to this module 655 * utility functions local to this module
656 */ 656 */
657 657
658/* utility function to handle differences between {pread,read}(64)? */ 658/* utility function to handle differences between {pread,read}(64)? */
659static Int64 _chm_fetch_bytes(struct chmFile *h, 659static Int64 _chm_fetch_bytes(struct chmFile *h,
660 UChar *buf, 660 UChar *buf,
661 UInt64 os, 661 UInt64 os,
662 Int64 len) 662 Int64 len)
663{ 663{
664 Int64 readLen=0, oldOs=0; 664 Int64 readLen=0, oldOs=0;
665 if (h->fd == CHM_NULL_FD) 665 if (h->fd == CHM_NULL_FD)
666 return readLen; 666 return readLen;
667 667
668 CHM_ACQUIRE_LOCK(h->mutex); 668 CHM_ACQUIRE_LOCK(h->mutex);
669#ifdef CHM_USE_WIN32IO 669#ifdef CHM_USE_WIN32IO
670 /* NOTE: this might be better done with CreateFileMapping, et cetera... */ 670 /* NOTE: this might be better done with CreateFileMapping, et cetera... */
671 { 671 {
672 DWORD origOffsetLo=0, origOffsetHi=0; 672 DWORD origOffsetLo=0, origOffsetHi=0;
673 DWORD offsetLo, offsetHi; 673 DWORD offsetLo, offsetHi;
674 DWORD actualLen=0; 674 DWORD actualLen=0;
675 675
676 /* awkward Win32 Seek/Tell */ 676 /* awkward Win32 Seek/Tell */
677 offsetLo = (unsigned long)(os & 0xffffffffL); 677 offsetLo = (unsigned long)(os & 0xffffffffL);
678 offsetHi = (unsigned long)((os >> 32) & 0xffffffffL); 678 offsetHi = (unsigned long)((os >> 32) & 0xffffffffL);
679 origOffsetLo = SetFilePointer(h->fd, 0, &origOffsetHi, FILE_CURRENT); 679 origOffsetLo = SetFilePointer(h->fd, 0, &origOffsetHi, FILE_CURRENT);
680 offsetLo = SetFilePointer(h->fd, offsetLo, &offsetHi, FILE_BEGIN); 680 offsetLo = SetFilePointer(h->fd, offsetLo, &offsetHi, FILE_BEGIN);
681 681
682 /* read the data */ 682 /* read the data */
683 if (ReadFile(h->fd, 683 if (ReadFile(h->fd,
684 buf, 684 buf,
685 (DWORD)len, 685 (DWORD)len,
686 &actualLen, 686 &actualLen,
687 NULL) == TRUE) 687 NULL) == TRUE)
688 readLen = actualLen; 688 readLen = actualLen;
689 else 689 else
690 readLen = 0; 690 readLen = 0;
691 691
692 /* restore original position */ 692 /* restore original position */
693 SetFilePointer(h->fd, origOffsetLo, &origOffsetHi, FILE_BEGIN); 693 SetFilePointer(h->fd, origOffsetLo, &origOffsetHi, FILE_BEGIN);
694 } 694 }
695#else 695#else
696#ifdef CHM_USE_PREAD 696#ifdef CHM_USE_PREAD
697#ifdef CHM_USE_IO64 697#ifdef CHM_USE_IO64
698 readLen = pread64(h->fd, buf, (long)len, os); 698 readLen = pread64(h->fd, buf, (long)len, os);
699#else 699#else
700 readLen = pread(h->fd, buf, (long)len, (unsigned long)os); 700 readLen = pread(h->fd, buf, (long)len, (unsigned long)os);
701#endif 701#endif
702#else 702#else
703#ifdef CHM_USE_IO64 703#ifdef CHM_USE_IO64
704 oldOs = lseek64(h->fd, 0, SEEK_CUR); 704 oldOs = lseek64(h->fd, 0, SEEK_CUR);
705 lseek64(h->fd, os, SEEK_SET); 705 lseek64(h->fd, os, SEEK_SET);
706 readLen = read(h->fd, buf, len); 706 readLen = read(h->fd, buf, len);
707 lseek64(h->fd, oldOs, SEEK_SET); 707 lseek64(h->fd, oldOs, SEEK_SET);
708#else 708#else
709 oldOs = lseek(h->fd, 0, SEEK_CUR); 709 oldOs = lseek(h->fd, 0, SEEK_CUR);
710 lseek(h->fd, (long)os, SEEK_SET); 710 lseek(h->fd, (long)os, SEEK_SET);
711 readLen = read(h->fd, buf, len); 711 readLen = read(h->fd, buf, len);
712 lseek(h->fd, (long)oldOs, SEEK_SET); 712 lseek(h->fd, (long)oldOs, SEEK_SET);
713#endif 713#endif
714#endif 714#endif
715#endif 715#endif
716 CHM_RELEASE_LOCK(h->mutex); 716 CHM_RELEASE_LOCK(h->mutex);
717 return readLen; 717 return readLen;
718} 718}
719 719
720/* open an ITS archive */ 720/* open an ITS archive */
721struct chmFile *chm_open(const char *filename) 721struct chmFile *chm_open(const char *filename)
722{ 722{
723 unsigned char sbuffer[256]; 723 unsigned char sbuffer[256];
724 unsigned long sremain; 724 unsigned long sremain;
725 unsigned char *sbufpos; 725 unsigned char *sbufpos;
726 struct chmFile *newHandle=NULL; 726 struct chmFile *newHandle=NULL;
727 struct chmItsfHeader itsfHeader; 727 struct chmItsfHeader itsfHeader;
728 struct chmItspHeader itspHeader; 728 struct chmItspHeader itspHeader;
729 struct chmUnitInfo uiSpan; 729 struct chmUnitInfo uiSpan;
730 struct chmUnitInfo uiLzxc; 730 struct chmUnitInfo uiLzxc;
731 struct chmLzxcControlData ctlData; 731 struct chmLzxcControlData ctlData;
732 732
733 /* allocate handle */ 733 /* allocate handle */
734 newHandle = (struct chmFile *)malloc(sizeof(struct chmFile)); 734 newHandle = (struct chmFile *)malloc(sizeof(struct chmFile));
735 newHandle->fd = CHM_NULL_FD; 735 newHandle->fd = CHM_NULL_FD;
736 newHandle->lzx_state = NULL; 736 newHandle->lzx_state = NULL;
737 newHandle->cache_blocks = NULL; 737 newHandle->cache_blocks = NULL;
738 newHandle->cache_block_indices = NULL; 738 newHandle->cache_block_indices = NULL;
739 newHandle->cache_num_blocks = 0; 739 newHandle->cache_num_blocks = 0;
740 740
741 /* open file */ 741 /* open file */
742#ifdef WIN32 742#ifdef WIN32
743 if ((newHandle->fd=CreateFileA(filename, 743 if ((newHandle->fd=CreateFileA(filename,
744 GENERIC_READ, 744 GENERIC_READ,
745 0, 745 0,
746 NULL, 746 NULL,
747 OPEN_EXISTING, 747 OPEN_EXISTING,
748 FILE_ATTRIBUTE_NORMAL, 748 FILE_ATTRIBUTE_NORMAL,
749 NULL)) == CHM_NULL_FD) 749 NULL)) == CHM_NULL_FD)
750 { 750 {
751 free(newHandle); 751 free(newHandle);
752 return NULL; 752 return NULL;
753 } 753 }
754#else 754#else
755 if ((newHandle->fd=open(filename, O_RDONLY)) == CHM_NULL_FD) 755 if ((newHandle->fd=open(filename, O_RDONLY)) == CHM_NULL_FD)
756 { 756 {
757 free(newHandle); 757 free(newHandle);
758 return NULL; 758 return NULL;
759 } 759 }
760#endif 760#endif
761 761
762 /* initialize mutexes, if needed */ 762 /* initialize mutexes, if needed */
763#ifdef CHM_MT 763#ifdef CHM_MT
764#ifdef WIN32 764#ifdef WIN32
765 InitializeCriticalSection(&newHandle->mutex); 765 InitializeCriticalSection(&newHandle->mutex);
766 InitializeCriticalSection(&newHandle->lzx_mutex); 766 InitializeCriticalSection(&newHandle->lzx_mutex);
767 InitializeCriticalSection(&newHandle->cache_mutex); 767 InitializeCriticalSection(&newHandle->cache_mutex);
768#else 768#else
769 pthread_mutex_init(&newHandle->mutex, NULL); 769 pthread_mutex_init(&newHandle->mutex, NULL);
770 pthread_mutex_init(&newHandle->lzx_mutex, NULL); 770 pthread_mutex_init(&newHandle->lzx_mutex, NULL);
771 pthread_mutex_init(&newHandle->cache_mutex, NULL); 771 pthread_mutex_init(&newHandle->cache_mutex, NULL);
772#endif 772#endif
773#endif 773#endif
774 774
775 /* read and verify header */ 775 /* read and verify header */
776 sremain = _CHM_ITSF_V3_LEN; 776 sremain = _CHM_ITSF_V3_LEN;
777 sbufpos = sbuffer; 777 sbufpos = sbuffer;
778 if (_chm_fetch_bytes(newHandle, sbuffer, (UInt64)0, sremain) != sremain || 778 if (_chm_fetch_bytes(newHandle, sbuffer, (UInt64)0, sremain) != sremain ||
779 !_unmarshal_itsf_header(&sbufpos, &sremain, &itsfHeader)) 779 !_unmarshal_itsf_header(&sbufpos, &sremain, &itsfHeader))
780 { 780 {
781 chm_close(newHandle); 781 chm_close(newHandle);
782 return NULL; 782 return NULL;
783 } 783 }
784 784
785 /* stash important values from header */ 785 /* stash important values from header */
786 newHandle->dir_offset = itsfHeader.dir_offset; 786 newHandle->dir_offset = itsfHeader.dir_offset;
787 newHandle->dir_len = itsfHeader.dir_len; 787 newHandle->dir_len = itsfHeader.dir_len;
788 newHandle->data_offset = itsfHeader.data_offset; 788 newHandle->data_offset = itsfHeader.data_offset;
789 789
790 /* now, read and verify the directory header chunk */ 790 /* now, read and verify the directory header chunk */
791 sremain = _CHM_ITSP_V1_LEN; 791 sremain = _CHM_ITSP_V1_LEN;
792 sbufpos = sbuffer; 792 sbufpos = sbuffer;
793 if (_chm_fetch_bytes(newHandle, sbuffer, 793 if (_chm_fetch_bytes(newHandle, sbuffer,
794 (UInt64)itsfHeader.dir_offset, sremain) != sremain || 794 (UInt64)itsfHeader.dir_offset, sremain) != sremain ||
795 !_unmarshal_itsp_header(&sbufpos, &sremain, &itspHeader)) 795 !_unmarshal_itsp_header(&sbufpos, &sremain, &itspHeader))
796 { 796 {
797 chm_close(newHandle); 797 chm_close(newHandle);
798 return NULL; 798 return NULL;
799 } 799 }
800 800
801 /* grab essential information from ITSP header */ 801 /* grab essential information from ITSP header */
802 newHandle->dir_offset += itspHeader.header_len; 802 newHandle->dir_offset += itspHeader.header_len;
803 newHandle->dir_len -= itspHeader.header_len; 803 newHandle->dir_len -= itspHeader.header_len;
804 newHandle->index_root = itspHeader.index_root; 804 newHandle->index_root = itspHeader.index_root;
805 newHandle->index_head = itspHeader.index_head; 805 newHandle->index_head = itspHeader.index_head;
806 newHandle->block_len = itspHeader.block_len; 806 newHandle->block_len = itspHeader.block_len;
807 807
808 /* if the index root is -1, this means we don't have any PMGI blocks. 808 /* if the index root is -1, this means we don't have any PMGI blocks.
809 * as a result, we must use the sole PMGL block as the index root 809 * as a result, we must use the sole PMGL block as the index root
810 */ 810 */
811 if (newHandle->index_root == -1) 811 if (newHandle->index_root == -1)
812 newHandle->index_root = newHandle->index_head; 812 newHandle->index_root = newHandle->index_head;
813 813
814 /* prefetch most commonly needed unit infos */ 814 /* prefetch most commonly needed unit infos */
815 if (CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle, 815 if (CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle,
816 _CHMU_SPANINFO, 816 _CHMU_SPANINFO,
817 &uiSpan) || 817 &uiSpan) ||
818 uiSpan.space == CHM_COMPRESSED || 818 uiSpan.space == CHM_COMPRESSED ||
819 CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle, 819 CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle,
820 _CHMU_RESET_TABLE, 820 _CHMU_RESET_TABLE,
821 &newHandle->rt_unit) || 821 &newHandle->rt_unit) ||
822 newHandle->rt_unit.space == CHM_COMPRESSED || 822 newHandle->rt_unit.space == CHM_COMPRESSED ||
823 CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle, 823 CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle,
824 _CHMU_CONTENT, 824 _CHMU_CONTENT,
825 &newHandle->cn_unit) || 825 &newHandle->cn_unit) ||
826 newHandle->cn_unit.space == CHM_COMPRESSED || 826 newHandle->cn_unit.space == CHM_COMPRESSED ||
827 CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle, 827 CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle,
828 _CHMU_LZXC_CONTROLDATA, 828 _CHMU_LZXC_CONTROLDATA,
829 &uiLzxc) || 829 &uiLzxc) ||
830 uiLzxc.space == CHM_COMPRESSED) 830 uiLzxc.space == CHM_COMPRESSED)
831 { 831 {
832 chm_close(newHandle); 832 chm_close(newHandle);
833 return NULL; 833 return NULL;
834 } 834 }
835 835
836 /* try to read span */ 836 /* try to read span */
837 /* N.B.: we've already checked that uiSpan is in the uncompressed section, 837 /* N.B.: we've already checked that uiSpan is in the uncompressed section,
838 * so this should not require attempting to decompress, which may 838 * so this should not require attempting to decompress, which may
839 * rely on having a valid "span" 839 * rely on having a valid "span"
840 */ 840 */
841 sremain = 8; 841 sremain = 8;
842 sbufpos = sbuffer; 842 sbufpos = sbuffer;
843 if (chm_retrieve_object(newHandle, &uiSpan, sbuffer, 843 if (chm_retrieve_object(newHandle, &uiSpan, sbuffer,
844 0, sremain) != sremain || 844 0, sremain) != sremain ||
845 !_unmarshal_uint64(&sbufpos, &sremain, &newHandle->span)) 845 !_unmarshal_uint64(&sbufpos, &sremain, &newHandle->span))
846 { 846 {
847 chm_close(newHandle); 847 chm_close(newHandle);
848 return NULL; 848 return NULL;
849 } 849 }
850 850
851 /* read reset table info */ 851 /* read reset table info */
852 sremain = _CHM_LZXC_RESETTABLE_V1_LEN; 852 sremain = _CHM_LZXC_RESETTABLE_V1_LEN;
853 sbufpos = sbuffer; 853 sbufpos = sbuffer;
854 if (chm_retrieve_object(newHandle, &newHandle->rt_unit, sbuffer, 854 if (chm_retrieve_object(newHandle, &newHandle->rt_unit, sbuffer,
855 0, sremain) != sremain || 855 0, sremain) != sremain ||
856 !_unmarshal_lzxc_reset_table(&sbufpos, &sremain, 856 !_unmarshal_lzxc_reset_table(&sbufpos, &sremain,
857 &newHandle->reset_table)) 857 &newHandle->reset_table))
858 { 858 {
859 chm_close(newHandle); 859 chm_close(newHandle);
860 return NULL; 860 return NULL;
861 } 861 }
862 862
863 /* read control data */ 863 /* read control data */
864 sremain = (unsigned long)uiLzxc.length; 864 sremain = (unsigned long)uiLzxc.length;
865 sbufpos = sbuffer; 865 sbufpos = sbuffer;
866 if (chm_retrieve_object(newHandle, &uiLzxc, sbuffer, 866 if (chm_retrieve_object(newHandle, &uiLzxc, sbuffer,
867 0, sremain) != sremain || 867 0, sremain) != sremain ||
868 !_unmarshal_lzxc_control_data(&sbufpos, &sremain, 868 !_unmarshal_lzxc_control_data(&sbufpos, &sremain,
869 &ctlData)) 869 &ctlData))
870 { 870 {
871 chm_close(newHandle); 871 chm_close(newHandle);
872 return NULL; 872 return NULL;
873 } 873 }
874 newHandle->window_size = ctlData.windowSize; 874 newHandle->window_size = ctlData.windowSize;
875 newHandle->reset_interval = ctlData.resetInterval; 875 newHandle->reset_interval = ctlData.resetInterval;
876 newHandle->reset_blkcount = newHandle->reset_interval / 876 newHandle->reset_blkcount = newHandle->reset_interval /
877 (newHandle->window_size / 2); 877 (newHandle->window_size / 2);
878 878
879 /* initialize cache */ 879 /* initialize cache */
880 chm_set_param(newHandle, CHM_PARAM_MAX_BLOCKS_CACHED, 880 chm_set_param(newHandle, CHM_PARAM_MAX_BLOCKS_CACHED,
881 CHM_MAX_BLOCKS_CACHED); 881 CHM_MAX_BLOCKS_CACHED);
882 882
883 return newHandle; 883 return newHandle;
884} 884}
885 885
886/* close an ITS archive */ 886/* close an ITS archive */
887void chm_close(struct chmFile *h) 887void chm_close(struct chmFile *h)
888{ 888{
889 if (h != NULL) 889 if (h != NULL)
890 { 890 {
891 if (h->fd != CHM_NULL_FD) 891 if (h->fd != CHM_NULL_FD)
892 CHM_CLOSE_FILE(h->fd); 892 CHM_CLOSE_FILE(h->fd);
893 h->fd = CHM_NULL_FD; 893 h->fd = CHM_NULL_FD;
894 894
895#ifdef CHM_MT 895#ifdef CHM_MT
896#ifdef WIN32 896#ifdef WIN32
897 DeleteCriticalSection(&h->mutex); 897 DeleteCriticalSection(&h->mutex);
898 DeleteCriticalSection(&h->lzx_mutex); 898 DeleteCriticalSection(&h->lzx_mutex);
899 DeleteCriticalSection(&h->cache_mutex); 899 DeleteCriticalSection(&h->cache_mutex);
900#else 900#else
901 pthread_mutex_destroy(&h->mutex); 901 pthread_mutex_destroy(&h->mutex);
902 pthread_mutex_destroy(&h->lzx_mutex); 902 pthread_mutex_destroy(&h->lzx_mutex);
903 pthread_mutex_destroy(&h->cache_mutex); 903 pthread_mutex_destroy(&h->cache_mutex);
904#endif 904#endif
905#endif 905#endif
906 906
907 if (h->lzx_state) 907 if (h->lzx_state)
908 LZXteardown(h->lzx_state); 908 LZXteardown(h->lzx_state);
909 h->lzx_state = NULL; 909 h->lzx_state = NULL;
910 910
911 if (h->cache_blocks) 911 if (h->cache_blocks)
912 { 912 {
913 int i; 913 int i;
914 for (i=0; i<h->cache_num_blocks; i++) 914 for (i=0; i<h->cache_num_blocks; i++)
915 { 915 {
916 if (h->cache_blocks[i]) 916 if (h->cache_blocks[i])
917 free(h->cache_blocks[i]); 917 free(h->cache_blocks[i]);
918 } 918 }
919 free(h->cache_blocks); 919 free(h->cache_blocks);
920 h->cache_blocks = NULL; 920 h->cache_blocks = NULL;
921 } 921 }
922 922
923 if (h->cache_block_indices) 923 if (h->cache_block_indices)
924 free(h->cache_block_indices); 924 free(h->cache_block_indices);
925 h->cache_block_indices = NULL; 925 h->cache_block_indices = NULL;
926 926
927 free(h); 927 free(h);
928 } 928 }
929} 929}
930 930
931/* 931/*
932 * set a parameter on the file handle. 932 * set a parameter on the file handle.
933 * valid parameter types: 933 * valid parameter types:
934 * CHM_PARAM_MAX_BLOCKS_CACHED: 934 * CHM_PARAM_MAX_BLOCKS_CACHED:
935 * how many decompressed blocks should be cached? A simple 935 * how many decompressed blocks should be cached? A simple
936 * caching scheme is used, wherein the index of the block is 936 * caching scheme is used, wherein the index of the block is
937 * used as a hash value, and hash collision results in the 937 * used as a hash value, and hash collision results in the
938 * invalidation of the previously cached block. 938 * invalidation of the previously cached block.
939 */ 939 */
940void chm_set_param(struct chmFile *h, 940void chm_set_param(struct chmFile *h,
941 int paramType, 941 int paramType,
942 int paramVal) 942 int paramVal)
943{ 943{
944 switch (paramType) 944 switch (paramType)
945 { 945 {
946 case CHM_PARAM_MAX_BLOCKS_CACHED: 946 case CHM_PARAM_MAX_BLOCKS_CACHED:
947 CHM_ACQUIRE_LOCK(h->cache_mutex); 947 CHM_ACQUIRE_LOCK(h->cache_mutex);
948 if (paramVal != h->cache_num_blocks) 948 if (paramVal != h->cache_num_blocks)
949 { 949 {
950 UChar **newBlocks; 950 UChar **newBlocks;
951 UInt64 *newIndices; 951 UInt64 *newIndices;
952 int i; 952 int i;
953 953
954 /* allocate new cached blocks */ 954 /* allocate new cached blocks */
955 newBlocks = (UChar **)malloc(paramVal * sizeof (UChar *)); 955 newBlocks = (UChar **)malloc(paramVal * sizeof (UChar *));
956 newIndices = (UInt64 *)malloc(paramVal * sizeof (UInt64)); 956 newIndices = (UInt64 *)malloc(paramVal * sizeof (UInt64));
957 for (i=0; i<paramVal; i++) 957 for (i=0; i<paramVal; i++)
958 { 958 {
959 newBlocks[i] = NULL; 959 newBlocks[i] = NULL;
960 newIndices[i] = 0; 960 newIndices[i] = 0;
961 } 961 }
962 962
963 /* re-distribute old cached blocks */ 963 /* re-distribute old cached blocks */
964 if (h->cache_blocks) 964 if (h->cache_blocks)
965 { 965 {
966 for (i=0; i<h->cache_num_blocks; i++) 966 for (i=0; i<h->cache_num_blocks; i++)
967 { 967 {
968 int newSlot = (int)(h->cache_block_indices[i] % paramVal); 968 int newSlot = (int)(h->cache_block_indices[i] % paramVal);
969 969
970 if (h->cache_blocks[i]) 970 if (h->cache_blocks[i])
971 { 971 {
972 /* in case of collision, destroy newcomer */ 972 /* in case of collision, destroy newcomer */
973 if (newBlocks[newSlot]) 973 if (newBlocks[newSlot])
974 { 974 {
975 free(h->cache_blocks[i]); 975 free(h->cache_blocks[i]);
976 h->cache_blocks[i] = NULL; 976 h->cache_blocks[i] = NULL;
977 } 977 }
978 else 978 else
979 { 979 {
980 newBlocks[newSlot] = h->cache_blocks[i]; 980 newBlocks[newSlot] = h->cache_blocks[i];
981 newIndices[newSlot] = 981 newIndices[newSlot] =
982 h->cache_block_indices[i]; 982 h->cache_block_indices[i];
983 } 983 }
984 } 984 }
985 } 985 }
986 986
987 free(h->cache_blocks); 987 free(h->cache_blocks);
988 free(h->cache_block_indices); 988 free(h->cache_block_indices);
989 } 989 }
990 990
991 /* now, set new values */ 991 /* now, set new values */
992 h->cache_blocks = newBlocks; 992 h->cache_blocks = newBlocks;
993 h->cache_block_indices = newIndices; 993 h->cache_block_indices = newIndices;
994 h->cache_num_blocks = paramVal; 994 h->cache_num_blocks = paramVal;
995 } 995 }
996 CHM_RELEASE_LOCK(h->cache_mutex); 996 CHM_RELEASE_LOCK(h->cache_mutex);
997 break; 997 break;
998 998
999 default: 999 default:
1000 break; 1000 break;
1001 } 1001 }
1002} 1002}
1003 1003
1004/* 1004/*
1005 * helper methods for chm_resolve_object 1005 * helper methods for chm_resolve_object
1006 */ 1006 */
1007 1007
1008/* skip a compressed dword */ 1008/* skip a compressed dword */
1009static void _chm_skip_cword(UChar **pEntry) 1009static void _chm_skip_cword(UChar **pEntry)
1010{ 1010{
1011 while (*(*pEntry)++ >= 0x80) 1011 while (*(*pEntry)++ >= 0x80)
1012 ; 1012 ;
1013} 1013}
1014 1014
1015/* skip the data from a PMGL entry */ 1015/* skip the data from a PMGL entry */
1016static void _chm_skip_PMGL_entry_data(UChar **pEntry) 1016static void _chm_skip_PMGL_entry_data(UChar **pEntry)
1017{ 1017{
1018 _chm_skip_cword(pEntry); 1018 _chm_skip_cword(pEntry);
1019 _chm_skip_cword(pEntry); 1019 _chm_skip_cword(pEntry);
1020 _chm_skip_cword(pEntry); 1020 _chm_skip_cword(pEntry);
1021} 1021}
1022 1022
1023/* parse a compressed dword */ 1023/* parse a compressed dword */
1024static UInt64 _chm_parse_cword(UChar **pEntry) 1024static UInt64 _chm_parse_cword(UChar **pEntry)
1025{ 1025{
1026 UInt64 accum = 0; 1026 UInt64 accum = 0;
1027 UChar temp; 1027 UChar temp;
1028 while ((temp=*(*pEntry)++) >= 0x80) 1028 while ((temp=*(*pEntry)++) >= 0x80)
1029 { 1029 {
1030 accum <<= 7; 1030 accum <<= 7;
1031 accum += temp & 0x7f; 1031 accum += temp & 0x7f;
1032 } 1032 }
1033 1033
1034 return (accum << 7) + temp; 1034 return (accum << 7) + temp;
1035} 1035}
1036 1036
1037/* parse a utf-8 string into an ASCII char buffer */ 1037/* parse a utf-8 string into an ASCII char buffer */
1038static int _chm_parse_UTF8(UChar **pEntry, UInt64 count, char *path) 1038static int _chm_parse_UTF8(UChar **pEntry, UInt64 count, char *path)
1039{ 1039{
1040 /* XXX: implement UTF-8 support, including a real mapping onto 1040 /* XXX: implement UTF-8 support, including a real mapping onto
1041 * ISO-8859-1? probably there is a library to do this? As is 1041 * ISO-8859-1? probably there is a library to do this? As is
1042 * immediately apparent from the below code, I'm only handling files 1042 * immediately apparent from the below code, I'm only handling files
1043 * in which none of the strings contain UTF-8 multi-byte characters. 1043 * in which none of the strings contain UTF-8 multi-byte characters.
1044 */ 1044 */
1045 while (count != 0) 1045 while (count != 0)
1046 { 1046 {
1047 if (*(*pEntry) > 0x7f) 1047 if (*(*pEntry) > 0x7f)
1048 return 0; 1048 return 0;
1049 1049
1050 *path++ = (char)(*(*pEntry)++); 1050 *path++ = (char)(*(*pEntry)++);
1051 --count; 1051 --count;
1052 } 1052 }
1053 1053
1054 *path = '\0'; 1054 *path = '\0';
1055 return 1; 1055 return 1;
1056} 1056}
1057 1057
1058/* parse a PMGL entry into a chmUnitInfo struct; return 1 on success. */ 1058/* parse a PMGL entry into a chmUnitInfo struct; return 1 on success. */
1059static int _chm_parse_PMGL_entry(UChar **pEntry, struct chmUnitInfo *ui) 1059static int _chm_parse_PMGL_entry(UChar **pEntry, struct chmUnitInfo *ui)
1060{ 1060{
1061 UInt64 strLen; 1061 UInt64 strLen;
1062 1062
1063 /* parse str len */ 1063 /* parse str len */
1064 strLen = _chm_parse_cword(pEntry); 1064 strLen = _chm_parse_cword(pEntry);
1065 if (strLen > CHM_MAX_PATHLEN) 1065 if (strLen > CHM_MAX_PATHLEN)
1066 return 0; 1066 return 0;
1067 1067
1068 /* parse path */ 1068 /* parse path */
1069 if (! _chm_parse_UTF8(pEntry, strLen, ui->path)) 1069 if (! _chm_parse_UTF8(pEntry, strLen, ui->path))
1070 return 0; 1070 return 0;
1071 1071
1072 /* parse info */ 1072 /* parse info */
1073 ui->space = (int)_chm_parse_cword(pEntry); 1073 ui->space = (int)_chm_parse_cword(pEntry);
1074 ui->start = _chm_parse_cword(pEntry); 1074 ui->start = _chm_parse_cword(pEntry);
1075 ui->length = _chm_parse_cword(pEntry); 1075 ui->length = _chm_parse_cword(pEntry);
1076 return 1; 1076 return 1;
1077} 1077}
1078 1078
1079/* find an exact entry in PMGL; return NULL if we fail */ 1079/* find an exact entry in PMGL; return NULL if we fail */
1080static UChar *_chm_find_in_PMGL(UChar *page_buf, 1080static UChar *_chm_find_in_PMGL(UChar *page_buf,
1081 UInt32 block_len, 1081 UInt32 block_len,
1082 const char *objPath) 1082 const char *objPath)
1083{ 1083{
1084 /* XXX: modify this to do a binary search using the nice index structure 1084 /* XXX: modify this to do a binary search using the nice index structure
1085 * that is provided for us. 1085 * that is provided for us.
1086 */ 1086 */
1087 struct chmPmglHeader header; 1087 struct chmPmglHeader header;
1088 UInt32 hremain; 1088 UInt32 hremain;
1089 UChar *end; 1089 UChar *end;
1090 UChar *cur; 1090 UChar *cur;
1091 UChar *temp; 1091 UChar *temp;
1092 UInt64 strLen; 1092 UInt64 strLen;
1093 char buffer[CHM_MAX_PATHLEN+1]; 1093 char buffer[CHM_MAX_PATHLEN+1];
1094 1094
1095 /* figure out where to start and end */ 1095 /* figure out where to start and end */
1096 cur = page_buf; 1096 cur = page_buf;
1097 hremain = _CHM_PMGL_LEN; 1097 hremain = _CHM_PMGL_LEN;
1098 if (! _unmarshal_pmgl_header(&cur, &hremain, &header)) 1098 if (! _unmarshal_pmgl_header(&cur, &hremain, &header))
1099 return NULL; 1099 return NULL;
1100 end = page_buf + block_len - (header.free_space); 1100 end = page_buf + block_len - (header.free_space);
1101 1101
1102 /* now, scan progressively */ 1102 /* now, scan progressively */
1103 while (cur < end) 1103 while (cur < end)
1104 { 1104 {
1105 /* grab the name */ 1105 /* grab the name */
1106 temp = cur; 1106 temp = cur;
1107 strLen = _chm_parse_cword(&cur); 1107 strLen = _chm_parse_cword(&cur);
1108 if (! _chm_parse_UTF8(&cur, strLen, buffer)) 1108 if (! _chm_parse_UTF8(&cur, strLen, buffer))
1109 return NULL; 1109 return NULL;
1110 1110
1111 /* check if it is the right name */ 1111 /* check if it is the right name */
1112#ifdef WIN32 1112#ifdef WIN32
1113 if (! stricmp(buffer, objPath)) 1113 if (! stricmp(buffer, objPath))
1114 return temp; 1114 return temp;
1115#else 1115#else
1116 if (! strcasecmp(buffer, objPath)) 1116 if (! strcasecmp(buffer, objPath))
1117 return temp; 1117 return temp;
1118#endif 1118#endif
1119 1119
1120 _chm_skip_PMGL_entry_data(&cur); 1120 _chm_skip_PMGL_entry_data(&cur);
1121 } 1121 }
1122 1122
1123 return NULL; 1123 return NULL;
1124} 1124}
1125 1125
1126/* find which block should be searched next for the entry; -1 if no block */ 1126/* find which block should be searched next for the entry; -1 if no block */
1127static Int32 _chm_find_in_PMGI(UChar *page_buf, 1127static Int32 _chm_find_in_PMGI(UChar *page_buf,
1128 UInt32 block_len, 1128 UInt32 block_len,
1129 const char *objPath) 1129 const char *objPath)
1130{ 1130{
1131 /* XXX: modify this to do a binary search using the nice index structure 1131 /* XXX: modify this to do a binary search using the nice index structure
1132 * that is provided for us 1132 * that is provided for us
1133 */ 1133 */
1134 struct chmPmgiHeader header; 1134 struct chmPmgiHeader header;
1135 UInt32 hremain; 1135 UInt32 hremain;
1136 int page=-1; 1136 int page=-1;
1137 UChar *end; 1137 UChar *end;
1138 UChar *cur; 1138 UChar *cur;
1139 UInt64 strLen; 1139 UInt64 strLen;
1140 char buffer[CHM_MAX_PATHLEN+1]; 1140 char buffer[CHM_MAX_PATHLEN+1];
1141 1141
1142 /* figure out where to start and end */ 1142 /* figure out where to start and end */
1143 cur = page_buf; 1143 cur = page_buf;
1144 hremain = _CHM_PMGI_LEN; 1144 hremain = _CHM_PMGI_LEN;
1145 if (! _unmarshal_pmgi_header(&cur, &hremain, &header)) 1145 if (! _unmarshal_pmgi_header(&cur, &hremain, &header))
1146 return -1; 1146 return -1;
1147 end = page_buf + block_len - (header.free_space); 1147 end = page_buf + block_len - (header.free_space);
1148 1148
1149 /* now, scan progressively */ 1149 /* now, scan progressively */
1150 while (cur < end) 1150 while (cur < end)
1151 { 1151 {
1152 /* grab the name */ 1152 /* grab the name */
1153 strLen = _chm_parse_cword(&cur); 1153 strLen = _chm_parse_cword(&cur);
1154 if (! _chm_parse_UTF8(&cur, strLen, buffer)) 1154 if (! _chm_parse_UTF8(&cur, strLen, buffer))
1155 return -1; 1155 return -1;
1156 1156
1157 /* check if it is the right name */ 1157 /* check if it is the right name */
1158#ifdef WIN32 1158#ifdef WIN32
1159 if (stricmp(buffer, objPath) > 0) 1159 if (stricmp(buffer, objPath) > 0)
1160 return page; 1160 return page;
1161#else 1161#else
1162 if (strcasecmp(buffer, objPath) > 0) 1162 if (strcasecmp(buffer, objPath) > 0)
1163 return page; 1163 return page;
1164#endif 1164#endif
1165 1165
1166 /* load next value for path */ 1166 /* load next value for path */
1167 page = (int)_chm_parse_cword(&cur); 1167 page = (int)_chm_parse_cword(&cur);
1168 } 1168 }
1169 1169
1170 return page; 1170 return page;
1171} 1171}
1172 1172
1173/* resolve a particular object from the archive */ 1173/* resolve a particular object from the archive */
1174int chm_resolve_object(struct chmFile *h, 1174int chm_resolve_object(struct chmFile *h,
1175 const char *objPath, 1175 const char *objPath,
1176 struct chmUnitInfo *ui) 1176 struct chmUnitInfo *ui)
1177{ 1177{
1178 /* 1178 /*
1179 * XXX: implement caching scheme for dir pages 1179 * XXX: implement caching scheme for dir pages
1180 */ 1180 */
1181 1181
1182 Int32 curPage; 1182 Int32 curPage;
1183 1183
1184 /* buffer to hold whatever page we're looking at */ 1184 /* buffer to hold whatever page we're looking at */
1185#ifdef WIN32 1185#ifdef WIN32
1186 UChar *page_buf = alloca(h->block_len); 1186 UChar *page_buf = alloca(h->block_len);
1187#else 1187#else
1188 UChar page_buf[h->block_len]; 1188 UChar page_buf[h->block_len];
1189#endif 1189#endif
1190 1190
1191 /* starting page */ 1191 /* starting page */
1192 curPage = h->index_root; 1192 curPage = h->index_root;
1193 1193
1194 /* until we have either returned or given up */ 1194 /* until we have either returned or given up */
1195 while (curPage != -1) 1195 while (curPage != -1)
1196 { 1196 {
1197 1197
1198 /* try to fetch the index page */ 1198 /* try to fetch the index page */
1199 if (_chm_fetch_bytes(h, page_buf, 1199 if (_chm_fetch_bytes(h, page_buf,
1200 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len, 1200 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len,
1201 h->block_len) != h->block_len) 1201 h->block_len) != h->block_len)
1202 return CHM_RESOLVE_FAILURE; 1202 return CHM_RESOLVE_FAILURE;
1203 1203
1204 /* now, if it is a leaf node: */ 1204 /* now, if it is a leaf node: */
1205 if (memcmp(page_buf, _chm_pmgl_marker, 4) == 0) 1205 if (memcmp(page_buf, _chm_pmgl_marker, 4) == 0)
1206 { 1206 {
1207 /* scan block */ 1207 /* scan block */
1208 UChar *pEntry = _chm_find_in_PMGL(page_buf, 1208 UChar *pEntry = _chm_find_in_PMGL(page_buf,
1209 h->block_len, 1209 h->block_len,
1210 objPath); 1210 objPath);
1211 if (pEntry == NULL) 1211 if (pEntry == NULL)
1212 return CHM_RESOLVE_FAILURE; 1212 return CHM_RESOLVE_FAILURE;
1213 1213
1214 /* parse entry and return */ 1214 /* parse entry and return */
1215 _chm_parse_PMGL_entry(&pEntry, ui); 1215 _chm_parse_PMGL_entry(&pEntry, ui);
1216 return CHM_RESOLVE_SUCCESS; 1216 return CHM_RESOLVE_SUCCESS;
1217 } 1217 }
1218 1218
1219 /* else, if it is a branch node: */ 1219 /* else, if it is a branch node: */
1220 else if (memcmp(page_buf, _chm_pmgi_marker, 4) == 0) 1220 else if (memcmp(page_buf, _chm_pmgi_marker, 4) == 0)
1221 curPage = _chm_find_in_PMGI(page_buf, h->block_len, objPath); 1221 curPage = _chm_find_in_PMGI(page_buf, h->block_len, objPath);
1222 1222
1223 /* else, we are confused. give up. */ 1223 /* else, we are confused. give up. */
1224 else 1224 else
1225 return CHM_RESOLVE_FAILURE; 1225 return CHM_RESOLVE_FAILURE;
1226 } 1226 }
1227 1227
1228 /* didn't find anything. fail. */ 1228 /* didn't find anything. fail. */
1229 return CHM_RESOLVE_FAILURE; 1229 return CHM_RESOLVE_FAILURE;
1230} 1230}
1231 1231
1232/* 1232/*
1233 * utility methods for dealing with compressed data 1233 * utility methods for dealing with compressed data
1234 */ 1234 */
1235 1235
1236/* get the bounds of a compressed block. return 0 on failure */ 1236/* get the bounds of a compressed block. return 0 on failure */
1237static int _chm_get_cmpblock_bounds(struct chmFile *h, 1237static int _chm_get_cmpblock_bounds(struct chmFile *h,
1238 UInt64 block, 1238 UInt64 block,
1239 UInt64 *start, 1239 UInt64 *start,
1240 Int64 *len) 1240 Int64 *len)
1241{ 1241{
1242 UChar buffer[8], *dummy; 1242 UChar buffer[8], *dummy;
1243 UInt32 remain; 1243 UInt32 remain;
1244 1244
1245 /* for all but the last block, use the reset table */ 1245 /* for all but the last block, use the reset table */
1246 if (block < h->reset_table.block_count-1) 1246 if (block < h->reset_table.block_count-1)
1247 { 1247 {
1248 /* unpack the start address */ 1248 /* unpack the start address */
1249 dummy = buffer; 1249 dummy = buffer;
1250 remain = 8; 1250 remain = 8;
1251 if (_chm_fetch_bytes(h, buffer, 1251 if (_chm_fetch_bytes(h, buffer,
1252 (UInt64)h->data_offset 1252 (UInt64)h->data_offset
1253 + (UInt64)h->rt_unit.start 1253 + (UInt64)h->rt_unit.start
1254 + (UInt64)h->reset_table.table_offset 1254 + (UInt64)h->reset_table.table_offset
1255 + (UInt64)block*8, 1255 + (UInt64)block*8,
1256 remain) != remain || 1256 remain) != remain ||
1257 !_unmarshal_uint64(&dummy, &remain, start)) 1257 !_unmarshal_uint64(&dummy, &remain, start))
1258 return 0; 1258 return 0;
1259 1259
1260 /* unpack the end address */ 1260 /* unpack the end address */
1261 dummy = buffer; 1261 dummy = buffer;
1262 remain = 8; 1262 remain = 8;
1263 if (_chm_fetch_bytes(h, buffer, 1263 if (_chm_fetch_bytes(h, buffer,
1264 (UInt64)h->data_offset 1264 (UInt64)h->data_offset
1265 + (UInt64)h->rt_unit.start 1265 + (UInt64)h->rt_unit.start
1266 + (UInt64)h->reset_table.table_offset 1266 + (UInt64)h->reset_table.table_offset
1267 + (UInt64)block*8 + 8, 1267 + (UInt64)block*8 + 8,
1268 remain) != remain || 1268 remain) != remain ||
1269 !_unmarshal_int64(&dummy, &remain, len)) 1269 !_unmarshal_int64(&dummy, &remain, len))
1270 return 0; 1270 return 0;
1271 } 1271 }
1272 1272
1273 /* for the last block, use the span in addition to the reset table */ 1273 /* for the last block, use the span in addition to the reset table */
1274 else 1274 else
1275 { 1275 {
1276 /* unpack the start address */ 1276 /* unpack the start address */
1277 dummy = buffer; 1277 dummy = buffer;
1278 remain = 8; 1278 remain = 8;
1279 if (_chm_fetch_bytes(h, buffer, 1279 if (_chm_fetch_bytes(h, buffer,
1280 (UInt64)h->data_offset 1280 (UInt64)h->data_offset
1281 + (UInt64)h->rt_unit.start 1281 + (UInt64)h->rt_unit.start
1282 + (UInt64)h->reset_table.table_offset 1282 + (UInt64)h->reset_table.table_offset
1283 + (UInt64)block*8, 1283 + (UInt64)block*8,
1284 remain) != remain || 1284 remain) != remain ||
1285 !_unmarshal_uint64(&dummy, &remain, start)) 1285 !_unmarshal_uint64(&dummy, &remain, start))
1286 return 0; 1286 return 0;
1287 1287
1288 *len = h->reset_table.compressed_len; 1288 *len = h->reset_table.compressed_len;
1289 } 1289 }
1290 1290
1291 /* compute the length and absolute start address */ 1291 /* compute the length and absolute start address */
1292 *len -= *start; 1292 *len -= *start;
1293 *start += h->data_offset + h->cn_unit.start; 1293 *start += h->data_offset + h->cn_unit.start;
1294 1294
1295 return 1; 1295 return 1;
1296} 1296}
1297 1297
1298/* decompress the block. must have lzx_mutex. */ 1298/* decompress the block. must have lzx_mutex. */
1299static Int64 _chm_decompress_block(struct chmFile *h, 1299static Int64 _chm_decompress_block(struct chmFile *h,
1300 UInt64 block, 1300 UInt64 block,
1301 UChar **ubuffer) 1301 UChar **ubuffer)
1302{ 1302{
1303#ifdef WIN32 1303#ifdef WIN32
1304 UChar *cbuffer = alloca(((unsigned int)h->reset_table.block_len + 6144)); 1304 UChar *cbuffer = alloca(((unsigned int)h->reset_table.block_len + 6144));
1305#else 1305#else
1306 UChar cbuffer[h->reset_table.block_len + 6144]; /* compressed buffer */ 1306 UChar cbuffer[h->reset_table.block_len + 6144]; /* compressed buffer */
1307#endif 1307#endif
1308 UInt64 cmpStart; /* compressed start */ 1308 UInt64 cmpStart; /* compressed start */
1309 Int64 cmpLen; /* compressed len */ 1309 Int64 cmpLen; /* compressed len */
1310 int indexSlot; /* cache index slot */ 1310 int indexSlot; /* cache index slot */
1311 UChar *lbuffer; /* local buffer ptr */ 1311 UChar *lbuffer; /* local buffer ptr */
1312 UInt32 blockAlign = (UInt32)(block % h->reset_blkcount); /* reset intvl. aln. */ 1312 UInt32 blockAlign = (UInt32)(block % h->reset_blkcount); /* reset intvl. aln. */
1313 UInt32 i; /* local loop index */ 1313 UInt32 i; /* local loop index */
1314 1314
1315 /* check if we need previous blocks */ 1315 /* check if we need previous blocks */
1316 if (blockAlign != 0) 1316 if (blockAlign != 0)
1317 { 1317 {
1318 /* fetch all required previous blocks since last reset */ 1318 /* fetch all required previous blocks since last reset */
1319 for (i = h->reset_blkcount - blockAlign; i > 0; i--) 1319 for (i = h->reset_blkcount - blockAlign; i > 0; i--)
1320 { 1320 {
1321 1321
1322 /* check if we most recently decompressed the previous block */ 1322 /* check if we most recently decompressed the previous block */
1323 if (h->lzx_last_block != block-i) 1323 if (h->lzx_last_block != block-i)
1324 { 1324 {
1325 indexSlot = (int)((block-i) % h->cache_num_blocks); 1325 indexSlot = (int)((block-i) % h->cache_num_blocks);
1326 h->cache_block_indices[indexSlot] = block-i; 1326 h->cache_block_indices[indexSlot] = block-i;
1327 if (! h->cache_blocks[indexSlot]) 1327 if (! h->cache_blocks[indexSlot])
1328 h->cache_blocks[indexSlot] = (UChar *)malloc( 1328 h->cache_blocks[indexSlot] = (UChar *)malloc(
1329 (unsigned int)(h->reset_table.block_len)); 1329 (unsigned int)(h->reset_table.block_len));
1330 lbuffer = h->cache_blocks[indexSlot]; 1330 lbuffer = h->cache_blocks[indexSlot];
1331 1331
1332 /* decompress the previous block */ 1332 /* decompress the previous block */
1333 LZXreset(h->lzx_state); 1333 LZXreset(h->lzx_state);
1334 if (!_chm_get_cmpblock_bounds(h, block-i, &cmpStart, &cmpLen) || 1334 if (!_chm_get_cmpblock_bounds(h, block-i, &cmpStart, &cmpLen) ||
1335 _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen || 1335 _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen ||
1336 LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen, 1336 LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen,
1337 (int)h->reset_table.block_len) != DECR_OK) 1337 (int)h->reset_table.block_len) != DECR_OK)
1338 return (Int64)0; 1338 return (Int64)0;
1339 } 1339 }
1340 1340
1341 h->lzx_last_block = (int)(block - i); 1341 h->lzx_last_block = (int)(block - i);
1342 } 1342 }
1343 } 1343 }
1344 else 1344 else
1345 LZXreset(h->lzx_state); 1345 LZXreset(h->lzx_state);
1346 1346
1347 /* allocate slot in cache */ 1347 /* allocate slot in cache */
1348 indexSlot = (int)(block % h->cache_num_blocks); 1348 indexSlot = (int)(block % h->cache_num_blocks);
1349 h->cache_block_indices[indexSlot] = block; 1349 h->cache_block_indices[indexSlot] = block;
1350 if (! h->cache_blocks[indexSlot]) 1350 if (! h->cache_blocks[indexSlot])
1351 h->cache_blocks[indexSlot] = (UChar *)malloc( 1351 h->cache_blocks[indexSlot] = (UChar *)malloc(
1352 ((unsigned int)h->reset_table.block_len)); 1352 ((unsigned int)h->reset_table.block_len));
1353 lbuffer = h->cache_blocks[indexSlot]; 1353 lbuffer = h->cache_blocks[indexSlot];
1354 *ubuffer = lbuffer; 1354 *ubuffer = lbuffer;
1355 1355
1356 /* decompress the block we actually want */ 1356 /* decompress the block we actually want */
1357 if (! _chm_get_cmpblock_bounds(h, block, &cmpStart, &cmpLen) || 1357 if (! _chm_get_cmpblock_bounds(h, block, &cmpStart, &cmpLen) ||
1358 _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen || 1358 _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen ||
1359 LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen, 1359 LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen,
1360 (int)h->reset_table.block_len) != DECR_OK) 1360 (int)h->reset_table.block_len) != DECR_OK)
1361 return (Int64)0; 1361 return (Int64)0;
1362 h->lzx_last_block = (int)block; 1362 h->lzx_last_block = (int)block;
1363 1363
1364 /* XXX: modify LZX routines to return the length of the data they 1364 /* XXX: modify LZX routines to return the length of the data they
1365 * decompressed and return that instead, for an extra sanity check. 1365 * decompressed and return that instead, for an extra sanity check.
1366 */ 1366 */
1367 return h->reset_table.block_len; 1367 return h->reset_table.block_len;
1368} 1368}
1369 1369
1370/* grab a region from a compressed block */ 1370/* grab a region from a compressed block */
1371static Int64 _chm_decompress_region(struct chmFile *h, 1371static Int64 _chm_decompress_region(struct chmFile *h,
1372 UChar *buf, 1372 UChar *buf,
1373 UInt64 start, 1373 UInt64 start,
1374 Int64 len) 1374 Int64 len)
1375{ 1375{
1376 UInt64 nBlock, nOffset; 1376 UInt64 nBlock, nOffset;
1377 UInt64 nLen; 1377 UInt64 nLen;
1378 UInt64 gotLen; 1378 UInt64 gotLen;
1379 UChar *ubuffer; 1379 UChar *ubuffer;
1380 1380
1381 if (len <= 0) 1381 if (len <= 0)
1382 return (Int64)0; 1382 return (Int64)0;
1383 1383
1384 /* figure out what we need to read */ 1384 /* figure out what we need to read */
1385 nBlock = start / h->reset_table.block_len; 1385 nBlock = start / h->reset_table.block_len;
1386 nOffset = start % h->reset_table.block_len; 1386 nOffset = start % h->reset_table.block_len;
1387 nLen = len; 1387 nLen = len;
1388 if (nLen > (h->reset_table.block_len - nOffset)) 1388 if (nLen > (h->reset_table.block_len - nOffset))
1389 nLen = h->reset_table.block_len - nOffset; 1389 nLen = h->reset_table.block_len - nOffset;
1390 1390
1391 /* if block is cached, return data from it. */ 1391 /* if block is cached, return data from it. */
1392 CHM_ACQUIRE_LOCK(h->lzx_mutex); 1392 CHM_ACQUIRE_LOCK(h->lzx_mutex);
1393 CHM_ACQUIRE_LOCK(h->cache_mutex); 1393 CHM_ACQUIRE_LOCK(h->cache_mutex);
1394 if (h->cache_block_indices[nBlock % h->cache_num_blocks] == nBlock && 1394 if (h->cache_block_indices[nBlock % h->cache_num_blocks] == nBlock &&
1395 h->cache_blocks[nBlock % h->cache_num_blocks] != NULL) 1395 h->cache_blocks[nBlock % h->cache_num_blocks] != NULL)
1396 { 1396 {
1397 memcpy(buf, 1397 memcpy(buf,
1398 h->cache_blocks[nBlock % h->cache_num_blocks] + nOffset, 1398 h->cache_blocks[nBlock % h->cache_num_blocks] + nOffset,
1399 (unsigned int)nLen); 1399 (unsigned int)nLen);
1400 CHM_RELEASE_LOCK(h->cache_mutex); 1400 CHM_RELEASE_LOCK(h->cache_mutex);
1401 CHM_RELEASE_LOCK(h->lzx_mutex); 1401 CHM_RELEASE_LOCK(h->lzx_mutex);
1402 return nLen; 1402 return nLen;
1403 } 1403 }
1404 CHM_RELEASE_LOCK(h->cache_mutex); 1404 CHM_RELEASE_LOCK(h->cache_mutex);
1405 1405
1406 /* data request not satisfied, so... start up the decompressor machine */ 1406 /* data request not satisfied, so... start up the decompressor machine */
1407 if (! h->lzx_state) 1407 if (! h->lzx_state)
1408 { 1408 {
1409 int window_size = ffs(h->window_size) - 1; 1409 int window_size = ffs(h->window_size) - 1;
1410 h->lzx_last_block = -1; 1410 h->lzx_last_block = -1;
1411 h->lzx_state = LZXinit(window_size); 1411 h->lzx_state = LZXinit(window_size);
1412 } 1412 }
1413 1413
1414 /* decompress some data */ 1414 /* decompress some data */
1415 gotLen = _chm_decompress_block(h, nBlock, &ubuffer); 1415 gotLen = _chm_decompress_block(h, nBlock, &ubuffer);
1416 if (gotLen < nLen) 1416 if (gotLen < nLen)
1417 nLen = gotLen; 1417 nLen = gotLen;
1418 memcpy(buf, ubuffer+nOffset, (unsigned int)nLen); 1418 memcpy(buf, ubuffer+nOffset, (unsigned int)nLen);
1419 CHM_RELEASE_LOCK(h->lzx_mutex); 1419 CHM_RELEASE_LOCK(h->lzx_mutex);
1420 return nLen; 1420 return nLen;
1421} 1421}
1422 1422
1423/* retrieve (part of) an object */ 1423/* retrieve (part of) an object */
1424LONGINT64 chm_retrieve_object(struct chmFile *h, 1424LONGINT64 chm_retrieve_object(struct chmFile *h,
1425 struct chmUnitInfo *ui, 1425 struct chmUnitInfo *ui,
1426 unsigned char *buf, 1426 unsigned char *buf,
1427 LONGUINT64 addr, 1427 LONGUINT64 addr,
1428 LONGINT64 len) 1428 LONGINT64 len)
1429{ 1429{
1430 /* must be valid file handle */ 1430 /* must be valid file handle */
1431 if (h == NULL) 1431 if (h == NULL)
1432 return (Int64)0; 1432 return (Int64)0;
1433 1433
1434 /* starting address must be in correct range */ 1434 /* starting address must be in correct range */
1435 if (addr < 0 || addr >= ui->length) 1435 if (addr < 0 || addr >= ui->length)
1436 return (Int64)0; 1436 return (Int64)0;
1437 1437
1438 /* clip length */ 1438 /* clip length */
1439 if (addr + len > ui->length) 1439 if (addr + len > ui->length)
1440 len = ui->length - addr; 1440 len = ui->length - addr;
1441 1441
1442 /* if the file is uncompressed, it's simple */ 1442 /* if the file is uncompressed, it's simple */
1443 if (ui->space == CHM_UNCOMPRESSED) 1443 if (ui->space == CHM_UNCOMPRESSED)
1444 { 1444 {
1445 /* read data */ 1445 /* read data */
1446 return _chm_fetch_bytes(h, 1446 return _chm_fetch_bytes(h,
1447 buf, 1447 buf,
1448 (UInt64)h->data_offset + (UInt64)ui->start + (UInt64)addr, 1448 (UInt64)h->data_offset + (UInt64)ui->start + (UInt64)addr,
1449 len); 1449 len);
1450 } 1450 }
1451 1451
1452 /* else if the file is compressed, it's a little trickier */ 1452 /* else if the file is compressed, it's a little trickier */
1453 else /* ui->space == CHM_COMPRESSED */ 1453 else /* ui->space == CHM_COMPRESSED */
1454 { 1454 {
1455 Int64 swath=0, total=0; 1455 Int64 swath=0, total=0;
1456 do { 1456 do {
1457 1457
1458 /* swill another mouthful */ 1458 /* swill another mouthful */
1459 swath = _chm_decompress_region(h, buf, ui->start + addr, len); 1459 swath = _chm_decompress_region(h, buf, ui->start + addr, len);
1460 1460
1461 /* if we didn't get any... */ 1461 /* if we didn't get any... */
1462 if (swath == 0) 1462 if (swath == 0)
1463 return total; 1463 return total;
1464 1464
1465 /* update stats */ 1465 /* update stats */
1466 total += swath; 1466 total += swath;
1467 len -= swath; 1467 len -= swath;
1468 addr += swath; 1468 addr += swath;
1469 buf += swath; 1469 buf += swath;
1470 1470
1471 } while (len != 0); 1471 } while (len != 0);
1472 1472
1473 return total; 1473 return total;
1474 } 1474 }
1475} 1475}
1476 1476
1477/* enumerate the objects in the .chm archive */ 1477/* enumerate the objects in the .chm archive */
1478int chm_enumerate(struct chmFile *h, 1478int chm_enumerate(struct chmFile *h,
1479 int what, 1479 int what,
1480 CHM_ENUMERATOR e, 1480 CHM_ENUMERATOR e,
1481 void *context) 1481 void *context)
1482{ 1482{
1483 Int32 curPage; 1483 Int32 curPage;
1484 1484
1485 /* buffer to hold whatever page we're looking at */ 1485 /* buffer to hold whatever page we're looking at */
1486#ifdef WIN32 1486#ifdef WIN32
1487 UChar *page_buf = alloca((unsigned int)h->block_len); 1487 UChar *page_buf = alloca((unsigned int)h->block_len);
1488#else 1488#else
1489 UChar page_buf[h->block_len]; 1489 UChar page_buf[h->block_len];
1490#endif 1490#endif
1491 struct chmPmglHeader header; 1491 struct chmPmglHeader header;
1492 UChar *end; 1492 UChar *end;
1493 UChar *cur; 1493 UChar *cur;
1494 unsigned long lenRemain; 1494 unsigned long lenRemain;
1495 1495
1496 /* the current ui */ 1496 /* the current ui */
1497 struct chmUnitInfo ui; 1497 struct chmUnitInfo ui;
1498 int flag; 1498 int flag;
1499 1499
1500 /* starting page */ 1500 /* starting page */
1501 curPage = h->index_head; 1501 curPage = h->index_head;
1502 1502
1503 /* until we have either returned or given up */ 1503 /* until we have either returned or given up */
1504 while (curPage != -1) 1504 while (curPage != -1)
1505 { 1505 {
1506 1506
1507 /* try to fetch the index page */ 1507 /* try to fetch the index page */
1508 if (_chm_fetch_bytes(h, 1508 if (_chm_fetch_bytes(h,
1509 page_buf, 1509 page_buf,
1510 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len, 1510 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len,
1511 h->block_len) != h->block_len) 1511 h->block_len) != h->block_len)
1512 return 0; 1512 return 0;
1513 1513
1514 /* figure out start and end for this page */ 1514 /* figure out start and end for this page */
1515 cur = page_buf; 1515 cur = page_buf;
1516 lenRemain = _CHM_PMGL_LEN; 1516 lenRemain = _CHM_PMGL_LEN;
1517 if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header)) 1517 if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header))
1518 return 0; 1518 return 0;
1519 end = page_buf + h->block_len - (header.free_space); 1519 end = page_buf + h->block_len - (header.free_space);
1520 1520
1521 /* loop over this page */ 1521 /* loop over this page */
1522 while (cur < end) 1522 while (cur < end)
1523 { 1523 {
1524 if (! _chm_parse_PMGL_entry(&cur, &ui)) 1524 if (! _chm_parse_PMGL_entry(&cur, &ui))
1525 return 0; 1525 return 0;
1526 1526
1527 /* check for DIRS */ 1527 /* check for DIRS */
1528 if (ui.length == 0 && !(what & CHM_ENUMERATE_DIRS)) 1528 if (ui.length == 0 && !(what & CHM_ENUMERATE_DIRS))
1529 continue; 1529 continue;
1530 1530
1531 /* check for FILES */ 1531 /* check for FILES */
1532 if (ui.length != 0 && !(what & CHM_ENUMERATE_FILES)) 1532 if (ui.length != 0 && !(what & CHM_ENUMERATE_FILES))
1533 continue; 1533 continue;
1534 1534
1535 /* check for NORMAL vs. META */ 1535 /* check for NORMAL vs. META */
1536 if (ui.path[0] == '/') 1536 if (ui.path[0] == '/')
1537 { 1537 {
1538 1538
1539 /* check for NORMAL vs. SPECIAL */ 1539 /* check for NORMAL vs. SPECIAL */
1540 if (ui.path[1] == '#' || ui.path[1] == '$') 1540 if (ui.path[1] == '#' || ui.path[1] == '$')
1541 flag = CHM_ENUMERATE_SPECIAL; 1541 flag = CHM_ENUMERATE_SPECIAL;
1542 else 1542 else
1543 flag = CHM_ENUMERATE_NORMAL; 1543 flag = CHM_ENUMERATE_NORMAL;
1544 } 1544 }
1545 else 1545 else
1546 flag = CHM_ENUMERATE_META; 1546 flag = CHM_ENUMERATE_META;
1547 if (! (what & flag)) 1547 if (! (what & flag))
1548 continue; 1548 continue;
1549 1549
1550 /* call the enumerator */ 1550 /* call the enumerator */
1551 { 1551 {
1552 int status = (*e)(h, &ui, context); 1552 int status = (*e)(h, &ui, context);
1553 switch (status) 1553 switch (status)
1554 { 1554 {
1555 case CHM_ENUMERATOR_FAILURE: return 0; 1555 case CHM_ENUMERATOR_FAILURE: return 0;
1556 case CHM_ENUMERATOR_CONTINUE: break; 1556 case CHM_ENUMERATOR_CONTINUE: break;
1557 case CHM_ENUMERATOR_SUCCESS: return 1; 1557 case CHM_ENUMERATOR_SUCCESS: return 1;
1558 default: break; 1558 default: break;
1559 } 1559 }
1560 } 1560 }
1561 } 1561 }
1562 1562
1563 /* advance to next page */ 1563 /* advance to next page */
1564 curPage = header.block_next; 1564 curPage = header.block_next;
1565 } 1565 }
1566 1566
1567 return 1; 1567 return 1;
1568} 1568}
1569 1569
1570int chm_enumerate_dir(struct chmFile *h, 1570int chm_enumerate_dir(struct chmFile *h,
1571 const char *prefix, 1571 const char *prefix,
1572 int what, 1572 int what,
1573 CHM_ENUMERATOR e, 1573 CHM_ENUMERATOR e,
1574 void *context) 1574 void *context)
1575{ 1575{
1576 /* 1576 /*
1577 * XXX: do this efficiently (i.e. using the tree index) 1577 * XXX: do this efficiently (i.e. using the tree index)
1578 */ 1578 */
1579 1579
1580 Int32 curPage; 1580 Int32 curPage;
1581 1581
1582 /* buffer to hold whatever page we're looking at */ 1582 /* buffer to hold whatever page we're looking at */
1583#ifdef WIN32 1583#ifdef WIN32
1584 UChar *page_buf = alloca((unsigned int)h->block_len); 1584 UChar *page_buf = alloca((unsigned int)h->block_len);
1585#else 1585#else
1586 UChar page_buf[h->block_len]; 1586 UChar page_buf[h->block_len];
1587#endif 1587#endif
1588 struct chmPmglHeader header; 1588 struct chmPmglHeader header;
1589 UChar *end; 1589 UChar *end;
1590 UChar *cur; 1590 UChar *cur;
1591 unsigned long lenRemain; 1591 unsigned long lenRemain;
1592 1592
1593 /* set to 1 once we've started */ 1593 /* set to 1 once we've started */
1594 int it_has_begun=0; 1594 int it_has_begun=0;
1595 1595
1596 /* the current ui */ 1596 /* the current ui */
1597 struct chmUnitInfo ui; 1597 struct chmUnitInfo ui;
1598 int flag; 1598 int flag;
1599 1599
1600 /* the length of the prefix */ 1600 /* the length of the prefix */
1601 char prefixRectified[CHM_MAX_PATHLEN+1]; 1601 char prefixRectified[CHM_MAX_PATHLEN+1];
1602 int prefixLen; 1602 int prefixLen;
1603 char lastPath[CHM_MAX_PATHLEN]; 1603 char lastPath[CHM_MAX_PATHLEN+1];
1604 int lastPathLen; 1604 int lastPathLen;
1605 1605
1606 /* starting page */ 1606 /* starting page */
1607 curPage = h->index_head; 1607 curPage = h->index_head;
1608 1608
1609 /* initialize pathname state */ 1609 /* initialize pathname state */
1610 strncpy(prefixRectified, prefix, CHM_MAX_PATHLEN); 1610 strncpy(prefixRectified, prefix, CHM_MAX_PATHLEN);
1611 prefixLen = strlen(prefixRectified); 1611 prefixLen = strlen(prefixRectified);
1612 if (prefixLen != 0) 1612 if (prefixLen != 0)
1613 { 1613 {
1614 if (prefixRectified[prefixLen-1] != '/') 1614 if (prefixRectified[prefixLen-1] != '/')
1615 { 1615 {
1616 prefixRectified[prefixLen] = '/'; 1616 prefixRectified[prefixLen] = '/';
1617 prefixRectified[prefixLen+1] = '\0'; 1617 prefixRectified[prefixLen+1] = '\0';
1618 ++prefixLen; 1618 ++prefixLen;
1619 } 1619 }
1620 } 1620 }
1621 lastPath[0] = '\0'; 1621 lastPath[0] = '\0';
1622 lastPathLen = -1; 1622 lastPathLen = -1;
1623 1623
1624 /* until we have either returned or given up */ 1624 /* until we have either returned or given up */
1625 while (curPage != -1) 1625 while (curPage != -1)
1626 { 1626 {
1627 1627
1628 /* try to fetch the index page */ 1628 /* try to fetch the index page */
1629 if (_chm_fetch_bytes(h, 1629 if (_chm_fetch_bytes(h,
1630 page_buf, 1630 page_buf,
1631 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len, 1631 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len,
1632 h->block_len) != h->block_len) 1632 h->block_len) != h->block_len)
1633 return 0; 1633 return 0;
1634 1634
1635 /* figure out start and end for this page */ 1635 /* figure out start and end for this page */
1636 cur = page_buf; 1636 cur = page_buf;
1637 lenRemain = _CHM_PMGL_LEN; 1637 lenRemain = _CHM_PMGL_LEN;
1638 if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header)) 1638 if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header))
1639 return 0; 1639 return 0;
1640 end = page_buf + h->block_len - (header.free_space); 1640 end = page_buf + h->block_len - (header.free_space);
1641 1641
1642 /* loop over this page */ 1642 /* loop over this page */
1643 while (cur < end) 1643 while (cur < end)
1644 { 1644 {
1645 if (! _chm_parse_PMGL_entry(&cur, &ui)) 1645 if (! _chm_parse_PMGL_entry(&cur, &ui))
1646 return 0; 1646 return 0;
1647 1647
1648 /* check if we should start */ 1648 /* check if we should start */
1649 if (! it_has_begun) 1649 if (! it_has_begun)
1650 { 1650 {
1651 if (ui.length == 0 && strncmp(ui.path, prefixRectified, prefixLen) == 0) 1651 if (ui.length == 0 && strncmp(ui.path, prefixRectified, prefixLen) == 0)
1652 it_has_begun = 1; 1652 it_has_begun = 1;
1653 else 1653 else
1654 continue; 1654 continue;
1655 1655
1656 if (ui.path[prefixLen] == '\0') 1656 if (ui.path[prefixLen] == '\0')
1657 continue; 1657 continue;
1658 } 1658 }
1659 1659
1660 /* check if we should stop */ 1660 /* check if we should stop */
1661 else 1661 else
1662 { 1662 {
1663 if (strncmp(ui.path, prefixRectified, prefixLen) != 0) 1663 if (strncmp(ui.path, prefixRectified, prefixLen) != 0)
1664 return 1; 1664 return 1;
1665 } 1665 }
1666 1666
1667 /* check if we should include this path */ 1667 /* check if we should include this path */
1668 if (lastPathLen != -1) 1668 if (lastPathLen != -1)
1669 { 1669 {
1670 if (strncmp(ui.path, lastPath, lastPathLen) == 0) 1670 if (strncmp(ui.path, lastPath, lastPathLen) == 0)
1671 continue; 1671 continue;
1672 } 1672 }
1673 strcpy(lastPath, ui.path); 1673 strncpy(lastPath, ui.path, CHM_MAX_PATHLEN);
1674 lastPath[CHM_MAX_PATHLEN] = '\0';
1674 lastPathLen = strlen(lastPath); 1675 lastPathLen = strlen(lastPath);
1675 1676
1676 /* check for DIRS */ 1677 /* check for DIRS */
1677 if (ui.length == 0 && !(what & CHM_ENUMERATE_DIRS)) 1678 if (ui.length == 0 && !(what & CHM_ENUMERATE_DIRS))
1678 continue; 1679 continue;
1679 1680
1680 /* check for FILES */ 1681 /* check for FILES */
1681 if (ui.length != 0 && !(what & CHM_ENUMERATE_FILES)) 1682 if (ui.length != 0 && !(what & CHM_ENUMERATE_FILES))
1682 continue; 1683 continue;
1683 1684
1684 /* check for NORMAL vs. META */ 1685 /* check for NORMAL vs. META */
1685 if (ui.path[0] == '/') 1686 if (ui.path[0] == '/')
1686 { 1687 {
1687 1688
1688 /* check for NORMAL vs. SPECIAL */ 1689 /* check for NORMAL vs. SPECIAL */
1689 if (ui.path[1] == '#' || ui.path[1] == '$') 1690 if (ui.path[1] == '#' || ui.path[1] == '$')
1690 flag = CHM_ENUMERATE_SPECIAL; 1691 flag = CHM_ENUMERATE_SPECIAL;
1691 else 1692 else
1692 flag = CHM_ENUMERATE_NORMAL; 1693 flag = CHM_ENUMERATE_NORMAL;
1693 } 1694 }
1694 else 1695 else
1695 flag = CHM_ENUMERATE_META; 1696 flag = CHM_ENUMERATE_META;
1696 if (! (what & flag)) 1697 if (! (what & flag))
1697 continue; 1698 continue;
1698 1699
1699 /* call the enumerator */ 1700 /* call the enumerator */
1700 { 1701 {
1701 int status = (*e)(h, &ui, context); 1702 int status = (*e)(h, &ui, context);
1702 switch (status) 1703 switch (status)
1703 { 1704 {
1704 case CHM_ENUMERATOR_FAILURE: return 0; 1705 case CHM_ENUMERATOR_FAILURE: return 0;
1705 case CHM_ENUMERATOR_CONTINUE: break; 1706 case CHM_ENUMERATOR_CONTINUE: break;
1706 case CHM_ENUMERATOR_SUCCESS: return 1; 1707 case CHM_ENUMERATOR_SUCCESS: return 1;
1707 default: break; 1708 default: break;
1708 } 1709 }
1709 } 1710 }
1710 } 1711 }
1711 1712
1712 /* advance to next page */ 1713 /* advance to next page */
1713 curPage = header.block_next; 1714 curPage = header.block_next;
1714 } 1715 }
1715 1716
1716 return 1; 1717 return 1;
1717} 1718}
1718 1719
1719/* resolve a particular object from the archive */ 1720/* resolve a particular object from the archive */
1720int chm_resolve_location(struct chmFile *h, 1721int chm_resolve_location(struct chmFile *h,
1721 unsigned long pos, 1722 unsigned long pos,
1722 struct chmUnitInfo *ui) 1723 struct chmUnitInfo *ui)
1723{ 1724{
1724 /* 1725 /*
1725 * XXX: implement caching scheme for dir pages 1726 * XXX: implement caching scheme for dir pages
1726 */ 1727 */
1727 1728
1728 Int32 curPage; 1729 Int32 curPage;
1729 1730
1730 /* buffer to hold whatever page we're looking at */ 1731 /* buffer to hold whatever page we're looking at */
1731#ifdef WIN32 1732#ifdef WIN32
1732 UChar *page_buf = alloca(h->block_len); 1733 UChar *page_buf = alloca(h->block_len);
1733#else 1734#else
1734 UChar page_buf[h->block_len]; 1735 UChar page_buf[h->block_len];
1735#endif 1736#endif
1736 1737
1737 /* starting page */ 1738 /* starting page */
1738 curPage = h->index_root; 1739 curPage = h->index_root;
1739 1740
1740 /* until we have either returned or given up */ 1741 /* until we have either returned or given up */
1741 while (curPage != -1) 1742 while (curPage != -1)
1742 { 1743 {
1743 1744
1744 /* try to fetch the index page */ 1745 /* try to fetch the index page */
1745 if (_chm_fetch_bytes(h, page_buf, 1746 if (_chm_fetch_bytes(h, page_buf,
1746 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len, 1747 (UInt64)h->dir_offset + (UInt64)curPage*h->block_len,
1747 h->block_len) != h->block_len) 1748 h->block_len) != h->block_len)
1748 return CHM_RESOLVE_FAILURE; 1749 return CHM_RESOLVE_FAILURE;
1749 1750
1750 /* now, if it is a leaf node: */ 1751 /* now, if it is a leaf node: */
1751 if (memcmp(page_buf, _chm_pmgl_marker, 4) == 0) 1752 if (memcmp(page_buf, _chm_pmgl_marker, 4) == 0)
1752 { 1753 {
1753 /* scan block */ 1754 /* scan block */
1754 /* UChar *pEntry = _chm_find_in_PMGL(page_buf, h->block_len, objPath);*/ 1755 /* UChar *pEntry = _chm_find_in_PMGL(page_buf, h->block_len, objPath);*/
1755 { 1756 {
1756 /* XXX: modify this to do a binary search using the nice index structure 1757 /* XXX: modify this to do a binary search using the nice index structure
1757 * that is provided for us. 1758 * that is provided for us.
1758 */ 1759 */
1759 struct chmPmglHeader header; 1760 struct chmPmglHeader header;
1760 UInt32 hremain; 1761 UInt32 hremain;
1761 UChar *end; 1762 UChar *end;
1762 UChar *cur; 1763 UChar *cur;
1763 UChar *temp; 1764 UChar *temp;
1764/* 1765/*
1765 UInt64 strLen; 1766 UInt64 strLen;
1766 char buffer[CHM_MAX_PATHLEN+1]; 1767 char buffer[CHM_MAX_PATHLEN+1];
1767*/ 1768*/
1768 /* figure out where to start and end */ 1769 /* figure out where to start and end */
1769 cur = page_buf; 1770 cur = page_buf;
1770 hremain = _CHM_PMGL_LEN; 1771 hremain = _CHM_PMGL_LEN;
1771 if (! _unmarshal_pmgl_header(&cur, &hremain, &header)) 1772 if (! _unmarshal_pmgl_header(&cur, &hremain, &header))
1772 return CHM_RESOLVE_FAILURE; 1773 return CHM_RESOLVE_FAILURE;
1773 end = page_buf + h->block_len - (header.free_space); 1774 end = page_buf + h->block_len - (header.free_space);
1774 1775
1775 /* now, scan progressively */ 1776 /* now, scan progressively */
1776 while (cur < end) 1777 while (cur < end)
1777 { 1778 {
1778 UInt32 st = 0; 1779 UInt32 st = 0;
1779 UInt32 nd = 0; 1780 UInt32 nd = 0;
1780 /* grab the name */ 1781 /* grab the name */
1781 temp = cur; 1782 temp = cur;
1782 1783
1783 if (_chm_parse_PMGL_entry(&cur, ui) == 0) 1784 if (_chm_parse_PMGL_entry(&cur, ui) == 0)
1784 { 1785 {
1785 return CHM_RESOLVE_FAILURE; 1786 return CHM_RESOLVE_FAILURE;
1786 } 1787 }
1787 st = ui->start; 1788 st = ui->start;
1788 nd = ui->start+ui->length; 1789 nd = ui->start+ui->length;
1789 if ((st <= pos) && (pos < nd)) 1790 if ((st <= pos) && (pos < nd))
1790 { 1791 {
1791 printf("Resolve:[%u,%u,%u]\n", st, pos, nd); 1792 printf("Resolve:[%u,%u,%u]\n", st, pos, nd);
1792 return CHM_RESOLVE_SUCCESS; 1793 return CHM_RESOLVE_SUCCESS;
1793 } 1794 }
1794 } 1795 }
1795 1796
1796 return CHM_RESOLVE_FAILURE; 1797 return CHM_RESOLVE_FAILURE;
1797 } 1798 }
1798 1799
1799 } 1800 }
1800 1801
1801 /* else, if it is a branch node: */ 1802 /* else, if it is a branch node: */
1802 else if (memcmp(page_buf, _chm_pmgi_marker, 4) == 0) 1803 else if (memcmp(page_buf, _chm_pmgi_marker, 4) == 0)
1803 { 1804 {
1804 /* curPage = _chm_find_in_PMGI(page_buf, h->block_len, objPath);*/ 1805 /* curPage = _chm_find_in_PMGI(page_buf, h->block_len, objPath);*/
1805 return CHM_RESOLVE_FAILURE; 1806 return CHM_RESOLVE_FAILURE;
1806 if (0) 1807 if (0)
1807 { 1808 {
1808 /* XXX: modify this to do a binary search using the nice index structure 1809 /* XXX: modify this to do a binary search using the nice index structure
1809 * that is provided for us 1810 * that is provided for us
1810 */ 1811 */
1811 struct chmPmgiHeader header; 1812 struct chmPmgiHeader header;
1812 UInt32 hremain; 1813 UInt32 hremain;
1813 int page=-1; 1814 int page=-1;
1814 UChar *end; 1815 UChar *end;
1815 UChar *cur; 1816 UChar *cur;
1816 UInt64 strLen; 1817 UInt64 strLen;
1817 char buffer[CHM_MAX_PATHLEN+1]; 1818 char buffer[CHM_MAX_PATHLEN+1];
1818 1819
1819 /* figure out where to start and end */ 1820 /* figure out where to start and end */
1820 cur = page_buf; 1821 cur = page_buf;
1821 hremain = _CHM_PMGI_LEN; 1822 hremain = _CHM_PMGI_LEN;
1822 if (! _unmarshal_pmgi_header(&cur, &hremain, &header)) 1823 if (! _unmarshal_pmgi_header(&cur, &hremain, &header))
1823 return -1; 1824 return -1;
1824 end = page_buf + h->block_len - (header.free_space); 1825 end = page_buf + h->block_len - (header.free_space);
1825 1826
1826 /* now, scan progressively */ 1827 /* now, scan progressively */
1827 while (cur < end) 1828 while (cur < end)
1828 { 1829 {
1829 1830
1830 1831
1831 1832
1832 if (_chm_parse_PMGL_entry(&cur, ui) == 0) 1833 if (_chm_parse_PMGL_entry(&cur, ui) == 0)
1833 { 1834 {
1834 return CHM_RESOLVE_FAILURE; 1835 return CHM_RESOLVE_FAILURE;
1835 } 1836 }
1836 1837
1837 if (ui->start <= pos && pos < ui->start + ui->length) 1838 if (ui->start <= pos && pos < ui->start + ui->length)
1838 { 1839 {
1839 return CHM_RESOLVE_SUCCESS; 1840 return CHM_RESOLVE_SUCCESS;
1840 } 1841 }
1841 1842
1842 1843
1843 1844
1844 1845
1845 1846
1846 /* grab the name */ 1847 /* grab the name */
1847 strLen = _chm_parse_cword(&cur); 1848 strLen = _chm_parse_cword(&cur);
1848 if (! _chm_parse_UTF8(&cur, strLen, buffer)) 1849 if (! _chm_parse_UTF8(&cur, strLen, buffer))
1849 return -1; 1850 return -1;
1850 1851
1851 /* check if it is the right name */ 1852 /* check if it is the right name */
1852 /* 1853 /*
1853#ifdef WIN32 1854#ifdef WIN32
1854 if (stricmp(buffer, objPath) > 0) 1855 if (stricmp(buffer, objPath) > 0)
1855 return page; 1856 return page;
1856#else 1857#else
1857 if (strcasecmp(buffer, objPath) > 0) 1858 if (strcasecmp(buffer, objPath) > 0)
1858 return page; 1859 return page;
1859#endif 1860#endif
1860 */ 1861 */
1861 /* load next value for path */ 1862 /* load next value for path */
1862 page = (int)_chm_parse_cword(&cur); 1863 page = (int)_chm_parse_cword(&cur);
1863 } 1864 }
1864 1865
1865 curPage = page; 1866 curPage = page;
1866 } 1867 }
1867 } 1868 }
1868 /* else, we are confused. give up. */ 1869 /* else, we are confused. give up. */
1869 else 1870 else
1870 return CHM_RESOLVE_FAILURE; 1871 return CHM_RESOLVE_FAILURE;
1871 } 1872 }
1872 1873
1873 /* didn't find anything. fail. */ 1874 /* didn't find anything. fail. */
1874 return CHM_RESOLVE_FAILURE; 1875 return CHM_RESOLVE_FAILURE;
1875 1876
1876} 1877}
diff --git a/noncore/settings/sysinfo/contrib/dhry.c b/noncore/settings/sysinfo/contrib/dhry.c
index 20b627c..07fd1c0 100644
--- a/noncore/settings/sysinfo/contrib/dhry.c
+++ b/noncore/settings/sysinfo/contrib/dhry.c
@@ -1,1010 +1,1010 @@
1/*****************************************************/ 1/*****************************************************/
2/* Various timer routines. */ 2/* Various timer routines. */
3/* Al Aburto, aburto@nosc.mil, 18 Feb 1997 */ 3/* Al Aburto, aburto@nosc.mil, 18 Feb 1997 */
4/* */ 4/* */
5/* t = dtime() outputs the current time in seconds. */ 5/* t = dtime() outputs the current time in seconds. */
6/* Use CAUTION as some of these routines will mess */ 6/* Use CAUTION as some of these routines will mess */
7/* up when timing across the hour mark!!! */ 7/* up when timing across the hour mark!!! */
8/* */ 8/* */
9/* For timing I use the 'user' time whenever */ 9/* For timing I use the 'user' time whenever */
10/* possible. Using 'user+sys' time is a separate */ 10/* possible. Using 'user+sys' time is a separate */
11/* issue. */ 11/* issue. */
12/* */ 12/* */
13/* Example Usage: */ 13/* Example Usage: */
14/* [timer options added here] */ 14/* [timer options added here] */
15/* main() */ 15/* main() */
16/* { */ 16/* { */
17/* double starttime,benchtime,dtime(); */ 17/* double starttime,benchtime,dtime(); */
18/* */ 18/* */
19/* starttime = dtime(); */ 19/* starttime = dtime(); */
20/* [routine to time] */ 20/* [routine to time] */
21/* benchtime = dtime() - starttime; */ 21/* benchtime = dtime() - starttime; */
22/* } */ 22/* } */
23/* */ 23/* */
24/* [timer code below added here] */ 24/* [timer code below added here] */
25/*****************************************************/ 25/*****************************************************/
26 26
27/***************************************************************/ 27/***************************************************************/
28/* Timer options. You MUST uncomment one of the options below */ 28/* Timer options. You MUST uncomment one of the options below */
29/* or compile, for example, with the '-DUNIX' option. */ 29/* or compile, for example, with the '-DUNIX' option. */
30/***************************************************************/ 30/***************************************************************/
31/* #define Amiga */ 31/* #define Amiga */
32/* #define UNIX */ 32/* #define UNIX */
33/* #define UNIX_Old */ 33/* #define UNIX_Old */
34/* #define VMS */ 34/* #define VMS */
35/* #define BORLAND_C */ 35/* #define BORLAND_C */
36/* #define MSC */ 36/* #define MSC */
37/* #define MAC */ 37/* #define MAC */
38/* #define IPSC */ 38/* #define IPSC */
39/* #define FORTRAN_SEC */ 39/* #define FORTRAN_SEC */
40/* #define GTODay */ 40/* #define GTODay */
41/* #define CTimer */ 41/* #define CTimer */
42/* #define UXPM */ 42/* #define UXPM */
43/* #define MAC_TMgr */ 43/* #define MAC_TMgr */
44/* #define PARIX */ 44/* #define PARIX */
45/* #define POSIX */ 45/* #define POSIX */
46/* #define WIN32 */ 46/* #define WIN32 */
47/* #define POSIX1 */ 47/* #define POSIX1 */
48/***********************/ 48/***********************/
49 49
50/*********************************/ 50/*********************************/
51/* Timer code. */ 51/* Timer code. */
52/*********************************/ 52/*********************************/
53/*******************/ 53/*******************/
54/* Amiga dtime() */ 54/* Amiga dtime() */
55/*******************/ 55/*******************/
56#ifdef Amiga 56#ifdef Amiga
57#include <ctype.h> 57#include <ctype.h>
58#define HZ 50 58#define HZ 50
59 59
60double dtime() 60double dtime()
61{ 61{
62 double q; 62 double q;
63 63
64 struct tt 64 struct tt
65 { 65 {
66 long days; 66 long days;
67 long minutes; 67 long minutes;
68 long ticks; 68 long ticks;
69 } tt; 69 } tt;
70 70
71 DateStamp(&tt); 71 DateStamp(&tt);
72 72
73 q = ((double)(tt.ticks + (tt.minutes * 60L * 50L))) / (double)HZ; 73 q = ((double)(tt.ticks + (tt.minutes * 60L * 50L))) / (double)HZ;
74 74
75 return q; 75 return q;
76} 76}
77#endif 77#endif
78 78
79/*****************************************************/ 79/*****************************************************/
80/* UNIX dtime(). This is the preferred UNIX timer. */ 80/* UNIX dtime(). This is the preferred UNIX timer. */
81/* Provided by: Markku Kolkka, mk59200@cc.tut.fi */ 81/* Provided by: Markku Kolkka, mk59200@cc.tut.fi */
82/* HP-UX Addition by: Bo Thide', bt@irfu.se */ 82/* HP-UX Addition by: Bo Thide', bt@irfu.se */
83/*****************************************************/ 83/*****************************************************/
84#ifdef UNIX 84#ifdef UNIX
85#include <sys/time.h> 85#include <sys/time.h>
86#include <sys/resource.h> 86#include <sys/resource.h>
87 87
88#ifdef hpux 88#ifdef hpux
89#include <sys/syscall.h> 89#include <sys/syscall.h>
90#define getrusage(a,b) syscall(SYS_getrusage,a,b) 90#define getrusage(a,b) syscall(SYS_getrusage,a,b)
91#endif 91#endif
92 92
93struct rusage rusage; 93struct rusage rusage;
94 94
95double dtime() 95double dtime()
96{ 96{
97 double q; 97 double q;
98 98
99 getrusage(RUSAGE_SELF,&rusage); 99 getrusage(RUSAGE_SELF,&rusage);
100 100
101 q = (double)(rusage.ru_utime.tv_sec); 101 q = (double)(rusage.ru_utime.tv_sec);
102 q = q + (double)(rusage.ru_utime.tv_usec) * 1.0e-06; 102 q = q + (double)(rusage.ru_utime.tv_usec) * 1.0e-06;
103 103
104 return q; 104 return q;
105} 105}
106#endif 106#endif
107 107
108/***************************************************/ 108/***************************************************/
109/* UNIX_Old dtime(). This is the old UNIX timer. */ 109/* UNIX_Old dtime(). This is the old UNIX timer. */
110/* Make sure HZ is properly defined in param.h !! */ 110/* Make sure HZ is properly defined in param.h !! */
111/***************************************************/ 111/***************************************************/
112#ifdef UNIX_Old 112#ifdef UNIX_Old
113#include <sys/types.h> 113#include <sys/types.h>
114#include <sys/times.h> 114#include <sys/times.h>
115#include <sys/param.h> 115#include <sys/param.h>
116 116
117#ifndef HZ 117#ifndef HZ
118#define HZ 60 118#define HZ 60
119#endif 119#endif
120 120
121struct tms tms; 121struct tms tms;
122 122
123double dtime() 123double dtime()
124{ 124{
125 double q; 125 double q;
126 126
127 times(&tms); 127 times(&tms);
128 128
129 q = (double)(tms.tms_utime) / (double)HZ; 129 q = (double)(tms.tms_utime) / (double)HZ;
130 130
131 return q; 131 return q;
132} 132}
133#endif 133#endif
134 134
135/*********************************************************/ 135/*********************************************************/
136/* VMS dtime() for VMS systems. */ 136/* VMS dtime() for VMS systems. */
137/* Provided by: RAMO@uvphys.phys.UVic.CA */ 137/* Provided by: RAMO@uvphys.phys.UVic.CA */
138/* Some people have run into problems with this timer. */ 138/* Some people have run into problems with this timer. */
139/*********************************************************/ 139/*********************************************************/
140#ifdef VMS 140#ifdef VMS
141#include time 141#include time
142 142
143#ifndef HZ 143#ifndef HZ
144#define HZ 100 144#define HZ 100
145#endif 145#endif
146 146
147struct tbuffer_t 147struct tbuffer_t
148 { 148 {
149 int proc_user_time; 149 int proc_user_time;
150 int proc_system_time; 150 int proc_system_time;
151 int child_user_time; 151 int child_user_time;
152 int child_system_time; 152 int child_system_time;
153 }; 153 };
154 154
155struct tbuffer_t tms; 155struct tbuffer_t tms;
156 156
157double dtime() 157double dtime()
158{ 158{
159 double q; 159 double q;
160 160
161 times(&tms); 161 times(&tms);
162 162
163 q = (double)(tms.proc_user_time) / (double)HZ; 163 q = (double)(tms.proc_user_time) / (double)HZ;
164 164
165 return q; 165 return q;
166} 166}
167#endif 167#endif
168 168
169/******************************/ 169/******************************/
170/* BORLAND C dtime() for DOS */ 170/* BORLAND C dtime() for DOS */
171/******************************/ 171/******************************/
172#ifdef BORLAND_C 172#ifdef BORLAND_C
173#include <ctype.h> 173#include <ctype.h>
174#include <dos.h> 174#include <dos.h>
175#include <time.h> 175#include <time.h>
176 176
177#define HZ 100 177#define HZ 100
178struct time tnow; 178struct time tnow;
179 179
180double dtime() 180double dtime()
181{ 181{
182 double q; 182 double q;
183 183
184 gettime(&tnow); 184 gettime(&tnow);
185 185
186 q = 60.0 * (double)(tnow.ti_min); 186 q = 60.0 * (double)(tnow.ti_min);
187 q = q + (double)(tnow.ti_sec); 187 q = q + (double)(tnow.ti_sec);
188 q = q + (double)(tnow.ti_hund)/(double)HZ; 188 q = q + (double)(tnow.ti_hund)/(double)HZ;
189 189
190 return q; 190 return q;
191} 191}
192#endif 192#endif
193 193
194/**************************************/ 194/**************************************/
195/* Microsoft C (MSC) dtime() for DOS */ 195/* Microsoft C (MSC) dtime() for DOS */
196/**************************************/ 196/**************************************/
197#ifdef MSC 197#ifdef MSC
198#include <time.h> 198#include <time.h>
199#include <ctype.h> 199#include <ctype.h>
200 200
201#define HZ CLOCKS_PER_SEC 201#define HZ CLOCKS_PER_SEC
202clock_t tnow; 202clock_t tnow;
203 203
204double dtime() 204double dtime()
205{ 205{
206 double q; 206 double q;
207 207
208 tnow = clock(); 208 tnow = clock();
209 209
210 q = (double)tnow / (double)HZ; 210 q = (double)tnow / (double)HZ;
211 211
212 return q; 212 return q;
213} 213}
214#endif 214#endif
215 215
216/*************************************/ 216/*************************************/
217/* Macintosh (MAC) Think C dtime() */ 217/* Macintosh (MAC) Think C dtime() */
218/*************************************/ 218/*************************************/
219#ifdef MAC 219#ifdef MAC
220#include <time.h> 220#include <time.h>
221 221
222#define HZ 60 222#define HZ 60
223 223
224double dtime() 224double dtime()
225{ 225{
226 double q; 226 double q;
227 227
228 q = (double)clock() / (double)HZ; 228 q = (double)clock() / (double)HZ;
229 229
230 return q; 230 return q;
231} 231}
232#endif 232#endif
233 233
234/************************************************************/ 234/************************************************************/
235/* iPSC/860 (IPSC) dtime() for i860. */ 235/* iPSC/860 (IPSC) dtime() for i860. */
236/* Provided by: Dan Yergeau, yergeau@gloworm.Stanford.EDU */ 236/* Provided by: Dan Yergeau, yergeau@gloworm.Stanford.EDU */
237/************************************************************/ 237/************************************************************/
238#ifdef IPSC 238#ifdef IPSC
239extern double dclock(); 239extern double dclock();
240 240
241double dtime() 241double dtime()
242{ 242{
243 double q; 243 double q;
244 244
245 q = dclock(); 245 q = dclock();
246 246
247 return q; 247 return q;
248} 248}
249#endif 249#endif
250 250
251/**************************************************/ 251/**************************************************/
252/* FORTRAN dtime() for Cray type systems. */ 252/* FORTRAN dtime() for Cray type systems. */
253/* This is the preferred timer for Cray systems. */ 253/* This is the preferred timer for Cray systems. */
254/**************************************************/ 254/**************************************************/
255#ifdef FORTRAN_SEC 255#ifdef FORTRAN_SEC
256 256
257fortran double second(); 257fortran double second();
258 258
259double dtime() 259double dtime()
260{ 260{
261 double q; 261 double q;
262 262
263 second(&q); 263 second(&q);
264 264
265 return q; 265 return q;
266} 266}
267#endif 267#endif
268 268
269/***********************************************************/ 269/***********************************************************/
270/* UNICOS C dtime() for Cray UNICOS systems. Don't use */ 270/* UNICOS C dtime() for Cray UNICOS systems. Don't use */
271/* unless absolutely necessary as returned time includes */ 271/* unless absolutely necessary as returned time includes */
272/* 'user+system' time. Provided by: R. Mike Dority, */ 272/* 'user+system' time. Provided by: R. Mike Dority, */
273/* dority@craysea.cray.com */ 273/* dority@craysea.cray.com */
274/***********************************************************/ 274/***********************************************************/
275#ifdef CTimer 275#ifdef CTimer
276#include <time.h> 276#include <time.h>
277 277
278double dtime() 278double dtime()
279{ 279{
280 double q; 280 double q;
281 clock_t clock(void); 281 clock_t clock(void);
282 282
283 q = (double)clock() / (double)CLOCKS_PER_SEC; 283 q = (double)clock() / (double)CLOCKS_PER_SEC;
284 284
285 return q; 285 return q;
286} 286}
287#endif 287#endif
288 288
289/********************************************/ 289/********************************************/
290/* Another UNIX timer using gettimeofday(). */ 290/* Another UNIX timer using gettimeofday(). */
291/* However, getrusage() is preferred. */ 291/* However, getrusage() is preferred. */
292/********************************************/ 292/********************************************/
293#ifdef GTODay 293#ifdef GTODay
294#include <sys/time.h> 294#include <sys/time.h>
295 295
296struct timeval tnow; 296struct timeval tnow;
297 297
298double dtime() 298double dtime()
299{ 299{
300 double q; 300 double q;
301 301
302 gettimeofday(&tnow,NULL); 302 gettimeofday(&tnow,NULL);
303 q = (double)tnow.tv_sec + (double)tnow.tv_usec * 1.0e-6; 303 q = (double)tnow.tv_sec + (double)tnow.tv_usec * 1.0e-6;
304 304
305 return q; 305 return q;
306} 306}
307#endif 307#endif
308 308
309/*****************************************************/ 309/*****************************************************/
310/* Fujitsu UXP/M timer. */ 310/* Fujitsu UXP/M timer. */
311/* Provided by: Mathew Lim, ANUSF, M.Lim@anu.edu.au */ 311/* Provided by: Mathew Lim, ANUSF, M.Lim@anu.edu.au */
312/*****************************************************/ 312/*****************************************************/
313#ifdef UXPM 313#ifdef UXPM
314#include <sys/types.h> 314#include <sys/types.h>
315#include <sys/timesu.h> 315#include <sys/timesu.h>
316struct tmsu rusage; 316struct tmsu rusage;
317 317
318double dtime() 318double dtime()
319{ 319{
320 double q; 320 double q;
321 321
322 timesu(&rusage); 322 timesu(&rusage);
323 323
324 q = (double)(rusage.tms_utime) * 1.0e-06; 324 q = (double)(rusage.tms_utime) * 1.0e-06;
325 325
326 return q; 326 return q;
327} 327}
328#endif 328#endif
329 329
330/**********************************************/ 330/**********************************************/
331/* Macintosh (MAC_TMgr) Think C dtime() */ 331/* Macintosh (MAC_TMgr) Think C dtime() */
332/* requires Think C Language Extensions or */ 332/* requires Think C Language Extensions or */
333/* #include <MacHeaders> in the prefix */ 333/* #include <MacHeaders> in the prefix */
334/* provided by Francis H Schiffer 3rd (fhs) */ 334/* provided by Francis H Schiffer 3rd (fhs) */
335/* skipschiffer@genie.geis.com */ 335/* skipschiffer@genie.geis.com */
336/**********************************************/ 336/**********************************************/
337#ifdef MAC_TMgr 337#ifdef MAC_TMgr
338#include <Timer.h> 338#include <Timer.h>
339#include <stdlib.h> 339#include <stdlib.h>
340 340
341static TMTask mgrTimer; 341static TMTask mgrTimer;
342static Boolean mgrInited = false; 342static Boolean mgrInited = false;
343static double mgrClock; 343static double mgrClock;
344 344
345#define RMV_TIMER RmvTime( (QElemPtr)&mgrTimer ) 345#define RMV_TIMER RmvTime( (QElemPtr)&mgrTimer )
346#define MAX_TIME 1800000000L 346#define MAX_TIME 1800000000L
347/* MAX_TIME limits time between calls to */ 347/* MAX_TIME limits time between calls to */
348/* dtime( ) to no more than 30 minutes */ 348/* dtime( ) to no more than 30 minutes */
349/* this limitation could be removed by */ 349/* this limitation could be removed by */
350/* creating a completion routine to sum */ 350/* creating a completion routine to sum */
351/* 30 minute segments (fhs 1994 feb 9) */ 351/* 30 minute segments (fhs 1994 feb 9) */
352 352
353static void Remove_timer( ) 353static void Remove_timer( )
354{ 354{
355 RMV_TIMER; 355 RMV_TIMER;
356 mgrInited = false; 356 mgrInited = false;
357} 357}
358 358
359double dtime( ) 359double dtime( )
360{ 360{
361 if( mgrInited ) { 361 if( mgrInited ) {
362 RMV_TIMER; 362 RMV_TIMER;
363 mgrClock += (MAX_TIME + mgrTimer.tmCount)*1.0e-6; 363 mgrClock += (MAX_TIME + mgrTimer.tmCount)*1.0e-6;
364 } else { 364 } else {
365 if( _atexit( &Remove_timer ) == 0 ) mgrInited = true; 365 if( _atexit( &Remove_timer ) == 0 ) mgrInited = true;
366 mgrClock = 0.0; 366 mgrClock = 0.0;
367 } 367 }
368 368
369 if ( mgrInited ) 369 if ( mgrInited )
370 { 370 {
371 mgrTimer.tmAddr = NULL; 371 mgrTimer.tmAddr = NULL;
372 mgrTimer.tmCount = 0; 372 mgrTimer.tmCount = 0;
373 mgrTimer.tmWakeUp = 0; 373 mgrTimer.tmWakeUp = 0;
374 mgrTimer.tmReserved = 0; 374 mgrTimer.tmReserved = 0;
375 InsTime( (QElemPtr)&mgrTimer ); 375 InsTime( (QElemPtr)&mgrTimer );
376 PrimeTime( (QElemPtr)&mgrTimer, -MAX_TIME ); 376 PrimeTime( (QElemPtr)&mgrTimer, -MAX_TIME );
377 } 377 }
378 return( mgrClock ); 378 return( mgrClock );
379} 379}
380#endif 380#endif
381 381
382/***********************************************************/ 382/***********************************************************/
383/* Parsytec GCel timer. */ 383/* Parsytec GCel timer. */
384/* Provided by: Georg Wambach, gw@informatik.uni-koeln.de */ 384/* Provided by: Georg Wambach, gw@informatik.uni-koeln.de */
385/***********************************************************/ 385/***********************************************************/
386#ifdef PARIX 386#ifdef PARIX
387#include <sys/time.h> 387#include <sys/time.h>
388 388
389double dtime() 389double dtime()
390{ 390{
391 double q; 391 double q;
392 392
393 q = (double) (TimeNowHigh()) / (double) CLK_TCK_HIGH; 393 q = (double) (TimeNowHigh()) / (double) CLK_TCK_HIGH;
394 394
395 return q; 395 return q;
396} 396}
397#endif 397#endif
398 398
399/************************************************/ 399/************************************************/
400/* Sun Solaris POSIX dtime() routine */ 400/* Sun Solaris POSIX dtime() routine */
401/* Provided by: Case Larsen, CTLarsen.lbl.gov */ 401/* Provided by: Case Larsen, CTLarsen.lbl.gov */
402/************************************************/ 402/************************************************/
403#ifdef POSIX 403#ifdef POSIX
404#include <sys/time.h> 404#include <sys/time.h>
405#include <sys/resource.h> 405#include <sys/resource.h>
406#include <sys/rusage.h> 406#include <sys/rusage.h>
407 407
408#ifdef __hpux 408#ifdef __hpux
409#include <sys/syscall.h> 409#include <sys/syscall.h>
410#endif 410#endif
411 411
412struct rusage rusage; 412struct rusage rusage;
413 413
414double dtime() 414double dtime()
415{ 415{
416 double q; 416 double q;
417 417
418 getrusage(RUSAGE_SELF,&rusage); 418 getrusage(RUSAGE_SELF,&rusage);
419 419
420 q = (double)(rusage.ru_utime.tv_sec); 420 q = (double)(rusage.ru_utime.tv_sec);
421 q = q + (double)(rusage.ru_utime.tv_nsec) * 1.0e-09; 421 q = q + (double)(rusage.ru_utime.tv_nsec) * 1.0e-09;
422 422
423 return q; 423 return q;
424} 424}
425#endif 425#endif
426 426
427 427
428/****************************************************/ 428/****************************************************/
429/* Windows NT (32 bit) dtime() routine */ 429/* Windows NT (32 bit) dtime() routine */
430/* Provided by: Piers Haken, piersh@microsoft.com */ 430/* Provided by: Piers Haken, piersh@microsoft.com */
431/****************************************************/ 431/****************************************************/
432#ifdef WIN32 432#ifdef WIN32
433#include <windows.h> 433#include <windows.h>
434 434
435double dtime(void) 435double dtime(void)
436{ 436{
437 double q; 437 double q;
438 438
439 q = (double)GetTickCount() * 1.0e-03; 439 q = (double)GetTickCount() * 1.0e-03;
440 440
441 return q; 441 return q;
442} 442}
443#endif 443#endif
444 444
445/*****************************************************/ 445/*****************************************************/
446/* Time according to POSIX.1 - <J.Pelan@qub.ac.uk> */ 446/* Time according to POSIX.1 - <J.Pelan@qub.ac.uk> */
447/* Ref: "POSIX Programmer's Guide" O'Reilly & Assoc.*/ 447/* Ref: "POSIX Programmer's Guide" O'Reilly & Assoc.*/
448/*****************************************************/ 448/*****************************************************/
449#ifdef POSIX1 449#ifdef POSIX1
450#define _POSIX_SOURCE 1 450#define _POSIX_SOURCE 1
451#include <unistd.h> 451#include <unistd.h>
452#include <limits.h> 452#include <limits.h>
453#include <sys/times.h> 453#include <sys/times.h>
454 454
455struct tms tms; 455struct tms tms;
456 456
457double dtime() 457double dtime()
458{ 458{
459 double q; 459 double q;
460 times(&tms); 460 times(&tms);
461 q = (double)tms.tms_utime / (double)CLK_TCK; 461 q = (double)tms.tms_utime / (double)CLK_TCK;
462 return q; 462 return q;
463} 463}
464#endif 464#endif
465/* 465/*
466 ************************************************************************* 466 *************************************************************************
467 * 467 *
468 * "DHRYSTONE" Benchmark Program 468 * "DHRYSTONE" Benchmark Program
469 * ----------------------------- 469 * -----------------------------
470 * 470 *
471 * Version: C, Version 2.1 471 * Version: C, Version 2.1
472 * 472 *
473 * File: dhry_1.c (part 2 of 3) 473 * File: dhry_1.c (part 2 of 3)
474 * 474 *
475 * Date: May 25, 1988 475 * Date: May 25, 1988
476 * 476 *
477 * Author: Reinhold P. Weicker 477 * Author: Reinhold P. Weicker
478 * 478 *
479 ************************************************************************* 479 *************************************************************************
480 */ 480 */
481 481
482#include <stdio.h> 482#include <stdio.h>
483#include <stdlib.h> 483#include <stdlib.h>
484#include <string.h> 484#include <string.h>
485#include "dhry.h" 485#include "dhry.h"
486 486
487/* Global Variables: */ 487/* Global Variables: */
488 488
489Rec_Pointer Ptr_Glob, 489Rec_Pointer Ptr_Glob,
490 Next_Ptr_Glob; 490 Next_Ptr_Glob;
491int Int_Glob; 491int Int_Glob;
492Boolean Bool_Glob; 492Boolean Bool_Glob;
493char Ch_1_Glob, 493char Ch_1_Glob,
494 Ch_2_Glob; 494 Ch_2_Glob;
495int Arr_1_Glob [50]; 495int Arr_1_Glob [50];
496int Arr_2_Glob [50] [50]; 496int Arr_2_Glob [50] [50];
497 497
498char Reg_Define[] = "Register option selected."; 498char Reg_Define[32] = "Register option selected.";
499 499
500//extern char *malloc (); 500//extern char *malloc ();
501Enumeration Func_1 (); 501Enumeration Func_1 ();
502 /* 502 /*
503 forward declaration necessary since Enumeration may not simply be int 503 forward declaration necessary since Enumeration may not simply be int
504 */ 504 */
505 505
506#ifndef ROPT 506#ifndef ROPT
507#define REG 507#define REG
508 /* REG becomes defined as empty */ 508 /* REG becomes defined as empty */
509 /* i.e. no register variables */ 509 /* i.e. no register variables */
510#else 510#else
511#define REG register 511#define REG register
512#endif 512#endif
513 513
514 514
515/* variables for time measurement: */ 515/* variables for time measurement: */
516 516
517#define Too_Small_Time 2 517#define Too_Small_Time 2
518 /* Measurements should last at least 2 seconds */ 518 /* Measurements should last at least 2 seconds */
519 519
520double Begin_Time, 520double Begin_Time,
521 End_Time, 521 End_Time,
522 User_Time; 522 User_Time;
523 523
524double Microseconds, 524double Microseconds,
525 Dhrystones_Per_Second, 525 Dhrystones_Per_Second,
526 Vax_Mips; 526 Vax_Mips;
527 527
528/* end of variables for time measurement */ 528/* end of variables for time measurement */
529 529
530/**********************************************************************************************/ 530/**********************************************************************************************/
531 531
532 532
533Proc_1 (Ptr_Val_Par) 533Proc_1 (Ptr_Val_Par)
534/******************/ 534/******************/
535 535
536REG Rec_Pointer Ptr_Val_Par; 536REG Rec_Pointer Ptr_Val_Par;
537 /* executed once */ 537 /* executed once */
538{ 538{
539 REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; 539 REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
540 /* == Ptr_Glob_Next */ 540 /* == Ptr_Glob_Next */
541 /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ 541 /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
542 /* corresponds to "rename" in Ada, "with" in Pascal */ 542 /* corresponds to "rename" in Ada, "with" in Pascal */
543 543
544 structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); 544 structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
545 Ptr_Val_Par->variant.var_1.Int_Comp = 5; 545 Ptr_Val_Par->variant.var_1.Int_Comp = 5;
546 Next_Record->variant.var_1.Int_Comp 546 Next_Record->variant.var_1.Int_Comp
547 = Ptr_Val_Par->variant.var_1.Int_Comp; 547 = Ptr_Val_Par->variant.var_1.Int_Comp;
548 Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; 548 Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
549 Proc_3 (&Next_Record->Ptr_Comp); 549 Proc_3 (&Next_Record->Ptr_Comp);
550 /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp 550 /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
551 == Ptr_Glob->Ptr_Comp */ 551 == Ptr_Glob->Ptr_Comp */
552 if (Next_Record->Discr == Ident_1) 552 if (Next_Record->Discr == Ident_1)
553 /* then, executed */ 553 /* then, executed */
554 { 554 {
555 Next_Record->variant.var_1.Int_Comp = 6; 555 Next_Record->variant.var_1.Int_Comp = 6;
556 Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, 556 Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
557 &Next_Record->variant.var_1.Enum_Comp); 557 &Next_Record->variant.var_1.Enum_Comp);
558 Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; 558 Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
559 Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, 559 Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
560 &Next_Record->variant.var_1.Int_Comp); 560 &Next_Record->variant.var_1.Int_Comp);
561 } 561 }
562 else /* not executed */ 562 else /* not executed */
563 structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); 563 structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
564} /* Proc_1 */ 564} /* Proc_1 */
565 565
566 566
567Proc_2 (Int_Par_Ref) 567Proc_2 (Int_Par_Ref)
568/******************/ 568/******************/
569 /* executed once */ 569 /* executed once */
570 /* *Int_Par_Ref == 1, becomes 4 */ 570 /* *Int_Par_Ref == 1, becomes 4 */
571 571
572One_Fifty *Int_Par_Ref; 572One_Fifty *Int_Par_Ref;
573{ 573{
574 One_Fifty Int_Loc; 574 One_Fifty Int_Loc;
575 Enumeration Enum_Loc; 575 Enumeration Enum_Loc;
576 576
577 Int_Loc = *Int_Par_Ref + 10; 577 Int_Loc = *Int_Par_Ref + 10;
578 do /* executed once */ 578 do /* executed once */
579 if (Ch_1_Glob == 'A') 579 if (Ch_1_Glob == 'A')
580 /* then, executed */ 580 /* then, executed */
581 { 581 {
582 Int_Loc -= 1; 582 Int_Loc -= 1;
583 *Int_Par_Ref = Int_Loc - Int_Glob; 583 *Int_Par_Ref = Int_Loc - Int_Glob;
584 Enum_Loc = Ident_1; 584 Enum_Loc = Ident_1;
585 } /* if */ 585 } /* if */
586 while (Enum_Loc != Ident_1); /* true */ 586 while (Enum_Loc != Ident_1); /* true */
587} /* Proc_2 */ 587} /* Proc_2 */
588 588
589 589
590Proc_3 (Ptr_Ref_Par) 590Proc_3 (Ptr_Ref_Par)
591/******************/ 591/******************/
592 /* executed once */ 592 /* executed once */
593 /* Ptr_Ref_Par becomes Ptr_Glob */ 593 /* Ptr_Ref_Par becomes Ptr_Glob */
594 594
595Rec_Pointer *Ptr_Ref_Par; 595Rec_Pointer *Ptr_Ref_Par;
596 596
597{ 597{
598 if (Ptr_Glob != Null) 598 if (Ptr_Glob != Null)
599 /* then, executed */ 599 /* then, executed */
600 *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; 600 *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
601 Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); 601 Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
602} /* Proc_3 */ 602} /* Proc_3 */
603 603
604 604
605Proc_4 () /* without parameters */ 605Proc_4 () /* without parameters */
606/*******/ 606/*******/
607 /* executed once */ 607 /* executed once */
608{ 608{
609 Boolean Bool_Loc; 609 Boolean Bool_Loc;
610 610
611 Bool_Loc = Ch_1_Glob == 'A'; 611 Bool_Loc = Ch_1_Glob == 'A';
612 Bool_Glob = Bool_Loc | Bool_Glob; 612 Bool_Glob = Bool_Loc | Bool_Glob;
613 Ch_2_Glob = 'B'; 613 Ch_2_Glob = 'B';
614} /* Proc_4 */ 614} /* Proc_4 */
615 615
616 616
617Proc_5 () /* without parameters */ 617Proc_5 () /* without parameters */
618/*******/ 618/*******/
619 /* executed once */ 619 /* executed once */
620{ 620{
621 Ch_1_Glob = 'A'; 621 Ch_1_Glob = 'A';
622 Bool_Glob = false; 622 Bool_Glob = false;
623} /* Proc_5 */ 623} /* Proc_5 */
624 624
625 625
626 /* Procedure for the assignment of structures, */ 626 /* Procedure for the assignment of structures, */
627 /* if the C compiler doesn't support this feature */ 627 /* if the C compiler doesn't support this feature */
628#ifdef NOSTRUCTASSIGN 628#ifdef NOSTRUCTASSIGN
629memcpy (d, s, l) 629memcpy (d, s, l)
630register char *d; 630register char *d;
631register char *s; 631register char *s;
632register int l; 632register int l;
633{ 633{
634 while (l--) *d++ = *s++; 634 while (l--) *d++ = *s++;
635} 635}
636#endif 636#endif
637 637
638 638
639Proc_6 (Enum_Val_Par, Enum_Ref_Par) 639Proc_6 (Enum_Val_Par, Enum_Ref_Par)
640/*********************************/ 640/*********************************/
641 /* executed once */ 641 /* executed once */
642 /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ 642 /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
643 643
644Enumeration Enum_Val_Par; 644Enumeration Enum_Val_Par;
645Enumeration *Enum_Ref_Par; 645Enumeration *Enum_Ref_Par;
646{ 646{
647 *Enum_Ref_Par = Enum_Val_Par; 647 *Enum_Ref_Par = Enum_Val_Par;
648 if (! Func_3 (Enum_Val_Par)) 648 if (! Func_3 (Enum_Val_Par))
649 /* then, not executed */ 649 /* then, not executed */
650 *Enum_Ref_Par = Ident_4; 650 *Enum_Ref_Par = Ident_4;
651 switch (Enum_Val_Par) 651 switch (Enum_Val_Par)
652 { 652 {
653 case Ident_1: 653 case Ident_1:
654 *Enum_Ref_Par = Ident_1; 654 *Enum_Ref_Par = Ident_1;
655 break; 655 break;
656 case Ident_2: 656 case Ident_2:
657 if (Int_Glob > 100) 657 if (Int_Glob > 100)
658 /* then */ 658 /* then */
659 *Enum_Ref_Par = Ident_1; 659 *Enum_Ref_Par = Ident_1;
660 else *Enum_Ref_Par = Ident_4; 660 else *Enum_Ref_Par = Ident_4;
661 break; 661 break;
662 case Ident_3: /* executed */ 662 case Ident_3: /* executed */
663 *Enum_Ref_Par = Ident_2; 663 *Enum_Ref_Par = Ident_2;
664 break; 664 break;
665 case Ident_4: break; 665 case Ident_4: break;
666 case Ident_5: 666 case Ident_5:
667 *Enum_Ref_Par = Ident_3; 667 *Enum_Ref_Par = Ident_3;
668 break; 668 break;
669 } /* switch */ 669 } /* switch */
670} /* Proc_6 */ 670} /* Proc_6 */
671 671
672 672
673Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref) 673Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
674/**********************************************/ 674/**********************************************/
675 /* executed three times */ 675 /* executed three times */
676 /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ 676 /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
677 /* Int_Par_Ref becomes 7 */ 677 /* Int_Par_Ref becomes 7 */
678 /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ 678 /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
679 /* Int_Par_Ref becomes 17 */ 679 /* Int_Par_Ref becomes 17 */
680 /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ 680 /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
681 /* Int_Par_Ref becomes 18 */ 681 /* Int_Par_Ref becomes 18 */
682One_Fifty Int_1_Par_Val; 682One_Fifty Int_1_Par_Val;
683One_Fifty Int_2_Par_Val; 683One_Fifty Int_2_Par_Val;
684One_Fifty *Int_Par_Ref; 684One_Fifty *Int_Par_Ref;
685{ 685{
686 One_Fifty Int_Loc; 686 One_Fifty Int_Loc;
687 687
688 Int_Loc = Int_1_Par_Val + 2; 688 Int_Loc = Int_1_Par_Val + 2;
689 *Int_Par_Ref = Int_2_Par_Val + Int_Loc; 689 *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
690} /* Proc_7 */ 690} /* Proc_7 */
691 691
692 692
693Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val) 693Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
694/*********************************************************************/ 694/*********************************************************************/
695 /* executed once */ 695 /* executed once */
696 /* Int_Par_Val_1 == 3 */ 696 /* Int_Par_Val_1 == 3 */
697 /* Int_Par_Val_2 == 7 */ 697 /* Int_Par_Val_2 == 7 */
698Arr_1_Dim Arr_1_Par_Ref; 698Arr_1_Dim Arr_1_Par_Ref;
699Arr_2_Dim Arr_2_Par_Ref; 699Arr_2_Dim Arr_2_Par_Ref;
700int Int_1_Par_Val; 700int Int_1_Par_Val;
701int Int_2_Par_Val; 701int Int_2_Par_Val;
702{ 702{
703 REG One_Fifty Int_Index; 703 REG One_Fifty Int_Index;
704 REG One_Fifty Int_Loc; 704 REG One_Fifty Int_Loc;
705 705
706 Int_Loc = Int_1_Par_Val + 5; 706 Int_Loc = Int_1_Par_Val + 5;
707 Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; 707 Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
708 Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; 708 Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
709 Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; 709 Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
710 for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) 710 for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
711 Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; 711 Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
712 Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; 712 Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
713 Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; 713 Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
714 Int_Glob = 5; 714 Int_Glob = 5;
715} /* Proc_8 */ 715} /* Proc_8 */
716 716
717 717
718Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val) 718Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val)
719/*************************************************/ 719/*************************************************/
720 /* executed three times */ 720 /* executed three times */
721 /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ 721 /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
722 /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ 722 /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
723 /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ 723 /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
724 724
725Capital_Letter Ch_1_Par_Val; 725Capital_Letter Ch_1_Par_Val;
726Capital_Letter Ch_2_Par_Val; 726Capital_Letter Ch_2_Par_Val;
727{ 727{
728 Capital_Letter Ch_1_Loc; 728 Capital_Letter Ch_1_Loc;
729 Capital_Letter Ch_2_Loc; 729 Capital_Letter Ch_2_Loc;
730 730
731 Ch_1_Loc = Ch_1_Par_Val; 731 Ch_1_Loc = Ch_1_Par_Val;
732 Ch_2_Loc = Ch_1_Loc; 732 Ch_2_Loc = Ch_1_Loc;
733 if (Ch_2_Loc != Ch_2_Par_Val) 733 if (Ch_2_Loc != Ch_2_Par_Val)
734 /* then, executed */ 734 /* then, executed */
735 return (Ident_1); 735 return (Ident_1);
736 else /* not executed */ 736 else /* not executed */
737 { 737 {
738 Ch_1_Glob = Ch_1_Loc; 738 Ch_1_Glob = Ch_1_Loc;
739 return (Ident_2); 739 return (Ident_2);
740 } 740 }
741} /* Func_1 */ 741} /* Func_1 */
742 742
743 743
744Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref) 744Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
745/*************************************************/ 745/*************************************************/
746 /* executed once */ 746 /* executed once */
747 /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ 747 /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
748 /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ 748 /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
749 749
750Str_30 Str_1_Par_Ref; 750Str_30 Str_1_Par_Ref;
751Str_30 Str_2_Par_Ref; 751Str_30 Str_2_Par_Ref;
752{ 752{
753 REG One_Thirty Int_Loc; 753 REG One_Thirty Int_Loc;
754 Capital_Letter Ch_Loc; 754 Capital_Letter Ch_Loc;
755 755
756 Int_Loc = 2; 756 Int_Loc = 2;
757 while (Int_Loc <= 2) /* loop body executed once */ 757 while (Int_Loc <= 2) /* loop body executed once */
758 if (Func_1 (Str_1_Par_Ref[Int_Loc], 758 if (Func_1 (Str_1_Par_Ref[Int_Loc],
759 Str_2_Par_Ref[Int_Loc+1]) == Ident_1) 759 Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
760 /* then, executed */ 760 /* then, executed */
761 { 761 {
762 Ch_Loc = 'A'; 762 Ch_Loc = 'A';
763 Int_Loc += 1; 763 Int_Loc += 1;
764 } /* if, while */ 764 } /* if, while */
765 if (Ch_Loc >= 'W' && Ch_Loc < 'Z') 765 if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
766 /* then, not executed */ 766 /* then, not executed */
767 Int_Loc = 7; 767 Int_Loc = 7;
768 if (Ch_Loc == 'R') 768 if (Ch_Loc == 'R')
769 /* then, not executed */ 769 /* then, not executed */
770 return (true); 770 return (true);
771 else /* executed */ 771 else /* executed */
772 { 772 {
773 if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) 773 if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
774 /* then, not executed */ 774 /* then, not executed */
775 { 775 {
776 Int_Loc += 7; 776 Int_Loc += 7;
777 Int_Glob = Int_Loc; 777 Int_Glob = Int_Loc;
778 return (true); 778 return (true);
779 } 779 }
780 else /* executed */ 780 else /* executed */
781 return (false); 781 return (false);
782 } /* if Ch_Loc */ 782 } /* if Ch_Loc */
783} /* Func_2 */ 783} /* Func_2 */
784 784
785 785
786Boolean Func_3 (Enum_Par_Val) 786Boolean Func_3 (Enum_Par_Val)
787/***************************/ 787/***************************/
788 /* executed once */ 788 /* executed once */
789 /* Enum_Par_Val == Ident_3 */ 789 /* Enum_Par_Val == Ident_3 */
790Enumeration Enum_Par_Val; 790Enumeration Enum_Par_Val;
791{ 791{
792 Enumeration Enum_Loc; 792 Enumeration Enum_Loc;
793 793
794 Enum_Loc = Enum_Par_Val; 794 Enum_Loc = Enum_Par_Val;
795 if (Enum_Loc == Ident_3) 795 if (Enum_Loc == Ident_3)
796 /* then, executed */ 796 /* then, executed */
797 return (true); 797 return (true);
798 else /* not executed */ 798 else /* not executed */
799 return (false); 799 return (false);
800} /* Func_3 */ 800} /* Func_3 */
801 801
802/*********************************************************************************/ 802/*********************************************************************************/
803 803
804double dhry_main( int n ) 804double dhry_main( int n )
805/*****/ 805/*****/
806 806
807 /* main program, corresponds to procedures */ 807 /* main program, corresponds to procedures */
808 /* Main and Proc_0 in the Ada version */ 808 /* Main and Proc_0 in the Ada version */
809{ 809{
810 One_Fifty Int_1_Loc; 810 One_Fifty Int_1_Loc;
811 REG One_Fifty Int_2_Loc; 811 REG One_Fifty Int_2_Loc;
812 One_Fifty Int_3_Loc; 812 One_Fifty Int_3_Loc;
813 REG char Ch_Index; 813 REG char Ch_Index;
814 Enumeration Enum_Loc; 814 Enumeration Enum_Loc;
815 Str_30 Str_1_Loc; 815 Str_30 Str_1_Loc;
816 Str_30 Str_2_Loc; 816 Str_30 Str_2_Loc;
817 REG int Run_Index; 817 REG int Run_Index;
818 REG int Number_Of_Runs; 818 REG int Number_Of_Runs;
819 819
820 FILE *Ap; 820 FILE *Ap;
821 821
822 /* Initializations */ 822 /* Initializations */
823 823
824/* if ((Ap = fopen("dhry.res","a+")) == NULL) 824/* if ((Ap = fopen("dhry.res","a+")) == NULL)
825 { 825 {
826 printf("Can not open dhry.res\n\n"); 826 printf("Can not open dhry.res\n\n");
827 exit(1); 827 exit(1);
828 } 828 }
829*/ 829*/
830 Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); 830 Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
831 Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); 831 Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
832 832
833 Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; 833 Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
834 Ptr_Glob->Discr = Ident_1; 834 Ptr_Glob->Discr = Ident_1;
835 Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; 835 Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
836 Ptr_Glob->variant.var_1.Int_Comp = 40; 836 Ptr_Glob->variant.var_1.Int_Comp = 40;
837 strcpy (Ptr_Glob->variant.var_1.Str_Comp, 837 strcpy (Ptr_Glob->variant.var_1.Str_Comp,
838 "DHRYSTONE PROGRAM, SOME STRING"); 838 "DHRYSTONE PROGRAM, SOME STRING");
839 strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); 839 strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
840 840
841 Arr_2_Glob [8][7] = 10; 841 Arr_2_Glob [8][7] = 10;
842 /* Was missing in published program. Without this statement, */ 842 /* Was missing in published program. Without this statement, */
843 /* Arr_2_Glob [8][7] would have an undefined value. */ 843 /* Arr_2_Glob [8][7] would have an undefined value. */
844 /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ 844 /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
845 /* overflow may occur for this array element. */ 845 /* overflow may occur for this array element. */
846 846
847/* 847/*
848 if (Reg) 848 if (Reg)
849 { 849 {
850 printf ("Program compiled with 'register' attribute\n"); 850 printf ("Program compiled with 'register' attribute\n");
851 printf ("\n"); 851 printf ("\n");
852 } 852 }
853 else 853 else
854 { 854 {
855 printf ("Program compiled without 'register' attribute\n"); 855 printf ("Program compiled without 'register' attribute\n");
856 printf ("\n"); 856 printf ("\n");
857 } 857 }
858*/ 858*/
859 Number_Of_Runs = n; 859 Number_Of_Runs = n;
860 860
861 /***************/ 861 /***************/
862 /* Start timer */ 862 /* Start timer */
863 /***************/ 863 /***************/
864 864
865 Begin_Time = dtime(); 865 Begin_Time = dtime();
866 866
867 for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) 867 for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
868 { 868 {
869 869
870 Proc_5(); 870 Proc_5();
871 Proc_4(); 871 Proc_4();
872 /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ 872 /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
873 Int_1_Loc = 2; 873 Int_1_Loc = 2;
874 Int_2_Loc = 3; 874 Int_2_Loc = 3;
875 strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); 875 strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
876 Enum_Loc = Ident_2; 876 Enum_Loc = Ident_2;
877 Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); 877 Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
878 /* Bool_Glob == 1 */ 878 /* Bool_Glob == 1 */
879 while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ 879 while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
880 { 880 {
881 Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; 881 Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
882 /* Int_3_Loc == 7 */ 882 /* Int_3_Loc == 7 */
883 Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); 883 Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
884 /* Int_3_Loc == 7 */ 884 /* Int_3_Loc == 7 */
885 Int_1_Loc += 1; 885 Int_1_Loc += 1;
886 } /* while */ 886 } /* while */
887 /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 887 /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
888 Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); 888 Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
889 /* Int_Glob == 5 */ 889 /* Int_Glob == 5 */
890 Proc_1 (Ptr_Glob); 890 Proc_1 (Ptr_Glob);
891 for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) 891 for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
892 /* loop body executed twice */ 892 /* loop body executed twice */
893 { 893 {
894 if (Enum_Loc == Func_1 (Ch_Index, 'C')) 894 if (Enum_Loc == Func_1 (Ch_Index, 'C'))
895 /* then, not executed */ 895 /* then, not executed */
896 { 896 {
897 Proc_6 (Ident_1, &Enum_Loc); 897 Proc_6 (Ident_1, &Enum_Loc);
898 strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); 898 strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
899 Int_2_Loc = Run_Index; 899 Int_2_Loc = Run_Index;
900 Int_Glob = Run_Index; 900 Int_Glob = Run_Index;
901 } 901 }
902 } 902 }
903 /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 903 /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
904 Int_2_Loc = Int_2_Loc * Int_1_Loc; 904 Int_2_Loc = Int_2_Loc * Int_1_Loc;
905 Int_1_Loc = Int_2_Loc / Int_3_Loc; 905 Int_1_Loc = Int_2_Loc / Int_3_Loc;
906 Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; 906 Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
907 /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ 907 /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
908 Proc_2 (&Int_1_Loc); 908 Proc_2 (&Int_1_Loc);
909 /* Int_1_Loc == 5 */ 909 /* Int_1_Loc == 5 */
910 910
911 } /* loop "for Run_Index" */ 911 } /* loop "for Run_Index" */
912 912
913 /**************/ 913 /**************/
914 /* Stop timer */ 914 /* Stop timer */
915 /**************/ 915 /**************/
916 916
917 End_Time = dtime(); 917 End_Time = dtime();
918 918
919/* 919/*
920 printf ("Execution ends\n"); 920 printf ("Execution ends\n");
921 printf ("\n"); 921 printf ("\n");
922 printf ("Final values of the variables used in the benchmark:\n"); 922 printf ("Final values of the variables used in the benchmark:\n");
923 printf ("\n"); 923 printf ("\n");
924 printf ("Int_Glob: %d\n", Int_Glob); 924 printf ("Int_Glob: %d\n", Int_Glob);
925 printf (" should be: %d\n", 5); 925 printf (" should be: %d\n", 5);
926 printf ("Bool_Glob: %d\n", Bool_Glob); 926 printf ("Bool_Glob: %d\n", Bool_Glob);
927 printf (" should be: %d\n", 1); 927 printf (" should be: %d\n", 1);
928 printf ("Ch_1_Glob: %c\n", Ch_1_Glob); 928 printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
929 printf (" should be: %c\n", 'A'); 929 printf (" should be: %c\n", 'A');
930 printf ("Ch_2_Glob: %c\n", Ch_2_Glob); 930 printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
931 printf (" should be: %c\n", 'B'); 931 printf (" should be: %c\n", 'B');
932 printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); 932 printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
933 printf (" should be: %d\n", 7); 933 printf (" should be: %d\n", 7);
934 printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); 934 printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
935 printf (" should be: Number_Of_Runs + 10\n"); 935 printf (" should be: Number_Of_Runs + 10\n");
936 printf ("Ptr_Glob->\n"); 936 printf ("Ptr_Glob->\n");
937 printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); 937 printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp);
938 printf (" should be: (implementation-dependent)\n"); 938 printf (" should be: (implementation-dependent)\n");
939 printf (" Discr: %d\n", Ptr_Glob->Discr); 939 printf (" Discr: %d\n", Ptr_Glob->Discr);
940 printf (" should be: %d\n", 0); 940 printf (" should be: %d\n", 0);
941 printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); 941 printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
942 printf (" should be: %d\n", 2); 942 printf (" should be: %d\n", 2);
943 printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); 943 printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp);
944 printf (" should be: %d\n", 17); 944 printf (" should be: %d\n", 17);
945 printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); 945 printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
946 printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); 946 printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
947 printf ("Next_Ptr_Glob->\n"); 947 printf ("Next_Ptr_Glob->\n");
948 printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); 948 printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
949 printf (" should be: (implementation-dependent), same as above\n"); 949 printf (" should be: (implementation-dependent), same as above\n");
950 printf (" Discr: %d\n", Next_Ptr_Glob->Discr); 950 printf (" Discr: %d\n", Next_Ptr_Glob->Discr);
951 printf (" should be: %d\n", 0); 951 printf (" should be: %d\n", 0);
952 printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); 952 printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
953 printf (" should be: %d\n", 1); 953 printf (" should be: %d\n", 1);
954 printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); 954 printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
955 printf (" should be: %d\n", 18); 955 printf (" should be: %d\n", 18);
956 printf (" Str_Comp: %s\n", Next_Ptr_Glob->variant.var_1.Str_Comp); 956 printf (" Str_Comp: %s\n", Next_Ptr_Glob->variant.var_1.Str_Comp);
957 printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); 957 printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
958 printf ("Int_1_Loc: %d\n", Int_1_Loc); 958 printf ("Int_1_Loc: %d\n", Int_1_Loc);
959 printf (" should be: %d\n", 5); 959 printf (" should be: %d\n", 5);
960 printf ("Int_2_Loc: %d\n", Int_2_Loc); 960 printf ("Int_2_Loc: %d\n", Int_2_Loc);
961 printf (" should be: %d\n", 13); 961 printf (" should be: %d\n", 13);
962 printf ("Int_3_Loc: %d\n", Int_3_Loc); 962 printf ("Int_3_Loc: %d\n", Int_3_Loc);
963 printf (" should be: %d\n", 7); 963 printf (" should be: %d\n", 7);
964 printf ("Enum_Loc: %d\n", Enum_Loc); 964 printf ("Enum_Loc: %d\n", Enum_Loc);
965 printf (" should be: %d\n", 1); 965 printf (" should be: %d\n", 1);
966 printf ("Str_1_Loc: %s\n", Str_1_Loc); 966 printf ("Str_1_Loc: %s\n", Str_1_Loc);
967 printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); 967 printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
968 printf ("Str_2_Loc: %s\n", Str_2_Loc); 968 printf ("Str_2_Loc: %s\n", Str_2_Loc);
969 printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); 969 printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
970 printf ("\n"); 970 printf ("\n");
971*/ 971*/
972 User_Time = End_Time - Begin_Time; 972 User_Time = End_Time - Begin_Time;
973 973
974 if (User_Time < Too_Small_Time) return -1; 974 if (User_Time < Too_Small_Time) return -1;
975 else 975 else
976 { 976 {
977 Microseconds = User_Time * Mic_secs_Per_Second 977 Microseconds = User_Time * Mic_secs_Per_Second
978 / (double) Number_Of_Runs; 978 / (double) Number_Of_Runs;
979 Dhrystones_Per_Second = (double) Number_Of_Runs / User_Time; 979 Dhrystones_Per_Second = (double) Number_Of_Runs / User_Time;
980 Vax_Mips = Dhrystones_Per_Second / 1757.0; 980 Vax_Mips = Dhrystones_Per_Second / 1757.0;
981 981
982#ifdef ROPT 982#ifdef ROPT
983 //printf ("Register option selected? YES\n"); 983 //printf ("Register option selected? YES\n");
984#else 984#else
985 //printf ("Register option selected? NO\n"); 985 //printf ("Register option selected? NO\n");
986 strcpy(Reg_Define, "Register option not selected."); 986 strncpy(Reg_Define, "Register option not selected.", 30);
987#endif 987#endif
988 printf ("Microseconds for one run through Dhrystone: "); 988 printf ("Microseconds for one run through Dhrystone: ");
989 printf ("%7.1lf \n", Microseconds); 989 printf ("%7.1lf \n", Microseconds);
990 printf ("Dhrystones per Second: "); 990 printf ("Dhrystones per Second: ");
991 printf ("%10.1lf \n", Dhrystones_Per_Second); 991 printf ("%10.1lf \n", Dhrystones_Per_Second);
992 printf ("VAX MIPS rating = %10.3lf \n",Vax_Mips); 992 printf ("VAX MIPS rating = %10.3lf \n",Vax_Mips);
993 printf ("\n"); 993 printf ("\n");
994 994
995 return Dhrystones_Per_Second; 995 return Dhrystones_Per_Second;
996 996
997/* 997/*
998 998
999 fprintf(Ap,"\n"); 999 fprintf(Ap,"\n");
1000 fprintf(Ap,"Dhrystone Benchmark, Version 2.1 (Language: C)\n"); 1000 fprintf(Ap,"Dhrystone Benchmark, Version 2.1 (Language: C)\n");
1001 fprintf(Ap,"%s\n",Reg_Define); 1001 fprintf(Ap,"%s\n",Reg_Define);
1002 fprintf(Ap,"Microseconds for one loop: %7.1lf\n",Microseconds); 1002 fprintf(Ap,"Microseconds for one loop: %7.1lf\n",Microseconds);
1003 fprintf(Ap,"Dhrystones per second: %10.1lf\n",Dhrystones_Per_Second); 1003 fprintf(Ap,"Dhrystones per second: %10.1lf\n",Dhrystones_Per_Second);
1004 fprintf(Ap,"VAX MIPS rating: %10.3lf\n",Vax_Mips); 1004 fprintf(Ap,"VAX MIPS rating: %10.3lf\n",Vax_Mips);
1005 fclose(Ap); 1005 fclose(Ap);
1006*/ 1006*/
1007 1007
1008 } 1008 }
1009 1009
1010} 1010}