|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ ! 2: static char rcsid[] = "$Header: que2.c,v 2.3 84/07/23 13:02:38 guido Exp $"; ! 3: ! 4: /* ! 5: * B editor -- Manipulate queues of nodes, higher levels. ! 6: */ ! 7: ! 8: #include <ctype.h> ! 9: ! 10: #include "b.h" ! 11: #include "feat.h" ! 12: #include "bobj.h" ! 13: #include "node.h" ! 14: #include "supr.h" ! 15: #include "queu.h" ! 16: #include "gram.h" ! 17: #include "tabl.h" ! 18: ! 19: ! 20: extern bool lefttorite; ! 21: /* Set by edit() to signal we parse purely left-to-right */ ! 22: extern bool dflag; /* Debug mode even if NDEBUG on */ ! 23: ! 24: ! 25: /* ! 26: * Insert a queue of nodes at the focus ! 27: * (which had better be some kind of a hole). ! 28: * The nodes may also be a text, in which case the individual characters ! 29: * are inserted. ! 30: * Extensive changes to the parse tree may occur, and the node may be ! 31: * broken up in its constituent parts (texts and other nodes) which ! 32: * are then inserted individually. ! 33: */ ! 34: ! 35: Visible bool ! 36: ins_queue(ep, pq, pq2) ! 37: register environ *ep; ! 38: register queue *pq; ! 39: register queue *pq2; ! 40: { ! 41: register bool ok = Yes; ! 42: register node n; ! 43: register queue oldq2; ! 44: environ saveenv; ! 45: int oldindentation = focindent(ep); ! 46: int indentation = oldindentation; ! 47: ! 48: leftvhole(ep); ! 49: while (ok && !emptyqueue(*pq)) { ! 50: n = queuebehead(pq); ! 51: if (Type(n) == Tex) { ! 52: ok = ins_string(ep, Str((value) n), pq2, 0); ! 53: switch (Str((value) n)[Length((value) n) - 1]) { /* Last char */ ! 54: case '\t': ! 55: ++indentation; ! 56: break; ! 57: case '\b': ! 58: --indentation; ! 59: break; ! 60: case '\n': ! 61: while (focindent(ep) > indentation) { ! 62: if (!ins_newline(ep)) ! 63: break; ! 64: } ! 65: break; ! 66: } ! 67: } ! 68: else { ! 69: Ecopy(*ep, saveenv); ! 70: oldq2 = qcopy(*pq2); ! 71: if (!ins_node(&saveenv, n, pq2)) { ! 72: Erelease(saveenv); ! 73: qrelease(*pq2); ! 74: *pq2 = oldq2; ! 75: if (symbol(n) == Hole) ! 76: ok = ins_string(ep, "?", pq2, 0); ! 77: else ! 78: splitnode(n, pq); ! 79: } ! 80: else { ! 81: Erelease(*ep); ! 82: Emove(saveenv, *ep); ! 83: qrelease(oldq2); ! 84: } ! 85: } ! 86: noderelease(n); ! 87: } ! 88: if (!ok) ! 89: qshow(*pq, "ins_queue"); ! 90: qrelease(*pq); ! 91: for (indentation = focindent(ep); ! 92: indentation > oldindentation; --indentation) ! 93: stringtoqueue("\b", pq2); /* Pass on indentation to outer level */ ! 94: return ok; ! 95: } ! 96: ! 97: ! 98: /* ! 99: * Subroutine to insert a queue to the right of the focus ! 100: * without affecting the focus position. ! 101: */ ! 102: ! 103: Visible bool ! 104: app_queue(ep, pq) ! 105: environ *ep; ! 106: queue *pq; ! 107: { ! 108: int where; ! 109: static int markbit = 1; /* To properly handle recursive calls */ ! 110: ! 111: if (emptyqueue(*pq)) ! 112: return Yes; ! 113: where = focoffset(ep); ! 114: markbit <<= 1; ! 115: markpath(&ep->focus, markbit); ! 116: if (!ins_queue(ep, pq, pq)) { ! 117: markbit >>= 1; ! 118: return No; ! 119: } ! 120: firstmarked(&ep->focus, markbit) || Abort(); ! 121: unmkpath(&ep->focus, markbit); ! 122: markbit >>= 1; ! 123: ep->spflag = No; ! 124: fixfocus(ep, where); ! 125: return Yes; ! 126: } ! 127: ! 128: ! 129: /* ! 130: * Advance to next thing after current position. ! 131: */ ! 132: ! 133: Visible bool ! 134: move_on(ep) ! 135: register environ *ep; ! 136: { ! 137: register node n; ! 138: register string *rp; ! 139: register int sym; ! 140: register int ich = ichild(ep->focus); ! 141: ! 142: if (!up(&ep->focus)) ! 143: return No; ! 144: higher(ep); ! 145: n = tree(ep->focus); ! 146: rp = noderepr(n); ! 147: if (Fw_positive(rp[ich])) { ! 148: ep->mode = FHOLE; ! 149: ep->s1 = 2*ich + 1; ! 150: ep->s2 = 0; ! 151: if (ep->spflag) { ! 152: ep->spflag = No; ! 153: if (rp[ich][0] == ' ') { ! 154: ++ep->s2; ! 155: if (fwidth(rp[ich]) > 1) ! 156: return Yes; ! 157: } ! 158: else ! 159: return Yes; ! 160: } ! 161: else ! 162: return Yes; ! 163: } ! 164: if (ich < nchildren(n)) { ! 165: s_downi(ep, ich+1); ! 166: sym = symbol(tree(ep->focus)); ! 167: if (sym == Hole || sym == Optional) ! 168: ep->mode = WHOLE; ! 169: else ! 170: ep->mode = ATBEGIN; ! 171: return Yes; ! 172: } ! 173: ep->mode = ATEND; ! 174: return Yes; ! 175: } ! 176: ! 177: ! 178: /* ! 179: * Like move_on but moves through fixed texts, skipping only spaces ! 180: * and empty strings. ! 181: * <<<<< This code is a dinosaur and should be revised. >>>>> ! 182: */ ! 183: ! 184: Visible bool ! 185: fix_move(ep) ! 186: register environ *ep; ! 187: { ! 188: register int ich; ! 189: register int i; ! 190: register string *rp; ! 191: register string cp; ! 192: ! 193: Assert(ep->mode == FHOLE); ! 194: ! 195: ich = ep->s1/2; ! 196: rp = noderepr(tree(ep->focus)); ! 197: cp = rp[ich]; ! 198: if (cp) { ! 199: i = ep->s2; ! 200: Assert(i <= Fwidth(cp)); ! 201: if (cp[i] == ' ') { ! 202: do { ! 203: ++i; ! 204: } while (cp[i] == ' '); ! 205: } ! 206: if (cp[i] == '\b' || cp[i] == '\t') { ! 207: ++i; ! 208: Assert(!cp[i]); ! 209: } ! 210: else if (cp[i]) { ! 211: if (i == ep->s2) ! 212: return No; ! 213: ep->s2 = i; ! 214: return Yes; ! 215: } ! 216: } ! 217: ! 218: if (ich >= nchildren(tree(ep->focus))) ! 219: ep->mode = ATEND; ! 220: else { ! 221: s_downi(ep, ich+1); ! 222: if (symbol(tree(ep->focus)) == Hole ! 223: || symbol(tree(ep->focus)) == Optional) ! 224: ep->mode = WHOLE; ! 225: else ! 226: ep->mode = ATBEGIN; ! 227: } ! 228: return Yes; ! 229: } ! 230: ! 231: ! 232: /* ! 233: * Insert a node in the parse tree. ! 234: */ ! 235: ! 236: Hidden bool ! 237: ins_node(ep, n, pq) ! 238: register environ *ep; ! 239: register node n; ! 240: register queue *pq; ! 241: { ! 242: register int sym; ! 243: register node nn; ! 244: register markbits x; ! 245: string *rp; ! 246: ! 247: if (symbol(n) == Optional) ! 248: return Yes; ! 249: ! 250: for (;;) { ! 251: switch (ep->mode) { ! 252: ! 253: case FHOLE: ! 254: if (ep->s2 < lenitem(ep) || !fix_move(ep)) ! 255: return No; ! 256: continue; ! 257: ! 258: case VHOLE: ! 259: if (ep->s2 < lenitem(ep) || !move_on(ep)) ! 260: return No; ! 261: continue; ! 262: ! 263: case ATBEGIN: ! 264: sym = symbol(tree(ep->focus)); ! 265: if (sym == Optional || sym == Hole) { ! 266: ep->mode = WHOLE; ! 267: continue; ! 268: } ! 269: x = marks(tree(ep->focus)); ! 270: if (joinnodes(&ep->focus, n, tree(ep->focus), No)) { ! 271: if (x) { ! 272: s_downi(ep, 2); ! 273: markpath(&ep->focus, x); ! 274: s_up(ep); ! 275: } ! 276: s_down(ep); ! 277: ep->mode = ATEND; ! 278: leftvhole(ep); ! 279: return Yes; ! 280: } ! 281: nn = tree(ep->focus); ! 282: rp = noderepr(nn); ! 283: if (nchildren(nn) >= 1 && Fw_zero(rp[0])) { ! 284: sym = symbol(firstchild(nn)); ! 285: if (sym == Hole || sym == Optional) { ! 286: s_down(ep); ! 287: if (fitnode(&ep->focus, n)) { ! 288: ep->mode = ATEND; ! 289: leftvhole(ep); ! 290: return Yes; ! 291: } ! 292: s_up(ep); ! 293: } ! 294: } ! 295: nn = nodecopy(nn); ! 296: if (!fitnode(&ep->focus, n)) { ! 297: addtoqueue(pq, nn); ! 298: noderelease(nn); ! 299: delfocus(&ep->focus); ! 300: ep->mode = WHOLE; ! 301: continue; ! 302: } ! 303: if (downrite(&ep->focus)) { ! 304: if (Type(tree(ep->focus)) != Tex) { ! 305: sym = symbol(tree(ep->focus)); ! 306: if (sym == Hole || sym == Optional) { ! 307: if (fitnode(&ep->focus, nn)) { ! 308: noderelease(nn); ! 309: nn = Nnil; ! 310: } ! 311: } ! 312: } ! 313: else ! 314: up(&ep->focus); ! 315: } ! 316: if (nn) { ! 317: addtoqueue(pq, nn); ! 318: noderelease(nn); ! 319: } ! 320: ep->mode = ATEND; ! 321: leftvhole(ep); ! 322: return Yes; ! 323: ! 324: case WHOLE: ! 325: sym = symbol(tree(ep->focus)); ! 326: Assert(sym == Optional || sym == Hole); ! 327: do { ! 328: higher(ep); /* Only for second time around */ ! 329: if (fitnode(&ep->focus, n)) { ! 330: ep->mode = ATEND; ! 331: leftvhole(ep); ! 332: return Yes; ! 333: } ! 334: } while (resttoqueue(&ep->focus, pq)); ! 335: ep->mode = ATEND; ! 336: /* Fall through */ ! 337: case ATEND: ! 338: do { ! 339: higher(ep); /* Only for second time around */ ! 340: if (joinnodes(&ep->focus, tree(ep->focus), n, ep->spflag)) { ! 341: ep->spflag = No; ! 342: leftvhole(ep); ! 343: return Yes; ! 344: } ! 345: } while (resttoqueue(&ep->focus, pq) ! 346: || move_on(ep) && ep->mode == ATEND); ! 347: return No; ! 348: ! 349: default: ! 350: return No; ! 351: ! 352: } ! 353: } ! 354: } ! 355: ! 356: ! 357: /* ! 358: * Insert a string in the parse tree. ! 359: */ ! 360: ! 361: #define NEXT (++str, alt_c = 0) ! 362: ! 363: Visible bool ! 364: ins_string(ep, str, pq, alt_c) ! 365: register environ *ep; ! 366: /*auto*/ string str; ! 367: register queue *pq; ! 368: int alt_c; ! 369: { ! 370: register node nn; ! 371: auto value v; ! 372: char buf[1024]; ! 373: register string repr; ! 374: string oldstr; ! 375: register int sym; ! 376: register int len; ! 377: bool interactive = alt_c != 0; ! 378: ! 379: if (alt_c < 0) ! 380: alt_c = 0; ! 381: while (*str) { ! 382: switch (*str) { ! 383: ! 384: case '\n': ! 385: if (!ins_newline(ep)) ! 386: return No; ! 387: /* Fall through */ ! 388: case '\t': ! 389: case '\b': ! 390: NEXT; ! 391: continue; ! 392: ! 393: } ! 394: switch (ep->mode) { ! 395: ! 396: case ATBEGIN: ! 397: nn = tree(ep->focus); ! 398: if (Type(nn) == Tex) { ! 399: ep->s1 = 2*ichild(ep->focus); ! 400: ep->s2 = 0; ! 401: ep->mode = VHOLE; ! 402: s_up(ep); ! 403: continue; ! 404: } ! 405: sym = symbol(nn); ! 406: if (sym != Optional && sym != Hole) { ! 407: if (fwidth(noderepr(nn)[0]) == 0) { ! 408: if (down(&ep->focus)) ! 409: break; ! 410: } ! 411: addtoqueue(pq, nn); ! 412: delfocus(&ep->focus); ! 413: } ! 414: ep->mode = WHOLE; ! 415: /* Fall through */ ! 416: case WHOLE: ! 417: nn = tree(ep->focus); ! 418: sym = symbol(nn); ! 419: Assert(sym == Hole || sym == Optional); ! 420: while ((len = fitstring(&ep->focus, str, alt_c)) == 0) { ! 421: if (sym == Optional) { ! 422: if (!move_on(ep)) { ! 423: if (*str == ' ') ! 424: NEXT; ! 425: else ! 426: return No; ! 427: } ! 428: break; ! 429: } ! 430: if (!interactive && *str == '?') { ! 431: NEXT; ! 432: ep->mode = ATEND; ! 433: break; ! 434: } ! 435: if (resttoqueue(&ep->focus, pq)) ! 436: higher(ep); ! 437: else if (spacefix(ep)) ! 438: break; ! 439: else if (*str == ' ') { ! 440: NEXT; ! 441: break; ! 442: } ! 443: else if (interactive) ! 444: return No; ! 445: else { ! 446: ep->mode = ATEND; ! 447: break; ! 448: } ! 449: } ! 450: if (len > 0) { ! 451: str += len; ! 452: alt_c = 0; ! 453: fixfocus(ep, len); ! 454: } ! 455: break; ! 456: ! 457: case ATEND: ! 458: if (add_string(ep, &str, alt_c)) { ! 459: alt_c = 0; ! 460: break; ! 461: } ! 462: len = joinstring(&ep->focus, str, ep->spflag, ! 463: alt_c ? alt_c : interactive ? -1 : 0, Yes); ! 464: if (len > 0) { ! 465: s_downi(ep, 2); ! 466: ep->spflag = No; ! 467: fixfocus(ep, len); ! 468: } ! 469: else { ! 470: if (resttoqueue(&ep->focus, pq)) { ! 471: higher(ep); ! 472: break; ! 473: } ! 474: if (move_on(ep)) ! 475: break; ! 476: if (*str == ' ') { ! 477: NEXT; ! 478: break; ! 479: } ! 480: return No; ! 481: } ! 482: str += len; ! 483: alt_c = 0; ! 484: break; ! 485: ! 486: case FHOLE: ! 487: nn = tree(ep->focus); ! 488: repr = noderepr(nn)[ep->s1/2]; ! 489: if (ep->s2 >= fwidth(repr) ! 490: && (ep->s2 <= 0 || ep->spflag || !isalpha(repr[0]) ! 491: || repr[ep->s2-1] == ' ')) { /* At end */ ! 492: if (ep->s1/2 < nchildren(nn)) { ! 493: s_downi(ep, ep->s1/2 + 1); ! 494: ep->mode = ATBEGIN; /* Of next child */ ! 495: } ! 496: else ! 497: ep->mode = ATEND; ! 498: break; ! 499: } ! 500: if ((*str == ':' || *str == ' ') && *str == repr[ep->s2]) { ! 501: /***** ! 502: * Quick hack for insertion of test-suites and refinements: ! 503: *****/ ! 504: ++ep->s2; ! 505: NEXT; ! 506: continue; ! 507: } ! 508: if (!lefttorite) ! 509: nosuggtoqueue(ep, pq); ! 510: oldstr = str; ! 511: if (resuggest(ep, &str, alt_c) || soften(ep, &str, alt_c)) { ! 512: if (str > oldstr) ! 513: alt_c = 0; ! 514: continue; ! 515: } ! 516: if (fix_move(ep)) ! 517: continue; ! 518: return No; ! 519: ! 520: case VHOLE: ! 521: Assert(!(ep->s1&1)); ! 522: nn = tree(ep->focus); ! 523: #ifdef USERSUGG ! 524: if (symbol(nn) == Suggestion) { ! 525: if (newsugg(ep, &str, alt_c)) ! 526: alt_c = 0; ! 527: else ! 528: killsugg(ep); ! 529: continue; ! 530: } ! 531: #endif USERSUGG ! 532: s_downi(ep, ep->s1/2); ! 533: v = copy((value) tree(ep->focus)); ! 534: len = 0; ! 535: if (!ep->spflag) { ! 536: for (; len < sizeof buf - 1 && str[len] ! 537: && mayinsert(nn, ep->s1/2, !!(ep->s2 + len), ! 538: str[len]); ! 539: ++len) { ! 540: buf[len] = str[len]; ! 541: } ! 542: if (len <= 0 && alt_c ! 543: && mayinsert(nn, ep->s1/2, !!(ep->s2 + len), alt_c)) { ! 544: buf[0] = alt_c; ! 545: len = 1; ! 546: } ! 547: } ! 548: if (len > 0) { /* Effectuate change */ ! 549: str += len; ! 550: alt_c = 0; ! 551: Assert(Type(v) == Tex); ! 552: buf[len] = 0; ! 553: putintrim(&v, ep->s2, Length(v) - ep->s2, buf); ! 554: replace(&ep->focus, (node) v); ! 555: s_up(ep); ! 556: ep->spflag = No; ! 557: ep->s2 += len; ! 558: } ! 559: else { /* Nothing inserted */ ! 560: if (ep->s2 == 0) { /* Whole string rejected */ ! 561: addtoqueue(pq, (node)v); ! 562: release(v); ! 563: s_up(ep); ! 564: delfocus(&ep->focus); ! 565: ep->mode = WHOLE; ! 566: break; ! 567: } ! 568: if (ep->s2 < Length(v)) { ! 569: addstringtoqueue(pq, Str(v) + ep->s2); ! 570: putintrim(&v, ep->s2, 0, ""); ! 571: replace(&ep->focus, (node) v); ! 572: } ! 573: else ! 574: release(v); ! 575: move_on(ep) || Abort(); /* ==> up, cancelling s_downi! */ ! 576: } ! 577: break; ! 578: ! 579: default: ! 580: Abort(); ! 581: ! 582: } ! 583: } ! 584: ! 585: return Yes; ! 586: } ! 587: ! 588: ! 589: /* ! 590: * See if two nodes can be joined in a hole. ! 591: * 'Spflag' indicates whether a space must be present between the nodes ! 592: * (required or forbidden). ! 593: * Either of n1, n2 may actually be the current contents of the hole. ! 594: */ ! 595: ! 596: Hidden bool ! 597: joinnodes(pp, n1, n2, spflag) ! 598: path *pp; ! 599: node n1; ! 600: node n2; ! 601: bool spflag; ! 602: { ! 603: path pa = parent(*pp); ! 604: int sympa = pa ? symbol(tree(pa)) : Rootsymbol; ! 605: struct table *tp = &table[sympa]; ! 606: struct classinfo *ci = tp->r_class[ichild(*pp) - 1]; ! 607: classptr cp = ci->c_join; ! 608: int sym1 = symbol(n1); ! 609: int sym2 = symbol(n2); ! 610: int symcp; ! 611: int symfound = -1; ! 612: ! 613: if (!cp) ! 614: return No; ! 615: for (; *cp; cp += 2) { ! 616: if (cp[0] != spflag + 1) ! 617: continue; ! 618: symcp = cp[1]; ! 619: tp = &table[symcp]; ! 620: if (isinclass(sym1, tp->r_class[0]) ! 621: && isinclass(sym2, tp->r_class[1])) { ! 622: symfound = symcp; ! 623: break; ! 624: } ! 625: } ! 626: ! 627: if (symfound < 0) ! 628: return No; ! 629: n1 = nodecopy(n1); ! 630: n2 = nodecopy(n2); /* 'Cause one of them may overlap tree(*pp) */ ! 631: replace(pp, table[symfound].r_node); ! 632: down(pp) || Abort(); ! 633: replace(pp, n1); ! 634: rite(pp) || Abort(); ! 635: replace(pp, n2); ! 636: up(pp) || Abort(); ! 637: return Yes; ! 638: } ! 639: ! 640: ! 641: /* ! 642: * Try to join a node (implicit as tree(*pp)) with some text. ! 643: * That is, try to replace the node by one with it as first child, ! 644: * (some of) the text as second child, and nothing or a space in between. ! 645: * ! 646: * 'Spflag' indicates whether a space is desirable between the nodes ! 647: * (but if No it is only used as advice). ! 648: * ! 649: * Returns the number of characters consumed from str. ! 650: */ ! 651: ! 652: Visible int ! 653: joinstring(pp, str, spflag, alt_c, mayindent) ! 654: path *pp; ! 655: register string str; ! 656: register bool spflag; ! 657: int alt_c; ! 658: bool mayindent; ! 659: { ! 660: register struct table *tp; ! 661: path pa = parent(*pp); ! 662: node n1; ! 663: struct classinfo *ci; ! 664: register classptr cp; ! 665: int sympa = pa ? symbol(tree(pa)) : Rootsymbol; ! 666: register int sym1; ! 667: register int symcp; ! 668: int symfound; ! 669: int len; ! 670: char buf[2]; ! 671: bool interactive = alt_c != 0; ! 672: ! 673: if (alt_c < 0) ! 674: alt_c = 0; ! 675: ci = table[sympa].r_class[ichild(*pp) - 1]; ! 676: Assert(ci); ! 677: cp = ci->c_join; ! 678: if (!cp) ! 679: return 0; ! 680: ! 681: n1 = tree(*pp); ! 682: sym1 = symbol(n1); ! 683: symfound = -1; ! 684: for (; *cp; cp += 2) { ! 685: if (cp[0] < spflag + 1) ! 686: continue; ! 687: symcp = cp[1]; ! 688: tp = &table[symcp]; ! 689: if (!mayindent && tp->r_repr[1] && index(tp->r_repr[1], '\t')) ! 690: continue; ! 691: if (isinclass(sym1, tp->r_class[0]) ! 692: && ((canfitchar(str[0], tp->r_class[1])) ! 693: || str[0] == '?' && !interactive)) { ! 694: if (cp[0] == spflag + 1) { ! 695: symfound = symcp; ! 696: break; ! 697: } ! 698: if (symfound < 0) ! 699: symfound = symcp; ! 700: } ! 701: } ! 702: ! 703: if (symfound < 0) { /* 1-level recursion */ ! 704: if (!alt_c) ! 705: return 0; ! 706: buf[0] = alt_c; ! 707: buf[1] = 0; ! 708: return joinstring(pp, buf, spflag, 0, mayindent); ! 709: } ! 710: n1 = nodecopy(n1); /* 'Cause it overlaps tree(*pp) */ ! 711: replace(pp, table[symfound].r_node); ! 712: down(pp) || Abort(); ! 713: replace(pp, n1); ! 714: rite(pp) || Abort(); ! 715: len = fitstring(pp, str, 0); ! 716: if (len == 0 && str[0] == '?') ! 717: len = 1; ! 718: Assert(len > 0); /* Disagreement between canfitchar and fitstring */ ! 719: up(pp) || Abort(); ! 720: return len; ! 721: } ! 722: ! 723: ! 724: /* ! 725: * Similar to joinstring, but now the string must match the delimiter ! 726: * rather than being acceptable as second child. ! 727: * (Interface has changed to resemble resuggest/soften.) ! 728: */ ! 729: ! 730: Hidden bool ! 731: add_string(ep, pstr, alt_c) ! 732: environ *ep; ! 733: string *pstr; ! 734: int alt_c; /* Yet unused */ ! 735: { ! 736: register struct table *tp; ! 737: path pa = parent(ep->focus); ! 738: node n1; ! 739: struct classinfo *ci; ! 740: register classptr cp; ! 741: int sympa = pa ? symbol(tree(pa)) : Rootsymbol; ! 742: register int sym1; ! 743: register int symcp; ! 744: register int c; ! 745: ! 746: ci = table[sympa].r_class[ichild(ep->focus) - 1]; ! 747: Assert(ci); ! 748: cp = ci->c_append; ! 749: if (!cp) ! 750: return No; ! 751: n1 = tree(ep->focus); ! 752: sym1 = symbol(n1); ! 753: c = **pstr; ! 754: for (; *cp; cp += 2) { ! 755: if ((*cp&0177) != c) ! 756: continue; ! 757: symcp = cp[1]; ! 758: tp = &table[symcp]; ! 759: if (isinclass(sym1, tp->r_class[0])) ! 760: break; ! 761: } ! 762: if (!*cp) ! 763: return No; ! 764: ++*pstr; ! 765: if (c == ' ') { ! 766: ep->spflag = Yes; ! 767: return Yes; ! 768: } ! 769: n1 = nodecopy(n1); /* 'Cause it overlaps tree(ep->focus) */ ! 770: replace(&ep->focus, table[symcp].r_node); ! 771: s_down(ep); ! 772: replace(&ep->focus, n1); ! 773: s_up(ep); ! 774: ep->mode = FHOLE; ! 775: ep->s1 = 3; ! 776: ep->s2 = (*cp&0200) ? 2 : 1; ! 777: ep->spflag = No; ! 778: return Yes; ! 779: } ! 780: ! 781: ! 782: /* ! 783: * See whether a character may start a new node in a hole with given class. ! 784: */ ! 785: ! 786: Visible bool ! 787: canfitchar(c, ci) ! 788: int c; ! 789: struct classinfo *ci; ! 790: { ! 791: register classptr cp; ! 792: register int code = Code(c); ! 793: ! 794: Assert(ci); ! 795: cp = ci->c_insert; ! 796: Assert(cp); ! 797: for (; *cp; cp += 2) { ! 798: if (cp[0] == code) ! 799: return Yes; ! 800: } ! 801: return No; ! 802: } ! 803: ! 804: ! 805: /* ! 806: * Debug routine to print a queue. ! 807: */ ! 808: ! 809: Visible Procedure ! 810: qshow(q, where) ! 811: queue q; ! 812: string where; ! 813: { ! 814: #ifndef NDEBUG ! 815: node n; ! 816: char buf[256]; ! 817: string cp; ! 818: string sp; ! 819: ! 820: sprintf(buf, "%s:", where); ! 821: cp = buf + strlen(buf); ! 822: for (;q; q = q->q_link) { ! 823: n = q->q_data; ! 824: *cp++ = ' '; ! 825: if (Type(n) == Tex) { ! 826: *cp++ = '"'; ! 827: for (sp = Str((value) n); *sp; ++sp) { ! 828: if (isprint(*sp) || *sp == ' ') { ! 829: *cp++ = *sp; ! 830: if (*sp == '"') ! 831: *cp++ = *sp; ! 832: } ! 833: else { ! 834: sprintf(cp, "\\%03o", *sp&0377); ! 835: cp += 4; ! 836: } ! 837: } ! 838: *cp++ = '"'; ! 839: } ! 840: else { ! 841: strncpy(cp, table[symbol(n)].r_name, 80); ! 842: cp += strlen(cp); ! 843: } ! 844: if (cp >= buf+80) { ! 845: strcpy(buf+76, "..."); ! 846: break; ! 847: } ! 848: } ! 849: *cp = 0; ! 850: debug(buf); ! 851: #endif NDEBUG ! 852: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.