Source:NetHack 3.4.0/dlb.c

Below is the full text to dlb.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/dlb.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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