|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2: /* $Header: b2fil.c,v 1.1 84/06/28 00:49:11 timo Exp $ */
3:
4: /* Facilities supplied by the file system */
5:
6: #include "b.h"
7: #include "b0con.h"
8: #include <sys/types.h>
9: #include <sys/stat.h>
10: #include "b1obj.h"
11: #include "b2fil.h"
12: #include "b2scr.h"
13:
14: /*This file defines the facilities needed for dealing with files,
15: apart from C's standard I/O facilities which are used throughout the system.
16:
17: Units are held on files in a 'workspace', which on Unix is modelled
18: using directories. The function 'f_uname' converts a unit name into a
19: unique filename. On Unix this is done by prepending a character to the unit
20: name to indicate the kind of unit (for how'to ', and for tests and yields
21: < for zeroadic, " for monadic and > for dyadic; these have been chosen as
22: characters that are not usually used in filenames), and truncating the
23: name if necessary. If the name does have to be truncated, then it is
24: hashed to produce a character that is appended to the filename, in an attempt
25: to produce a unique filename. Even so, it is still possible for different
26: unit names to produce the same filename, and in the unlikely event of this
27: happening you get an error message that the unit already exists when you
28: try to create the clashing unit name.
29:
30: Filenames are at most SAFEFNLEN characters long, which on standard Unix
31: systems gives you one spare character for making backups or whatever.
32:
33: It would be better if the B system effectively maintained its own directories
34: that mapped units onto files in the real file system, as is done for targets.
35: With operating systems with a more limited file system (eg even shorter
36: filenames) this is the only possibility.
37:
38: */
39:
40: #define COML 60
41: char com_line[COML];
42: #define At_eos(s) ((s)+= strlen(s))
43:
44: Visible Procedure f_edit(fname, errline) value fname; intlet errline; {
45: /*The default editor is called with a first parameter of the line number
46: and a second parameter of the file name*/
47: string cl= com_line;
48: int c;
49: if (filtered) {
50: ignsigs();
51: printf("\001: +%d %s\n", errline, strval(fname));
52: fflush(stdout);
53: do { c= fgetc(stdin); } while (c != '\n' && c != EOF);
54: re_sigs();
55: return;
56: }
57: if (getenv("BEDITOR") == NULL) strcpy (cl, DEDI);
58: else strcpy(cl, getenv("BEDITOR"));
59: if (*(cl+strlen(cl)-1) == '+') {
60: if (errline != 0) sprintf(At_eos(cl), "%d", errline);
61: else *(cl+strlen(cl)-1)= ' ';
62: }
63: app_fname(At_eos(cl), fname);
64: system(com_line);
65: }
66:
67: Visible value f_save(fname) value fname; {
68: /* saves the file in a temporary file, whose name is returned */
69: /* Here the OS does the copy: you may have to do this yourself */
70: string cl; value sname= mk_text(SAVEFILE);
71: strcpy(cl= com_line, "cp");
72: app_fname(At_eos(cl), fname);
73: app_fname(At_eos(cl), sname);
74: system(com_line);
75: return sname;
76: }
77:
78: Visible Procedure f_rename(fname, nfname) value fname, nfname; {
79: string cl;
80: strcpy(cl= com_line, "mv");
81: app_fname(At_eos(cl), fname);
82: app_fname(At_eos(cl), nfname);
83: system(com_line);
84: /* what if mv fails??? */
85: }
86:
87: Visible Procedure f_delete(fname) value fname; {
88: string cl;
89: strcpy(cl= com_line, "rm");
90: app_fname(At_eos(cl), fname);
91: system(com_line);
92: }
93:
94: Visible bool f_exists(fname) value fname; {
95: FILE *f= fopen(strval(fname), "r");
96: if (f==NULL) return No;
97: fclose(f);
98: return Yes;
99: }
100:
101: #define SAFEFNLEN 13
102:
103: Hidden double f_hash(v) value v; {
104: int len= length(v), k; double d= '"'+.404*len;
105: /*That '"' is strange I know, but it's necessary for compatibility*/
106: value ch;
107: k_Over_len {
108: ch= thof(k+1, v);
109: d= .987*d+.277*charval(ch);
110: release(ch);
111: }
112: return d;
113: }
114:
115: Visible value f_uname(name, type) value name; literal type; {
116: static char fname[SAFEFNLEN+1]; string sfn= fname;
117: *sfn= type;
118: if (length(name) < SAFEFNLEN) strcpy(sfn+1, strval(name));
119: else {
120: double hh= f_hash(name)*321.987; char h;
121: strncpy(sfn+1, strval(name), SAFEFNLEN-2);
122: hh= hh-floor(hh); h= (char) floor(hh*29) + '!';
123: if (h >= '"') h++;
124: if (h >= '\'') h++;
125: if (h >= '/') h++;
126: if (h >= '0') h+= 10;
127: if (h >= 'A') h+= 26;
128: if (h >= 'a') h+= 26;
129: *(sfn+SAFEFNLEN-1)= h; *(sfn+SAFEFNLEN)= '\0';
130: }
131: return mk_text(fname);
132: }
133:
134: Hidden value try(t, n) value t; intlet n; {
135: value eq= mk_text("="), fn, a, b, c;
136: int len= length(t);
137: if (n == 0) fn= concat(eq, t);
138: else { /* PUT "="^(n<<1)^t IN fn */
139: fn= concat(eq, a= concat(b= convert(c= mk_integer(n), No, No), t));
140: release(a); release(b); release(c);
141: }
142: release(eq);
143: if (len > SAFEFNLEN) {
144: fn= trim(a= fn, 0, len-SAFEFNLEN);
145: release(a);
146: }
147: return(fn);
148: }
149:
150: Visible value f_tname(t) value t; {
151: value fn= try(t, 0);
152: intlet i= 0;
153: while (f_exists(fn)) {
154: release(fn);
155: fn= try(t, ++i);
156: }
157: return(fn);
158: }
159:
160: Hidden Procedure app_fname(ceos, fname) string ceos; value fname; {
161: string fp= strval(fname); intlet k, len= strlen(fp);
162: *ceos++= ' ';
163: k_Over_len {
164: *ceos++= '\\';
165: *ceos++= *fp++; /*should really use charval(thof(...))*/
166: }
167: *ceos= '\0';
168: }
169:
170: Visible unsigned f_size(ifile) FILE *ifile; {
171: struct stat sb;
172: if (fstat(fileno(ifile), &sb) != 0) syserr("can't stat file");
173: return( (unsigned) (sb.st_size) );
174: }
175:
176: Visible bool f_interactive(ifile) FILE *ifile; {
177: return isatty(fileno(ifile));
178: }
179:
180: Visible Procedure lst_uhds() {
181: /*List the headings of the units in this workspace*/
182: system("for i in \\'* \\<* \\\"* \\>*; do head -1 $i 2>/dev/null; done");
183: /*just for now, you understand*/
184: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.