Wikia

Wikihack

Source:SLASH'EM 0.0.7E7F2/dlb.c

2,032pages on
this wiki
Talk0

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.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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 <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.   #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*/

Around Wikia's network

Random Wiki