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

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
                      2: 
                      3: /*
                      4:   $Header: b3loc.c,v 1.4 85/08/27 10:56:45 timo Exp $
                      5: */
                      6: 
                      7: /* B locations and environments */
                      8: #include "b.h"
                      9: #include "b0con.h"
                     10: #include "b1obj.h"
                     11: #include "b3env.h" /* for bndtgs */
                     12: #include "b3sem.h"
                     13: #include "b3sou.h" /* for tarvalue() */
                     14: #include "b3err.h" /* for still_ok */
                     15: 
                     16: Hidden value* location(l) loc l; {
                     17:        value *ll;
                     18:        if (Is_locloc(l)) {
                     19:                if (!in_env(curnv->tab, l, &ll))
                     20:                        error(MESS(3600, "target not initialised"));
                     21:                return ll;
                     22:        } else if (Is_simploc(l)) {
                     23:                simploc *sl= Simploc(l);
                     24:                if (!in_env(sl->e->tab, sl->i, &ll))
                     25:                    if (Is_locloc(sl->i))
                     26:                        error(MESS(3601, "target not initialised"));
                     27:                    else error3(0, sl->i,
                     28:                        MESS(3602, " hasn't been initialised"));
                     29:                return ll;
                     30:        } else if (Is_tbseloc(l)) {
                     31:                tbseloc *tl= Tbseloc(l);
                     32:                ll= location(tl->R);
                     33:                if (still_ok) { 
                     34:                        ll= adrassoc(*ll, tl->K);
                     35:                        if (ll == Pnil && still_ok) error(MESS(3603, "key not in table"));
                     36:                }
                     37:                return ll;
                     38:        } else {
                     39:                syserr(MESS(3604, "call of location with improper type"));
                     40:                return (value *) Dummy;
                     41:        }
                     42: }
                     43: 
                     44: Hidden Procedure uniquify(l) loc l; {
                     45:        if (Is_simploc(l)) {
                     46:                simploc *sl= Simploc(l);
                     47:                value *ta= &(sl->e->tab), ke= sl->i;
                     48:                uniql(ta);
                     49:                check_location(l);
                     50:                if (still_ok) {
                     51:                        if (Is_compound(*ta)) uniql(Field(*ta, intval(ke)));
                     52:                        else {  value *aa, v;
                     53:                                VOID uniq_assoc(*ta, ke);
                     54:                                aa= adrassoc(*ta, ke);
                     55:                                v= copy(tarvalue(ke, *aa));
                     56:                                release(*aa);
                     57:                                *aa= v;
                     58:                                uniql(aa);
                     59:                        }
                     60:                }
                     61:        } else if (Is_tbseloc(l)) {
                     62:                tbseloc *tl= Tbseloc(l);
                     63:                value t, ke;
                     64:                uniquify(tl->R);
                     65:                if (still_ok) { t= *location(tl->R); ke= tl->K; }
                     66:                if (still_ok) {
                     67:                        if (!Is_table(t)) error(MESS(3605, "selection on non-table"));
                     68:                        else if (empty(t)) error(MESS(3606, "selection on empty table"));
                     69:                        else {
                     70:                                check_location(l);
                     71:                                if (still_ok) VOID uniq_assoc(t, ke);
                     72:                        }
                     73:                }
                     74:        } else if (Is_trimloc(l)) { syserr(MESS(3607, "uniquifying trimloc"));
                     75:        } else if (Is_compound(l)) { syserr(MESS(3608, "uniquifying comploc"));
                     76:        } else syserr(MESS(3609, "uniquifying non-location"));
                     77: }
                     78: 
                     79: Visible Procedure check_location(l) loc l; {
                     80:        VOID location(l);
                     81:        /* location may produce an error message */
                     82: }
                     83: 
                     84: Visible value content(l) loc l; {
                     85:        value *ll= location(l);
                     86:        return still_ok ? copy(*ll) : Vnil;
                     87: }
                     88: 
                     89: Visible loc trim_loc(l, v, sign) loc l; value v; char sign; {
                     90:        loc root, res; value text, B, C;
                     91:        if (Is_simploc(l) || Is_tbseloc(l)) {
                     92:                uniquify(l); /* Call tarvalue at proper time */
                     93:                root= l;
                     94:                B= zero; C= zero;
                     95:        } else if (Is_trimloc(l)) {
                     96:                trimloc *rr= Trimloc(l);
                     97:                root= rr->R;
                     98:                B= rr->B; C= rr->C;
                     99:        } else {
                    100:                error(MESS(3610, "trim (@ or |) on target of improper type"));
                    101:                return Lnil;
                    102:        }
                    103:        text= content(root);
                    104:        if (!still_ok);
                    105:        else if (!Is_text(text)) {
                    106:                error(MESS(3611, "in the target t@p or t|p, t does not contain a text"));
                    107:        } else {
                    108:                value s= size(text), w, x, b_plus_c;
                    109:                if (sign == '@') B= sum(B, w=diff(v, one));
                    110:                else {  C= sum(C, w=diff(x= diff(s, B), v)); release(x); }
                    111:                release(w);
                    112:                b_plus_c= sum(B, C);
                    113:                if (still_ok && (compare(B,zero)<0 || compare(C,zero)<0
                    114:                              || compare(b_plus_c,s)>0))
                    115:                        error(MESS(3612, "in the target t@p or t|p, p is out of bounds"));
                    116:                else res= mk_trimloc(root, B, C);
                    117:                if (sign == '@') release(B); 
                    118:                else release(C);
                    119:                release(s); release(b_plus_c);
                    120:        }
                    121:        release(text);
                    122:        if (still_ok) return res; else return Lnil;
                    123: }
                    124: 
                    125: Visible loc tbsel_loc(R, K) loc R; value K; {
                    126:        if (Is_simploc(R) || Is_tbseloc(R)) return mk_tbseloc(R, K);
                    127:        else error(MESS(3613, "selection on target of improper type"));
                    128:        return Lnil;
                    129: }
                    130: 
                    131: Visible loc local_loc(i) basidf i; { return mk_simploc(i, curnv); }
                    132: 
                    133: Visible loc global_loc(i) basidf i; { return mk_simploc(i, prmnv); }
                    134: 
                    135: Hidden Procedure put_trim(v, tl) value v; trimloc *tl; {
                    136:        value rr, nn, head, tail, part;
                    137:        value B= tl->B, C= tl->C, len, len_minus_c, tail_start;
                    138:        rr= *location(tl->R);
                    139:        len= size(rr);
                    140:        len_minus_c= diff(len, C); release(len);
                    141:        tail_start= sum(len_minus_c, one); release(len_minus_c);
                    142:        if (compare(B, zero)<0 || compare(C, zero)<0
                    143:         || compare(B, tail_start)>=0)
                    144:                error(MESS(3614, "trim (@ or |) on text location out of bounds"));
                    145:        else {
                    146:                head= curtail(rr, B); /* rr|B */
                    147:                tail= behead(rr, tail_start); /* rr@(#rr-C+1) */
                    148:                part= concat(head, v); release(head);
                    149:                nn= concat(part, tail); release(part); release(tail);
                    150:                put(nn, tl->R); release(nn);
                    151:        }
                    152:        release(tail_start);
                    153: }
                    154: 
                    155: Visible Procedure put(v, l) value v; loc l; {
                    156:        if (Is_locloc(l)) {
                    157:                e_replace(v, &curnv->tab, l);
                    158:        } else if (Is_simploc(l)) {
                    159:                simploc *sl= Simploc(l);
                    160:                e_replace(v, &(sl->e->tab), sl->i);
                    161:        } else if (Is_trimloc(l)) {
                    162:                if (!Is_text(v)) error(MESS(3615, "putting non-text in trim (@ or |)"));
                    163:                else put_trim(v, Trimloc(l));
                    164:        } else if (Is_compound(l)) {
                    165:                intlet k, len= Nfields(l);
                    166:                if (!Is_compound(v))
                    167:                    error(MESS(3616, "putting non-compound in compound location"));
                    168:                else if (Nfields(v) != Nfields(l))
                    169:                    error(MESS(3617, "putting compound in compound location of different length"));
                    170:                else k_Overfields { put(*Field(v, k), *Field(l, k)); }
                    171:        } else if (Is_tbseloc(l)) {
                    172:                tbseloc *tl= Tbseloc(l); value *rootloc;
                    173:                uniquify(tl->R);
                    174:                if (still_ok) {
                    175:                        rootloc= location(tl->R);
                    176:                        if (still_ok && !Is_table(*rootloc))
                    177:                                error(MESS(3621, "selection on non-table"));
                    178:                        if (still_ok) replace(v, rootloc, tl->K);
                    179:                }
                    180:        } else error(MESS(3618, "putting in non-target"));
                    181: }
                    182: 
                    183: /* Check for correct effect of multiple put-command: catches PUT 1, 2 IN x, x.  
                    184:    The assignment cannot be undone, but this is not considered a problem.
                    185:    For trimmed-texts, no checks are made because the language definition
                    186:    itself causes problem (try PUT "abc", "" IN x@2|1, x@3|1). */
                    187: 
                    188: Hidden bool putck(v, l) value v; loc l; {
                    189:        intlet k, len; value w;
                    190:        if (!still_ok) return No;
                    191:        if (Is_compound(l)) {
                    192:                if (!Is_compound(v) || Nfields(v) != (len= Nfields(l)))
                    193:                        return No; /* Severe type error */
                    194:                k_Overfields
                    195:                        { if (!putck(*Field(v, k), *Field(l, k))) return No; }
                    196:                return Yes;
                    197:        }
                    198:        if (Is_trimloc(l)) return Yes; /* Don't check trim locations */
                    199:        w= *location(l);
                    200:        /* Unfortunately, this may already cause an error, e.g. after
                    201:           PUT 1, {} IN t[1], t.  This can't be helped unless we introduce
                    202:           a flag so that location will shut up. */
                    203:        return still_ok && compare(v, w) == 0;
                    204: }
                    205: 
                    206: /* The check can't be called from within put because put is recursive,
                    207:    and so is the check: then, for the inner levels the check would be done
                    208:    twice.  Moreover, we don't want to clutter up put, which is called
                    209:    internally in, many places. */
                    210: 
                    211: Visible Procedure put_with_check(v, l) value v; loc l; {
                    212:        intlet i, k, len; bool ok;
                    213:        put(v, l);
                    214:        if (!still_ok || !Is_compound(l))
                    215:                return; /* Single target can't be wrong */
                    216:        len= Nfields(l); ok= Yes;
                    217:        /* Quick check for putting in all different local targets: */
                    218:        k_Overfields {
                    219:                if (!IsSmallInt(*Field(l, k))) { ok= No; break; }
                    220:                for (i= k-1; i >= 0; --i) {
                    221:                        if (*Field(l, i) == *Field(l, k)) { ok= No; break; }
                    222:                }
                    223:                if (!ok) break;
                    224:        }
                    225:        if (ok) return; /* All different local basic-targets */
                    226:        if (!putck(v, l))
                    227:                error(MESS(3619, "putting different values in same location"));
                    228: }
                    229: 
                    230: 
                    231: Hidden bool l_exists(l) loc l; {
                    232:        if (Is_simploc(l)) {
                    233:                simploc *sl= Simploc(l);
                    234:                return envassoc(sl->e->tab, sl->i) != Pnil;
                    235:        } else if (Is_trimloc(l)) {
                    236:                error(MESS(3620, "deleting trimmed (@ or |) target"));
                    237:                return No;
                    238:        } else if (Is_compound(l)) {
                    239:                intlet k, len= Nfields(l);
                    240:                k_Overfields { if (!l_exists(*Field(l, k))) return No; }
                    241:                return Yes;
                    242:        } else if (Is_tbseloc(l)) {
                    243:                tbseloc *tl= Tbseloc(l); value *ll;
                    244:                uniquify(tl->R); /* call tarvalue() at proper place */
                    245:                if (still_ok) ll= location(tl->R);
                    246:                if (still_ok && !Is_table(*ll))
                    247:                        error(MESS(3621, "selection on non-table"));
                    248:                return still_ok && in_keys(tl->K, *ll);
                    249:        } else {
                    250:                error(MESS(3622, "deleting non-target"));
                    251:                return No;
                    252:        }
                    253: }
                    254: 
                    255: /* Delete a location if it exists */
                    256: 
                    257: Hidden Procedure l_del(l) loc l; {
                    258:        if (Is_simploc(l)) {
                    259:                simploc *sl= Simploc(l);
                    260:                e_delete(&(sl->e->tab), sl->i);
                    261:        } else if (Is_trimloc(l)) {
                    262:                error(MESS(3623, "deleting trimmed (@ or |) target"));
                    263:        } else if (Is_compound(l)) {
                    264:                intlet k, len= Nfields(l);
                    265:                k_Overfields { l_del(*Field(l, k)); }
                    266:        } else if (Is_tbseloc(l)) {
                    267:                tbseloc *tl= Tbseloc(l);
                    268:                value *lc;
                    269:                uniquify(tl->R);
                    270:                if (still_ok) {
                    271:                        lc= location(tl->R);
                    272:                        if (in_keys(tl->K, *lc)) delete(lc, tl->K);
                    273:                }
                    274:        } else error(MESS(3624, "deleting non-target"));
                    275: }
                    276: 
                    277: Visible Procedure l_delete(l) loc l; {
                    278:        if (l_exists(l)) l_del(l);
                    279:        else if (still_ok) error(MESS(3625, "deleting non-existent target"));
                    280: }
                    281: 
                    282: Visible Procedure l_insert(v, l) value v; loc l; {
                    283:        value *ll;
                    284:        uniquify(l);
                    285:        if (still_ok) {
                    286:                ll= location(l);
                    287:                if (!Is_list(*ll)) error(MESS(3626, "inserting in non-list"));
                    288:                else insert(v, ll);
                    289:        }
                    290: }
                    291: 
                    292: Visible Procedure l_remove(v, l) value v; loc l; {
                    293:        value *ll;
                    294:        uniquify(l);
                    295:        if (still_ok) {
                    296:                ll= location(l);
                    297:                if (!Is_list(*ll)) error(MESS(3627, "removing from non-list"));
                    298:                else if (empty(*ll)) error(MESS(3628, "removing from empty list"));
                    299:                else remove(v, ll);
                    300:        }
                    301: }
                    302: 
                    303: /* Warning: choose is only as good as the accuracy of the random-number */
                    304: /* generator. In particular, for very large values of v, elements will  */
                    305: /* be chosen unfairly. Choose should be rewritten to cope with this     */
                    306: 
                    307: Visible Procedure choose(l, v) loc l; value v; {
                    308:        value w, s, r;
                    309:        if (!Is_tlt(v)) error(MESS(3629, "choosing from non-text, -list or -table"));
                    310:        else if (empty(v)) error(MESS(3630, "choosing from empty text, list or table"));
                    311:        else {
                    312:                /* PUT (floor(random*#v) + 1) th'of v IN l */
                    313:                s= size(v);
                    314:                r= prod(w= random(), s); release(w); release(s);
                    315:                w= floorf(r); release(r);
                    316:                r= sum(w, one); release(w);
                    317:                put(w= th_of(r, v), l); release(w); release(r);
                    318:        }
                    319: }
                    320: 
                    321: Visible Procedure draw(l) loc l; {
                    322:        value r= random();
                    323:        put(r, l);
                    324:        release(r);
                    325: }
                    326: 
                    327: Visible Procedure bind(l) loc l; {
                    328:        if (*bndtgs != Vnil) {
                    329:                if (Is_simploc(l)) {
                    330:                        simploc *ll= Simploc(l);
                    331:                        if (!in(ll->i, *bndtgs)) /* kludge */ /* what for? */
                    332:                                insert(ll->i, bndtgs);
                    333:                } else if (Is_compound(l)) {
                    334:                        intlet k, len= Nfields(l);
                    335:                        k_Overfields { bind(*Field(l, k)); }
                    336:                } else error(MESS(3631, "binding non-identifier"));
                    337:        }
                    338:        l_del(l);
                    339: }
                    340: 
                    341: Visible Procedure unbind(l) loc l; {
                    342:        if (*bndtgs != Vnil) {
                    343:                if (Is_simploc(l)) {
                    344:                        simploc *ll= Simploc(l);
                    345:                        if (in(ll->i, *bndtgs))
                    346:                                remove(ll->i, bndtgs);
                    347:                } else if (Is_compound(l)) {
                    348:                        intlet k, len= Nfields(l);
                    349:                        k_Overfields { unbind(*Field(l, k)); }
                    350:                } else error(MESS(3632, "unbinding non-identifier"));
                    351:        }
                    352:        l_del(l);
                    353: }

unix.superglobalmegacorp.com

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