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

Defined functions

canexit defined in line 783; used 1 times
clrenv defined in line 647; used 2 times
dbmess defined in line 730; used 2 times
demo defined in line 181; used 1 times
dofile defined in line 218; used 2 times
editdocument defined in line 270; used 2 times
enddemo defined in line 669; used 1 times
execute defined in line 472; used 2 times
findhole defined in line 807; used 2 times
getinput defined in line 101; used 1 times
  • in line 85
mainloop defined in line 62; used 1 times

Defined variables

lefttorite defined in line 39; used 4 times
rcsid defined in line 2; never used
savewhere defined in line 49; used 8 times

Defined macros

ACCSUGG defined in line 487; used 16 times
CMDPROMPT defined in line 23; used 2 times
KILLSUGG defined in line 488; used 1 times
MAXHIST defined in line 42; used 7 times
Mod defined in line 44; used 3 times
Pred defined in line 46; used 5 times
Succ defined in line 45; used 6 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1917
Valid CSS Valid XHTML 1.0 Strict