1: /*************************************************************************
   2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
   3:  * provided to you without charge for use only on a licensed Unix        *
   4:  * system.  You may copy JOVE provided that this notice is included with *
   5:  * the copy.  You may not sell copies of this program or versions        *
   6:  * modified for use on microcomputer systems, unless the copies are      *
   7:  * included with a Unix system distribution and the source is provided.  *
   8:  *************************************************************************/
   9: 
  10: #include "jove.h"
  11: #include "ctype.h"
  12: #include <signal.h>
  13: 
  14: struct cmd *
  15: FindCmd(proc)
  16: register int    (*proc)();
  17: {
  18:     register struct cmd *cp;
  19: 
  20:     for (cp = commands; cp->Name; cp++)
  21:         if (cp->c_proc == proc)
  22:             return cp;
  23:     return 0;
  24: }
  25: 
  26: int Interactive;    /* True when we invoke with the command handler? */
  27: char    *ProcFmt = ": %f ";
  28: 
  29: ExecCmd(cp)
  30: data_obj    *cp;
  31: {
  32:     LastCmd = cp;
  33:     if (cp->Type & MAJOR_MODE)
  34:         SetMajor((cp->Type >> 8));
  35:     else if (cp->Type & MINOR_MODE)
  36:         TogMinor((cp->Type >> 8));
  37:     else    switch (cp->Type&TYPEMASK) {
  38:         case MACRO:
  39:             do_macro((struct macro *) cp);
  40:             break;
  41: 
  42:         case FUNCTION:
  43:             {
  44:                 struct cmd  *cmd = (struct cmd *) cp;
  45: 
  46:             if (cmd->c_proc)
  47:                 (*cmd->c_proc)();
  48:             }
  49:     }
  50: }
  51: 
  52: Line *
  53: lastline(lp)
  54: register Line   *lp;
  55: {
  56:     while (lp->l_next)
  57:         lp = lp->l_next;
  58:     return lp;
  59: }
  60: 
  61: Upper(c)
  62: register int    c;
  63: {
  64:     return (islower(c) ? toupper(c) : c);
  65: }
  66: 
  67: int alarmed = 0;
  68: 
  69: char    key_strokes[100];
  70: static char *key_p = key_strokes;
  71: 
  72: init_strokes()
  73: {
  74:     key_strokes[0] = 0;
  75:     key_p = key_strokes;
  76: }
  77: 
  78: add_stroke(c)
  79: {
  80:     if (key_p + 5 > &key_strokes[(sizeof key_strokes) - 1])
  81:         key_p = key_strokes;
  82:     sprintf(key_p, "%p ", c);
  83:     key_p += strlen(key_p);
  84: }
  85: 
  86: slowpoke()
  87: {
  88:     alarmed++;
  89:     f_mess(key_strokes);
  90: }
  91: 
  92: #ifdef BSD4_2
  93: #	define N_SEC  1   /* will be precisely 1 second on 4.2 */
  94: #else
  95: #	define N_SEC  2   /* but from 0 to 2 seconds otherwise */
  96: #endif
  97: 
  98: waitchar()
  99: {
 100: #ifdef EUNICE
 101:     return getch();
 102: #endif
 103:     unsigned int    old_time;
 104:     int c;
 105:     int (*oldproc)();
 106: 
 107:     alarmed = 0;
 108:     oldproc = signal(SIGALRM, slowpoke);
 109: 
 110:     if ((old_time = alarm((unsigned) N_SEC)) == 0)
 111:         old_time = UpdFreq;
 112:     c = getch();
 113:     (void) alarm(old_time);
 114:     (void) signal(SIGALRM, oldproc);
 115: 
 116:     return c;
 117: }
 118: 
 119: /* dir > 0 means forward; else means backward. */
 120: 
 121: char *
 122: StrIndex(dir, buf, charpos, what)
 123: char    *buf,
 124:     what;
 125: {
 126:     char    *cp = &buf[charpos],
 127:         c;
 128: 
 129:     if (dir > 0) {
 130:         while (c = *cp++)
 131:             if (c == what)
 132:                 return (cp - 1);
 133:     } else {
 134:         while (cp >= buf && (c = *cp--))
 135:             if (c == what)
 136:                 return (cp + 1);
 137:     }
 138:     return 0;
 139: }
 140: 
 141: blnkp(buf)
 142: register char   *buf;
 143: {
 144:     register char   c;
 145: 
 146:     while ((c = *buf++) && (c == ' ' || c == '\t'))
 147:         ;
 148:     return c == 0;  /* It's zero if we got to the end of the Line */
 149: }
 150: 
 151: Line *
 152: next_line(line, num)
 153: register Line   *line;
 154: register int    num;
 155: {
 156:     if (num < 0)
 157:         return prev_line(line, -num);
 158:     if (line)
 159:         while (--num >= 0 && line->l_next != 0)
 160:             line = line->l_next;
 161:     return line;
 162: }
 163: 
 164: Line *
 165: prev_line(line, num)
 166: register Line   *line;
 167: register int    num;
 168: {
 169:     if (num < 0)
 170:         return next_line(line, -num);
 171:     if (line)
 172:         while (--num >= 0 && line->l_prev != 0)
 173:             line = line->l_prev;
 174:     return line;
 175: }
 176: 
 177: DotTo(line, col)
 178: Line    *line;
 179: {
 180:     Bufpos  bp;
 181: 
 182:     bp.p_line = line;
 183:     bp.p_char = col;
 184:     SetDot(&bp);
 185: }
 186: 
 187: /* If bp->p_line is != current line, then save current line.  Then set dot
 188:    to bp->p_line, and if they weren't equal get that line into linebuf.  */
 189: 
 190: SetDot(bp)
 191: register Bufpos *bp;
 192: {
 193:     register int    notequal;
 194: 
 195:     if (bp == 0)
 196:         return;
 197: 
 198:     notequal = bp->p_line != curline;
 199:     if (notequal)
 200:         lsave();
 201:     if (bp->p_line)
 202:         curline = bp->p_line;
 203:     curchar = bp->p_char;
 204:     if (notequal)
 205:         getDOT();
 206: }
 207: 
 208: ToLast()
 209: {
 210:     SetLine(curbuf->b_last);
 211:     Eol();
 212: }
 213: 
 214: int MarkThresh = 22;    /* Average screen size ... */
 215: static int  line_diff;
 216: 
 217: LineDist(nextp, endp)
 218: register Line   *nextp,
 219:         *endp;
 220: {
 221:     (void) inorder(nextp, 0, endp, 0);
 222:     return line_diff;
 223: }
 224: 
 225: inorder(nextp, char1, endp, char2)
 226: register Line   *nextp,
 227:         *endp;
 228: {
 229:     int count = 0;
 230:     register Line   *prevp = nextp;
 231: 
 232:     line_diff = 0;
 233:     if (nextp == endp)
 234:         return char1 < char2;
 235: 
 236:     while (nextp || prevp) {
 237:         if (nextp == endp || prevp == endp)
 238:             break;
 239:         if (nextp)
 240:             nextp = nextp->l_next;
 241:         if (prevp)
 242:             prevp = prevp->l_prev;
 243:         count++;
 244:     }
 245:     if (nextp == 0 && prevp == 0)
 246:         return -1;
 247:     line_diff = count;
 248: 
 249:     return nextp == endp;
 250: }
 251: 
 252: PushPntp(line)
 253: register Line   *line;
 254: {
 255:     exp_p = 0;
 256:     if (LineDist(curline, line) >= MarkThresh)
 257:         SetMark();
 258: }
 259: 
 260: ToFirst()
 261: {
 262:     SetLine(curbuf->b_first);
 263: }
 264: 
 265: length(line)
 266: Line    *line;
 267: {
 268:     return strlen(lcontents(line));
 269: };
 270: 
 271: to_word(dir)
 272: register int    dir;
 273: {
 274:     register char   c;
 275: 
 276:     if (dir > 0) {
 277:         while ((c = linebuf[curchar]) != 0 && !isword(c))
 278:             curchar++;
 279:         if (eolp()) {
 280:             if (curline->l_next == 0)
 281:                 return;
 282:             SetLine(curline->l_next);
 283:             to_word(dir);
 284:             return;
 285:         }
 286:     } else {
 287:         while (!bolp() && (c = linebuf[curchar - 1], !isword(c)))
 288:             --curchar;
 289:         if (bolp()) {
 290:             if (curline->l_prev == 0)
 291:                 return;
 292:             SetLine(curline->l_prev);
 293:             Eol();
 294:             to_word(dir);
 295:         }
 296:     }
 297: }
 298: 
 299: /* Are there any modified buffers?  Allp means include B_PROCESS and
 300:    B_IPROCESS buffers in the check, but never scratch buffers. */
 301: 
 302: ModBufs(allp)
 303: {
 304:     register Buffer *b;
 305: 
 306:     for (b = world; b != 0; b = b->b_next) {
 307:         if (b->b_type == B_SCRATCH)
 308:             continue;
 309:         if ((b->b_type == B_FILE || allp) && IsModified(b))
 310:             return 1;
 311:     }
 312:     return 0;
 313: }
 314: 
 315: char *
 316: filename(b)
 317: register Buffer *b;
 318: {
 319:     return b->b_fname ? pr_name(b->b_fname) : "[No file]";
 320: }
 321: 
 322: char *
 323: itoa(num)
 324: register int    num;
 325: {
 326:     static char line[15];
 327: 
 328:     sprintf(line, "%d", num);
 329:     return line;
 330: }
 331: 
 332: min(a, b)
 333: register int    a,
 334:         b;
 335: {
 336:     return (a < b) ? a : b;
 337: }
 338: 
 339: max(a, b)
 340: register int    a,
 341:         b;
 342: {
 343:     return (a > b) ? a : b;
 344: }
 345: 
 346: tiewind(wp, bp)
 347: register Window *wp;
 348: register Buffer *bp;
 349: {
 350:     UpdModLine++;   /* Kludge ... but speeds things up considerably */
 351:     wp->w_line = bp->b_dot;
 352:     wp->w_char = bp->b_char;
 353:     wp->w_bufp = bp;
 354: }
 355: 
 356: extern int  Jr_Len;
 357: 
 358: char *
 359: lcontents(line)
 360: register Line   *line;
 361: {
 362:     if (line == curline)
 363:         return linebuf;
 364:     else
 365:         return lbptr(line);
 366: }
 367: 
 368: char *
 369: ltobuf(line, buf)
 370: Line    *line;
 371: char    *buf;
 372: {
 373:     if (line == curline) {
 374:         if (buf != linebuf)
 375:             strcpy(buf, linebuf);
 376:         Jr_Len = strlen(linebuf);
 377:     } else
 378:         (void) getline(line->l_dline, buf);
 379:     return buf;
 380: }
 381: 
 382: /* Return none-zero if we had to rearrange the order. */
 383: 
 384: fixorder(line1, char1, line2, char2)
 385: register Line   **line1,
 386:         **line2;
 387: register int    *char1,
 388:         *char2;
 389: {
 390:     Line    *tline;
 391:     int tchar;
 392: 
 393:     if (inorder(*line1, *char1, *line2, *char2))
 394:         return 0;
 395: 
 396:     tline = *line1;
 397:     tchar = *char1;
 398:     *line1 = *line2;
 399:     *char1 = *char2;
 400:     *line2 = tline;
 401:     *char2 = tchar;
 402: 
 403:     return 1;
 404: }
 405: 
 406: inlist(first, what)
 407: register Line   *first,
 408:         *what;
 409: {
 410:     while (first) {
 411:         if (first == what)
 412:             return 1;
 413:         first = first->l_next;
 414:     }
 415:     return 0;
 416: }
 417: 
 418: /* Make `buf' modified and tell the redisplay code to update the modeline
 419:    if it will need to be changed. */
 420: 
 421: int ModCount = 0;
 422: 
 423: modify()
 424: {
 425:     extern int  DOLsave;
 426: 
 427:     if (!curbuf->b_modified)
 428:         UpdModLine++;
 429:     curbuf->b_modified++;
 430:     DOLsave++;
 431:     if (!Asking)
 432:         ModCount++;
 433: }
 434: 
 435: unmodify()
 436: {
 437:     if (curbuf->b_modified)
 438:         UpdModLine++;
 439:     curbuf->b_modified = 0;
 440: }
 441: 
 442: numcomp(s1, s2)
 443: register char   *s1,
 444:         *s2;
 445: {
 446:     register int    count = 0;
 447: 
 448:     while (*s1 != 0 && *s1++ == *s2++)
 449:         count++;
 450:     return count;
 451: }
 452: 
 453: char *
 454: copystr(str)
 455: char    *str;
 456: {
 457:     char    *val = emalloc(strlen(str) + 1);
 458: 
 459:     strcpy(val, str);
 460:     return val;
 461: }
 462: 
 463: #ifndef byte_copy
 464: byte_copy(from, to, count)
 465: register char   *from,
 466:         *to;
 467: register int    count;
 468: {
 469:     while (--count >= 0)
 470:         *to++ = *from++;
 471: }
 472: #endif
 473: 
 474: len_error(flag)
 475: {
 476:     char    *mesg = "[line too long]";
 477: 
 478:     (flag == COMPLAIN) ? complain(mesg) : error(mesg);
 479: }
 480: 
 481: /* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
 482: 
 483: ins_c(c, buf, atchar, num, max)
 484: char    c, *buf;
 485: {
 486:     register char   *pp, *pp1;
 487:     register int    len;
 488:     int numchars;   /* Number of characters to copy forward */
 489: 
 490:     if (num <= 0)
 491:         return;
 492:     len = atchar + strlen(&buf[atchar]);
 493:     if (len + num >= max)
 494:         len_error(COMPLAIN);
 495:     pp = &buf[len + 1];     /* + 1 so we can --pp (not pp--) */
 496:     pp1 = &buf[len + num + 1];
 497:     numchars = len - atchar;
 498:     while (numchars-- >= 0)
 499:         *--pp1 = *--pp;
 500:     pp = &buf[atchar];
 501:     while (--num >= 0)
 502:         *pp++ = c;
 503: }
 504: 
 505: TwoBlank()
 506: {
 507:     register Line   *next = curline->l_next;
 508: 
 509:     return ((next != 0) &&
 510:         (*(lcontents(next)) == '\0') &&
 511:         (next->l_next != 0) &&
 512:         (*(lcontents(next->l_next)) == '\0'));
 513: }
 514: 
 515: linecopy(onto, atchar, from)
 516: register char   *onto,
 517:         *from;
 518: {
 519:     register char   *endp = &onto[LBSIZE - 2];
 520: 
 521:     onto += atchar;
 522: 
 523:     while (*onto = *from++)
 524:         if (onto++ >= endp)
 525:             len_error(ERROR);
 526: }
 527: 
 528: char *
 529: IOerr(err, file)
 530: char    *err, *file;
 531: {
 532:     return sprint("Couldn't %s \"%s\".", err, file);
 533: }
 534: 
 535: pclose(p)
 536: int *p;
 537: {
 538:     (void) close(p[0]);
 539:     (void) close(p[1]);
 540: }
 541: 
 542: dopipe(p)
 543: int p[];
 544: {
 545:     if (pipe(p) == -1)
 546:         complain("[Pipe failed]");
 547: }
 548: 
 549: /* NOSTRICT */
 550: 
 551: char *
 552: emalloc(size)
 553: {
 554:     char    *ptr;
 555: 
 556:     if (ptr = malloc((unsigned) size))
 557:         return ptr;
 558:     /* Try garbage collecting lines */
 559:     GCchunks();
 560:     if (ptr = malloc((unsigned) size))
 561:         return ptr;
 562:     /* Uh ... Oh screw it! */
 563:     error("[Out of memory] ");
 564:     /* NOTREACHED */
 565: }
 566: 
 567: /* Return the basename of file F. */
 568: 
 569: char *
 570: basename(f)
 571: register char   *f;
 572: {
 573:     register char   *cp;
 574: 
 575:     if (cp = rindex(f, '/'))
 576:         return cp + 1;
 577:     else
 578:         return f;
 579: }
 580: 
 581: push_env(savejmp)
 582: jmp_buf savejmp;
 583: {
 584:     byte_copy((char *) mainjmp, (char *) savejmp, sizeof (jmp_buf));
 585: }
 586: 
 587: pop_env(savejmp)
 588: jmp_buf savejmp;
 589: {
 590:     byte_copy((char *) savejmp, (char *) mainjmp, sizeof (jmp_buf));
 591: }
 592: 
 593: #ifdef LOAD_AV
 594: #  ifdef BSD4_2
 595: #    ifdef PURDUE_EE
 596: 
 597: get_la(dp)
 598: double *dp;
 599: {
 600:     *dp = (double) loadav(0) / 100.0;
 601: }
 602: 
 603: #    else PURDUE_EE
 604: 
 605: #include <nlist.h>
 606: 
 607: static struct   nlist nl[] = {
 608:     { "_avenrun" },
 609: #define X_AVENRUN   0
 610:     { "" }
 611: };
 612: 
 613: get_la(dp)
 614: double  *dp;
 615: {
 616:     double  avenrun[3];
 617:     static int  kmem = 0;
 618: 
 619:     if (kmem == -1) {
 620:         *dp = 4.0;  /* So shell commands will say "Chugging" */
 621:         return;
 622:     } else if (kmem == 0) {
 623:         if ((kmem = open("/dev/kmem", 0)) == -1) {
 624:             f_mess("Can't open kmem for load average.");
 625:             *dp = 4.0;
 626:             return;
 627:         }
 628:         nlist("/vmunix", nl);
 629:     }
 630:     lseek(kmem, (long) nl[X_AVENRUN].n_value, 0);
 631:     read(kmem, (char *) avenrun, sizeof(avenrun));
 632:     *dp = avenrun[0];
 633: }
 634: 
 635: #    endif PURDUE_EE
 636: #  else BSD4_2
 637: 
 638: get_la(dp)
 639: double  *dp;
 640: {
 641:     short   avg[3];
 642: 
 643:     gldav(avg);
 644:     *dp = (double) avg[0] / 256;
 645: }
 646: 
 647: #  endif BSD4_2
 648: #endif LOAD_AV
 649: 
 650: /* get the time buf, designated by *timep, from FROM to TO. */
 651: char *
 652: get_time(timep, buf, from, to)
 653: char    *buf;
 654: time_t  *timep;
 655: {
 656:     time_t  now;
 657:     char    *cp;
 658:     extern char *ctime();
 659: 
 660:     if (timep != 0)
 661:         now = *timep;
 662:     else
 663:         (void) time(&now);
 664:     cp = ctime(&now) + from;
 665:     if (to == -1)
 666:         cp[strlen(cp) - 1] = '\0';      /* Get rid of \n */
 667:     else
 668:         cp[to - from] = '\0';
 669:     if (buf) {
 670:         strcpy(buf, cp);
 671:         return buf;
 672:     } else
 673:         return cp;
 674: }
 675: 
 676: /* Return length of null terminated string. */
 677: 
 678: strlen(s)
 679: register char   *s;
 680: {
 681:     register char   *base = s + 1;  /* Can you say kludge? */
 682: 
 683:     while (*s++)
 684:         ;
 685:     return (s - base);
 686: }
 687: 
 688: char *
 689: index(s, c)
 690: register char   *s;
 691: register int    c;
 692: {
 693:     register int    c1;
 694: 
 695:     if (c != 0)
 696:         while (c1 = *s++)
 697:             if (c == c1)
 698:                 return s - 1;
 699:     return 0;
 700: }
 701: 
 702: strcmp(s1, s2)
 703: register char   *s1,
 704:         *s2;
 705: {
 706:     if (!s1 || !s2)
 707:         return 1;   /* Which is not zero ... */
 708:     while (*s1 == *s2++)
 709:         if (*s1++ == '\0')
 710:             return 0;
 711:     return (*s1 - *--s2);
 712: }
 713: 
 714: casecmp(s1, s2)
 715: register char   *s1,
 716:         *s2;
 717: {
 718:     if (!s1 || !s2)
 719:         return 1;   /* Which is not zero ... */
 720:     while (*s1 == *s2++ || Upper(*s1) == Upper(s2[-1]))
 721:         if (*s1++ == '\0')
 722:             return 0;
 723:     return (*s1 - *--s2);
 724: }
 725: 
 726: casencmp(s1, s2, n)
 727: register char   *s1,
 728:         *s2;
 729: register int    n;
 730: {
 731:     if (!s1 || !s2)
 732:         return 1;   /* Which is not zero ... */
 733:     while (--n >= 0  && (*s1 == *s2++ || Upper(*s1) == Upper(s2[-1])))
 734:         if (*s1++ == '\0')
 735:             return 0;
 736:     return ((n < 0) ? 0 : *s1 - *--s2);
 737: }
 738: 
 739: null_ncpy(to, from, n)
 740: char    *to,
 741:     *from;
 742: {
 743:     (void) strncpy(to, from, n);
 744:     to[n] = '\0';
 745: }
 746: 
 747: strcpy(t, f)
 748: register char   *t,
 749:         *f;
 750: {
 751:     while (*t++ = *f++)
 752:         ;
 753: }
 754: 
 755: /* Tries to pause for delay/10 seconds OR until a character is typed
 756:    at the keyboard.  This works well on BSD4_2 and not so well on the
 757:    rest.  Returns 1 if it returned because of keyboard input, or 0
 758:    otherwise. */
 759: 
 760: SitFor(delay)
 761: int delay;
 762: {
 763: #ifdef BSD4_2
 764: #include <sys/time.h>
 765: 
 766:     struct timeval  timer;
 767:     int readfds = 1,
 768:         writefds = 0,
 769:         exceptfds = 0;
 770: 
 771:     timer.tv_sec = (delay / 10);
 772:     timer.tv_usec = (delay % 10) * 100000;
 773: 
 774:     if (charp())
 775:         return 1;
 776:     /* gross that I had to snarf this from getch() */
 777:     if (!UpdMesg && !Asking) {  /* Don't erase if we are asking */
 778:         if (mesgbuf[0] && !errormsg)
 779:             message(NullStr);
 780:     }
 781:     redisplay();
 782:     return select(1, &readfds, &writefds, &exceptfds, &timer);
 783: #else
 784:     static float cps[] = {
 785:         0.0,
 786:         5.0,
 787:         7.5,
 788:         11.0,
 789:         13.4,
 790:         15.0,
 791:         20.0,
 792:         30.0,
 793:         60.0,
 794:         120.0,
 795:         180.0,
 796:         240.0,
 797:         480.0,
 798:         960.0,
 799:         1920.0,
 800:         1920.0,
 801:     };
 802:     float   nsecs;
 803:     register int    nchars;
 804: 
 805:     if (charp())
 806:         return 1;
 807:     nsecs = (float) delay / 10;
 808:     nchars = (int) (nsecs * cps[ospeed]);
 809:     redisplay();
 810:     while ((--nchars > 0) && !InputPending) {
 811:         putchar(0);
 812:         if (OkayAbort) {
 813:             OkayAbort = 0;
 814:             InputPending = charp();
 815:         }
 816:     }
 817:     return InputPending;
 818: #endif
 819: }
 820: 
 821: sindex(pattern, string)
 822: register char   *pattern,
 823:         *string;
 824: {
 825:     register int    len = strlen(pattern);
 826: 
 827:     while (*string != '\0') {
 828:         if (*pattern == *string && strncmp(pattern, string, len) == 0)
 829:             return TRUE;
 830:         string++;
 831:     }
 832:     return FALSE;
 833: }

Defined functions

FindCmd defined in line 14; used 4 times
LineDist defined in line 217; used 4 times
ModBufs defined in line 302; used 4 times
PushPntp defined in line 252; used 4 times
SitFor defined in line 760; used 5 times
TwoBlank defined in line 505; used 2 times
add_stroke defined in line 78; used 1 times
byte_copy defined in line 464; never used
casecmp defined in line 714; used 2 times
casencmp defined in line 726; used 3 times
dopipe defined in line 542; used 2 times
filename defined in line 315; used 3 times
get_la defined in line 638; used 2 times
get_time defined in line 651; used 3 times
index defined in line 688; never used
init_strokes defined in line 72; used 2 times
inlist defined in line 406; used 4 times
ins_c defined in line 483; used 2 times
itoa defined in line 322; used 2 times
len_error defined in line 474; used 5 times
linecopy defined in line 515; used 4 times
numcomp defined in line 442; used 5 times
pclose defined in line 535; used 4 times
prev_line defined in line 164; used 10 times
sindex defined in line 821; used 5 times
slowpoke defined in line 86; used 1 times
tiewind defined in line 346; used 5 times
to_word defined in line 271; used 7 times
waitchar defined in line 98; used 6 times

Defined variables

Interactive defined in line 26; used 2 times
MarkThresh defined in line 214; used 4 times
ModCount defined in line 421; used 1 times
alarmed defined in line 67; used 9 times
key_p defined in line 70; used 6 times
key_strokes defined in line 69; used 19 times
line_diff defined in line 215; used 3 times
nl defined in line 607; used 2 times

Defined macros

N_SEC defined in line 95; used 1 times
X_AVENRUN defined in line 609; used 1 times
Last modified: 1986-03-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3293
Valid CSS Valid XHTML 1.0 Strict