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

Defined functions

adj defined in line 619; used 3 times
adjleft defined in line 639; never used
adjright defined in line 647; never used
bstrval defined in line 146; used 3 times
centre defined in line 643; never used
concato defined in line 526; used 17 times
convert defined in line 655; used 5 times
ibehead defined in line 283; used 2 times
iconcat defined in line 299; used 5 times
icurtail defined in line 291; used 2 times
irepeat defined in line 310; used 1 times
jrepeat defined in line 330; used 1 times
mkbtext defined in line 91; used 3 times
putintrim defined in line 558; never used
trim defined in line 543; used 4 times
wrbtext defined in line 464; used 3 times
wrtext defined in line 454; used 1 times
zip defined in line 191; used 3 times

Defined struct's

stackelem defined in line 174; never used

Defined typedef's

stack defined in line 179; used 3 times
stackelem defined in line 177; used 2 times
stackptr defined in line 180; used 11 times

Defined macros

Centre defined in line 617; used 2 times
Incr defined in line 66; used 4 times
IsBottom defined in line 64; never used
IsInner defined in line 63; used 2 times
Left defined in line 615; used 2 times
Odd defined in line 308; used 2 times
Pop defined in line 185; used 2 times
Push defined in line 184; never used
Right defined in line 616; used 1 times
Snil defined in line 182; used 4 times
VERSION2 defined in line 524; used 1 times
q1 defined in line 193; used 11 times
q2 defined in line 194; used 8 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4436
Valid CSS Valid XHTML 1.0 Strict