Source:Dlb.c
From Wikihack
Below is the full text to src/dlb.c from NetHack 3.4.3. To link to a particular line, write [[dlb.c#line123]], for example.
[edit] Top of file
1. /* SCCS Id: @(#)dlb.c 3.4 1997/07/29 */ 2. /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1993. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4.
| The NetHack General Public License applies to screenshots, source code and other content from NetHack. |
5. #include "config.h" 6. #include "dlb.h" 7. 8. #ifdef __DJGPP__ 9. #include <string.h> 10. #endif 11. 12. #define DATAPREFIX 4 13. 14. #ifdef DLB 15. /* 16. * Data librarian. Present a STDIO-like interface to NetHack while 17. * multiplexing on one or more "data libraries". If a file is not found 18. * in a given library, look for it outside the libraries. 19. */ 20. 21. typedef struct dlb_procs { 22. boolean NDECL((*dlb_init_proc)); 23. void NDECL((*dlb_cleanup_proc)); 24. boolean FDECL((*dlb_fopen_proc), (DLB_P,const char *,const char *)); 25. int FDECL((*dlb_fclose_proc), (DLB_P)); 26. int FDECL((*dlb_fread_proc), (char *,int,int,DLB_P)); 27. int FDECL((*dlb_fseek_proc), (DLB_P,long,int)); 28. char *FDECL((*dlb_fgets_proc), (char *,int,DLB_P)); 29. int FDECL((*dlb_fgetc_proc), (DLB_P)); 30. long FDECL((*dlb_ftell_proc), (DLB_P)); 31. } dlb_procs_t; 32. 33. /* without extern.h via hack.h, these haven't been declared for us */ 34. extern FILE *FDECL(fopen_datafile, (const char *,const char *,int)); 35. 36. #ifdef DLBLIB 37. /* 38. * Library Implementation: 39. * 40. * When initialized, we open all library files and read in their tables 41. * of contents. The library files stay open all the time. When 42. * a open is requested, the libraries' directories are searched. If 43. * successful, we return a descriptor that contains the library, file 44. * size, and current file mark. This descriptor is used for all 45. * successive calls. 46. * 47. * The ability to open more than one library is supported but used 48. * only in the Amiga port (the second library holds the sound files). 49. * For Unix, the idea would be to split the NetHack library 50. * into text and binary parts, where the text version could be shared. 51. */ 52. 53. #define MAX_LIBS 4 54. static library dlb_libs[MAX_LIBS]; 55. 56. static boolean FDECL(readlibdir,(library *lp)); 57. static boolean FDECL(find_file,(const char *name, library **lib, long *startp, 58. long *sizep)); 59. static boolean NDECL(lib_dlb_init); 60. static void NDECL(lib_dlb_cleanup); 61. static boolean FDECL(lib_dlb_fopen,(dlb *, const char *, const char *)); 62. static int FDECL(lib_dlb_fclose,(dlb *)); 63. static int FDECL(lib_dlb_fread,(char *, int, int, dlb *)); 64. static int FDECL(lib_dlb_fseek,(dlb *, long, int)); 65. static char *FDECL(lib_dlb_fgets,(char *, int, dlb *)); 66. static int FDECL(lib_dlb_fgetc,(dlb *)); 67. static long FDECL(lib_dlb_ftell,(dlb *)); 68. 69. /* not static because shared with dlb_main.c */ 70. boolean FDECL(open_library,(const char *lib_name, library *lp)); 71. void FDECL(close_library,(library *lp)); 72. 73. /* without extern.h via hack.h, these haven't been declared for us */ 74. extern char *FDECL(eos, (char *)); 75. 76. 77.
[edit] readlibdir
78. /* 79. * Read the directory out of the library. Return 1 if successful, 80. * 0 if it failed. 81. * 82. * NOTE: An improvement of the file structure should be the file 83. * size as part of the directory entry or perhaps in place of the 84. * offset -- the offset can be calculated by a running tally of 85. * the sizes. 86. * 87. * Library file structure: 88. * 89. * HEADER: 90. * %3ld library FORMAT revision (currently rev 1) 91. * %1c space 92. * %8ld # of files in archive (includes 1 for directory) 93. * %1c space 94. * %8ld size of allocation for string space for directory names 95. * %1c space 96. * %8ld library offset - sanity check - lseek target for start of first file 97. * %1c space 98. * %8ld size - sanity check - byte size of complete archive file 99. * 100. * followed by one DIRECTORY entry for each file in the archive, including 101. * the directory itself: 102. * %1c handling information (compression, etc.) Always ' ' in rev 1. 103. * %s file name 104. * %1c space 105. * %8ld offset in archive file of start of this file 106. * %c newline 107. * 108. * followed by the contents of the files 109. */ 110. #define DLB_MIN_VERS 1 /* min library version readable by this code */ 111. #define DLB_MAX_VERS 1 /* max library version readable by this code */ 112. 113. /* 114. * Read the directory from the library file. This will allocate and 115. * fill in our globals. The file pointer is reset back to position 116. * zero. If any part fails, leave nothing that needs to be deallocated. 117. * 118. * Return TRUE on success, FALSE on failure. 119. */ 120. static boolean 121. readlibdir(lp) 122. library *lp; /* library pointer to fill in */ 123. { 124. int i; 125. char *sp; 126. long liboffset, totalsize; 127. 128. if (fscanf(lp->fdata, "%ld %ld %ld %ld %ld\n", 129. &lp->rev,&lp->nentries,&lp->strsize,&liboffset,&totalsize) != 5) 130. return FALSE; 131. if (lp->rev > DLB_MAX_VERS || lp->rev < DLB_MIN_VERS) return FALSE; 132. 133. lp->dir = (libdir *) alloc(lp->nentries * sizeof(libdir)); 134. lp->sspace = (char *) alloc(lp->strsize); 135. 136. /* read in each directory entry */ 137. for (i = 0, sp = lp->sspace; i < lp->nentries; i++) { 138. lp->dir[i].fname = sp; 139. if (fscanf(lp->fdata, "%c%s %ld\n", 140. &lp->dir[i].handling, sp, &lp->dir[i].foffset) != 3) { 141. free((genericptr_t) lp->dir); 142. free((genericptr_t) lp->sspace); 143. lp->dir = (libdir *) 0; 144. lp->sspace = (char *) 0; 145. return FALSE; 146. } 147. sp = eos(sp) + 1; 148. } 149. 150. /* calculate file sizes using offset information */ 151. for (i = 0; i < lp->nentries; i++) { 152. if (i == lp->nentries - 1) 153. lp->dir[i].fsize = totalsize - lp->dir[i].foffset; 154. else 155. lp->dir[i].fsize = lp->dir[i+1].foffset - lp->dir[i].foffset; 156. } 157. 158. (void) fseek(lp->fdata, 0L, SEEK_SET); /* reset back to zero */ 159. lp->fmark = 0; 160. 161. return TRUE; 162. } 163.
[edit] find_file
164. /* 165. * Look for the file in our directory structure. Return 1 if successful, 166. * 0 if not found. Fill in the size and starting position. 167. */ 168. static boolean 169. find_file(name, lib, startp, sizep) 170. const char *name; 171. library **lib; 172. long *startp, *sizep; 173. { 174. int i, j; 175. library *lp; 176. 177. for (i = 0; i < MAX_LIBS && dlb_libs[i].fdata; i++) { 178. lp = &dlb_libs[i]; 179. for (j = 0; j < lp->nentries; j++) { 180. if (FILENAME_CMP(name, lp->dir[j].fname) == 0) { 181. *lib = lp; 182. *startp = lp->dir[j].foffset; 183. *sizep = lp->dir[j].fsize; 184. return TRUE; 185. } 186. } 187. } 188. *lib = (library *) 0; 189. *startp = *sizep = 0; 190. return FALSE; 191. } 192.
[edit] open_library
193. /* 194. * Open the library of the given name and fill in the given library 195. * structure. Return TRUE if successful, FALSE otherwise. 196. */ 197. boolean 198. open_library(lib_name, lp) 199. const char *lib_name; 200. library *lp; 201. { 202. boolean status = FALSE; 203. 204. lp->fdata = fopen_datafile(lib_name, RDBMODE, DATAPREFIX); 205. if (lp->fdata) { 206. if (readlibdir(lp)) { 207. status = TRUE; 208. } else { 209. (void) fclose(lp->fdata); 210. lp->fdata = (FILE *) 0; 211. } 212. } 213. return status; 214. } 215.
[edit] close_library
216. void 217. close_library(lp) 218. library *lp; 219. { 220. (void) fclose(lp->fdata); 221. free((genericptr_t) lp->dir); 222. free((genericptr_t) lp->sspace); 223. 224. (void) memset((char *)lp, 0, sizeof(library)); 225. } 226.
[edit] lib_dlb_init
227. /* 228. * Open the library file once using stdio. Keep it open, but 229. * keep track of the file position. 230. */ 231. static boolean 232. lib_dlb_init() 233. { 234. /* zero out array */ 235. (void) memset((char *)&dlb_libs[0], 0, sizeof(dlb_libs)); 236. 237. /* To open more than one library, add open library calls here. */ 238. if (!open_library(DLBFILE, &dlb_libs[0])) return FALSE; 239. #ifdef DLBFILE2 240. if (!open_library(DLBFILE2, &dlb_libs[1])) { 241. close_library(&dlb_libs[0]); 242. return FALSE; 243. } 244. #endif 245. return TRUE; 246. } 247.
[edit] lib_dlb_cleanup
248. static void 249. lib_dlb_cleanup() 250. { 251. int i; 252. 253. /* close the data file(s) */ 254. for (i = 0; i < MAX_LIBS && dlb_libs[i].fdata; i++) 255. close_library(&dlb_libs[i]); 256. } 257.
[edit] lib_dlb_fopen
258. static boolean 259. lib_dlb_fopen(dp, name, mode) 260. dlb *dp; 261. const char *name, *mode; 262. { 263. long start, size; 264. library *lp; 265. 266. /* look up file in directory */ 267. if (find_file(name, &lp, &start, &size)) { 268. dp->lib = lp; 269. dp->start = start; 270. dp->size = size; 271. dp->mark = 0; 272. return TRUE; 273. } 274. 275. return FALSE; /* failed */ 276. } 277.
[edit] lib_dlb_fclose
278. static int 279. lib_dlb_fclose(dp) 280. dlb *dp; 281. { 282. /* nothing needs to be done */ 283. return 0; 284. } 285.
[edit] lib_dlb_fread
286. static int 287. lib_dlb_fread(buf, size, quan, dp) 288. char *buf; 289. int size, quan; 290. dlb *dp; 291. { 292. long pos, nread, nbytes; 293. 294. /* make sure we don't read into the next file */ 295. if ((dp->size - dp->mark) < (size * quan)) 296. quan = (dp->size - dp->mark) / size; 297. if (quan == 0) return 0; 298. 299. pos = dp->start + dp->mark; 300. if (dp->lib->fmark != pos) { 301. fseek(dp->lib->fdata, pos, SEEK_SET); /* check for error??? */ 302. dp->lib->fmark = pos; 303. } 304. 305. nread = fread(buf, size, quan, dp->lib->fdata); 306. nbytes = nread * size; 307. dp->mark += nbytes; 308. dp->lib->fmark += nbytes; 309. 310. return nread; 311. } 312.
[edit] lib_dlb_fseek
313. static int 314. lib_dlb_fseek(dp, pos, whence) 315. dlb *dp; 316. long pos; 317. int whence; 318. { 319. long curpos; 320. 321. switch (whence) { 322. case SEEK_CUR: curpos = dp->mark + pos; break; 323. case SEEK_END: curpos = dp->size - pos; break; 324. default: /* set */ curpos = pos; break; 325. } 326. if (curpos < 0) curpos = 0; 327. if (curpos > dp->size) curpos = dp->size; 328. 329. dp->mark = curpos; 330. return 0; 331. } 332.
[edit] lib_dlb_fgets
333. static char * 334. lib_dlb_fgets(buf, len, dp) 335. char *buf; 336. int len; 337. dlb *dp; 338. { 339. int i; 340. char *bp, c = 0; 341. 342. if (len <= 0) return buf; /* sanity check */ 343. 344. /* return NULL on EOF */ 345. if (dp->mark >= dp->size) return (char *) 0; 346. 347. len--; /* save room for null */ 348. for (i = 0, bp = buf; 349. i < len && dp->mark < dp->size && c != '\n'; i++, bp++) { 350. if (dlb_fread(bp, 1, 1, dp) <= 0) break; /* EOF or error */ 351. c = *bp; 352. } 353. *bp = '\0'; 354. 355. #if defined(MSDOS) || defined(WIN32) 356. if ((bp = index(buf, '\r')) != 0) { 357. *bp++ = '\n'; 358. *bp = '\0'; 359. } 360. #endif 361. 362. return buf; 363. } 364.
[edit] lib_dlb_fgetc
365. static int 366. lib_dlb_fgetc(dp) 367. dlb *dp; 368. { 369. char c; 370. 371. if (lib_dlb_fread(&c, 1, 1, dp) != 1) return EOF; 372. return (int) c; 373. } 374. 375.
[edit] lib_dlb_ftell
376. static long 377. lib_dlb_ftell(dp) 378. dlb *dp; 379. { 380. return dp->mark; 381. } 382.
383. const dlb_procs_t lib_dlb_procs = { 384. lib_dlb_init, 385. lib_dlb_cleanup, 386. lib_dlb_fopen, 387. lib_dlb_fclose, 388. lib_dlb_fread, 389. lib_dlb_fseek, 390. lib_dlb_fgets, 391. lib_dlb_fgetc, 392. lib_dlb_ftell 393. }; 394. 395. #endif /* DLBLIB */ 396. 397. #ifdef DLBRSRC 398. const dlb_procs_t rsrc_dlb_procs = { 399. rsrc_dlb_init, 400. rsrc_dlb_cleanup, 401. rsrc_dlb_fopen, 402. rsrc_dlb_fclose, 403. rsrc_dlb_fread, 404. rsrc_dlb_fseek, 405. rsrc_dlb_fgets, 406. rsrc_dlb_fgetc, 407. rsrc_dlb_ftell 408. }; 409. #endif 410. 411. /* Global wrapper functions ------------------------------------------------ */ 412. 413. #define do_dlb_init (*dlb_procs->dlb_init_proc) 414. #define do_dlb_cleanup (*dlb_procs->dlb_cleanup_proc) 415. #define do_dlb_fopen (*dlb_procs->dlb_fopen_proc) 416. #define do_dlb_fclose (*dlb_procs->dlb_fclose_proc) 417. #define do_dlb_fread (*dlb_procs->dlb_fread_proc) 418. #define do_dlb_fseek (*dlb_procs->dlb_fseek_proc) 419. #define do_dlb_fgets (*dlb_procs->dlb_fgets_proc) 420. #define do_dlb_fgetc (*dlb_procs->dlb_fgetc_proc) 421. #define do_dlb_ftell (*dlb_procs->dlb_ftell_proc) 422. 423. static const dlb_procs_t *dlb_procs; 424. static boolean dlb_initialized = FALSE; 425.
[edit] dlb_init
426. boolean 427. dlb_init() 428. { 429. if (!dlb_initialized) { 430. #ifdef DLBLIB 431. dlb_procs = &lib_dlb_procs; 432. #endif 433. #ifdef DLBRSRC 434. dlb_procs = &rsrc_dlb_procs; 435. #endif 436. 437. if (dlb_procs) 438. dlb_initialized = do_dlb_init(); 439. } 440. 441. return dlb_initialized; 442. } 443.
[edit] dlb_cleanup
444. void 445. dlb_cleanup() 446. { 447. if (dlb_initialized) { 448. do_dlb_cleanup(); 449. dlb_initialized = FALSE; 450. } 451. } 452.
[edit] dlb_fopen
453. dlb * 454. dlb_fopen(name, mode) 455. const char *name, *mode; 456. { 457. FILE *fp; 458. dlb *dp; 459. 460. if (!dlb_initialized) return (dlb *) 0; 461. 462. dp = (dlb *) alloc(sizeof(dlb)); 463. if (do_dlb_fopen(dp, name, mode)) 464. dp->fp = (FILE *) 0; 465. else if ((fp = fopen_datafile(name, mode, DATAPREFIX)) != 0) 466. dp->fp = fp; 467. else { 468. /* can't find anything */ 469. free((genericptr_t) dp); 470. dp = (dlb *) 0; 471. } 472. 473. return dp; 474. } 475.
[edit] dlb_fclose
476. int 477. dlb_fclose(dp) 478. dlb *dp; 479. { 480. int ret = 0; 481. 482. if (dlb_initialized) { 483. if (dp->fp) ret = fclose(dp->fp); 484. else ret = do_dlb_fclose(dp); 485. 486. free((genericptr_t) dp); 487. } 488. return ret; 489. } 490.
[edit] dlb_fread
491. int 492. dlb_fread(buf, size, quan, dp) 493. char *buf; 494. int size, quan; 495. dlb *dp; 496. { 497. if (!dlb_initialized || size <= 0 || quan <= 0) return 0; 498. if (dp->fp) return (int) fread(buf, size, quan, dp->fp); 499. return do_dlb_fread(buf, size, quan, dp); 500. } 501.
[edit] dlb_fseek
502. int 503. dlb_fseek(dp, pos, whence) 504. dlb *dp; 505. long pos; 506. int whence; 507. { 508. if (!dlb_initialized) return EOF; 509. if (dp->fp) return fseek(dp->fp, pos, whence); 510. return do_dlb_fseek(dp, pos, whence); 511. } 512.
[edit] dlb_fgets
513. char * 514. dlb_fgets(buf, len, dp) 515. char *buf; 516. int len; 517. dlb *dp; 518. { 519. if (!dlb_initialized) return (char *) 0; 520. if (dp->fp) return fgets(buf, len, dp->fp); 521. return do_dlb_fgets(buf, len, dp); 522. } 523.
[edit] dlb_fgetc
524. int 525. dlb_fgetc(dp) 526. dlb *dp; 527. { 528. if (!dlb_initialized) return EOF; 529. if (dp->fp) return fgetc(dp->fp); 530. return do_dlb_fgetc(dp); 531. } 532.
[edit] dlb_ftell
533. long 534. dlb_ftell(dp) 535. dlb *dp; 536. { 537. if (!dlb_initialized) return 0; 538. if (dp->fp) return ftell(dp->fp); 539. return do_dlb_ftell(dp); 540. } 541. 542. #endif /* DLB */ 543. 544. /*dlb.c*/
