|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ ! 2: static char rcsid[] = "$Header: demo.c,v 2.6 85/08/22 16:01:21 timo Exp $"; ! 3: ! 4: /* ! 5: * B editor -- Editor command processor. ! 6: */ ! 7: ! 8: #include <ctype.h> ! 9: ! 10: #include "b.h" ! 11: #include "feat.h" ! 12: #include "erro.h" ! 13: #include "bobj.h" ! 14: #include "node.h" ! 15: #include "gram.h" ! 16: #include "keys.h" ! 17: #include "supr.h" ! 18: ! 19: #ifdef BTOP ! 20: #include <setjmp.h> ! 21: ! 22: #ifndef CMDPROMPT ! 23: #define CMDPROMPT ">>> " /* Prompt user for immediate command */ ! 24: #endif CMDPROMPT ! 25: #endif BTOP ! 26: ! 27: ! 28: value editqueue(); ! 29: ! 30: /* Command line flags */ ! 31: extern bool dflag; ! 32: extern bool slowterminal; ! 33: ! 34: #ifdef SAVEBUF ! 35: extern char copysavefile[]; ! 36: #endif SAVEBUF ! 37: ! 38: ! 39: Visible bool lefttorite; ! 40: /* Saves some time in nosuggtoqueue() for read from file */ ! 41: ! 42: #define MAXHIST 101 /* One more than the number of UNDO's allowed. */ ! 43: ! 44: #define Mod(k) (((k)+MAXHIST) % MAXHIST) ! 45: #define Succ(k) (((k)+1) % MAXHIST) ! 46: #define Pred(k) (((k)+MAXHIST-1) % MAXHIST) ! 47: ! 48: Hidden environ *tobesaved; ! 49: Hidden string savewhere; ! 50: ! 51: ! 52: #ifdef BTOP ! 53: ! 54: extern jmp_buf jumpback; ! 55: extern bool interrupted; ! 56: extern bool canjump; ! 57: ! 58: /* ! 59: * Main loop, called from main program if -t option present. ! 60: */ ! 61: ! 62: Visible Procedure ! 63: mainloop() ! 64: { ! 65: environ env; ! 66: environ *ep = &env; ! 67: FILE *pdown; ! 68: FILE *pup; ! 69: int cmdchar; ! 70: ! 71: savewhere = (string)NULL; ! 72: tobesaved = (environ*)NULL; ! 73: start_b(&pdown, &pup); ! 74: clrenv(ep); ! 75: #ifdef SAVEBUF ! 76: ep->copybuffer = editqueue(copysavefile); ! 77: if (ep->copybuffer) ! 78: ep->copyflag = Yes; ! 79: #endif SAVEBUF ! 80: ! 81: for (;;) { ! 82: cmdchar = sleur(); ! 83: if (cmdchar == EOF) ! 84: break; ! 85: getinput(ep, cmdchar, pdown, pup); ! 86: } ! 87: #ifdef SAVEBUF ! 88: if (ep->copyflag) ! 89: savequeue(ep->copybuffer, copysavefile); ! 90: else ! 91: savequeue(Vnil, copysavefile); ! 92: #endif SAVEBUF ! 93: Erelease(*ep); ! 94: } ! 95: ! 96: ! 97: /* ! 98: * Provide input for the interpreter. ! 99: */ ! 100: ! 101: Hidden Procedure ! 102: getinput(ep, cmdchar, pdown, pup) ! 103: environ *ep; ! 104: int cmdchar; ! 105: FILE *pdown; ! 106: FILE *pup; ! 107: { ! 108: int n; ! 109: char buffer[100]; ! 110: char filename[100]; ! 111: int lineno; ! 112: ! 113: ! 114: switch (cmdchar) { ! 115: ! 116: case '>': /* Immediate command */ ! 117: case 'E': /* Expression */ ! 118: case 'R': /* Raw input */ ! 119: case 'Y': /* Yes/No */ ! 120: if (cmdchar == '>') ! 121: setroot("Imm_cmd"); ! 122: else if (cmdchar == 'E') ! 123: setroot("Expression"); ! 124: else ! 125: setroot("Raw_input"); ! 126: delfocus(&ep->focus); ! 127: initshow(); ! 128: if (cmdchar == '>') ! 129: cmdprompt(CMDPROMPT); ! 130: editdocument(ep); ! 131: endshow(); ! 132: top(&ep->focus); ! 133: ep->mode = WHOLE; ! 134: if (!interrupted) ! 135: send(ep->focus, pdown); ! 136: delete(ep); ! 137: break; ! 138: ! 139: case ':': ! 140: case '=': ! 141: fgets(buffer, sizeof buffer, pup); ! 142: if (index(buffer, '+')) ! 143: n = sscanf(buffer, " +%d %s", &lineno, filename) - 1; ! 144: else { ! 145: n = sscanf(buffer, " %s", filename); ! 146: lineno = 0; ! 147: } ! 148: if (n == 1) { ! 149: initshow(); ! 150: dofile(ep, filename, lineno); ! 151: endshow(); ! 152: top(&ep->focus); ! 153: ep->mode = WHOLE; ! 154: delete(ep); ! 155: if (!ep->copyflag) { ! 156: release(ep->copybuffer); ! 157: ep->copybuffer = Vnil; ! 158: } ! 159: } ! 160: putc('\n', pdown); ! 161: interrupted = No; /* Interrupts handled locally in editdocument! */ ! 162: break; ! 163: ! 164: default: ! 165: printf("[Unrecognized command character '%c' (0%o)]\n", ! 166: cmdchar&0177, cmdchar); ! 167: ! 168: } ! 169: } ! 170: ! 171: #endif BTOP ! 172: ! 173: ! 174: #ifdef FILEARGS ! 175: ! 176: /* ! 177: * Edit a single unit or target, called from main program if file name ! 178: * arguments are present. ! 179: */ ! 180: ! 181: Visible Procedure ! 182: demo(filename, linenumber) ! 183: string filename; ! 184: int linenumber; ! 185: { ! 186: environ env; ! 187: environ *ep = &env; ! 188: bool ok; ! 189: ! 190: clrenv(ep); ! 191: #ifdef SAVEBUF ! 192: ep->copybuffer = editqueue(copysavefile); ! 193: if (ep->copybuffer) ! 194: ep->copyflag = Yes; ! 195: #endif SAVEBUF ! 196: initshow(); ! 197: ok = dofile(ep, filename, linenumber); ! 198: endshow(); ! 199: if (!ok) ! 200: return No; ! 201: #ifdef SAVEBUF ! 202: if (ep->copyflag) ! 203: savequeue(ep->copybuffer, copysavefile); ! 204: else ! 205: savequeue(Vnil, copysavefile); ! 206: #endif SAVEBUF ! 207: Erelease(*ep); ! 208: return Yes; ! 209: } ! 210: ! 211: #endif !FILEARGS ! 212: ! 213: ! 214: /* ! 215: * Edit a unit or target, using the environment offered as a parameter. ! 216: */ ! 217: ! 218: Hidden bool ! 219: dofile(ep, filename, linenumber) ! 220: environ *ep; ! 221: string filename; ! 222: int linenumber; ! 223: { ! 224: #ifdef HELPFUL ! 225: static bool didmessage; ! 226: ! 227: if (!didmessage) { ! 228: didmessage = Yes; ! 229: message("[Press ? or ESC-? for help]"); ! 230: } ! 231: #endif HELPFUL ! 232: #ifdef SAVEPOS ! 233: if (linenumber <= 0) ! 234: linenumber = getpos(filename); ! 235: #endif SAVEPOS ! 236: setroot(filename[0] == '=' ? "Target_edit" : "Unit_edit"); ! 237: savewhere = filename; ! 238: tobesaved = (environ*)NULL; ! 239: ! 240: lefttorite = Yes; ! 241: edit(ep, filename, linenumber); ! 242: #ifdef USERSUGG ! 243: readsugg(ep->focus); ! 244: #endif USERSUGG ! 245: lefttorite = No; ! 246: ! 247: ep->generation = 0; ! 248: if (!editdocument(ep)) ! 249: return No; ! 250: if (ep->generation > 0) { ! 251: if (!save(ep->focus, filename)) ! 252: error("Cannot save unit: %s", unixerror(filename)); ! 253: #ifdef USERSUGG ! 254: writesugg(ep->focus); ! 255: #endif USERSUGG ! 256: } ! 257: #ifdef SAVEPOS ! 258: savepos(filename, lineno(ep)+1); ! 259: #endif SAVEPOS ! 260: savewhere = (char*)NULL; ! 261: tobesaved = (environ*)NULL; ! 262: return Yes; ! 263: } ! 264: ! 265: ! 266: /* ! 267: * Call the editor for a given document. ! 268: */ ! 269: ! 270: Hidden bool ! 271: editdocument(ep) ! 272: environ *ep; ! 273: { ! 274: int k; ! 275: int first = 0; ! 276: int last = 0; ! 277: int current = 0; ! 278: int onscreen = -1; ! 279: bool reverse = No; ! 280: environ newenv; ! 281: int cmd; ! 282: bool errors = No; ! 283: int undoage = 0; ! 284: bool done = No; ! 285: environ history[MAXHIST]; ! 286: ! 287: Ecopy(*ep, history[0]); ! 288: ! 289: for (;;) { /* Command interpretation loop */ ! 290: if (onscreen != current) ! 291: virtupdate(onscreen < 0 ? (environ*)NULL : &history[onscreen], ! 292: &history[current], ! 293: reverse && onscreen >= 0 ? ! 294: history[onscreen].highest : history[current].highest); ! 295: onscreen = current; ! 296: if (done) ! 297: break; ! 298: #ifdef BTOP ! 299: if (!interrupted && !moreinput()) ! 300: #else BTOP ! 301: if (!moreinput()) ! 302: #endif BTOP ! 303: actupdate(history[current].copyflag ? ! 304: history[current].copybuffer : Vnil, ! 305: #ifdef RECORDING ! 306: history[current].newmacro != Vnil, ! 307: #else !RECORDING ! 308: No, ! 309: #endif !RECORDING ! 310: No); ! 311: #ifdef BTOP ! 312: if (interrupted || setjmp(jumpback)) ! 313: break; ! 314: canjump = Yes; ! 315: #endif BTOP ! 316: cmd = inchar(); ! 317: #ifdef BTOP ! 318: canjump = No; ! 319: #endif BTOP ! 320: errors = No; ! 321: ! 322: switch (cmd) { ! 323: ! 324: #ifndef NDEBUG ! 325: case Ctl(@): /* Debug exit with variable dump */ ! 326: tobesaved = (environ*)NULL; ! 327: return No; ! 328: #endif NDEBUG ! 329: ! 330: #ifndef SMALLSYS ! 331: case Ctl(^): /* Debug status message */ ! 332: dbmess(&history[current]); ! 333: errors = Yes; /* Causes clear after new keystroke seen */ ! 334: continue; ! 335: #endif !SMALLSYS ! 336: ! 337: case UNDO: ! 338: if (current == first) ! 339: errors = Yes; ! 340: else { ! 341: if (onscreen == current) ! 342: reverse = Yes; ! 343: current = Pred(current); ! 344: undoage = Mod(last-current); ! 345: } ! 346: break; ! 347: ! 348: case REDO: ! 349: if (current == last) ! 350: errors = Yes; ! 351: else { ! 352: if (current == onscreen) ! 353: reverse = No; ! 354: if (history[Succ(current)].generation < ! 355: history[current].generation) ! 356: error(REDO_OLD); /***** Should refuse altogether??? *****/ ! 357: current = Succ(current); ! 358: undoage = Mod(last-current); ! 359: } ! 360: break; ! 361: ! 362: #ifdef HELPFUL ! 363: case HELP: ! 364: if (help()) ! 365: onscreen = -1; ! 366: break; ! 367: #endif HELPFUL ! 368: ! 369: case REDRAW: ! 370: onscreen = -1; ! 371: trmundefined(); ! 372: break; ! 373: ! 374: case EOF: ! 375: done = Yes; ! 376: break; ! 377: ! 378: default: ! 379: Ecopy(history[current], newenv); ! 380: newenv.highest = Maxintlet; ! 381: newenv.changed = No; ! 382: if (cmd != EXIT) ! 383: errors = !execute(&newenv, cmd) || !checkep(&newenv); ! 384: else ! 385: done = Yes; ! 386: if (errors) { ! 387: switch (cmd) { ! 388: case '\r': ! 389: case '\n': ! 390: if (newenv.mode == ATEND && !parent(newenv.focus)) { ! 391: errors = !checkep(&newenv); ! 392: if (!errors) ! 393: done = Yes; ! 394: } ! 395: break; ! 396: #ifdef HELPFUL ! 397: case '?': ! 398: if (help()) ! 399: onscreen = -1; ! 400: #endif HELPFUL ! 401: } ! 402: } ! 403: if (errors) ! 404: Erelease(newenv); ! 405: else { ! 406: #ifndef SMALLSYS ! 407: if (done) ! 408: done = canexit(&newenv); ! 409: #endif SMALLSYS ! 410: if (newenv.changed) ! 411: ++newenv.generation; ! 412: last = Succ(last); ! 413: current = Succ(current); ! 414: if (last == first) { ! 415: /* Array full (always after a while). Discard "oldest". */ ! 416: if (current == last ! 417: || undoage < Mod(current-first)) { ! 418: Erelease(history[first]); ! 419: first = Succ(first); ! 420: if (undoage < MAXHIST) ! 421: ++undoage; ! 422: } ! 423: else { ! 424: last = Pred(last); ! 425: Erelease(history[last]); ! 426: } ! 427: } ! 428: if (current != last ! 429: && newenv.highest < history[current].highest) ! 430: history[current].highest = newenv.highest; ! 431: /* Move entries beyond current one up. */ ! 432: for (k = last; k != current; k = Pred(k)) { ! 433: if (Pred(k) == onscreen) ! 434: onscreen = k; ! 435: Emove(history[Pred(k)], history[k]); ! 436: } ! 437: Ecopy(newenv, history[current]); ! 438: Erelease(history[current]); ! 439: } ! 440: break; /* default */ ! 441: ! 442: } /* switch */ ! 443: ! 444: if (errors && cmd != '?') { ! 445: if (!slowterminal && isascii(cmd) ! 446: && (isprint(cmd) || cmd == ' ')) ! 447: error(INS_BAD, cmd); ! 448: else ! 449: error((char*)NULL); ! 450: } ! 451: if (savewhere) ! 452: tobesaved = &history[current]; ! 453: } /* for (;;) */ ! 454: ! 455: actupdate(Vnil, No, Yes); ! 456: Erelease(*ep); ! 457: Ecopy(history[current], *ep); ! 458: if (savewhere) ! 459: tobesaved = ep; ! 460: for (current = first; current != last; current = Succ(current)) ! 461: Erelease(history[current]); ! 462: Erelease(history[last]); ! 463: /* endshow(); */ ! 464: return Yes; ! 465: } ! 466: ! 467: ! 468: /* ! 469: * Execute a command, return success or failure. ! 470: */ ! 471: ! 472: Hidden bool ! 473: execute(ep, cmd) ! 474: register environ *ep; ! 475: register int cmd; ! 476: { ! 477: register bool spflag = ep->spflag; ! 478: register int i; ! 479: environ env; ! 480: char buf[2]; ! 481: register char *cp; ! 482: #ifdef USERSUGG ! 483: bool sugg = symbol(tree(ep->focus)) == Suggestion; ! 484: #define ACCSUGG(ep) if (sugg) accsugg(ep) ! 485: #define KILLSUGG(ep) if (sugg) killsugg(ep) ! 486: #else !USERSUGG ! 487: #define ACCSUGG(ep) /* NULL */ ! 488: #define KILLSUGG(ep) /* NULL */ ! 489: #endif !USERSUGG ! 490: ! 491: #ifdef RECORDING ! 492: if (ep->newmacro && cmd != USEMACRO && cmd != SAVEMACRO) { ! 493: buf[0] = cmd; ! 494: buf[1] = 0; ! 495: concato(&ep->newmacro, buf); ! 496: } ! 497: #endif RECORDING ! 498: ep->spflag = No; ! 499: ! 500: switch (cmd) { ! 501: ! 502: #ifdef RECORDING ! 503: case SAVEMACRO: ! 504: ep->spflag = spflag; ! 505: if (ep->newmacro) { /* End definition */ ! 506: release(ep->oldmacro); ! 507: if (ep->newmacro && Length(ep->newmacro) > 0) { ! 508: ep->oldmacro = ep->newmacro; ! 509: message(REC_OK); ! 510: } ! 511: else { ! 512: release(ep->newmacro); ! 513: ep->oldmacro = Vnil; ! 514: } ! 515: ep->newmacro = Vnil; ! 516: } ! 517: else /* Start definition */ ! 518: ep->newmacro = mk_text(""); ! 519: return Yes; ! 520: ! 521: case USEMACRO: ! 522: if (!ep->oldmacro || Length(ep->oldmacro) <= 0) { ! 523: error(PLB_NOK); ! 524: return No; ! 525: } ! 526: ep->spflag = spflag; ! 527: cp = Str(ep->oldmacro); ! 528: for (i = 0; i < Length(ep->oldmacro); ++i) { ! 529: Ecopy(*ep, env); ! 530: if (execute(ep, cp[i]&0377) && checkep(ep)) ! 531: Erelease(env); ! 532: else { ! 533: Erelease(*ep); ! 534: Emove(env, *ep); ! 535: if (!i) ! 536: return No; ! 537: error((char*)NULL); /* Just a bell */ ! 538: /* The error must be signalled here, because the overall ! 539: command (USEMACRO) succeeds, so the main loop ! 540: doesn't ring the bell; but we want to inform the ! 541: that not everything was done either. */ ! 542: return Yes; ! 543: } ! 544: } ! 545: return Yes; ! 546: #endif RECORDING ! 547: ! 548: #ifndef SMALLSYS ! 549: case Ctl(_): /* 'Touch', i.e. set modified flag */ ! 550: ep->changed = Yes; ! 551: return Yes; ! 552: #endif SMALLSYS ! 553: ! 554: case GOTO: ! 555: ACCSUGG(ep); ! 556: #ifdef RECORDING ! 557: if (ep->newmacro) { ! 558: error(GOTO_REC); ! 559: return No; ! 560: } ! 561: #endif RECORDING ! 562: return gotocursor(ep); ! 563: ! 564: case NEXT: ! 565: ACCSUGG(ep); ! 566: return next(ep); ! 567: ! 568: case PREVIOUS: ! 569: ACCSUGG(ep); ! 570: return previous(ep); ! 571: ! 572: case LEFTARROW: ! 573: ACCSUGG(ep); ! 574: return leftarrow(ep); ! 575: ! 576: case RITEARROW: ! 577: ACCSUGG(ep); ! 578: return ritearrow(ep); ! 579: ! 580: case WIDEN: ! 581: ACCSUGG(ep); ! 582: return widen(ep); ! 583: ! 584: case EXTEND: ! 585: ACCSUGG(ep); ! 586: return extend(ep); ! 587: ! 588: case NARROW: ! 589: ACCSUGG(ep); ! 590: return narrow(ep); ! 591: ! 592: case RNARROW: ! 593: ACCSUGG(ep); ! 594: return rnarrow(ep); ! 595: ! 596: case UPARROW: ! 597: ACCSUGG(ep); ! 598: return uparrow(ep); ! 599: ! 600: case DOWNARROW: ! 601: ACCSUGG(ep); ! 602: return downarrow(ep); ! 603: ! 604: case UPLINE: ! 605: ACCSUGG(ep); ! 606: return upline(ep); ! 607: ! 608: case DOWNLINE: ! 609: ACCSUGG(ep); ! 610: return downline(ep); ! 611: ! 612: case COPY: ! 613: ACCSUGG(ep); ! 614: ep->spflag = spflag; ! 615: return copyinout(ep); ! 616: ! 617: case DELETE: ! 618: ACCSUGG(ep); ! 619: return delete(ep); ! 620: ! 621: case ACCEPT: ! 622: ACCSUGG(ep); ! 623: return accept(ep); ! 624: ! 625: default: ! 626: if (!isascii(cmd) || !isprint(cmd)) ! 627: return No; ! 628: ep->spflag = spflag; ! 629: return ins_char(ep, cmd, islower(cmd) ? toupper(cmd) : -1); ! 630: ! 631: case ' ': ! 632: ep->spflag = spflag; ! 633: return ins_char(ep, ' ', -1); ! 634: ! 635: case RETURN: ! 636: case NEWLINE: ! 637: KILLSUGG(ep); ! 638: return ins_newline(ep); ! 639: } ! 640: } ! 641: ! 642: ! 643: /* ! 644: * Initialize an environment variable. Most things are set to 0 or NULL. ! 645: */ ! 646: ! 647: Hidden Procedure ! 648: clrenv(ep) ! 649: environ *ep; ! 650: { ! 651: ep->focus = newpath(Pnil, gram(Optional), 1); ! 652: ep->mode = WHOLE; ! 653: ep->copyflag = ep->spflag = ep->changed = No; ! 654: ep->s1 = ep->s2 = ep->s3 = 0; ! 655: ep->highest = Maxintlet; ! 656: ep->copybuffer = Vnil; ! 657: #ifdef RECORDING ! 658: ep->oldmacro = ep->newmacro = Vnil; ! 659: #endif RECORDING ! 660: ep->generation = 0; ! 661: ep->changed = No; ! 662: } ! 663: ! 664: ! 665: /* ! 666: * Save parse tree and copy buffer. ! 667: */ ! 668: ! 669: Visible Procedure ! 670: enddemo() ! 671: { ! 672: register environ *ep = tobesaved; ! 673: ! 674: tobesaved = (environ*)NULL; ! 675: /* To avoid loops if saving is interrupted. */ ! 676: if (savewhere && ep) { ! 677: if (ep->generation > 0) { ! 678: save(ep->focus, savewhere); ! 679: #ifdef USERSUGG ! 680: writesugg(ep->focus); ! 681: #endif USERSUGG ! 682: } ! 683: #ifdef SAVEBUF ! 684: if (ep->copyflag) ! 685: savequeue(ep->copybuffer, copysavefile); ! 686: else ! 687: savequeue(Vnil, copysavefile); ! 688: #endif SAVEBUF ! 689: #ifdef SAVEPOS ! 690: savepos(savewhere, lineno(ep)+1); ! 691: #endif SAVEPOS ! 692: } ! 693: #ifdef BTOP ! 694: waitchild(); ! 695: #endif BTOP ! 696: } ! 697: ! 698: ! 699: /* ! 700: * Find out if the current position is higher in the tree ! 701: * than `ever' before (as remembered in ep->highest). ! 702: * The algorithm of pathlength() is repeated here to gain ! 703: * some efficiency by stopping as soon as it is clear ! 704: * no change can occur. ! 705: * (Higher() is called VERY often, so this pays). ! 706: */ ! 707: ! 708: Visible Procedure ! 709: higher(ep) ! 710: register environ *ep; ! 711: { ! 712: register path p = ep->focus; ! 713: register int pl = 0; ! 714: register int max = ep->highest; ! 715: ! 716: while (p) { ! 717: ++pl; ! 718: if (pl >= max) ! 719: return; ! 720: p = parent(p); ! 721: } ! 722: ep->highest = pl; ! 723: } ! 724: ! 725: ! 726: /* ! 727: * Issue debug status message. ! 728: */ ! 729: ! 730: Visible Procedure ! 731: dbmess(ep) ! 732: register environ *ep; ! 733: { ! 734: #ifndef SMALLSYS ! 735: char stuff[80]; ! 736: register string str = stuff; ! 737: ! 738: switch (ep->mode) { ! 739: case VHOLE: ! 740: sprintf(stuff, "VHOLE:%d.%d", ep->s1, ep->s2); ! 741: break; ! 742: case FHOLE: ! 743: sprintf(stuff, "FHOLE:%d.%d", ep->s1, ep->s2); ! 744: break; ! 745: case ATBEGIN: ! 746: str = "ATBEGIN"; ! 747: break; ! 748: case ATEND: ! 749: str = "ATEND"; ! 750: break; ! 751: case WHOLE: ! 752: str = "WHOLE"; ! 753: break; ! 754: case SUBRANGE: ! 755: sprintf(stuff, "SUBRANGE:%d.%d-%d", ep->s1, ep->s2, ep->s3); ! 756: break; ! 757: case SUBSET: ! 758: sprintf(stuff, "SUBSET:%d-%d", ep->s1, ep->s2); ! 759: break; ! 760: case SUBLIST: ! 761: sprintf(stuff, "SUBLIST...%d", ep->s3); ! 762: break; ! 763: default: ! 764: sprintf(stuff, "UNKNOWN:%d,%d,%d,%d", ! 765: ep->mode, ep->s1, ep->s2, ep->s3); ! 766: } ! 767: message( ! 768: #ifdef SAVEBUF ! 769: "%s, %s, wi=%d, hi=%d, (y,x,l)=(%d,%d,%d) %s", ! 770: symname(symbol(tree(ep->focus))), ! 771: #else !SAVEBUF ! 772: "%d, %s, wi=%d, hi=%d, (y,x,l)=(%d,%d,%d) %s", ! 773: symbol(tree(ep->focus)), ! 774: #endif SAVEBUF ! 775: str, width(tree(ep->focus)), ep->highest, ! 776: Ycoord(ep->focus), Xcoord(ep->focus), Level(ep->focus), ! 777: ep->spflag ? "spflag on" : ""); ! 778: #endif !SMALLSYS ! 779: } ! 780: ! 781: #ifndef SMALLSYS ! 782: ! 783: Hidden bool ! 784: canexit(ep) ! 785: environ *ep; ! 786: { ! 787: environ env; ! 788: ! 789: shrink(ep); ! 790: if (ishole(ep)) ! 791: delete(ep); ! 792: Ecopy(*ep, env); ! 793: top(&ep->focus); ! 794: higher(ep); ! 795: ep->mode = WHOLE; ! 796: if (findhole(&ep->focus)) { ! 797: Erelease(env); ! 798: error(EXIT_HOLES); /* There are holes left */ ! 799: return No; ! 800: } ! 801: Erelease(*ep); ! 802: Emove(env, *ep); ! 803: return Yes; ! 804: } ! 805: ! 806: ! 807: Hidden bool ! 808: findhole(pp) ! 809: register path *pp; ! 810: { ! 811: register node n = tree(*pp); ! 812: ! 813: if (Type(n) == Tex) ! 814: return No; ! 815: if (symbol(n) == Hole) ! 816: return Yes; ! 817: if (!down(pp)) ! 818: return No; ! 819: for (;;) { ! 820: if (findhole(pp)) ! 821: return Yes; ! 822: if (!rite(pp)) ! 823: break; ! 824: ! 825: } ! 826: up(pp) || Abort(); ! 827: return No; ! 828: } ! 829: ! 830: #endif !SMALLSYS
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.