Wikia

Wikihack

Source:Dlb.c

2,032pages on
this wiki
Talk0

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.

Top of file Edit

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.   

readlibdir Edit

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.  

find_file Edit

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.  

open_library Edit

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.  

close_library Edit

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.  

lib_dlb_init Edit

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.  

lib_dlb_cleanup Edit

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.  

lib_dlb_fopen Edit

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.  

lib_dlb_fclose Edit

278.  static int
279.  lib_dlb_fclose(dp)
280.      dlb *dp;
281.  {
282.      /* nothing needs to be done */
283.      return 0;
284.  }
285.  

lib_dlb_fread Edit

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.  

lib_dlb_fseek Edit

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.  

lib_dlb_fgets Edit

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.  

lib_dlb_fgetc Edit

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.  

lib_dlb_ftell Edit

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.  

dlb_init Edit

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.  

dlb_cleanup Edit

444.  void
445.  dlb_cleanup()
446.  {
447.      if (dlb_initialized) {
448.  	do_dlb_cleanup();
449.  	dlb_initialized = FALSE;
450.      }
451.  }
452.  

dlb_fopen Edit

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.  

dlb_fclose Edit

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.  

dlb_fread Edit

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.  

dlb_fseek Edit

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.  

dlb_fgets Edit

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.  

dlb_fgetc Edit

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.  

dlb_ftell Edit

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*/

Around Wikia's network

Random Wiki