summaryrefslogtreecommitdiff
path: root/systems/knuth/local/mfware-sparc/mft_ext.c
blob: b8fe8d31e6bd011c72f7bc37e9cb83ad259617ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/* External procedures for MFT*/
/* (culled from weavext.c and ext.c for WEAVE and TeX) */
/*   Written by: H. Trickey, 11/17/83   */
/* (modified for 8-bit input by don on 10/16/89) */

/* Note: these procedures aren't necessary; the default input_ln and
 * flush_buffer routines in tangle/weave work fine on UNIX.
 * However a very big time improvement is achieved by using these.
 *
 * These procedures are the same as for tangle, except for a slight offset
 * in which characters are output from outbuf in linewrite.
 */

#define BUF_SIZE 100		/* should agree with mft.web */

#include "mfpaths.h"		/* defines default MFINPUTS path */
#include "h00vars.h"		/* defines Pascal I/O structure */

extern short buffer[];		/* 0..BUF_SIZE.  Input goes here */
extern short outbuf[];		/* 0..OUT_BUF_SIZE. Output from here */
extern short xord[];
extern char xchr[];	/* character translation arrays */
extern char limit;		/* index into buffer.  Note that limit
				   is 0..buf_size (= 0..100) in mft.web; this
				   differs from the definition in weave.web */

/*
 * lineread reads from the Pascal text file with iorec pointer filep
 * into buffer[0], buffer[1],..., buffer[limit-1] (and
 * setting "limit").
 * Characters are read until a newline is found (which isn't put in the
 * buffer) or until the next character would go into buffer[BUF_SIZE].
 * And trailing blanks are to be ignored, so limit is really set to
 * one past the last non-blank.
 * The characters need to be translated, so really xord[c] is put into
 * the buffer when c is read.
 * If end-of-file is encountered, the funit field of *filep is set
 * appropriately.
 */
lineread(filep)
struct iorec *filep;
{
	register c;
	register short *cs; /* pointer into buffer where next char goes */
	register short *cnb; /* last non-blank character input */
	register FILE *iop; /* stdio-style FILE pointer */
	register int l; /* how many chars allowed before buffer overflow */
	
	iop = filep->fbuf;
	cnb = cs = &(buffer[0]);
	l = BUF_SIZE;
	  /* overflow when next char would go into buffer[BUF_SIZE] */
	while (--l>=0 && (c = getc(iop)) != EOF && c!='\n')
	    if((*cs++ = xord[c])!=' ') cnb = cs;
	if (c == EOF)
	    filep->funit |= EOFF; /* we hit end-of-file */
	limit = cnb-&(buffer[0]);
}

/*
 * linewrite writes to the Pascal text file with iorec pointer filep
 * from outbuf[1], outbuf[1],..., outbuf[cnt].
 * (Note the offset of indices vis a vis the tangext version of this.)
 * Translation is done, so that xchr[c] is output instead of c.
 */
 linewrite(filep,cnt)
 struct iorec *filep;
 int cnt;
 {
 	register FILE *iop; /* stdio-style FILE pointer */
	register short *cs; /* pointer to next character to output */
	register int l; /* how many characters left to output */
	
	iop = filep->fbuf;
	cs = &(outbuf[1]);
	l = cnt;
	while (--l>=0) putc(xchr[*cs++],iop);
}
	
/*
**	testeof(filep)
**
**  Test whether or not the Pascal text file with iorec pointer filep
**  has reached end-of-file (when the only I/O on it is done with
**  lineread, above).
**  We may have to read the next character and unget it to see if perhaps
**  the end-of-file is next.
*/

bool
testeof(filep)
register struct iorec *filep;
{
	register char c;
	register FILE *iop; /* stdio-style FILE pointer */
	if (filep->funit & EOFF)
		return(TRUE);
	else { /* check to see if next is EOF */
		iop = filep->fbuf;
		c = getc(iop);
		if (c == EOF)
			return(TRUE);
		else {
			ungetc(c,iop);
			return(FALSE);
			}
	}
}
/* and now, some routines to implement paths for file names.  These routines
   are taken from Howard Trickey's port of dvitype (2/19/84).  Howard
   adapted them from his port of TeX, ext.c */

char *inputpath;

char *getenv();

/*
 * setpaths is called to set up the pointer inputpath
 * as follows:  if the user's environment has a value for TEXINPUTS
 * then use it;  otherwise, use defaultinputpath.
 */
setpaths()
{
	register char *envpath;
	
	if ((envpath = getenv("TEXINPUTS")) != NULL)
	    inputpath = envpath;
	else
	    inputpath = defaultinputpath;
}

#define maxfilenamelength 100   /* should agree with mft.ch */
extern char stylename[],realnameoffile[]; /* these have size namelength */

/*
 *	testaccess(amode,filepath)
 *
 *  Test whether or not the file whose name is in the global curname
 *  can be opened for reading (if mode=READACCESS)
 *  or writing (if mode=WRITEACCESS).
* [the code here isn't as general as it should be ... it assumes that stylefile
*  is the only file name of interest! Maybe I'll fix this some day -- don]
 *
 *  The filepath argument is one of the ...FILEPATH constants defined below.
 *  If the filename given in curname does not begin with '/', we try 
 *  prepending all the ':'-separated areanames in the appropriate path to the
 *  filename until access can be made, if it ever can.
 *
 *  The realnameoffile global array will contain the name that yielded an
 *  access success.
 */

/* note that corresponding constants are defined in mft.ch */

#define READACCESS 4
#define WRITEACCESS 2

#define NOFILEPATH 0
#define GOODFILEPATH 3

bool
testaccess(amode,filepath)
    int amode,filepath;
{
    register bool ok;
    register char *p;
    char *curpathplace;
    int f;
    
    switch(filepath) {
	case NOFILEPATH: curpathplace = NULL; break;
	case GOODFILEPATH: curpathplace = inputpath; break;
	}
    if (stylename[0]=='/')	/* file name has absolute path */
	curpathplace = NULL;
    do {
	packrealnameoffile(&curpathplace);
	if (amode==READACCESS)
	    /* use system call "access" to see if we could read it */
	    if (access(realnameoffile,READACCESS)==0) ok = TRUE;
	    else ok = FALSE;
	else {
	    /* WRITEACCESS: use creat to see if we could create it, but close
	    the file again if we're OK, to let pc open it for real */
	    f = creat(realnameoffile,0666);
	    if (f>=0) ok = TRUE;
	    else ok = FALSE;
	    if (ok)
		close(f);
	    }
    } while (!ok && curpathplace != NULL);
    if (ok) {  /* pad realnameoffile with blanks, as Pascal wants */
	for (p = realnameoffile; *p != '\0'; p++)
	    /* nothing: find end of string */ ;
	while (p < &(realnameoffile[maxfilenamelength]))
	    *p++ = ' ';
	}
    return (ok);
}

/*
 * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp,
 * followed by '/', followed by the characters in stylename up until the
 * first blank there, and finally a '\0'.  The cpp pointer is left pointing
 * at the next directory in the path.
 * But: if *cpp == NULL, then we are supposed to use stylename as is.
 */
packrealnameoffile(cpp)
    char **cpp;
{
    register char *p,*realname;
    
    realname = realnameoffile;
    if ((p = *cpp)!=NULL) {
	while ((*p != ':') && (*p != '\0')) {
	    *realname++ = *p++;
	    if (realname == &(realnameoffile[maxfilenamelength-1]))
		break;
	    }
	if (*p == '\0') *cpp = NULL; /* at end of path now */
	else *cpp = p+1; /* else get past ':' */
	*realname++ = '/';  /* separate the area from the name to follow */
	}
    /* now append stylename to realname... */
    p = stylename;
    while (*p != ' ') {
	if (realname >= &(realnameoffile[maxfilenamelength-1])) {
	    fprintf(stderr,"! Full file name is too long\n");
	    break;
	    }
	*realname++ = *p++;
	}
    *realname = '\0';
}

bool testreadaccess(fn)
	char  *fn;
{
	register char *p;

	fn[maxfilenamelength-1] = ' ';
	p = fn;
	while (*p++ != ' ');
	p--;
	*p = '\0';
	if (access(fn,4)==0) {
	  *p = ' '; return(TRUE);}
	else {*p = ' '; return(FALSE);}
}