|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.