|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2:
3: /*
4: $Header: b3fil.c,v 1.4 85/08/27 10:56:00 timo Exp $
5: */
6:
7: /* Facilities supplied by the file system */
8:
9: #include "b.h"
10: #include "b0con.h"
11: #include "b0fea.h"
12: #include "b0fil.h"
13: #include "b1obj.h"
14: #include "b3scr.h"
15: #include "b3err.h"
16: #include "b3fil.h"
17:
18: #ifndef INTEGRATION
19:
20: /*This file defines the facilities needed for dealing with files,
21: apart from C's standard I/O facilities which are used throughout the system.
22:
23: Units are held on files in a 'workspace', which on Unix is modelled
24: using directories. The function 'f_uname' converts a unit name into a
25: unique filename. On Unix this is done by prepending a character to the unit
26: name to indicate the kind of unit (for how'to ', and for tests and yields
27: < for zeroadic, " for monadic and > for dyadic; these have been chosen as
28: characters that are not usually used in filenames), and truncating the
29: name if necessary. If the name does have to be truncated, then it is
30: hashed to produce a character that is appended to the filename, in an attempt
31: to produce a unique filename. Even so, it is still possible for different
32: unit names to produce the same filename, and in the unlikely event of this
33: happening you get an error message that the unit already exists when you
34: try to create the clashing unit name.
35:
36: Filenames are at most SAFEFNLEN characters long, which on standard Unix
37: systems gives you one spare character for making backups or whatever.
38:
39: It would be better if the B system effectively maintained its own directories
40: that mapped units onto files in the real file system, as is done for targets.
41: With operating systems with a more limited file system (eg even shorter
42: filenames) this is the only possibility.
43:
44: The B system can operate in two ways: with the interpreter in command,
45: and then the editor is called from the interpreter to edit units;
46: and with the editor in command, when the editor calls the interpreter to
47: execute commands. The variable 'filtered' is Yes when the editor is in
48: command, and No otherwise.
49: */
50:
51: #define COML 60
52: Hidden char com_line[COML];
53: #define At_eos(s) ((s)+= strlen(s))
54:
55: Visible Procedure f_edit(fname, errline) value fname; intlet errline; {
56: /*The default editor is called with a first parameter of the line number
57: and a second parameter of the file name*/
58: string cl= com_line; char c;
59: #ifdef unix
60: if (filtered) {
61: printf("\001: +%d %s\n", errline, strval(fname));
62: fflush(stdout);
63: do { c= fgetc(stdin); } while (c != '\n');
64: still_ok= Yes; /*ignore interrupts that occurred*/
65: } else {
66: strcpy(cl, editorfile);
67: if (*(cl+strlen(cl)-1) == '+') {
68: if (errline != 0) sprintf(At_eos(cl), "%d", errline);
69: else *(cl+strlen(cl)-1)= ' ';
70: }
71: app_fname(At_eos(cl), fname);
72: system(com_line);
73: }
74: #else !unix
75: fprintf(stderr, "*** Editing units not yet implemented\n");
76: #endif unix
77: }
78:
79: #else INTEGRATION
80:
81: Visible Procedure
82: f_edit(fname, errline, prompt)
83: value fname; intlet errline; literal prompt;
84: {
85: string filename= Str(fname);
86: btop(&filename, errline, prompt, 0);
87: still_ok= Yes;
88: }
89:
90: #endif
91:
92: Visible bool ws_writable() {
93: FILE *f= fopen(tempfile, "w");
94: if (f == NULL) return No;
95: fclose(f);
96: return Yes;
97: }
98:
99: Hidden bool f_copy(fname, sname) value fname, sname; {
100: string fn= strval(fname), sn;
101: FILE *fp= fopen(fn, "r"), *sp; int c; bool ok;
102: if (fp == NULL) return No;
103: sn= strval(sname);
104: sp= fopen(sn, "w");
105: if (sp == NULL) {
106: fclose(fp);
107: return No;
108: }
109: while ((c= getc(fp)) != EOF)
110: putc(c, sp);
111: fclose(fp);
112: ok= fflush(sp) != EOF;
113: if (fclose(sp) == EOF)
114: ok= No;
115: return ok;
116: }
117:
118: Visible value f_save(fname) value fname; {
119: /* saves the file in a temporary file, whose name is returned */
120: value sname= mk_text(tempfile);
121: VOID f_copy(fname, sname);
122: return sname;
123: }
124:
125: Visible Procedure f_rename(fname, nfname) value fname, nfname; {
126: char *f1, f2[100];
127: strcpy(f2, strval(nfname));
128: unlink(f2);
129: f1= strval(fname);
130: #ifndef RENAME
131: link(f1, f2);
132: unlink(f1);
133: #else
134: rename(f1, f2);
135: #endif
136: /* what if it fails??? */
137: }
138:
139: Visible Procedure f_delete(fname) value fname; {
140: unlink(strval(fname));
141: }
142:
143: Visible bool
144: f_exists(file)
145: string file;
146: {
147: FILE *f= fopen(file, "r");
148: if (f==NULL) return No;
149: fclose(f);
150: return Yes;
151: }
152:
153: #ifndef INTEGRATION
154:
155: Hidden Procedure app_fname(ceos, fname) string ceos; value fname; {
156: string fp= strval(fname); intlet k, len= strlen(fp);
157: *ceos++= ' ';
158: k_Over_len {
159: *ceos++= '\\';
160: *ceos++= *fp++; /*should really use charval(thof(...))*/
161: }
162: *ceos= '\0';
163: }
164:
165: #endif
166:
167: Visible unsigned f_size(ifile) FILE *ifile; {
168: long size, ftell();
169: fseek(ifile, 0l, 2);
170: size= ftell(ifile);
171: fseek(ifile, 0l, 0); /* rewind */
172: return size;
173: }
174:
175: Visible Procedure f_close(ofile) FILE *ofile; {
176: bool ok= fflush(ofile) != EOF;
177: if (fclose(ofile) == EOF || !ok)
178: error(MESS(3203, "write error (disk full?)"));
179: }
180:
181: Visible bool f_interactive(ifile) FILE *ifile; {
182: #ifdef ISATTY
183: return isatty(fileno(ifile));
184: #else
185: return fileno(ifile) < 3;
186: #endif
187: }
188:
189: #ifdef IBMPC
190:
191: #define FNMLEN 8
192: #define TYPLEN 3
193: #define SPCLEN 1
194:
195: #define FHW "how"
196: #define FZR "zer"
197: #define FMN "mon"
198: #define FDY "dya"
199: #define FTR "tar"
200:
201: Hidden string
202: filetype(type)
203: literal type;
204: {
205: switch (type) {
206: case Zer: return FZR;
207: case Mon: return FMN;
208: case Dya: return FDY;
209: case How: return FHW;
210: case Tar: return FTR;
211: default: syserr(MESS(3200, "filetype()"));
212: /* NOTREACHED */
213: }
214: }
215:
216: Hidden Procedure
217: cr_fname(name, type, fname, len, pname)
218: value name; string fname, *pname; literal type; int len;
219: {
220: *pname= fname;
221: strncpy(*pname, strval(name), len);
222: sprintf(fname + len, ".%s", filetype(type));
223: }
224:
225: #endif IBMPC
226:
227: #ifdef unix
228:
229: #define FNMLEN 12
230: #define TYPLEN 1
231: #define SPCLEN 0
232:
233: #define FHW '\''
234: #define FZR '<'
235: #define FMN '"'
236: #define FDY '>'
237: #define FTR '='
238:
239: Hidden literal
240: filetype(type)
241: literal type;
242: {
243: switch (type) {
244: case Zer: return FZR;
245: case Mon: return FMN;
246: case Dya: return FDY;
247: case How: return FHW;
248: case Tar: return FTR;
249: default: syserr(MESS(3201, "filetype()"));
250: /* NOTREACHED */
251: }
252: }
253:
254: Hidden Procedure
255: cr_fname(name, type, fname, len, pname)
256: value name; string fname, *pname; literal type; int len;
257: {
258: *fname= filetype(type);
259: fname[1]= '\0';
260: *pname= fname + 1;
261: strncat(fname, strval(name), len);
262: }
263:
264: #endif unix
265:
266: Hidden bool
267: exists(name)
268: string name;
269: {
270: value v= mk_text(name);
271: bool exist= in(v, file_names);
272: release(v);
273: return exist;
274: }
275:
276: Visible value
277: new_fname(name, type)
278: value name; literal type;
279: {
280: char fname[FNMLEN + TYPLEN + SPCLEN + 1];
281: intlet len= length(name);
282: string pname;
283: if (len > FNMLEN) len= FNMLEN;
284: cr_fname(name, type, fname, len, &pname);
285: while (exists(fname)) new(pname, len-1);
286: return mk_text(fname);
287: }
288:
289: #include <ctype.h>
290:
291: Hidden Procedure
292: new(name, n)
293: string name; int n;
294: {
295: if (n < 1) error(MESS(3202, "too many units"));
296: else if (!isdigit(name[n])) name[n]= '1';
297: else if (name[n] != '9') ++name[n];
298: else {
299: name[n]= '0';
300: new(name, --n);
301: }
302: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.