Annotation of 43BSD/contrib/B/src/bint/b3sou.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.