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: }