|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ ! 2: ! 3: /* ! 4: $Header: b3sou.c,v 1.4 85/08/22 16:59:08 timo Exp $ ! 5: */ ! 6: ! 7: /* Sources: maintaining units and values on external files */ ! 8: ! 9: #include "b.h" ! 10: #include "b0con.h" ! 11: #include "b0fea.h" ! 12: #include "b0fil.h" ! 13: #include "b1mem.h" ! 14: #include "b1obj.h" ! 15: #include "b2syn.h" ! 16: #include "b2par.h" ! 17: #include "b2nod.h" ! 18: #include "b3env.h" ! 19: #include "b3scr.h" ! 20: #include "b3err.h" ! 21: #include "b3sem.h" ! 22: #include "b3fil.h" ! 23: #include "b3sou.h" ! 24: #include "b3int.h" ! 25: ! 26: /************************** UNITS ************************************/ ! 27: ! 28: Hidden value b_perm; /* The table that maps tags to their file names */ ! 29: Hidden value b_units; /* The table that maps tags to their internal repr. */ ! 30: ! 31: Hidden bool ! 32: u_exists(pname, aa) ! 33: value pname, **aa; ! 34: { ! 35: return in_env(b_units, pname, aa); ! 36: } ! 37: ! 38: Visible Procedure ! 39: def_unit(pname, u) ! 40: value pname, u; ! 41: { ! 42: e_replace(u, &b_units, pname); ! 43: } ! 44: ! 45: Hidden Procedure ! 46: free_unit(pname) ! 47: value pname; ! 48: { ! 49: e_delete(&b_units, pname); ! 50: } ! 51: ! 52: Hidden Procedure ! 53: del_units() ! 54: { ! 55: int len= length(b_units), k; how *u; ! 56: for (k= len-1; k >= 0; --k) { ! 57: /* Reverse loop so deletions don't affect the numbering! */ ! 58: u= How_to(*assoc(b_units, k)); ! 59: if (!u->unparsed) free_unit(*key(b_units, k)); ! 60: /*Therefore standard B functions must be entered as unparsed*/ ! 61: } ! 62: } ! 63: ! 64: Visible Procedure ! 65: rem_unit(u) ! 66: parsetree u; ! 67: { ! 68: value pname= get_pname(u); ! 69: free_unit(pname); ! 70: release(pname); ! 71: } ! 72: ! 73: /********************************************************************** */ ! 74: ! 75: Visible Procedure ! 76: p_name_type(pname, name, type) ! 77: value pname, *name; literal *type; ! 78: { ! 79: *name= behead(pname, MkSmallInt(2)); ! 80: switch (strval(pname)[0]) { ! 81: case '0': *type= Zer; break; ! 82: case '1': *type= Mon; break; ! 83: case '2': *type= Dya; break; ! 84: case '3': *type= How; break; ! 85: case '4': *type= Tar; break; ! 86: default: syserr(MESS(4000, "p_name_type")); ! 87: /* NOTREACHED */ ! 88: } ! 89: } ! 90: ! 91: Visible value ! 92: permkey(name, type) ! 93: value name; literal type; ! 94: { ! 95: value v, w; string t; ! 96: switch (type) { ! 97: case Zer: t= "0"; break; ! 98: case Mon: t= "1"; break; ! 99: case Dya: t= "2"; break; ! 100: case How: t= "3"; break; ! 101: case Tar: t= "4"; break; ! 102: default: syserr(MESS(4001, "wrong permkey")); ! 103: } ! 104: w= mk_text(t); ! 105: v= concat(w, name); release(w); ! 106: return v; ! 107: } ! 108: ! 109: Visible bool ! 110: p_exists(pname, aa) ! 111: value pname, **aa; ! 112: { ! 113: return in_env(b_perm, pname, aa); ! 114: } ! 115: ! 116: Visible value file_names; ! 117: ! 118: Hidden Procedure ! 119: def_perm(pname, f) ! 120: value pname, f; ! 121: { ! 122: e_replace(f, &b_perm, pname); ! 123: if (!in(f, file_names)) insert(f, &file_names); ! 124: } ! 125: ! 126: Hidden Procedure ! 127: free_perm(pname) ! 128: value pname; ! 129: { ! 130: value *aa; ! 131: if (p_exists(pname, &aa)) { ! 132: remove(*aa, &file_names); ! 133: f_delete(*aa); ! 134: e_delete(&b_perm, pname); ! 135: } ! 136: } ! 137: ! 138: Hidden value ! 139: get_fname(pname) ! 140: value pname; ! 141: { ! 142: value *aa; ! 143: if (p_exists(pname, &aa)) return copy(*aa); ! 144: else { ! 145: value fname, name; literal type; ! 146: p_name_type(pname, &name, &type); ! 147: fname= new_fname(name, type); ! 148: def_perm(pname, fname); ! 149: release(name); ! 150: return fname; ! 151: } ! 152: } ! 153: ! 154: Hidden bool ! 155: p_version(name, type, pname) ! 156: value name, *pname; literal type; ! 157: { ! 158: value *aa; ! 159: *pname= permkey(name, type); ! 160: if (p_exists(*pname, &aa)) return Yes; ! 161: release(*pname); *pname= Vnil; ! 162: return No; ! 163: } ! 164: ! 165: Hidden bool ! 166: how_unit(pname) ! 167: value pname; ! 168: { ! 169: value name; literal type; ! 170: p_name_type(pname, &name, &type); ! 171: release(name); ! 172: return type == How; ! 173: } ! 174: ! 175: Hidden bool ! 176: zermon_units(pname, other_pname) ! 177: value pname, *other_pname; ! 178: { ! 179: value name; literal type; bool is; ! 180: p_name_type(pname, &name, &type); ! 181: is= (type == Zer && p_version(name, Mon, other_pname)) || ! 182: (type == Mon && p_version(name, Zer, other_pname)); ! 183: release(name); ! 184: return is; ! 185: } ! 186: ! 187: /***********************************************************************/ ! 188: ! 189: Hidden bool ! 190: is_loaded(pname, aa) ! 191: value pname, **aa; ! 192: { ! 193: value u= Vnil, npname= Vnil, get_unit(); ! 194: if (u_exists(pname, aa)) return Yes; /* already loaded */ ! 195: if (!p_exists(pname, aa)) return No; ! 196: ifile= fopen(strval(**aa), "r"); ! 197: if (ifile == NULL) { ! 198: vs_ifile(); ! 199: return No; ! 200: } ! 201: Eof= No; ! 202: first_ilev(); ! 203: u= get_unit(&npname, Yes); ! 204: if (still_ok) def_unit(npname, u); ! 205: fclose(ifile); ! 206: vs_ifile(); ! 207: Eof= No; ! 208: if (still_ok && !u_exists(pname, aa)) { ! 209: value name; literal type; ! 210: p_name_type(npname, &name, &type); ! 211: release(uname); uname= copy(pname); ! 212: curline= How_to(u)->unit; curlino= one; ! 213: error2(MESS(4002, "filename and unit name incompatible for "), name); ! 214: release(name); ! 215: } ! 216: release(u); release(npname); ! 217: return still_ok; ! 218: } ! 219: ! 220: /* Does the unit exist without faults? */ ! 221: ! 222: Visible bool ! 223: is_unit(name, type, aa) ! 224: value name, **aa; literal type; ! 225: { ! 226: value pname; ! 227: context c; bool is; ! 228: sv_context(&c); ! 229: cntxt= In_unit; ! 230: pname= permkey(name, type); ! 231: is= is_loaded(pname, aa); ! 232: release(pname); ! 233: set_context(&c); ! 234: return is; ! 235: } ! 236: ! 237: /***********************************************************************/ ! 238: ! 239: Hidden char DISCARD[]= "the unit name is already in use;\n\ ! 240: *** should the old unit be discarded?"; ! 241: ! 242: #define CANT_WRITE \ ! 243: MESS(4003, "cannot create file; need write permission in directory") ! 244: ! 245: #define CANT_READ MESS(4004, "unable to find file") ! 246: #define MON_VERSION MESS(4005, " is already a monadic function/predicate") ! 247: #define ZER_VERSION MESS(4006, " is already a zeroadic function/predicate") ! 248: ! 249: Hidden Procedure ! 250: u_name_type(v, name, type) ! 251: parsetree v; value *name; literal *type; ! 252: { ! 253: switch (Nodetype(v)) { ! 254: case HOW_TO: *name= copy(*Branch(v, UNIT_NAME)); ! 255: *type= How; ! 256: break; ! 257: case YIELD: ! 258: case TEST: *name= copy(*Branch(v, UNIT_NAME)); ! 259: switch (intval(*Branch(v, FPR_ADICITY))) { ! 260: case 0: *type= Zer; break; ! 261: case 1: *type= Mon; break; ! 262: case 2: *type= Dya; break; ! 263: default: syserr(MESS(4007, "wrong adicity")); ! 264: } ! 265: break; ! 266: default: syserr(MESS(4008, "wrong nodetype of unit")); ! 267: } ! 268: } ! 269: ! 270: Hidden value ! 271: get_unit(pname, filed) ! 272: value *pname; bool filed; ! 273: { ! 274: value name; literal type; ! 275: parsetree u= unit(No); ! 276: if (u == NilTree) return Vnil; ! 277: u_name_type(u, &name, &type); ! 278: *pname= permkey(name, type); ! 279: release(name); ! 280: switch (Nodetype(u)) { ! 281: case HOW_TO: return mk_how(u, filed); ! 282: case YIELD: return mk_fun(type, Use, u, filed); ! 283: case TEST: return mk_prd(type, Use, u, filed); ! 284: default: syserr(MESS(4009, "wrong nodetype in 'get_unit'")); ! 285: } ! 286: /* NOTREACHED */ ! 287: } ! 288: ! 289: Visible value ! 290: get_pname(v) ! 291: parsetree v; ! 292: { ! 293: value pname, name; literal type; ! 294: u_name_type(v, &name, &type); ! 295: pname= permkey(name, type); ! 296: release(name); ! 297: return pname; ! 298: } ! 299: ! 300: Hidden Procedure ! 301: get_heading(h, pname) ! 302: parsetree *h; value *pname; ! 303: { ! 304: *h= unit(Yes); ! 305: *pname= still_ok ? get_pname(*h) : Vnil; ! 306: } ! 307: ! 308: /* Create a unit via the editor or from the input stream */ ! 309: ! 310: Visible Procedure ! 311: create_unit() ! 312: { ! 313: value pname= Vnil, *aa; parsetree heading= NilTree; ! 314: if (!interactive) { ! 315: value v= get_unit(&pname, No); ! 316: if (still_ok) def_unit(pname, v); ! 317: release(v); release(pname); ! 318: return; ! 319: } ! 320: get_heading(&heading, &pname); ! 321: if (still_ok) { ! 322: value v; ! 323: if (p_exists(pname, &aa)) { ! 324: if (is_intended(DISCARD)) { ! 325: free_unit(pname); ! 326: free_perm(pname); ! 327: } else { ! 328: tx= ceol; ! 329: release(pname); ! 330: release(heading); ! 331: return; ! 332: } ! 333: } else if (zermon_units(pname, &v)) { ! 334: value name; literal type; ! 335: p_name_type(pname, &name, &type); ! 336: curline= heading; curlino= one; ! 337: error3(0, name, type == Zer ? MON_VERSION ! 338: : ZER_VERSION); ! 339: release(name); release(v); ! 340: } ! 341: } ! 342: if (still_ok) { ! 343: value fname= get_fname(pname); ! 344: FILE *ofile= fopen(strval(fname), "w"); ! 345: if (ofile == NULL) error(CANT_WRITE); ! 346: else { ! 347: txptr tp= fcol(); ! 348: do { fputc(Char(tp), ofile); } ! 349: while (Char(tp++) != '\n'); ! 350: f_close(ofile); ! 351: ed_unit(pname, fname); ! 352: } ! 353: release(fname); ! 354: } ! 355: release(pname); release(heading); ! 356: } ! 357: ! 358: ! 359: /***********************************************************************/ ! 360: ! 361: /* Edit a unit. The name of the unit is either given, or is defaulted ! 362: to the last unit edited or the last unit that gave an error, whichever ! 363: was most recent. ! 364: It is possible for the user to mess things up with the w command, for ! 365: instance, but this is not checked. It is allowed to rename the unit though, ! 366: or delete it completely. If the file is empty, the unit is disposed of. ! 367: Otherwise, the name and adicity are determined and if these have changed, ! 368: the new unit is written out to a new file, and the original written back. ! 369: Thus the original is not lost. ! 370: ! 371: Renaming, deleting, or changing the adicity of a test or yield ! 372: unfortunately requires all other units to be thrown away internally ! 373: (by del_units), since the unit parse trees may be wrong. For instance, ! 374: consider the effect on the following of making a formerly monadic ! 375: function f, into a zeroadic function: ! 376: WRITE f root 2 ! 377: */ ! 378: ! 379: Hidden char ZEROADIC[]= ! 380: "the unit name is in use both for a zeroadic and a dyadic version;\n\ ! 381: *** do you want to edit the zeroadic version?"; ! 382: ! 383: Hidden char MONADIC[]= ! 384: "the unit name is in use both for a monadic and a dyadic version;\n\ ! 385: *** do you want to edit the monadic version?"; ! 386: ! 387: Visible Procedure ! 388: edit_unit() ! 389: { ! 390: value name= Vnil, pname= Vnil, v= Vnil; bool ens_filed(); ! 391: value fname; ! 392: if (Ceol(tx)) { ! 393: if (erruname == Vnil) parerr(MESS(4010, "no current unit")); ! 394: else pname= copy(erruname); ! 395: } else if (is_keyword(&name)) ! 396: pname= permkey(name, How); ! 397: else if (is_tag(&name)) { ! 398: if (p_version(name, Zer, &pname)) { ! 399: if (p_version(name, Dya, &v) && !is_intended(ZEROADIC)) { ! 400: release(pname); pname= copy(v); ! 401: } ! 402: } else if (p_version(name, Mon, &pname)) { ! 403: if (p_version(name, Dya, &v) && !is_intended(MONADIC)) { ! 404: release(pname); pname= copy(v); ! 405: } ! 406: } else { ! 407: pname= permkey(name, Dya); ! 408: } ! 409: } else { ! 410: parerr(MESS(4011, "I find nothing editible here")); ! 411: } ! 412: if (still_ok && ens_filed(pname, &fname)) { ! 413: ed_unit(pname, fname); ! 414: release(fname); ! 415: } ! 416: release(name); release(pname); release(v); ! 417: } ! 418: ! 419: Hidden char NO_U_WRITE[]= ! 420: "you have no write permission in this workspace: you may not change the unit\n\ ! 421: *** do you still want to display the unit?"; ! 422: ! 423: Hidden char ZER_MON[]= ! 424: "the unit name is already in use for a zeroadic function or predicate;\n\ ! 425: *** should that unit be discarded?\n\ ! 426: *** (if not you have to change the monadic unit name)"; ! 427: ! 428: Hidden char MON_ZER[]= ! 429: "the unit name is already in use for a monadic function or predicate;\n\ ! 430: *** should that unit be discarded?\n\ ! 431: *** (if not you have to change the zeroadic unit name)"; ! 432: ! 433: Hidden Procedure ! 434: ed_unit(pname, fname) ! 435: value pname, fname; ! 436: { ! 437: value sname= Vnil, npname= Vnil, nfname= Vnil; ! 438: value u, *aa, v= Vnil, v_free= Vnil; ! 439: intlet err_line(); ! 440: bool new_def= Yes, same_name= No, still_there(), ed_again= No; ! 441: ! 442: if (!ws_writable() && !is_intended(NO_U_WRITE)) return; ! 443: sname= f_save(fname); /* in case the unit gets renamed */ ! 444: if (sname == Vnil) { ! 445: error(MESS(4012, "can't save to temporary file")); ! 446: return; ! 447: } ! 448: release(uname); uname= copy(pname); ! 449: #ifndef INTEGRATION ! 450: f_edit(fname, err_line(pname)); ! 451: #else ! 452: f_edit(fname, err_line(pname), unit_prompt); ! 453: #endif ! 454: if (!still_there(fname)) { ! 455: free_unit(pname); ! 456: if (!how_unit(pname)) del_units(); ! 457: release(erruname); erruname= Vnil; errlino= 0; ! 458: free_perm(pname); ! 459: f_delete(sname); ! 460: release(sname); ! 461: return; ! 462: } ! 463: first_ilev(); ! 464: u= get_unit(&npname, Yes); ! 465: fclose(ifile); vs_ifile(); Eof= No; ! 466: if (u == Vnil || npname == Vnil) ! 467: new_def= No; ! 468: else if (same_name= compare(pname, npname) == 0) ! 469: new_def= p_exists(pname, &aa); ! 470: else if (p_exists(npname, &aa)) ! 471: new_def= is_intended(DISCARD); ! 472: else if (zermon_units(npname, &v)) { ! 473: value name; literal type; ! 474: p_name_type(npname, &name, &type); ! 475: if (new_def= is_intended(type == Zer ? MON_ZER : ZER_MON)) { ! 476: free_unit(v); ! 477: v_free= copy(v); /* YIELD f => YIELD f x */ ! 478: } else { ! 479: nfname= new_fname(name, type); ! 480: f_rename(fname, nfname); ! 481: ed_again= Yes; ! 482: } ! 483: release(name); ! 484: } ! 485: if (new_def) { ! 486: if (!how_unit(npname)) del_units(); ! 487: if (still_ok) def_unit(npname, u); ! 488: else free_unit(npname); ! 489: if (!same_name) { ! 490: nfname= get_fname(npname); ! 491: f_rename(fname, nfname); ! 492: if (v_free) free_perm(v_free); ! 493: } ! 494: release(erruname); erruname= copy(npname); ! 495: } ! 496: if (!same_name) f_rename(sname, fname); ! 497: else f_delete(sname); ! 498: if (!p_exists(pname, &aa)) f_delete(fname); ! 499: if (ed_again) ed_unit(npname, nfname); ! 500: release(npname); release(u); release(sname); release(nfname); ! 501: release(v); release(v_free); ! 502: } ! 503: ! 504: /* Find out if the file exists, and is not empty. Some wretched editors ! 505: for some reason don't allow a file to be edited to empty, but insist it ! 506: should be at least one empty line. Thus an initial empty line may be ! 507: disregarded, but this is not harmful. */ ! 508: ! 509: Hidden bool still_there(fname) value fname; { ! 510: int k; ! 511: ifile= fopen(strval(fname), "r"); ! 512: if (ifile == NULL) { ! 513: vs_ifile(); ! 514: /* error(CANT_READ); */ ! 515: return No; ! 516: } else { ! 517: if ((k= getc(ifile)) == EOF || (k == '\n' && (k= getc(ifile)) == EOF)) { ! 518: fclose(ifile); ! 519: f_delete(fname); ! 520: vs_ifile(); ! 521: return No; ! 522: } ! 523: ungetc(k, ifile); ! 524: return Yes; ! 525: } ! 526: } ! 527: ! 528: /* Ensure the unit is filed. If the unit was read non-interactively (eg passed ! 529: as a parameter to b), it is only held in store. ! 530: Editing it puts it into a file. This is the safest way to copy a unit from ! 531: one workspace to another. ! 532: */ ! 533: ! 534: Hidden bool ! 535: ens_filed(pname, fname) ! 536: value pname, *fname; ! 537: { ! 538: value *aa; ! 539: if (p_exists(pname, &aa)) { ! 540: *fname= copy(*aa); ! 541: return Yes; ! 542: } else if (!u_exists(pname, &aa) || How_to(*aa)->unit == NilTree) { ! 543: pprerr(MESS(4013, "no such unit in this workspace")); ! 544: return No; ! 545: } else { ! 546: how *du= How_to(*aa); FILE *ofile; ! 547: if (du->filed == Yes) { ! 548: syserr(MESS(4014, "ens_filed()")); ! 549: return No; ! 550: } ! 551: *fname= get_fname(pname); ! 552: ofile= fopen(strval(*fname), "w"); ! 553: if (!ofile) { ! 554: error(CANT_WRITE); ! 555: release(*fname); ! 556: return No; ! 557: } else { ! 558: display(ofile, du->unit, No); ! 559: f_close(ofile); ! 560: du->filed= Yes; ! 561: return Yes; ! 562: } ! 563: } ! 564: } ! 565: ! 566: Hidden intlet ! 567: err_line(pname) ! 568: value pname; ! 569: { ! 570: if (errlino == 0 || erruname == Vnil || compare(erruname, pname) != 0) ! 571: return 0; ! 572: else { ! 573: intlet el= errlino; ! 574: errlino= 0; ! 575: return el; ! 576: } ! 577: } ! 578: ! 579: /************************** VALUES ***************************************/ ! 580: /* The permanent environment in the old format was kept as a single file */ ! 581: /* but this caused slow start ups if the file was big. */ ! 582: /* Thus the new version stores each permanent target on a separate file, */ ! 583: /* that furthermore is only loaded on demand. */ ! 584: /* To achieve this, a directory is kept of the permanent tags and their */ ! 585: /* file names. Care has to be taken that disaster occurring in */ ! 586: /* the middle of an update of this directory does the least harm. */ ! 587: /* Having the directory refer to a non-existent file is considered less */ ! 588: /* harmful than leaving a file around that can never be accessed, for */ ! 589: /* instance, so a file is deleted before its directory entry, */ ! 590: /* and so forth. */ ! 591: /*************************************************************************/ ! 592: ! 593: Hidden bool ! 594: t_exists(name, aa) ! 595: value name, **aa; ! 596: { ! 597: return in_env(prmnv->tab, name, aa); ! 598: } ! 599: ! 600: Hidden Procedure ! 601: def_target(name, t) ! 602: value name, t; ! 603: { ! 604: e_replace(t, &prmnv->tab, name); ! 605: } ! 606: ! 607: Hidden Procedure ! 608: free_target(name) ! 609: value name; ! 610: { ! 611: e_delete(&prmnv->tab, name); ! 612: } ! 613: ! 614: Hidden Procedure ! 615: tarfiled(name, v) ! 616: value name, v; ! 617: { ! 618: value p= mk_per(v); ! 619: def_target(name, p); ! 620: release(p); ! 621: } ! 622: ! 623: Visible value ! 624: tarvalue(name, v) ! 625: value name, v; ! 626: { ! 627: value getval(); ! 628: if (Is_filed(v)) { ! 629: per *p= Perm(v); ! 630: if (p->val == Vnil) { ! 631: value *aa, pname= permkey(name, Tar); ! 632: if (!p_exists(pname, &aa)) ! 633: syserr(MESS(4015, "tarvalue")); ! 634: release(pname); ! 635: p->val= getval(*aa, In_tarval); ! 636: } ! 637: return p->val; ! 638: } ! 639: return v; ! 640: } ! 641: ! 642: Hidden value last_tname= Vnil; /*last edited target */ ! 643: ! 644: Visible Procedure ! 645: edit_target() ! 646: { ! 647: value name= Vnil; bool ens_tfiled(); ! 648: value fname; ! 649: if (Ceol(tx)) { ! 650: if (last_tname == Vnil) ! 651: parerr(MESS(4016, "no current target")); ! 652: else ! 653: name= copy(last_tname); ! 654: } else if (!is_tag(&name)) ! 655: parerr(MESS(4017, "I find nothing editible here")); ! 656: if (still_ok && ens_tfiled(name, &fname)) { ! 657: ed_target(name, fname); ! 658: release(fname); ! 659: } ! 660: release(name); ! 661: } ! 662: ! 663: Hidden char NO_T_WRITE[]= ! 664: "you have no write permission in this workspace: you may not change the target\n\ ! 665: *** do you still want to display the target?"; ! 666: ! 667: Hidden Procedure ! 668: ed_target(name, fname) ! 669: value name, fname; ! 670: { ! 671: /* Edit a target. The value in the target is written to the file, ! 672: and then removed from the internal permanent environment so that ! 673: if a syntax error occurs when reading the value back, the value is ! 674: absent from the internal permanent environment. ! 675: Thus when editing the file to correct the syntax error, the ! 676: file doesn't get overwritten. ! 677: The contents may be completely deleted in which case the target is ! 678: deleted. ! 679: */ ! 680: value v, getval(); ! 681: if (!ws_writable() && !is_intended(NO_T_WRITE)) return; ! 682: #ifndef INTEGRATION ! 683: f_edit(fname, 0); ! 684: #else ! 685: f_edit(fname, 0, tar_prompt); ! 686: #endif ! 687: if (!still_there(fname)) { ! 688: value pname= permkey(name, Tar); ! 689: free_target(name); ! 690: free_perm(pname); ! 691: release(pname); ! 692: release(last_tname); last_tname= Vnil; ! 693: return; ! 694: } ! 695: release(last_tname); last_tname= copy(name); ! 696: fclose(ifile); /*since still_there leaves it open*/ ! 697: v= getval(fname, In_edval); ! 698: if (still_ok) def_target(name, v); ! 699: release(v); ! 700: } ! 701: ! 702: Hidden bool ! 703: ens_tfiled(name, fname) ! 704: value name, *fname; ! 705: { ! 706: value *aa; ! 707: if (!t_exists(name, &aa)) { ! 708: pprerr(MESS(4018, "no such target in this workspace")); ! 709: return No; ! 710: } else { ! 711: value pname= permkey(name, Tar); ! 712: *fname= get_fname(pname); ! 713: if (!Is_filed(*aa)) { ! 714: putval(*fname, *aa, No); ! 715: tarfiled(name, *aa); ! 716: } ! 717: release(pname); ! 718: return Yes; ! 719: } ! 720: } ! 721: ! 722: /***************************** Values on files ****************************/ ! 723: ! 724: Hidden value ! 725: getval(fname, ct) ! 726: value fname; ! 727: literal ct; /* context */ ! 728: { ! 729: char *buf= Nil; int k; parsetree e, code; value v= Vnil; ! 730: ifile= fopen(strval(fname), "r"); ! 731: if (ifile) { ! 732: txptr fcol_save= first_col, tx_save= tx; context c; ! 733: sv_context(&c); ! 734: cntxt= ct; ! 735: buf= getmem((unsigned)(f_size(ifile)+2)*sizeof(char)); ! 736: if (buf == Nil) ! 737: syserr(MESS(4019, "can't get buffer to read file")); ! 738: first_col= tx= ceol= buf; ! 739: while ((k= getc(ifile)) != EOF) ! 740: if (k != '\n') *ceol++= k; ! 741: *ceol= '\n'; ! 742: fclose(ifile); vs_ifile(); ! 743: e= expr(ceol); ! 744: if (still_ok) fix_nodes(&e, &code); ! 745: curline=e; curlino= one; ! 746: v= evalthread(code); curline= Vnil; ! 747: release(e); ! 748: if (buf != Nil) freemem((ptr) buf); ! 749: set_context(&c); ! 750: first_col= fcol_save; tx= tx_save; ! 751: } else { ! 752: error(CANT_READ); ! 753: vs_ifile(); ! 754: } ! 755: return v; ! 756: } ! 757: ! 758: Visible Procedure ! 759: getprmnv() ! 760: { ! 761: intlet k, len; value name, fname; literal type; ! 762: if (f_exists(BPERMFILE)) { ! 763: value fn; ! 764: fn= mk_text(BPERMFILE); ! 765: b_perm= getval(fn, In_prmnv); ! 766: release(fn); ! 767: if (!still_ok) exit(1); ! 768: len= length(b_perm); ! 769: k_Over_len { ! 770: p_name_type(*key(b_perm, k), &name, &type); ! 771: if (type == Tar) tarfiled(name, Vnil); ! 772: fname= copy(*assoc(b_perm, k)); ! 773: insert(fname, &file_names); ! 774: release(fname); release(name); ! 775: } ! 776: } else ! 777: b_perm= mk_elt(); ! 778: ! 779: #ifdef CONVERSION ! 780: if (f_exists(PRMNVFILE)) { /* convert from old to new format */ ! 781: value tab, v, pname, new_fname(); ! 782: value fn= mk_text(PRMNVFILE), save= mk_text(SAVEPRMNVFILE); ! 783: tab= getval(fn, In_prmnv); ! 784: if (!still_ok) exit(1); ! 785: len= length(tab); ! 786: k_Over_len { ! 787: name= copy(*key(tab, k)); ! 788: v= copy(*assoc(tab, k)); ! 789: def_target(name, v); ! 790: pname= permkey(name, Tar); ! 791: fname= get_fname(pname); ! 792: putval(fname, v, Yes); ! 793: tarfiled(name, v); ! 794: release(name); release(v); release(fname); ! 795: release(pname); ! 796: } ! 797: f_rename(fn, save); ! 798: if (len > 0) ! 799: printf("*** [Old permanent environment converted]\n"); ! 800: release(tab); release(fn); release(save); ! 801: } ! 802: #endif CONVERSION ! 803: } ! 804: ! 805: Hidden Procedure ! 806: putval(fname, v, silently) ! 807: value fname, v; bool silently; ! 808: { ! 809: FILE *ofile; value fn= mk_text(tempfile); bool was_ok= still_ok; ! 810: ofile= fopen(strval(fn), "w"); ! 811: if (ofile != NULL) { ! 812: redirect(ofile); ! 813: still_ok= Yes; ! 814: wri(v, No, No, Yes); newline(); ! 815: f_close(ofile); ! 816: redirect(stdout); ! 817: if (still_ok) f_rename(fn, fname); ! 818: } else if (!silently) error(CANT_WRITE); ! 819: still_ok= was_ok; ! 820: release(fn); ! 821: } ! 822: ! 823: Visible Procedure ! 824: putprmnv() ! 825: { ! 826: static bool active; ! 827: value v, name, fname, fn, *aa, pname; literal type; ! 828: int k, len; ! 829: if (active) return; ! 830: active= Yes; ! 831: len= length(b_perm); ! 832: for (k= len-1; k>=0; --k) { ! 833: p_name_type(*key(b_perm, k), &name, &type); ! 834: if (type == Tar && !t_exists(name, &aa)) ! 835: free_perm(*key(b_perm, k)); ! 836: release(name); ! 837: } ! 838: len= length(prmnv->tab); ! 839: k_Over_len { ! 840: v= copy(*assoc(prmnv->tab, k)); ! 841: if (!Is_filed(v)) { ! 842: name= copy(*key(prmnv->tab, k)); ! 843: pname= permkey(name, Tar); ! 844: fname= get_fname(pname); ! 845: putval(fname, v, Yes); ! 846: tarfiled(name, v); ! 847: release(name); release(fname); release(pname); ! 848: } ! 849: release(v); ! 850: } ! 851: fn= mk_text(BPERMFILE); ! 852: putval(fn, b_perm, Yes); ! 853: /* Remove the file if the permanent environment is empty */ ! 854: if (length(b_perm) == 0) f_delete(fn); ! 855: release(fn); ! 856: active= No; ! 857: } ! 858: ! 859: Visible Procedure ! 860: initsou() ! 861: { ! 862: b_units= mk_elt(); ! 863: file_names= mk_elt(); ! 864: } ! 865: ! 866: Visible Procedure ! 867: endsou() ! 868: { ! 869: /* Release everything around so "memory leakage" can be detected */ ! 870: release(b_units); b_units= Vnil; ! 871: release(b_perm); b_perm= Vnil; ! 872: release(file_names); file_names= Vnil; ! 873: release(last_tname); last_tname= Vnil; ! 874: } ! 875: ! 876: Visible Procedure ! 877: lst_uhds() ! 878: { ! 879: intlet k, len= length(b_perm); int c; ! 880: value name; literal type; ! 881: k_Over_len { ! 882: p_name_type(*key(b_perm, k), &name, &type); ! 883: if (type != Tar) { ! 884: FILE *fn= fopen(strval(*assoc(b_perm, k)), "r"); ! 885: if (fn) { ! 886: while ((c= getc(fn)) != EOF && c != '\n') ! 887: putc(c, stdout); ! 888: putc('\n', stdout); ! 889: fclose(fn); ! 890: } ! 891: } ! 892: release(name); ! 893: } ! 894: len= length(b_units); ! 895: k_Over_len { ! 896: how *u= How_to(*assoc(b_units, k)); ! 897: #ifndef TRY ! 898: value *aa; ! 899: if (u -> filed == No && !p_exists(*key(b_units, k), &aa)) ! 900: #else ! 901: if (u -> filed == No) ! 902: #endif ! 903: display(stdout, u -> unit, Yes); ! 904: } ! 905: fflush(stdout); ! 906: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.