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