1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2: /* $Header: convert.c,v 1.1 85/08/22 14:33:43 timo Exp $ */ 3: 4: /* 5: * Utility to recover the contents of a B workspace. 6: * 7: * Call as: convert [\'\"\<\>=]?* (this should be done by a shell script). 8: * 9: * It constructs a completely new ".b_perm" file with references to all files 10: * mentioned (if they exist). 11: * Files whose name starts with '=' and files with an extension of ".tar" 12: * or ".TAR" are taken to be targets; all others are assumed to contain 13: * units (if they contain garbage, they are ignored). (".tar" and ".TAR" 14: * are used on the IBM-PC.) 15: * For units, the name, type and adicity are extracted from the source; 16: * for targets, the target name is taken to be the file name with all 17: * illegal characters removed (upper case converted to lowercase). 18: * 19: * BUGS: 20: * - should augment the old ".b_perm" file instead of just overwriting it; 21: * - target names can get truncated when the original target name was longer 22: * than what fits in a legal file name. 23: * - doesn't detect multiple files defining the same name 24: * - on the IBM-PC, the file name expansion should be in the program for it to 25: * be of any use, because the MS-DOS "shell" doesn't expand * in file names 26: * 27: * $Log: convert.c,v $ 28: * Revision 1.1 85/08/22 14:33:43 timo 29: * Initial revision 30: * 31: * Revision 1.3.2.1 85/06/04 13:36:04 guido 32: * Create consistent branch 1.3.2. 33: * 34: * Revision 1.3 85/06/04 13:35:33 guido 35: * Added MS-DOS support. 36: * 37: * Revision 1.2 85/04/12 22:33:33 guido 38: * added treatment of targets; added warning and fatal error messages. 39: * 40: * Revision 1.1 85/01/29 12:48:09 guido 41: * used given file names instead of constructing file names from unit names. 42: * 43: * Revision --- frank 44: * created. 45: */ 46: 47: #include <stdio.h> 48: 49: #ifdef MSDOS 50: #define BPERMFILE "PERM.BIF" 51: #define DELIM '\\' 52: #define index strchr 53: #define rindex strrchr 54: #endif 55: 56: #ifdef unix 57: #define BPERMFILE ".b_perm" 58: #define DELIM '/' 59: #endif 60: 61: char *rindex(), *index(); 62: 63: #ifdef MSDOS 64: char *defargv[]= {"convert", "*.how", "*.zer", "*.mon", "*.dya", "*.tar", 0}; 65: #define defargc (sizeof defargv/sizeof defargv[0] - 1) 66: #endif 67: 68: FILE *ofile; 69: 70: char buffer[BUFSIZ]; 71: char *pbuf, *first, *last, *filename; 72: char *progname = "convert"; 73: int status= 0; 74: 75: #define Oputc(c) putc(c, ofile) 76: 77: /*VARARGS1*/ 78: warning(fmt, a1, a2) 79: char *fmt; 80: { 81: status= 1; 82: fprintf(stderr, "*** %s: ", progname); 83: fprintf(stderr, fmt, a1, a2); 84: fprintf(stderr, "\n"); 85: } 86: 87: /*VARARGS2*/ 88: quit(sts, msg, a1, a2) 89: int sts; 90: char *msg; 91: { 92: warning(msg, a1, a2); 93: exit(sts ? sts : status); 94: } 95: 96: main(argc, argv) 97: int argc; char **argv; 98: { 99: #ifndef MSDOS 100: if (argc < 2) 101: quit(2, "Usage: %s file ...", progname); 102: /* Don't do this under MSDOS -- program name is always 'c'... */ 103: progname= rindex(*argv, '/'); 104: if (progname) 105: ++progname; 106: else 107: progname= *argv; 108: #endif 109: 110: ofile= fopen(BPERMFILE, "w"); 111: if (!ofile) 112: quit(2, "%s: can't create %s", progname, BPERMFILE); 113: Oputc('{'); 114: #ifdef defargc 115: if (argc <= 1) { 116: argv= defargv; 117: argc= defargc; 118: } 119: #endif 120: while (argc > 1) { 121: --argc; ++argv; 122: treat_file(*argv); 123: } 124: Oputc('}'); 125: Oputc('\n'); 126: fclose(ofile); 127: exit(status); 128: } 129: 130: treat_file(file) 131: char *file; 132: { 133: FILE *ifile; 134: static int recursive= 0; 135: 136: ifile= fopen(filename= file, "r"); 137: if (!ifile) { 138: if (index(filename, '*') && !recursive) { 139: /* Assume failed '*' expansion */ 140: /* Ignore on UNIX, expand on MSDOS */ 141: #ifdef MSDOS 142: char **list= getfiles(filename); 143: if (list) { 144: recursive= 1; 145: for (; *list; ++list) 146: treat_file(*list); 147: recursive= 0; 148: } 149: #endif 150: } 151: else 152: warning("%s: can't read", filename); 153: } 154: else { 155: if (!fgets(buffer, BUFSIZ, ifile)) 156: warning("%s: empty file", filename); 157: else if (is_target(filename)) 158: treat_target(); 159: else 160: treat_line(); 161: fclose(ifile); 162: } 163: } 164: 165: #define CapLetter ('A' <= *pbuf && *pbuf <= 'Z') 166: #define Letter ('a' <= *pbuf && *pbuf <= 'z') 167: #define Digit ('0' <= *pbuf && *pbuf <= '9') 168: #define Quote (*pbuf == '\'' || *pbuf == '"') 169: #define Colon (*pbuf == ':') 170: #define Open (*pbuf == '(') 171: #define Close (*pbuf == ')') 172: #define Space (*pbuf == ' ' || *pbuf == '\t') 173: #define Tagmark (Letter || Digit || Quote) 174: #define Keymark (CapLetter || Digit || Quote) 175: 176: #define ToLower(c) ((c) - 'A' + 'a') 177: 178: skip_tag() 179: { 180: first= pbuf; 181: while (Tagmark) pbuf++; 182: last= pbuf; 183: } 184: 185: skip_keyword() 186: { 187: first= pbuf; 188: while (Keymark) pbuf++; 189: last= pbuf; 190: } 191: 192: skip_space() 193: { 194: while (Space) pbuf++; 195: } 196: 197: skip_open_close() 198: { 199: if (Open) { skip_to_close(); pbuf++; } 200: } 201: 202: skip_to_close() 203: { 204: while (++pbuf, !Close) if (Open) skip_to_close(); 205: } 206: 207: treat_line() 208: { 209: pbuf= buffer; 210: switch (*pbuf) { 211: case 'H': howto_unit(); break; 212: case 'Y': 213: case 'T': funprd_unit(); break; 214: default: warning("%s: not a valid B unit", filename); break; 215: } 216: } 217: 218: #define Zer 0 219: #define Mon 1 220: #define Dya 2 221: #define How 3 222: #define Tar 4 223: 224: howto_unit() 225: { 226: skip_keyword(); 227: skip_space(); 228: skip_keyword(); 229: put_entry(How); 230: } 231: 232: funprd_unit() 233: { 234: skip_keyword(); 235: skip_space(); 236: if (Letter) { 237: skip_tag(); 238: skip_space(); 239: if (Colon) put_entry(Zer); 240: else if (!Letter) put_entry(Mon); 241: else { 242: char *sv_first= first, *sv_last= last; 243: skip_tag(); 244: skip_space(); 245: if (Colon) { 246: first= sv_first; last= sv_last; 247: put_entry(Mon); 248: } else 249: put_entry(Dya); 250: } 251: } else { 252: skip_open_close(); 253: skip_space(); 254: skip_tag(); 255: put_entry(Dya); 256: } 257: } 258: 259: treat_target() 260: { 261: pbuf= filename; 262: #ifdef MSDOS 263: if (index(pbuf, ':')) 264: pbuf= index(pbuf, ':') + 1; 265: #endif 266: if (rindex(pbuf, DELIM)) 267: pbuf= index(pbuf, DELIM) + 1; 268: first= last= buffer; 269: while (*pbuf && !Letter && !CapLetter) 270: ++pbuf; 271: for (; *pbuf; ++pbuf) { 272: if (CapLetter) 273: *last++= ToLower(*pbuf); 274: else if (Letter || Digit || Quote) 275: *last++= *pbuf; 276: else if (*pbuf == '.') 277: break; /* Stop before extension ".tar" or ".TAR" */ 278: } 279: if (last == first) 280: warning("%s: cannot deduce target name", filename); 281: else 282: put_entry(Tar); 283: } 284: 285: put_entry(type) 286: int type; 287: { 288: static int first_elem= 1; 289: if (!first_elem) Oputc(';'); 290: else first_elem= 0; 291: Oputc('['); 292: put_key(type); 293: Oputc(']'); 294: Oputc(':'); 295: put_assoc(type); 296: } 297: 298: #define Text_quote '"' 299: #define Back_quote '`' 300: #define Double(c) if ((c) == Text_quote || (c) == Back_quote) Oputc(c) 301: 302: put_key(type) 303: int type; 304: { 305: char *p= first; 306: Oputc(Text_quote); 307: switch (type) { 308: case Zer: Oputc('0'); break; 309: case Mon: Oputc('1'); break; 310: case Dya: Oputc('2'); break; 311: case How: Oputc('3'); break; 312: case Tar: Oputc('4'); break; 313: default: break; 314: } 315: while (p < last) { 316: Double(*p); 317: Oputc(*p++); 318: } 319: Oputc(Text_quote); 320: } 321: 322: put_assoc(type) 323: int type; 324: { 325: char *p= filename; 326: Oputc(Text_quote); 327: while (*p != '\0') { 328: Double(*p); 329: Oputc(*p++); 330: } 331: Oputc(Text_quote); 332: } 333: 334: is_target(name) 335: char *name; 336: { 337: if (*name == '=') 338: return 1; 339: name= rindex(name, '.'); 340: if (!name) 341: return 0; 342: return strcmp(name, ".TAR") == 0 || strcmp(name, ".tar") == 0; 343: }