1 /* 	SCCS Id: @(#)multi.c 3.1	95/07/25
2 /*	Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1992, 1993, 1995  */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /*
6  * NB - internal structure under development.  End users should NOT
7  *      get too creative!
8  */
9 #include <exec/types.h>
10 #include <exec/memory.h>
11 #ifdef _DCC
12 # include <clib/dos_protos.h>
13 # include <clib/exec_protos.h>
14 #else
15 # include <proto/dos.h>
16 # include <proto/exec.h>
17 # include <dos.h>
18 #endif
19 #include <string.h>
20 #include <assert.h>
21 #include <ctype.h>
22 #include "multi.h"
23 
24 static int start_next_file(multifh *);	/* XXX should return enum */
25 BPTR
MultiOpen(char * dirfile,ULONG mode,union multiopts * mo)26 MultiOpen(char *dirfile, ULONG mode, union multiopts *mo){
27 	multifh *retval;
28 
29 	assert(mode==MODE_OLDFILE);	/* XXX no chioce this version */
30 	retval=(multifh *)AllocMem(sizeof(multifh),MEMF_CLEAR);
31 	if(retval){
32 		retval->mfh_dirfh=Open(dirfile,MODE_OLDFILE);
33 		if(retval->mfh_dirfh){
34 			retval->mfh_mo= *mo;
35 			if(start_next_file(retval)==1){
36 				return((BPTR)retval);		/* success */
37 			}
38 		}
39 	}
40 
41 	if(retval)FreeMem(retval,sizeof(multifh));
42 	return 0;
43 }
44 
45 ULONG
MultiRead(BPTR xmfp,void * where0,ULONG len)46 MultiRead(BPTR xmfp, void *where0, ULONG len){
47 	char *where = (char*)where0;
48 	multifh *mfp=(multifh *)xmfp;
49 	ULONG sofar=0;
50 	ULONG this;
51 
52 	if(len<=0)return len;
53 	if(mfp->mfh_fh==0)return 0;	/* pending EOF (possibly premature) */
54 
55 	while(sofar<len){
56 		this=Read(mfp->mfh_fh,where,len-sofar);
57 		if(this==-1) return -1;
58 		if(this==0){
59 			Close(mfp->mfh_fh);
60 			mfp->mfh_fh=0;
61 			if(start_next_file(mfp)<=0){
62 				return sofar;
63 			}
64 		}
65 		sofar += this; where += this;
66 	}
67 	return sofar;
68 }
69 
70 void
MultiClose(BPTR xmfp)71 MultiClose(BPTR xmfp){
72 	multifh *mfp=(multifh *)xmfp;
73 	if(mfp->mfh_dirfh)Close(mfp->mfh_dirfh);
74 	if(mfp->mfh_fh)Close(mfp->mfh_fh);
75 	FreeMem(mfp,sizeof(multifh));
76 }
77 
78 /* Return 0==no more data, -1 error.  Else more data available unless file
79  * is empty.
80  */
81 static
start_next_file(multifh * mfp)82 start_next_file(multifh *mfp){
83 	ULONG t;
84 	char line[100];		/* should be based on PATHLEN */
85 	char *eol;
86 
87 	while(1){
88 		t=Read(mfp->mfh_dirfh,line,99);
89 		if(t==0)return(0);
90 		if(t==-1)return(-1);
91 
92 		line[t]='\0';
93 		eol=strchr(line,'\n');
94 		if(eol){
95 			*eol='\0';
96 			Seek(mfp->mfh_dirfh,-(t-(eol-line))+1,OFFSET_CURRENT);
97 		}
98 		switch(line[0]){
99 		case '\0':
100 		case '#':
101 			break;			/* comment, blank lines */
102 		default:
103 			if(line[0]==mfp->mfh_mo.r.mor_tag){
104 						/* allow blanks after tag */
105 				char *file= &line[1];
106 				while(*file && isspace(*file))file++;
107 				mfp->mfh_fh=Open(file,MODE_OLDFILE);
108 				if(!mfp->mfh_fh){
109 					return -1;	/* error */
110 				}
111 				return 1;
112 			}
113 		}
114 	}
115 }
116