Source:SLASH'EM 0.0.7E7F2/dlb.c

Below is the full text to dlb.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/dlb.c#line123 ]], for example.

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