1: /* Copyright (c) 1979 Regents of the University of California */
   2: #include "ex.h"
   3: #include "ex_tty.h"
   4: #include "ex_vis.h"
   5: 
   6: #define blank()     isspace(wcursor[0])
   7: #define forbid(a)   if (a) goto errlab;
   8: 
   9: char    vscandir[2] =   { '/', 0 };
  10: 
  11: /*
  12:  * Decode an operator/operand type command.
  13:  * Eventually we switch to an operator subroutine in ex_vops.c.
  14:  * The work here is setting up a function variable to point
  15:  * to the routine we want, and manipulation of the variables
  16:  * wcursor and wdot, which mark the other end of the affected
  17:  * area.  If wdot is zero, then the current line is the other end,
  18:  * and if wcursor is zero, then the first non-blank location of the
  19:  * other line is implied.
  20:  */
  21: operate(c, cnt)
  22:     register int c, cnt;
  23: {
  24:     register int i;
  25:     int (*moveop)(), (*deleteop)();
  26:     register int (*opf)();
  27:     bool subop = 0;
  28:     char *oglobp, *ocurs;
  29:     register line *addr;
  30:     static char lastFKND, lastFCHR;
  31:     char d;
  32: 
  33:     moveop = vmove, deleteop = vdelete;
  34:     wcursor = cursor;
  35:     wdot = NOLINE;
  36:     notecnt = 0;
  37:     dir = 1;
  38:     switch (c) {
  39: 
  40:     /*
  41: 	 * d		delete operator.
  42: 	 */
  43:     case 'd':
  44:         moveop = vdelete;
  45:         deleteop = beep;
  46:         break;
  47: 
  48:     /*
  49: 	 * s		substitute characters, like c\040, i.e. change space.
  50: 	 */
  51:     case 's':
  52:         ungetkey(' ');
  53:         subop++;
  54:         /* fall into ... */
  55: 
  56:     /*
  57: 	 * c		Change operator.
  58: 	 */
  59:     case 'c':
  60:         if (c == 'c' && workcmd[0] == 'C' || workcmd[0] == 'S')
  61:             subop++;
  62:         moveop = vchange;
  63:         deleteop = beep;
  64:         break;
  65: 
  66:     /*
  67: 	 * !		Filter through a UNIX command.
  68: 	 */
  69:     case '!':
  70:         moveop = vfilter;
  71:         deleteop = beep;
  72:         break;
  73: 
  74:     /*
  75: 	 * y		Yank operator.  Place specified text so that it
  76: 	 *		can be put back with p/P.  Also yanks to named buffers.
  77: 	 */
  78:     case 'y':
  79:         moveop = vyankit;
  80:         deleteop = beep;
  81:         break;
  82: 
  83:     /*
  84: 	 * =		Reformat operator (for LISP).
  85: 	 */
  86: #ifdef LISPCODE
  87:     case '=':
  88:         forbid(!value(LISP));
  89:         /* fall into ... */
  90: #endif
  91: 
  92:     /*
  93: 	 * >		Right shift operator.
  94: 	 * <		Left shift operator.
  95: 	 */
  96:     case '<':
  97:     case '>':
  98:         moveop = vshftop;
  99:         deleteop = beep;
 100:         break;
 101: 
 102:     /*
 103: 	 * r		Replace character under cursor with single following
 104: 	 *		character.
 105: 	 */
 106:     case 'r':
 107:         vrep(cnt);
 108:         return;
 109: 
 110:     default:
 111:         goto nocount;
 112:     }
 113:     /*
 114: 	 * Had an operator, so accept another count.
 115: 	 * Multiply counts together.
 116: 	 */
 117:     if (isdigit(peekkey()) && peekkey() != '0') {
 118:         cnt *= vgetcnt();
 119:         Xcnt = cnt;
 120:         forbid (cnt <= 0);
 121:     }
 122: 
 123:     /*
 124: 	 * Get next character, mapping it and saving as
 125: 	 * part of command for repeat.
 126: 	 */
 127:     c = map(getesc());
 128:     if (c == 0)
 129:         return;
 130:     if (!subop)
 131:         *lastcp++ = c;
 132: nocount:
 133:     opf = moveop;
 134:     switch (c) {
 135: 
 136:     /*
 137: 	 * b		Back up a word.
 138: 	 * B		Back up a word, liberal definition.
 139: 	 */
 140:     case 'b':
 141:     case 'B':
 142:         dir = -1;
 143:         /* fall into ... */
 144: 
 145:     /*
 146: 	 * w		Forward a word.
 147: 	 * W		Forward a word, liberal definition.
 148: 	 */
 149:     case 'W':
 150:     case 'w':
 151:         wdkind = c & ' ';
 152:         forbid(lfind(2, cnt, opf, 0) < 0);
 153:         vmoving = 0;
 154:         break;
 155: 
 156:     /*
 157: 	 * E		to end of following blank/nonblank word
 158: 	 */
 159:     case 'E':
 160:         wdkind = 0;
 161:         goto ein;
 162: 
 163:     /*
 164: 	 * e		To end of following word.
 165: 	 */
 166:     case 'e':
 167:         wdkind = 1;
 168: ein:
 169:         forbid(lfind(3, cnt - 1, opf, 0) < 0);
 170:         vmoving = 0;
 171:         break;
 172: 
 173:     /*
 174: 	 * (		Back an s-expression.
 175: 	 */
 176:     case '(':
 177:         dir = -1;
 178:         /* fall into... */
 179: 
 180:     /*
 181: 	 * )		Forward an s-expression.
 182: 	 */
 183:     case ')':
 184:         forbid(lfind(0, cnt, opf, (line *) 0) < 0);
 185:         markDOT();
 186:         break;
 187: 
 188:     /*
 189: 	 * {		Back an s-expression, but don't stop on atoms.
 190: 	 *		In text mode, a paragraph.  For C, a balanced set
 191: 	 *		of {}'s.
 192: 	 */
 193:     case '{':
 194:         dir = -1;
 195:         /* fall into... */
 196: 
 197:     /*
 198: 	 * }		Forward an s-expression, but don't stop on atoms.
 199: 	 *		In text mode, back paragraph.  For C, back a balanced
 200: 	 *		set of {}'s.
 201: 	 */
 202:     case '}':
 203:         forbid(lfind(1, cnt, opf, (line *) 0) < 0);
 204:         markDOT();
 205:         break;
 206: 
 207:     /*
 208: 	 * %		To matching () or {}.  If not at ( or { scan for
 209: 	 *		first such after cursor on this line.
 210: 	 */
 211:     case '%':
 212:         vsave();
 213:         i = lmatchp((line *) 0);
 214:         getDOT();
 215:         forbid(!i);
 216:         if (opf != vmove)
 217:             if (dir > 0)
 218:                 wcursor++;
 219:             else
 220:                 cursor++;
 221:         else
 222:             markDOT();
 223:         vmoving = 0;
 224:         break;
 225: 
 226:     /*
 227: 	 * [		Back to beginning of defun, i.e. an ( in column 1.
 228: 	 *		For text, back to a section macro.
 229: 	 *		For C, back to a { in column 1 (~~ beg of function.)
 230: 	 */
 231:     case '[':
 232:         dir = -1;
 233:         /* fall into ... */
 234: 
 235:     /*
 236: 	 * ]		Forward to next defun, i.e. a ( in column 1.
 237: 	 *		For text, forward section.
 238: 	 *		For C, forward to a } in column 1 (if delete or such)
 239: 	 *		or if a move to a { in column 1.
 240: 	 */
 241:     case ']':
 242:         if (!vglobp)
 243:             forbid(getkey() != c);
 244:         vsave();
 245:         i = lbrack(c, opf);
 246:         getDOT();
 247:         forbid(!i);
 248:         markDOT();
 249:         if (ospeed > B300)
 250:             hold |= HOLDWIG;
 251:         break;
 252: 
 253:     /*
 254: 	 * ,		Invert last find with f F t or T, like inverse
 255: 	 *		of ;.
 256: 	 */
 257:     case ',':
 258:         forbid (lastFKND == 0);
 259:         c = isupper(lastFKND) ? tolower(lastFKND) : toupper(lastFKND);
 260:         ungetkey(lastFCHR);
 261:         if (vglobp == 0)
 262:             vglobp = "";
 263:         subop++;
 264:         goto nocount;
 265: 
 266:     /*
 267: 	 * 0		To beginning of real line.
 268: 	 */
 269:     case '0':
 270:         wcursor = linebuf;
 271:         vmoving = 0;
 272:         break;
 273: 
 274:     /*
 275: 	 * ;		Repeat last find with f F t or T.
 276: 	 */
 277:     case ';':
 278:         forbid (lastFKND == 0);
 279:         c = lastFKND;
 280:         ungetkey(lastFCHR);
 281:         subop++;
 282:         goto nocount;
 283: 
 284:     /*
 285: 	 * F		Find single character before cursor in current line.
 286: 	 * T		Like F, but stops before character.
 287: 	 */
 288:     case 'F':   /* inverted find */
 289:     case 'T':
 290:         dir = -1;
 291:         /* fall into ... */
 292: 
 293:     /*
 294: 	 * f		Find single character following cursor in current line.
 295: 	 * t		Like f, but stope before character.
 296: 	 */
 297:     case 'f':   /* find */
 298:     case 't':
 299:         i = getesc();
 300:         if (i == 0)
 301:             return;
 302:         if (!subop)
 303:             *lastcp++ = i;
 304:         if (vglobp == 0)
 305:             lastFKND = c, lastFCHR = i;
 306:         for (; cnt > 0; cnt--)
 307:             forbid (find(i) == 0);
 308:         vmoving = 0;
 309:         switch (c) {
 310: 
 311:         case 'T':
 312:             wcursor++;
 313:             break;
 314: 
 315:         case 't':
 316:             wcursor--;
 317:         case 'f':
 318: fixup:
 319:             if (moveop != vmove)
 320:                 wcursor++;
 321:             break;
 322:         }
 323:         break;
 324: 
 325:     /*
 326: 	 * |		Find specified print column in current line.
 327: 	 */
 328:     case '|':
 329:         if (Pline == numbline)
 330:             cnt += 8;
 331:         vmovcol = cnt;
 332:         vmoving = 1;
 333:         wcursor = vfindcol(cnt);
 334:         break;
 335: 
 336:     /*
 337: 	 * ^		To beginning of non-white space on line.
 338: 	 */
 339:     case '^':
 340:         wcursor = vskipwh(linebuf);
 341:         vmoving = 0;
 342:         break;
 343: 
 344:     /*
 345: 	 * $		To end of line.
 346: 	 */
 347:     case '$':
 348:         if (opf == vmove) {
 349:             vmoving = 1;
 350:             vmovcol = 20000;
 351:         } else
 352:             vmoving = 0;
 353:         if (cnt > 1) {
 354:             if (opf == vmove) {
 355:                 wcursor = 0;
 356:                 cnt--;
 357:             } else
 358:                 wcursor = linebuf;
 359:             /* This is wrong at EOF */
 360:             wdot = dot + cnt;
 361:             break;
 362:         }
 363:         if (linebuf[0]) {
 364:             wcursor = strend(linebuf) - 1;
 365:             goto fixup;
 366:         }
 367:         wcursor = linebuf;
 368:         break;
 369: 
 370:     /*
 371: 	 * h		Back a character.
 372: 	 * ^H		Back a character.
 373: 	 */
 374:     case 'h':
 375:     case CTRL(h):
 376:         dir = -1;
 377:         /* fall into ... */
 378: 
 379:     /*
 380: 	 * space	Forward a character.
 381: 	 */
 382:     case 'l':
 383:     case ' ':
 384:         forbid (margin() || opf == vmove && edge());
 385:         while (cnt > 0 && !margin())
 386:             wcursor += dir, cnt--;
 387:         if (margin() && opf == vmove || wcursor < linebuf)
 388:             wcursor -= dir;
 389:         vmoving = 0;
 390:         break;
 391: 
 392:     /*
 393: 	 * D		Delete to end of line, short for d$.
 394: 	 */
 395:     case 'D':
 396:         cnt = INF;
 397:         goto deleteit;
 398: 
 399:     /*
 400: 	 * X		Delete character before cursor.
 401: 	 */
 402:     case 'X':
 403:         dir = -1;
 404:         /* fall into ... */
 405: deleteit:
 406:     /*
 407: 	 * x		Delete character at cursor, leaving cursor where it is.
 408: 	 */
 409:     case 'x':
 410:         if (margin())
 411:             goto errlab;
 412:         while (cnt > 0 && !margin())
 413:             wcursor += dir, cnt--;
 414:         opf = deleteop;
 415:         vmoving = 0;
 416:         break;
 417: 
 418:     default:
 419:         /*
 420: 		 * Stuttered operators are equivalent to the operator on
 421: 		 * a line, thus turn dd into d_.
 422: 		 */
 423:         if (opf == vmove || c != workcmd[0]) {
 424: errlab:
 425:             beep();
 426:             vmacp = 0;
 427:             return;
 428:         }
 429:         /* fall into ... */
 430: 
 431:     /*
 432: 	 * _		Target for a line or group of lines.
 433: 	 *		Stuttering is more convenient; this is mostly
 434: 	 *		for aesthetics.
 435: 	 */
 436:     case '_':
 437:         wdot = dot + cnt - 1;
 438:         vmoving = 0;
 439:         wcursor = 0;
 440:         break;
 441: 
 442:     /*
 443: 	 * H		To first, home line on screen.
 444: 	 *		Count is for count'th line rather than first.
 445: 	 */
 446:     case 'H':
 447:         wdot = (dot - vcline) + cnt - 1;
 448:         if (opf == vmove)
 449:             markit(wdot);
 450:         vmoving = 0;
 451:         wcursor = 0;
 452:         break;
 453: 
 454:     /*
 455: 	 * -		Backwards lines, to first non-white character.
 456: 	 */
 457:     case '-':
 458:         wdot = dot - cnt;
 459:         vmoving = 0;
 460:         wcursor = 0;
 461:         break;
 462: 
 463:     /*
 464: 	 * ^P		To previous line same column.  Ridiculous on the
 465: 	 *		console of the VAX since it puts console in LSI mode.
 466: 	 */
 467:     case 'k':
 468:     case CTRL(p):
 469:         wdot = dot - cnt;
 470:         if (vmoving == 0)
 471:             vmoving = 1, vmovcol = column(cursor);
 472:         wcursor = 0;
 473:         break;
 474: 
 475:     /*
 476: 	 * L		To last line on screen, or count'th line from the
 477: 	 *		bottom.
 478: 	 */
 479:     case 'L':
 480:         wdot = dot + vcnt - vcline - cnt;
 481:         if (opf == vmove)
 482:             markit(wdot);
 483:         vmoving = 0;
 484:         wcursor = 0;
 485:         break;
 486: 
 487:     /*
 488: 	 * M		To the middle of the screen.
 489: 	 */
 490:     case 'M':
 491:         wdot = dot + ((vcnt + 1) / 2) - vcline - 1;
 492:         if (opf == vmove)
 493:             markit(wdot);
 494:         vmoving = 0;
 495:         wcursor = 0;
 496:         break;
 497: 
 498:     /*
 499: 	 * +		Forward line, to first non-white.
 500: 	 *
 501: 	 * CR		Convenient synonym for +.
 502: 	 */
 503:     case '+':
 504:     case CR:
 505:         wdot = dot + cnt;
 506:         vmoving = 0;
 507:         wcursor = 0;
 508:         break;
 509: 
 510:     /*
 511: 	 * ^N		To next line, same column if possible.
 512: 	 *
 513: 	 * LF		Linefeed is a convenient synonym for ^N.
 514: 	 */
 515:     case CTRL(n):
 516:     case 'j':
 517:     case NL:
 518:         wdot = dot + cnt;
 519:         if (vmoving == 0)
 520:             vmoving = 1, vmovcol = column(cursor);
 521:         wcursor = 0;
 522:         break;
 523: 
 524:     /*
 525: 	 * n		Search to next match of current pattern.
 526: 	 */
 527:     case 'n':
 528:         vglobp = vscandir;
 529:         c = *vglobp++;
 530:         goto nocount;
 531: 
 532:     /*
 533: 	 * N		Like n but in reverse direction.
 534: 	 */
 535:     case 'N':
 536:         vglobp = vscandir[0] == '/' ? "?" : "/";
 537:         c = *vglobp++;
 538:         goto nocount;
 539: 
 540:     /*
 541: 	 * '		Return to line specified by following mark,
 542: 	 *		first white position on line.
 543: 	 *
 544: 	 * `		Return to marked line at remembered column.
 545: 	 */
 546:     case '\'':
 547:     case '`':
 548:         d = c;
 549:         c = getesc();
 550:         if (c == 0)
 551:             return;
 552:         c = markreg(c);
 553:         forbid (c == 0);
 554:         wdot = getmark(c);
 555:         forbid (wdot == NOLINE);
 556:         vmoving = 0;
 557:         wcursor = d == '`' ? ncols[c - 'a'] : 0;
 558:         if (opf == vmove && (wdot != dot || (d == '`' && wcursor != cursor)))
 559:             markDOT();
 560:         if (wcursor) {
 561:             vsave();
 562:             getline(*wdot);
 563:             if (wcursor > strend(linebuf))
 564:                 wcursor = 0;
 565:             getDOT();
 566:         }
 567:         if (ospeed > B300)
 568:             hold |= HOLDWIG;
 569:         break;
 570: 
 571:     /*
 572: 	 * G		Goto count'th line, or last line if no count
 573: 	 *		given.
 574: 	 */
 575:     case 'G':
 576:         if (!Xhadcnt)
 577:             cnt = lineDOL();
 578:         wdot = zero + cnt;
 579:         forbid (wdot < one || wdot > dol);
 580:         if (opf == vmove)
 581:             markit(wdot);
 582:         vmoving = 0;
 583:         wcursor = 0;
 584:         break;
 585: 
 586:     /*
 587: 	 * /		Scan forward for following re.
 588: 	 * ?		Scan backward for following re.
 589: 	 */
 590:     case '/':
 591:     case '?':
 592:         vsave();
 593:         ocurs = cursor;
 594:         wcursor = 0;
 595:         if (readecho(c))
 596:             return;
 597:         if (!vglobp)
 598:             vscandir[0] = genbuf[0];
 599:         oglobp = globp; CP(vutmp, genbuf); globp = vutmp;
 600:         d = peekc; ungetchar(0); fixech();
 601:         CATCH
 602: #ifndef CBREAK
 603:             /*
 604: 			 * Lose typeahead (ick).
 605: 			 */
 606:             vcook();
 607: #endif
 608:             addr = address(cursor);
 609: #ifndef CBREAK
 610:             vraw();
 611: #endif
 612:         ONERR
 613: #ifndef CBREAK
 614:             vraw();
 615: #endif
 616:             globp = oglobp;
 617:             ungetchar(d);
 618:             splitw = 0;
 619:             vclean();
 620:             vjumpto(dot, ocurs, 0);
 621:             return;
 622:         ENDCATCH
 623:         if (globp == 0)
 624:             globp = "";
 625:         else if (peekc)
 626:             --globp;
 627:         ungetchar(d);
 628:         c = 0;
 629:         if (*globp == 'z')
 630:             globp++, c = '\n';
 631:         if (any(*globp, "^+-."))
 632:             c = *globp++;
 633:         i = 0;
 634:         while (isdigit(*globp))
 635:             i = i * 10 + *globp++ - '0';
 636:         if (*globp)
 637:             c = *globp++;
 638:         globp = oglobp;
 639:         splitw = 0;
 640:         vmoving = 0;
 641:         wcursor = loc1;
 642:         if (i != 0)
 643:             vsetsiz(i);
 644:         if (opf == vmove) {
 645: #ifdef OPENCODE
 646:             if (state == ONEOPEN || state == HARDOPEN)
 647:                 outline = destline = WBOT;
 648: #endif
 649:             if (addr != dot || loc1 != cursor)
 650:                 markDOT();
 651:             if (loc1 > linebuf && *loc1 == 0)
 652:                 loc1--;
 653:             if (c)
 654:                 vjumpto(addr, loc1, c);
 655:             else {
 656:                 vmoving = 0;
 657:                 if (loc1) {
 658:                     vmoving++;
 659:                     vmovcol = column(loc1);
 660:                 }
 661:                 getDOT();
 662: #ifdef OPENCODE
 663:                 if (state == CRTOPEN && addr != dot)
 664:                     vup1();
 665: #endif
 666:                 vupdown(addr - dot, NOSTR);
 667:             }
 668:             return;
 669:         }
 670:         lastcp[-1] = 'n';
 671:         getDOT();
 672:         wdot = addr;
 673:         break;
 674:     }
 675:     /*
 676: 	 * Apply.
 677: 	 */
 678:     if (vreg && wdot == 0)
 679:         wdot = dot;
 680:     (*opf)(c);
 681:     wdot = NOLINE;
 682: }
 683: 
 684: /*
 685:  * Find single character c, in direction dir from cursor.
 686:  */
 687: find(c)
 688:     char c;
 689: {
 690: 
 691:     for(;;) {
 692:         if (edge())
 693:             return (0);
 694:         wcursor += dir;
 695:         if (*wcursor == c)
 696:             return (1);
 697:     }
 698: }
 699: 
 700: /*
 701:  * Do a word motion with operator op, and cnt more words
 702:  * to go after this.
 703:  */
 704: word(op, cnt)
 705:     register int (*op)();
 706:     int cnt;
 707: {
 708:     register int which;
 709:     register char *iwc;
 710:     register line *iwdot = wdot;
 711: 
 712:     if (dir == 1) {
 713:         iwc = wcursor;
 714:         which = wordch(wcursor);
 715:         while (wordof(which, wcursor)) {
 716:             if (cnt == 1 && op != vmove && wcursor[1] == 0) {
 717:                 wcursor++;
 718:                 break;
 719:             }
 720:             if (!lnext())
 721:                 return (0);
 722:             if (wcursor == linebuf)
 723:                 break;
 724:         }
 725:         /* Unless last segment of a change skip blanks */
 726:         if (op != vchange || cnt > 1)
 727:             while (!margin() && blank())
 728:                 wcursor++;
 729:         else
 730:             if (wcursor == iwc && iwdot == wdot && *iwc)
 731:                 wcursor++;
 732:         if (op == vmove && margin())
 733:             wcursor--;
 734:     } else {
 735:         if (!lnext())
 736:             return (0);
 737:         while (blank())
 738:             if (!lnext())
 739:                 return (0);
 740:         if (!margin()) {
 741:             which = wordch(wcursor);
 742:             while (!margin() && wordof(which, wcursor))
 743:                 wcursor--;
 744:         }
 745:         if (wcursor < linebuf || !wordof(which, wcursor))
 746:             wcursor++;
 747:     }
 748:     return (1);
 749: }
 750: 
 751: /*
 752:  * To end of word, with operator op and cnt more motions
 753:  * remaining after this.
 754:  */
 755: eend(op)
 756:     register int (*op)();
 757: {
 758:     register int which;
 759: 
 760:     if (!lnext())
 761:         return;
 762:     while (blank())
 763:         if (!lnext())
 764:             return;
 765:     which = wordch(wcursor);
 766:     while (wordof(which, wcursor)) {
 767:         if (wcursor[1] == 0) {
 768:             wcursor++;
 769:             break;
 770:         }
 771:         if (!lnext())
 772:             return;
 773:     }
 774:     if (op != vchange && op != vdelete && wcursor > linebuf)
 775:         wcursor--;
 776: }
 777: 
 778: /*
 779:  * Wordof tells whether the character at *wc is in a word of
 780:  * kind which (blank/nonblank words are 0, conservative words 1).
 781:  */
 782: wordof(which, wc)
 783:     char which;
 784:     register char *wc;
 785: {
 786: 
 787:     if (isspace(*wc))
 788:         return (0);
 789:     return (!wdkind || wordch(wc) == which);
 790: }
 791: 
 792: /*
 793:  * Wordch tells whether character at *wc is a word character
 794:  * i.e. an alfa, digit, or underscore.
 795:  */
 796: wordch(wc)
 797:     char *wc;
 798: {
 799:     register int c;
 800: 
 801:     c = wc[0];
 802:     return (isalpha(c) || isdigit(c) || c == '_');
 803: }
 804: 
 805: /*
 806:  * Edge tells when we hit the last character in the current line.
 807:  */
 808: edge()
 809: {
 810: 
 811:     if (linebuf[0] == 0)
 812:         return (1);
 813:     if (dir == 1)
 814:         return (wcursor[1] == 0);
 815:     else
 816:         return (wcursor == linebuf);
 817: }
 818: 
 819: /*
 820:  * Margin tells us when we have fallen off the end of the line.
 821:  */
 822: margin()
 823: {
 824: 
 825:     return (wcursor < linebuf || wcursor[0] == 0);
 826: }

Defined functions

edge defined in line 808; used 2 times
eend defined in line 755; used 1 times
find defined in line 687; used 1 times
margin defined in line 822; used 9 times
operate defined in line 21; used 3 times
word defined in line 704; used 1 times
wordch defined in line 796; used 5 times
wordof defined in line 782; used 5 times

Defined variables

vscandir defined in line 9; used 3 times

Defined macros

blank defined in line 6; used 3 times
forbid defined in line 7; used 16 times
Last modified: 1980-09-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1415
Valid CSS Valid XHTML 1.0 Strict