Annotation of 43BSDTahoe/new/B/src/bint/b1tex.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
        !             2: 
        !             3: /*
        !             4:  * $Header: b1tex.c,v 1.4 85/08/22 16:52:36 timo Exp $
        !             5:  */
        !             6: 
        !             7: /* B texts */
        !             8: 
        !             9: #include "b.h"
        !            10: #include "b1obj.h"
        !            11: #ifndef INTEGRATION
        !            12: #include "b0con.h"
        !            13: #include "b1mem.h"
        !            14: #include "b1btr.h"
        !            15: #include "b1val.h"
        !            16: #endif
        !            17: #include "b1tlt.h"
        !            18: #include "b3err.h"
        !            19: 
        !            20: #ifndef INTEGRATION
        !            21: 
        !            22: /*
        !            23:  * Operations on texts represented as B-trees.
        !            24:  *
        !            25:  * Comments:
        !            26:  * - The functions with 'i' prepended (ibehead, etc.) do no argument
        !            27:  *   checking at all.  They actually implement the planned behaviour
        !            28:  *   of | and @, where out-of-bounds numerical values are truncated
        !            29:  *   rather than causing errors ("abc"|100 = "abc"@-100 = "abc").
        !            30:  * - The 'size' field of all texts must fit in a C int.  If the result of
        !            31:  *   ^ or ^^ would exceed Maxint in size, a user error is signalled.  If
        !            32:  *   the size of the *input* value(s) of any operation is Bigsize, a syserr
        !            33:  *   is signalled.
        !            34:  * - Argument checking: trims, concat and repeat must check their arguments
        !            35:  *   for user errors.
        !            36:  * - t^^n is implemented with an algorithm similar to the 'square and
        !            37:  *   multiply' algorithm for x**n, using the binary representation of n,
        !            38:  *   but it uses straightforward 'concat' operations.  A more efficient
        !            39:  *   scheme is possible [see IW219], but small code seems more important.
        !            40:  * - Degenerated cases (e.g. t@1, t|0, t^'' or t^^n) are not optimized,
        !            41:  *   but produce the desired result by virtue of the algorithms used.
        !            42:  *   The extra checking does not seem worth the overhead for the
        !            43:  *   non-degenerate cases.
        !            44:  * - The code for PUT v IN t@h|l is still there, but it is not compiled,
        !            45:  *   as the interpreter implements the same strategy directly.
        !            46:  * - 'trim()' is only used by f_uname in "b3fil.c".
        !            47:  * - Code for outputting texts has been added. This is called from wri()
        !            48:  *   to output a text, and has running time O(n), compared to O(n log n)
        !            49:  *   for the old code in wri().
        !            50:  *
        !            51:  * *** WARNING ***
        !            52:  * - The 'zip' routine and its subroutine 'copynptrs' assume that items and
        !            53:  *   pointers are stored contiguously, so that &Ptr(p, i+1) == &Ptr(p, i)+1
        !            54:  *   and &[IB]char(p, i+1) == &[IB]char(p, i)+1.  For pointers, the order
        !            55:  *   might be reversed in the future; then change the macro Incr(pp, n) below
        !            56:  *   to *decrement* the pointer!
        !            57:  * - Mkbtext and bstrval make the same assumption about items (using strncpy
        !            58:  *   to move charaters to/from a bottom node).
        !            59:  */
        !            60: 
        !            61: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !            62: 
        !            63: #define IsInner(p) (Flag(p) == Inner)
        !            64: #define IsBottom(p) (Flag(p) == Bottom)
        !            65: 
        !            66: #define Incr(pp, n) ((pp) += (n))
        !            67: 
        !            68: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !            69: 
        !            70: /* make a B text out of a C char */
        !            71: 
        !            72: Visible value mkchar(c) char c; {
        !            73:        char buf[2];
        !            74:        buf[0] = c;
        !            75:        buf[1] = '\0';
        !            76:        return mk_text(buf);
        !            77: }
        !            78: 
        !            79: Visible char charval(v) value v; {
        !            80:        if (!Character(v))
        !            81:                syserr(MESS(1600, "charval on non-char"));
        !            82:        return Bchar(Root(v), 0);
        !            83: }
        !            84: 
        !            85: Visible bool character(v) value v; {
        !            86:        return Character(v);
        !            87: }
        !            88: 
        !            89: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !            90: 
        !            91: Hidden btreeptr mkbtext(s, len) string s; int len; {
        !            92:        btreeptr p; int chunk, i, n, nbig;
        !            93: 
        !            94:        /*
        !            95:         * Determine level of tree.
        !            96:         * This is done for each inner node anew, to avoid having
        !            97:         * to keep an explicit stack.
        !            98:         * Problem is: make sure that for each node at the same
        !            99:         * level, the computation indeed finds the same level!
        !           100:         * (Don't care about efficiency here; in practice the trees
        !           101:         * built by mk_text rarely need more than two levels.)
        !           102:         */
        !           103:        chunk = 0;
        !           104:        i = Maxbottom; /* Next larger chunk size */
        !           105:        while (len > i) {
        !           106:                chunk = i;
        !           107:                i = (i+1) * Maxinner + Maxinner;
        !           108:        }
        !           109:        n = len / (chunk+1); /* Number of items at this level; n+1 subtrees */
        !           110:        chunk = len / (n+1); /* Use minimal chunk size for subtrees */
        !           111:        p = grabbtreenode(chunk ? Inner : Bottom, Ct);
        !           112:        Size(p) = len;
        !           113:        Lim(p) = n;
        !           114:        if (!chunk)
        !           115:                strncpy(&Bchar(p, 0), s, len);
        !           116:        else {
        !           117:                nbig = len+1 - (n+1)*chunk;
        !           118:                        /* There will be 'nbig' nodes of size 'chunk'. */
        !           119:                        /* The remaining 'n-nbig' will have size 'chunk-1'. */
        !           120:                for (i = 0; i < n; ++i) {
        !           121:                        Ptr(p, i) = mkbtext(s, chunk);
        !           122:                        s += chunk;
        !           123:                        Ichar(p, i) = *s++;
        !           124:                        len -= chunk+1;
        !           125:                        if (--nbig == 0)
        !           126:                                --chunk; /* This was the last 'big' node */
        !           127:                }
        !           128:                Ptr(p, i) = mkbtext(s, len);
        !           129:        }
        !           130:        return p;
        !           131: }
        !           132: 
        !           133: Visible value mk_text(s) string s; {
        !           134:        value v; int len = strlen(s);
        !           135: 
        !           136:        v = grab_tlt(Tex, Ct);
        !           137:        if (len == 0)
        !           138:                Root(v) = Bnil;
        !           139:        else
        !           140:                Root(v) = mkbtext(s, len);
        !           141:        return v;
        !           142: }
        !           143: 
        !           144: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !           145: 
        !           146: Hidden string bstrval(buf, p) string buf; btreeptr p; {
        !           147:        /* Returns *next* available position in buffer */
        !           148:        int i, n = Lim(p);
        !           149:        if (IsInner(p)) {
        !           150:                for (i = 0; i < n; ++i) {
        !           151:                        buf = bstrval(buf, Ptr(p, i));
        !           152:                        *buf++ = Ichar(p, i);
        !           153:                }
        !           154:                return bstrval(buf, Ptr(p, i));
        !           155:        }
        !           156:        strncpy(buf, &Bchar(p, 0), n);
        !           157:        return buf+n;
        !           158: }
        !           159: 
        !           160: Visible string strval(v) value v; {
        !           161:        static char *buffer; int len = Tltsize(v);
        !           162:        if (len == Bigsize) syserr(MESS(1601, "strval on big text"));
        !           163:        if (len == 0) return "";
        !           164:        if (buffer != NULL)
        !           165:                regetmem(&buffer, (unsigned) len+1);
        !           166:        else
        !           167:                buffer = getmem((unsigned) len+1);
        !           168:        *bstrval(buffer, Root(v)) = '\0';
        !           169:        return buffer;
        !           170: }
        !           171: 
        !           172: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !           173: 
        !           174: typedef struct stackelem {
        !           175:        btreeptr s_ptr;
        !           176:        int s_lim;
        !           177: } stackelem;
        !           178: 
        !           179: typedef stackelem stack[Maxheight];
        !           180: typedef stackelem *stackptr;
        !           181: 
        !           182: #define Snil ((stackptr)0)
        !           183: 
        !           184: #define Push(s, p, l) ((s)->s_ptr = (p), ((s)->s_lim = (l)), (s)++)
        !           185: #define Pop(s, p, l) (--(s), (p) = (s)->s_ptr, (l) = (s)->s_lim)
        !           186: 
        !           187: extern stackptr unzip();
        !           188: extern Procedure cpynptrs();
        !           189: extern int movnptrs();
        !           190: 
        !           191: Hidden btreeptr zip(s1, sp1, s2, sp2) stackptr s1, sp1, s2, sp2; {
        !           192:        btreeptr p1, p2, newptr[2]; int l1, l2, i, n, n2;
        !           193: #define q1 newptr[0]
        !           194: #define q2 newptr[1]
        !           195:        char newitem; bool overflow, underflow, inner;
        !           196:        char *cp; btreeptr *pp;
        !           197:        char cbuf[2*Maxbottom]; btreeptr pbuf[2*Maxinner+2];
        !           198: 
        !           199:        while (s1 < sp1 && s1->s_lim == 0)
        !           200:                ++s1;
        !           201:        while (s2 < sp2 && s2->s_lim == Lim(s2->s_ptr))
        !           202:                ++s2;
        !           203:        inner = overflow = underflow = No;
        !           204:        q1 = Bnil;
        !           205:        while (s1 < sp1 || s2 < sp2) {
        !           206:                if (s1 < sp1)
        !           207:                        Pop(sp1, p1, l1);
        !           208:                else
        !           209:                        p1 = Bnil;
        !           210:                if (s2 < sp2)
        !           211:                        Pop(sp2, p2, l2);
        !           212:                else
        !           213:                        p2 = Bnil;
        !           214:                cp = cbuf;
        !           215:                if (p1 != Bnil) {
        !           216:                        strncpy(cp, (inner ? &Ichar(p1, 0) : &Bchar(p1, 0)), l1);
        !           217:                        cp += l1;
        !           218:                }
        !           219:                if (overflow)
        !           220:                        *cp++ = newitem;
        !           221:                n = cp - cbuf;
        !           222:                if (p2 != Bnil) {
        !           223:                        strncpy(cp, (inner ? &Ichar(p2, l2) : &Bchar(p2, l2)), Lim(p2)-l2);
        !           224:                        n += Lim(p2)-l2;
        !           225:                }
        !           226:                if (inner) {
        !           227:                        pp = pbuf; /***** Change if reverse direction! *****/
        !           228:                        if (p1 != Bnil) {
        !           229:                                cpynptrs(pp, &Ptr(p1, 0), l1);
        !           230:                                Incr(pp, l1);
        !           231:                        }
        !           232:                        movnptrs(pp, newptr, 1+overflow);
        !           233:                        Incr(pp, 1+overflow);
        !           234:                        if (p2 != Bnil) {
        !           235:                                cpynptrs(pp, &Ptr(p2, l2+1), Lim(p2)-l2);
        !           236:                                Incr(pp, Lim(p2)-l2);
        !           237:                        }
        !           238:                        if (underflow) {
        !           239:                                underflow= No;
        !           240:                                n= uflow(n, p1 ? l1 : 0, cbuf, pbuf, Ct);
        !           241:                        }
        !           242:                }
        !           243:                overflow = No;
        !           244:                if (n > (inner ? Maxinner : Maxbottom)) {
        !           245:                        overflow = Yes;
        !           246:                        n2 = (n-1)/2;
        !           247:                        n -= n2+1;
        !           248:                }
        !           249:                else if (n < (inner ? Mininner : Minbottom))
        !           250:                        underflow = Yes;
        !           251:                q1 = grabbtreenode(inner ? Inner : Bottom, Ct);
        !           252:                Lim(q1) = n;
        !           253:                cp = cbuf;
        !           254:                strncpy((inner ? &Ichar(q1, 0) : &Bchar(q1, 0)), cp, n);
        !           255:                cp += n;
        !           256:                if (inner) {
        !           257:                        pp = pbuf;
        !           258:                        i = movnptrs(&Ptr(q1, 0), pp, n+1);
        !           259:                        Incr(pp, n+1);
        !           260:                        n += i;
        !           261:                }
        !           262:                Size(q1) = n;
        !           263:                if (overflow) {
        !           264:                        newitem = *cp++;
        !           265:                        q2 = grabbtreenode(inner ? Inner : Bottom, Ct);
        !           266:                        Lim(q2) = n2;
        !           267:                        strncpy((inner ? &Ichar(q2, 0) : &Bchar(q2, 0)), cp, n2);
        !           268:                        if (inner)
        !           269:                                n2 += movnptrs(&Ptr(q2, 0), pp, n2+1);
        !           270:                        Size(q2) = n2;
        !           271:                }
        !           272:                inner = Yes;
        !           273:        }
        !           274:        if (overflow)
        !           275:                q1 = mknewroot(q1, (itemptr)&newitem, q2, Ct);
        !           276:        return q1;
        !           277: #undef q1
        !           278: #undef q2
        !           279: }
        !           280: 
        !           281: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !           282: 
        !           283: Hidden value ibehead(v, h) value v; int h; { /* v@h */
        !           284:        stack s; stackptr sp;
        !           285:        sp = (stackptr) unzip(Root(v), h-1, s);
        !           286:        v = grab_tlt(Tex, Ct);
        !           287:        Root(v) = zip(Snil, Snil, s, sp);
        !           288:        return v;
        !           289: }
        !           290: 
        !           291: Hidden value icurtail(v, t) value v; int t; { /* v|t */
        !           292:        stack s; stackptr sp;
        !           293:        sp = (stackptr) unzip(Root(v), t, s);
        !           294:        v = grab_tlt(Tex, Ct);
        !           295:        Root(v) = zip(s, sp, Snil, Snil);
        !           296:        return v;
        !           297: }
        !           298: 
        !           299: Hidden value iconcat(v, w) value v, w; { /* v^w */
        !           300:        stack s1, s2;
        !           301:        stackptr sp1 = (stackptr) unzip(Root(v), Tltsize(v), s1);
        !           302:        stackptr sp2 = (stackptr) unzip(Root(w), 0, s2);
        !           303:        v = grab_tlt(Tex, Ct);
        !           304:        Root(v) = zip(s1, sp1, s2, sp2);
        !           305:        return v;
        !           306: }
        !           307: 
        !           308: #define Odd(n) (((n)&1) != 0)
        !           309: 
        !           310: Hidden value irepeat(v, n) value v; int n; { /* v^^n */
        !           311:        value x, w = grab_tlt(Tex, Ct);
        !           312:        Root(w) = Bnil;
        !           313:        v = copy(v);
        !           314:        while (n > 0) {
        !           315:                if (Odd(n)) {
        !           316:                        w = iconcat(x = w, v);
        !           317:                        release(x);
        !           318:                }
        !           319:                n /= 2;
        !           320:                if (n == 0)
        !           321:                        break;
        !           322:                v = iconcat(x = v, v);
        !           323:                release(x);
        !           324:        }
        !           325:        release(v);
        !           326:        return w;
        !           327: }
        !           328: 
        !           329: #ifdef UNUSED_CODE
        !           330: Hidden value jrepeat(v, n) value v; int n; { /* v^^n, recursive solution */
        !           331:        value w, x;
        !           332:        if (n <= 1) {
        !           333:                if (n == 1)
        !           334:                        return copy(v);
        !           335:                w = grab_tlt(Tex, Ct);
        !           336:                Root(w) = Bnil;
        !           337:                return w;
        !           338:        }
        !           339:        w = jrepeat(v, n/2);
        !           340:        w = iconcat(x = w, w);
        !           341:        release(x);
        !           342:        if (Odd(n)) {
        !           343:                w = iconcat(x = w, v);
        !           344:                release(x);
        !           345:        }
        !           346:        return w;
        !           347: }
        !           348: #endif UNUSED_CODE
        !           349: 
        !           350: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !           351: 
        !           352: Visible value curtail(t, after) value t, after; {
        !           353:        int syzcurv, syztext;
        !           354: 
        !           355:        if (!Is_text(t)) {
        !           356:                reqerr(MESS(1602, "in t|n, t is not a text"));
        !           357:                return Vnil;
        !           358:        }
        !           359:        if (!Is_number(after)) {
        !           360:                reqerr(MESS(1603, "in t|n, n is not a number"));
        !           361:                return Vnil;
        !           362:        }
        !           363:        syztext = Tltsize(t);
        !           364:        if (syztext == Bigsize)
        !           365:                syserr(MESS(1604, "curtail on very big text"));
        !           366:        if (large(after) || (syzcurv = intval(after)) < 0
        !           367:                || syztext < syzcurv) {
        !           368:                reqerr(MESS(1605, "in t|n, n is out of bounds"));
        !           369:                return Vnil;
        !           370:        }
        !           371:        return icurtail(t, syzcurv);
        !           372: }
        !           373: 
        !           374: Visible value behead(t, before) value t, before; {
        !           375:        int syzbehv, syztext;
        !           376: 
        !           377:        if (!Is_text(t)) {
        !           378:                reqerr(MESS(1606, "in t@n, t is not a text"));
        !           379:                return Vnil;
        !           380:        }
        !           381:        if (!Is_number(before)) {
        !           382:                reqerr(MESS(1607, "in t@n, n is not a number"));
        !           383:                return Vnil;
        !           384:        }
        !           385:        syztext = Tltsize(t);
        !           386:        if (syztext == Bigsize) syserr(MESS(1608, "behead on very big text"));
        !           387:        if (large(before) || (syzbehv = intval(before)) <= 0
        !           388:                || syztext < syzbehv-1) {
        !           389:                reqerr(MESS(1609, "in t@n, n is out of bounds"));
        !           390:                return Vnil;
        !           391:        }
        !           392:        return ibehead(t, syzbehv);
        !           393: }
        !           394: 
        !           395: #ifdef NOT_USED
        !           396: Visible value trim(v, b, c) value v; intlet b, c; { /*temporary*/
        !           397:        /* Only used in f_uname */
        !           398:        int len= Tltsize(v);
        !           399:        value r= ibehead(v, b+1), s;
        !           400:        s= icurtail(r, len-b-c); release(r);
        !           401:        return s;
        !           402: }
        !           403: #endif
        !           404: 
        !           405: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !           406: 
        !           407: Visible value concat(tleft, tright) value tleft, tright; {
        !           408:        int syzleft, syzright;
        !           409:        if (!Is_text(tleft) || !Is_text(tright)) {
        !           410:                reqerr(MESS(1610, "in t^u, t or u is not a text"));
        !           411:                return Vnil;
        !           412:        }
        !           413:        syzleft = Tltsize(tleft);
        !           414:        syzright =  Tltsize(tright);
        !           415:        if (syzleft == Bigsize || syzright == Bigsize)
        !           416:                syserr(MESS(1611, "concat on very big text"));
        !           417:        if (syzleft > Maxint-syzright
        !           418:                || syzright > Maxint-syzleft) {
        !           419:                reqerr(MESS(1612, "in t^u, the result is too long"));
        !           420:                return Vnil;
        !           421:        }
        !           422:        return iconcat(tleft, tright);
        !           423: }
        !           424: 
        !           425: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !           426: 
        !           427: Visible value repeat(t, n) value t, n; {
        !           428:        int tsize, k;
        !           429: 
        !           430:        if (!Is_text(t)) {
        !           431:                reqerr(MESS(1613, "in t^^n, t is not a text"));
        !           432:                return Vnil;
        !           433:        }
        !           434:        if (!Is_number(n)) {
        !           435:                reqerr(MESS(1614, "in t^^n, n is not a number"));
        !           436:                return Vnil;
        !           437:        }
        !           438:        if (numcomp(n, zero) < 0) {
        !           439:                reqerr(MESS(1615, "in t^^n, n is negative"));
        !           440:                return Vnil;
        !           441:        }
        !           442:        tsize = Tltsize(t);
        !           443:        if (tsize == 0) return copy(t);
        !           444: 
        !           445:        if (large(n) || Maxint/tsize < (k = intval(n))) {
        !           446:                reqerr(MESS(1616, "in t^^n, the result is too long"));
        !           447:                return Vnil;
        !           448:        }
        !           449:        return irepeat(t, k);
        !           450: }
        !           451: 
        !           452: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
        !           453: 
        !           454: Visible Procedure wrtext(putch, v, quote) int (*putch)(); value v; char quote; {
        !           455:        if (v == Vnil || !Is_text(v)) {
        !           456:                (*putch)('?');
        !           457:                return;
        !           458:        }
        !           459:        if (quote) (*putch)(quote);
        !           460:        if (Root(v) != Bnil) wrbtext(putch, Root(v), quote);
        !           461:        if (quote) (*putch)(quote);
        !           462: }
        !           463: 
        !           464: Hidden Procedure wrbtext(putch, p, quote)
        !           465:  int (*putch)(); btreeptr p; char quote; {
        !           466:        int i, n = Lim(p); char c;
        !           467:        if (IsInner(p)) {
        !           468:                for (i = 0; still_ok && i < n; ++i) {
        !           469:                        wrbtext(putch, Ptr(p, i), quote);
        !           470:                        c = Ichar(p, i);
        !           471:                        (*putch)(c);
        !           472:                        if (quote && (c == quote || c == '`')) (*putch)(c);
        !           473:                }
        !           474:                wrbtext(putch, Ptr(p, i), quote);
        !           475:        }
        !           476:        else if (quote) {
        !           477:                for (i = 0; i < n; ++i) {
        !           478:                        c = Bchar(p, i);
        !           479:                        (*putch)(c);
        !           480:                        if (c == quote || c == '`') (*putch)(c);
        !           481:                }
        !           482:        }
        !           483:        else {
        !           484:                for (i = 0; i < n; ++i) (*putch)(Bchar(p, i));
        !           485:        }
        !           486: }
        !           487: 
        !           488: #else INTEGRATION
        !           489: 
        !           490: Visible value mk_text(m) string m; {
        !           491:        value v; intlet len= strlen(m);
        !           492:        v= grab_tex(len);
        !           493:        strcpy(Str(v), m);
        !           494:        return v;
        !           495: }
        !           496: 
        !           497: Visible bool character(v) value v; {
        !           498:        if (Is_text(v) && Length(v) == 1) return Yes;
        !           499:        else return No;
        !           500: }
        !           501: 
        !           502: Visible char charval(v) value v; {
        !           503:        if (!Is_text(v) || Length(v) != 1) error(MESS(1617, "value not a character"));
        !           504:        return *Str(v);
        !           505: }
        !           506: 
        !           507: Visible string strval(v) value v; {
        !           508:        return Str(v);
        !           509: }
        !           510: 
        !           511: Visible value concat(s, t) value s, t; {
        !           512:        if (Type(s) != Tex)
        !           513:                error(MESS(1618, "in t^u, t is not a text"));
        !           514:        else if (Type(t) != Tex)
        !           515:                error(MESS(1619, "in t^u, t is a text, but u is not"));
        !           516:        else {
        !           517:                value c= grab_tex(Length(s)+Length(t));
        !           518:                strcpy(Str(c), Str(s)); strcpy(Str(c)+Length(s), Str(t));
        !           519:                return c;
        !           520:        }
        !           521:        return grab_tex(0);
        !           522: }
        !           523: 
        !           524: #define VERSION2
        !           525: 
        !           526: Visible Procedure concato(s, t) value *s; string t; {
        !           527:        if (Type(*s) != Tex)
        !           528:                error(MESS(1620, "attempt to join text with non-text"));
        !           529:        else {
        !           530: #ifdef VERSION1
        !           531:                xtndtex(s, strlen(t));
        !           532:                strcat(Str(*s), t);
        !           533: #endif
        !           534: #ifdef VERSION2
        !           535:                value v= mk_text(t);
        !           536:                value w= concat(*s, v);
        !           537:                release(*s); release(v);
        !           538:                *s= w;
        !           539: #endif
        !           540:        }
        !           541: }
        !           542: 
        !           543: Visible value trim(v, B, C) value v; intlet B, C; {
        !           544:        intlet len= Length(v), k;
        !           545:        if (Type(v) != Tex)
        !           546:                error(MESS(1621, "trim (@ or |) applied to non-text"));
        !           547:        else if (B < 0 || C < 0 || B+C > len)
        !           548:                error(MESS(1622, "trim (@ or |) out of bounds"));
        !           549:        else {
        !           550:                value w= grab_tex(len-=(B+C));
        !           551:                string vp= Str(v)+B, wp= Str(w);
        !           552:                Overall *wp++= *vp++; *wp= '\0';
        !           553:                return w;
        !           554:        }
        !           555:        return grab_tex(0);
        !           556: }
        !           557: 
        !           558: Visible Procedure
        !           559: putintrim(pn, head, tail, str)
        !           560:        value *pn;
        !           561:        intlet head, tail;
        !           562:        string str;
        !           563: {
        !           564:        value v = *pn;
        !           565:        intlet len= Length(v);
        !           566: 
        !           567:        if (Type(v) != Tex)
        !           568:                error(MESS(1623, "putintrim (@ or |) applied to non-text"));
        !           569:        else if (head < 0 || tail < 0 || head+tail > len)
        !           570:                error(MESS(1624, "putintrim (@ or |) out of bounds"));
        !           571:        else {
        !           572:                value w = head == 0 ? mk_text("") :
        !           573:                        head == len ? copy(v) : trim(v, 0, len - head);
        !           574:                if (*str)
        !           575:                        concato(&w, str);
        !           576:                if (tail > 0)
        !           577:                        concato(&w, Str(v)+(len - tail));
        !           578:                release(v);
        !           579:                *pn = w;
        !           580:        }
        !           581: }
        !           582: 
        !           583: Visible value curtail(v, n) value v, n; {
        !           584:        intlet c= intval(n);
        !           585:        v= trim(v, 0, Length(v) - c);
        !           586:        return v;
        !           587: }
        !           588: 
        !           589: Visible value behead(v, n) value v, n; {
        !           590:        intlet b= intval(n);
        !           591:        v= trim(v, b-1, 0);
        !           592:        return v;
        !           593: }
        !           594: 
        !           595: Visible value repeat(x, y) value x, y; {
        !           596:        intlet i= propintlet(intval(y));
        !           597:        if (Type(x) != Tex)
        !           598:                error(MESS(1625, "in t^^n, t is not a text"));
        !           599:        if (i < 0)
        !           600:                error(MESS(1626, "in t^^n, n is negative"));
        !           601:        else {
        !           602:                value r; string xp, rp; intlet p, q, xl= Length(x);
        !           603:                r= grab_tex(propintlet(i*xl));
        !           604:                rp= Str(r);
        !           605:                for (p= 0; p < i; p++) {
        !           606:                        xp= Str(x);
        !           607:                        for (q= 0; q < xl; q++) *rp++= *xp++;
        !           608:                }
        !           609:                *rp= '\0';
        !           610:                return r;
        !           611:        }
        !           612:        return grab_tex(0);
        !           613: }
        !           614: 
        !           615: #define Left 'L'
        !           616: #define Right 'R'
        !           617: #define Centre 'C'
        !           618: 
        !           619: Hidden value adj(x, y, side) value x, y; literal side; {
        !           620:        value r, v= convert(x, Yes, Yes); int i= intval(y);
        !           621:        intlet lv= Length(v), la, k, ls, rs;
        !           622:        string rp, vp;
        !           623:        la= propintlet(i) - lv;
        !           624:        if (la <= 0) return v;
        !           625:        r= grab_tex(lv+la); rp= Str(r); vp= Str(v);
        !           626: 
        !           627:        if (side == Left) { ls= 0; rs= la; }
        !           628:        else if (side == Centre) { ls= la/2; rs= (la+1)/2; }
        !           629:        else { ls= la; rs= 0; }
        !           630: 
        !           631:        for (k= 0; k < ls; k++) *rp++= ' ';
        !           632:        for (k= 0; k < lv; k++) *rp++= *vp++;
        !           633:        for (k= 0; k < rs; k++) *rp++= ' ';
        !           634:        *rp= 0;
        !           635:        release(v);
        !           636:        return r;
        !           637: }
        !           638: 
        !           639: Visible value adjleft(x, y) value x, y; {
        !           640:        return adj(x, y, Left);
        !           641: }
        !           642: 
        !           643: Visible value centre(x, y) value x, y; {
        !           644:        return adj(x, y, Centre);
        !           645: }
        !           646: 
        !           647: Visible value adjright(x, y) value x, y; {
        !           648:        return adj(x, y, Right);
        !           649: }
        !           650: 
        !           651: /* For reasons of efficiency, wri does not always call convert but writes
        !           652:    directly on the standard output. Modifications in convert should
        !           653:    be mirrored by changes in wri and vice versa. */
        !           654: 
        !           655: Visible value convert(v, coll, outer) value v; bool coll, outer; {
        !           656:        literal type= Type(v); intlet len= Length(v), k; value *vp= Ats(v);
        !           657:        value t, cv;
        !           658:        switch (type) {
        !           659:        case Num:
        !           660:                return mk_text(convnum(v));
        !           661:        case Tex:
        !           662:                if (outer) return copy(v);
        !           663:                else {string tp= (string) vp; char cs[2];
        !           664:                        cs[1]= '\0';
        !           665:                        t= mk_text("'");
        !           666:                        Overall {
        !           667:                                cs[0]= *tp++;
        !           668:                                concato(&t, cs);
        !           669:                                if (cs[0] == '\'' || cs[0] == '`')
        !           670:                                        concato(&t, cs);
        !           671:                        }
        !           672:                        concato(&t, "'");
        !           673:                        return t;
        !           674:                }
        !           675:        case Com:
        !           676:                outer&= coll;
        !           677:                t= mk_text(coll ? "" : "(");
        !           678:                Overall {
        !           679:                        concato(&t, Str(cv= convert(*vp++, No, outer)));
        !           680:                        release(cv);
        !           681:                        if (k != len-1) concato(&t, outer ? " " : ", ");
        !           682:                }
        !           683:                if (!coll) concato(&t, ")");
        !           684:                return t;
        !           685:        case Lis: case ELT:
        !           686:                t= mk_text("{");
        !           687:                Overall {
        !           688:                        concato(&t, Str(cv= convert(*vp++, No, No)));
        !           689:                        release(cv);
        !           690:                        if (k != len-1) concato(&t, "; ");
        !           691:                }
        !           692:                concato(&t, "}");
        !           693:                return t;
        !           694:        case Tab:
        !           695:                t= mk_text("{");
        !           696:                Overall {
        !           697:                        concato(&t, "[");
        !           698:                        concato(&t, Str(cv= convert(Cts(*vp), Yes, No)));
        !           699:                        release(cv);
        !           700:                        concato(&t, "]: ");
        !           701:                        concato(&t, Str(cv= convert(Dts(*vp++), No, No)));
        !           702:                        release(cv);
        !           703:                        if (k != len-1) concato(&t, "; ");
        !           704:                }
        !           705:                concato(&t, "}");
        !           706:                return t;
        !           707:        default:
        !           708:                syserr(MESS(1627, "converting value of unknown type"));
        !           709:                return (value) Dummy;
        !           710:        }
        !           711: }
        !           712: 
        !           713: #endif INTEGRATION

unix.superglobalmegacorp.com

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