Source:NetHack 3.2.0/dlb.c

Below is the full text to dlb.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.2	96/02/14	*/ 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 DLB 9.   /*  10.    * Data librarian. Present a STDIO-like interface to NetHack while 11.   * multiplexing on one or more "data" libraries. If a file is not found 12.   * in a given library, look for it outside the libraries. 13.   *  14.    * When initialized, we open all library files and read in their tables 15.   * of contents. The library files stay open all the time. When 16.   * a open is requested, the libraries' directories are searched. If 17. * successful, we return a descriptor that contains the library, file 18.   * size, and current file mark. This descriptor is used for all 19.   * successive calls. 20.   *  21.    * The ability to open more than one library is supported but used 22.   * only in the Amiga port (the second library holds the sound files). 23.   * For Unix, the idea would be to split the NetHack library 24.   * into text and binary parts, where the text version could be shared. 25.   */  26.    27.    28.   #define MAX_LIBS 4 29.  static library dlb_libs[MAX_LIBS]; 30.  static boolean dlb_initialized = FALSE; 31.   32.   static boolean FDECL(readlibdir,(library *lp)); 33.  static boolean FDECL(find_file,(const char *name, library **lib, long *startp, 34.  								long *sizep)); 35.   36.   /* not static because shared with dlb_main.c */ 37.  boolean FDECL(open_library,(const char *lib_name, library *lp)); 38.  void FDECL(close_library,(library *lp)); 39.   40.   /* without extern.h via hack.h, these haven't been declared for us */ 41.  extern char *FDECL(eos, (char *)); 42.  extern FILE *FDECL(fopen_datafile, (const char *,const char *)); 43.   44.   /*  45.    * Read the directory out of the library. Return 1 if successful, 46.   * 0 if it failed. 47.   *  48.    * NOTE: An improvement of the file structure should be the file 49.   * size as part of the directory entry or perhaps in place of the 50.   * offset -- the offset can be calculated by a running tally of  51. * the sizes. 52.   *  53.    * Library file structure: 54.   *  55.    * HEADER: 56.   * %3ld	library FORMAT revision (currently rev 1) 57.   * %1c	space 58.   * %8ld	# of files in archive (includes 1 for directory) 59.   * %1c	space 60.   * %8ld	size of allocation for string space for directory names 61.   * %1c	space 62.   * %8ld	library offset - sanity check - lseek target for start of first file 63.   * %1c	space 64.   * %8ld	size - sanity check - byte size of complete archive file 65.   *  66.    * followed by one DIRECTORY entry for each file in the archive, including 67.   *  the directory itself: 68.   * %1c	handling information (compression, etc.)  Always ' ' in rev 1. 69.   * %s	file name 70.   * %1c	space 71.   * %8ld	offset in archive file of start of this file 72.   * %c	newline 73.   *  74.    * followed by the contents of the files 75.   */  76.   #define DLB_MIN_VERS  1	/* min library version readable by this code */ 77.  #define DLB_MAX_VERS  1	/* max library version readable by this code */ 78.   79.   /*  80.    * Read the directory from the library file. This will allocate and 81.   * fill in our globals. The file pointer is reset back to position 82.   * zero. If any part fails, leave nothing that needs to be deallocated. 83.   *  84.    * Return TRUE on success, FALSE on failure. 85.   */  86.   static boolean 87.  readlibdir(lp) 88.      library *lp;	/* library pointer to fill in */ 89.  {  90.       int i;  91. char *sp; 92.      long liboffset, totalsize; 93.   94.       if (fscanf(lp->fdata, "%ld %ld %ld %ld %ld\n", 95.  	    &lp->rev,&lp->nentries,&lp->strsize,&liboffset,&totalsize) != 5) 96.  	return FALSE; 97.      if (lp->rev > DLB_MAX_VERS || lp->rev < DLB_MIN_VERS) return FALSE; 98.   99.       lp->dir = (libdir *) alloc(lp->nentries * sizeof(libdir)); 100.     lp->sspace = (char *) alloc(lp->strsize); 101.  102.      /* read in each directory entry */ 103.     for (i = 0, sp = lp->sspace; i < lp->nentries; i++) { 104. 	lp->dir[i].fname = sp; 105. 	if (fscanf(lp->fdata, "%c%s %ld\n", 106. 			&lp->dir[i].handling, sp, &lp->dir[i].foffset) != 3) { 107. 	    free((genericptr_t) lp->dir); 108. 	    free((genericptr_t) lp->sspace); 109. 	    lp->dir = (libdir *) 0; 110. 	    lp->sspace = (char *) 0; 111. 	    return FALSE; 112. 	}  113.  	sp = eos(sp) + 1; 114.     }  115.   116.      /* calculate file sizes using offset information */ 117.     for (i = 0; i < lp->nentries; i++) { 118. 	if (i == lp->nentries - 1) 119. 	    lp->dir[i].fsize = totalsize - lp->dir[i].foffset; 120. 	else 121. 	    lp->dir[i].fsize = lp->dir[i+1].foffset - lp->dir[i].foffset; 122.     }  123.   124.      (void) fseek(lp->fdata, 0L, SEEK_SET);	/* reset back to zero */ 125.     lp->fmark = 0; 126.  127.      return TRUE; 128. }  129.   130.  /*  131.   * Look for the file in our directory structure. Return 1 if successful, 132.  * 0 if not found. Fill in the size and starting position. 133.  */  134.  static boolean 135. find_file(name, lib, startp, sizep) 136.     const char *name; 137.     library **lib; 138.     long *startp, *sizep; 139. {  140.      int i, j;  141. library *lp; 142.  143.      for (i = 0; i < MAX_LIBS && dlb_libs[i].fdata; i++) { 144. 	lp = &dlb_libs[i]; 145. 	for (j = 0; j < lp->nentries; j++) { 146. 	    if (FILENAME_CMP(name, lp->dir[j].fname) == 0) { 147. 		*lib = lp; 148. 		*startp = lp->dir[j].foffset; 149. 		*sizep = lp->dir[j].fsize; 150. 		return TRUE; 151. 	    }  152.  	}  153.      }  154.      *lib = (library *) 0; 155.     *startp = *sizep = 0; 156.     return FALSE; 157. }  158.   159.  /*  160.   * Open the library of the given name and fill in the given library 161.  * structure. Return TRUE if successful, FALSE otherwise. 162.  */  163.  boolean 164. open_library(lib_name, lp) 165.     const char *lib_name; 166.     library *lp; 167. {  168.      boolean status = FALSE; 169.  170.      lp->fdata = fopen_datafile(lib_name, RDBMODE); 171.     if (lp->fdata) { 172. 	if (readlibdir(lp)) { 173. 	    status = TRUE; 174. 	} else { 175. 	    (void) fclose(lp->fdata); 176. 	    lp->fdata = (FILE *) 0; 177. 	}  178.      }  179.      return status; 180. }  181.   182.  void 183. close_library(lp) 184.     library *lp; 185. {  186.      (void) fclose(lp->fdata); 187.     free((genericptr_t) lp->dir); 188.     free((genericptr_t) lp->sspace); 189.  190.      (void) memset((char *)lp, 0, sizeof(library)); 191. }  192.   193.  /*  194.   * Open the library file once using stdio. Keep it open, but 195.  * keep track of the file position. 196.  */  197.  boolean 198. dlb_init 199. {  200.      if (dlb_initialized) return TRUE; 201.  202.      /* zero out array */ 203.     (void) memset((char *)&dlb_libs[0], 0, sizeof(dlb_libs)); 204.  205.      /* To open more than one library, add open library calls here. */ 206.      if (!open_library(DLBFILE, &dlb_libs[0])) return dlb_initialized; 207. #ifdef DLBFILE2 208.     if (!open_library(DLBFILE2, &dlb_libs[1])) return dlb_initialized; 209. #endif 210.  211.      dlb_initialized = TRUE; 212.  213.      return dlb_initialized; 214. }  215.   216.  void 217. dlb_cleanup 218. {  219.      int i;  220. 221.     if (dlb_initialized) { 222. 	/* close the data file(s) */ 223. 	for (i = 0; i < MAX_LIBS && dlb_libs[i].fdata; i++) 224. 	    close_library(&dlb_libs[i]); 225.  226.  	dlb_initialized = FALSE; 227.     }  228.  }  229.   230.  dlb * 231. dlb_fopen(name, mode) 232.     const char *name, *mode; 233. {  234.      long start, size; 235.     library *lp; 236.     FILE *fp; 237.     dlb *dp = (dlb *) 0; 238.  239.      if (!dlb_initialized) return (dlb *) 0; 240.  241.      /* look up file in directory */ 242.     if (find_file(name, &lp, &start, &size)) { 243. 	dp = (dlb *) alloc(sizeof(dlb)); 244. 	dp->fp = (FILE *) 0; 245. 	dp->lib = lp; 246. 	dp->start = start; 247. 	dp->size = size; 248. 	dp->mark = 0; 249.     } else if ((fp = fopen_datafile(name, mode)) != 0) { 250. 	/* use an external file */ 251. 	dp = (dlb *) alloc(sizeof(dlb)); 252. 	dp->fp = fp; 253. 	dp->lib = (library *) 0; 254. 	dp->start = 0; 255. 	dp->size = 0; 256. 	dp->mark = 0; 257.     }  258.      return dp; 259. }  260.   261.  int 262. dlb_fclose(dp) 263.     dlb *dp; 264. {  265.      if (dlb_initialized) { 266. 	if (dp->fp) (void) fclose(dp->fp); 267. 	free((genericptr_t) dp); 268. 	}  269.      return 0; 270. }  271.   272.  int 273. dlb_fread(buf, size, quan, dp) 274.     char *buf; 275.     int size, quan; 276.     dlb *dp; 277. {  278.      long pos, nread, nbytes; 279.  280.      if (!dlb_initialized || size <= 0 || quan <= 0) return 0; 281.     if (dp->fp) return 282. #ifdef __SASC_60 283. 	 (int) 284. #endif 285. 	 fread(buf, size, quan, dp->fp); 286.  287.      /* make sure we don't read into the next file */ 288.     if ((dp->size - dp->mark) < (size * quan)) 289. 	quan = (dp->size - dp->mark) / size; 290.     if (quan == 0) return 0; 291.  292.      pos = dp->start + dp->mark; 293.     if (dp->lib->fmark != pos) 294. 	fseek(dp->lib->fdata, pos, SEEK_SET);	/* check for error??? */ 295.   296.      nread = fread(buf, size, quan, dp->lib->fdata); 297.     nbytes = nread * size; 298.     dp->mark += nbytes; 299.     dp->lib->fmark += nbytes; 300.  301.      return nread; 302. }  303.   304.  int 305. dlb_fseek(dp, pos, whence) 306.     dlb *dp; 307.     long pos; 308.     int whence; 309. {  310.      long curpos; 311.  312.      if (!dlb_initialized) return EOF; 313.     if (dp->fp) return fseek(dp->fp, pos, whence); 314.  315.      switch (whence) { 316. 	case SEEK_CUR:	   curpos = dp->mark + pos;	break; 317. 	case SEEK_END:	   curpos = dp->size - pos;	break; 318. 	default: /* set */ curpos = pos;		break; 319.     }  320.      if (curpos < 0) curpos = 0; 321.     if (curpos > dp->size) curpos = dp->size; 322.  323.      dp->mark = curpos; 324.     return 0; 325. }  326.   327.  char * 328. dlb_fgets(buf, len, dp) 329.     char *buf; 330.     int len; 331.     dlb *dp; 332. {  333.      int i;  334. char *bp, c = 0; 335.  336.      if (!dlb_initialized) return (char *) 0; 337.     if (dp->fp) return fgets(buf, len, dp->fp); 338.  339.      if (len <= 0) return buf;	/* sanity check */ 340.  341.      /* return NULL on EOF */ 342.     if (dp->mark >= dp->size) return (char *) 0; 343.  344.      len--;	/* save room for null */ 345.     for (i = 0, bp = buf;  346.  		i < len && dp->mark < dp->size && c != '\n'; i++, bp++) { 347. 	if (dlb_fread(bp, 1, 1, dp) <= 0) break;	/* EOF or error */ 348. 	c = *bp; 349.     }  350.      *bp = '\0'; 351.  352.      return buf; 353. }  354.   355.  int 356. dlb_fgetc(dp) 357.     dlb *dp; 358. {  359.      char c;  360. 361.     if (!dlb_initialized) return EOF; 362.     if (dp->fp) return fgetc(dp->fp); 363.  364.      if (dlb_fread(&c, 1, 1, dp) != 1) return EOF; 365.     return (int) c;  366. } 367.   368.  long 369. dlb_ftell(dp) 370.     dlb *dp; 371. {  372.      if (!dlb_initialized) return 0; 373.     if (dp->fp) return ftell(dp->fp); 374.     return dp->mark; 375. }  376.   377.  #endif /* DLB */ 378.  379.  /*dlb.c*/