|
|
1.1 ! root 1: /* ! 2: * File: rmemmon.c ! 3: * Contents: gd, memmon ! 4: */ ! 5: ! 6: /* ! 7: * gd.c - graphics driver for AED 1024. ! 8: * Rewrite this file to use a different output device. ! 9: * ! 10: * Except for gdwidth(), which is used only for layout, these functions ! 11: * provide a ONE-DIMENSIONAL interface to the AED. ! 12: */ ! 13: ! 14: #include "../h/rt.h" ! 15: #include "gc.h" ! 16: ! 17: #ifdef MemMon ! 18: ! 19: #include <sgtty.h> ! 20: #include <varargs.h> ! 21: ! 22: #define Height 768 /* screen height */ ! 23: #define Width 1024 /* screen width */ ! 24: #define PromptArea 50 /* pixels to reserve for prompting */ ! 25: #define PromptSize 40 /* size of prompt block proper */ ! 26: #define MaxColors 256 /* maximum number of distinct colors */ ! 27: #define MaxScale 16 /* maximum scaling factor */ ! 28: #define EndRun() if(runaddr)putc(runaddr=0,ofile); /* end a run of pixels */ ! 29: ! 30: static FILE *ifile = 0; /* AED input file */ ! 31: static FILE *ofile = 0; /* AED output file */ ! 32: static int yscale = 1; /* vertical scaling factor */ ! 33: static int npixels = Height * Width - PromptArea; /* screen size (scaled) */ ! 34: static runaddr = 0; /* curr addr if pixel run in progress */ ! 35: static int bgcolor; /* current background color */ ! 36: ! 37: /* ! 38: * gdinit(filename) - initialize for graphics output. ! 39: */ ! 40: ! 41: gdinit(fname) ! 42: char *fname; ! 43: { ! 44: FILE *newf; ! 45: int ofd; ! 46: struct sgttyb ttyb; ! 47: static int ldisc = NTTYDISC; ! 48: static int lbits = LLITOUT; ! 49: ! 50: if ((newf = fopen(fname,"w")) == NULL) ! 51: error("can't open MemMon file"); ! 52: if (isatty(ofd = fileno(newf))) { ! 53: if (ioctl(ofd, TIOCSETD, &ldisc)) ! 54: error("can't select new tty driver for MemMon file"); ! 55: if (ioctl(ofd, TIOCGETP, &ttyb)) ! 56: error("can't get sgtty block for MemMon file"); ! 57: if (ioctl(ofd, TIOCLBIS, &lbits)) ! 58: error("can't set LLITOUT on MemMon file"); ! 59: ttyb.sg_flags &= ~(RAW+ECHO); ! 60: if (ioctl(ofd, TIOCSETP, &ttyb)) ! 61: error("can't set tty attributes for MemMon file"); ! 62: if (ifile = fopen(fname,"r")) { ! 63: #ifndef VMS ! 64: setbuf(ifile,NULL); ! 65: #endif VMS ! 66: } ! 67: else { ! 68: fprintf(stderr, "can't read MemMon file; will not pause\n"); ! 69: fflush(stderr); ! 70: } ! 71: } ! 72: ofile = newf; ! 73: fputs("\033SEN18D88",ofile); /* set encoding mode to binary */ ! 74: aedout("gii",0,767); /* set normal window boundaries */ ! 75: } ! 76: ! 77: /* ! 78: * gdmap(array,n) - set color map. Each entry of array (of size n) has three ! 79: * bits each of red, green, blue values in least signifigant bits. The ! 80: * constants in the table below were determined empirically. ! 81: */ ! 82: ! 83: gdmap(a,n) ! 84: int a[], n; ! 85: { ! 86: unsigned char buf[3*MaxColors+4]; ! 87: unsigned char *p; ! 88: static unsigned char rmap[] = { 0, 20, 45, 70, 100, 140, 190, 255}; ! 89: static unsigned char gmap[] = { 0, 40, 60, 80, 110, 150, 195, 255}; ! 90: static unsigned char bmap[] = { 0, 40, 60, 80, 110, 150, 195, 255}; ! 91: ! 92: EndRun(); ! 93: p = buf; ! 94: *p++ = 'K'; ! 95: *p++ = 0; ! 96: *p++ = n; ! 97: while (n--) { ! 98: *p++ = rmap [ *a >> 6 ]; ! 99: *p++ = gmap [ (*a >> 3) & 7 ]; ! 100: *p++ = bmap [ *a++ & 7 ]; ! 101: } ! 102: fwrite(buf,1,p-buf,ofile); ! 103: } ! 104: ! 105: /* ! 106: * gdflood(c) - fill screen with color c. ! 107: */ ! 108: ! 109: gdflood(c) ! 110: int c; ! 111: { ! 112: EndRun(); ! 113: aedout("[b",c); /* set background color */ ! 114: aedout("~"); /* erase screen (kills scaling) */ ! 115: aedout("Ebb",1,yscale); /* reset scaling */ ! 116: bgcolor = c; /* save background color */ ! 117: } ! 118: ! 119: /* ! 120: * gdscale(n) - set vertical scaling factor. ! 121: */ ! 122: ! 123: gdscale(n) ! 124: int n; ! 125: { ! 126: EndRun(); ! 127: if (n > MaxScale) ! 128: n = MaxScale; ! 129: yscale = n; ! 130: npixels = (Height / n) * Width - PromptArea; ! 131: aedout("Ebb",1,n); /* set zoom to handle y scaling (only!) */ ! 132: } ! 133: ! 134: /* ! 135: * gdsize(n) - return size of display with scaling factor n; ! 136: */ ! 137: ! 138: gdsize(n) ! 139: int n; ! 140: { ! 141: if (n > MaxScale) ! 142: n = MaxScale; ! 143: return (Height / n) * Width - PromptArea; ! 144: } ! 145: ! 146: /* ! 147: * gdwidth() - return width of display with current scaling. ! 148: */ ! 149: ! 150: gdwidth() ! 151: { ! 152: return Width; ! 153: } ! 154: ! 155: /* ! 156: * gdpaint(start,n,color,b) - paint n pixels in given color. ! 157: * If b >= 0, the last pixel is to be that color instead (for a border) ! 158: */ ! 159: ! 160: gdpaint(s,n,c,b) ! 161: int s, n, c, b; ! 162: { ! 163: if (s < 0 || s >= npixels || n <= 0) ! 164: return; ! 165: if (s + n > npixels) ! 166: n = npixels - s; ! 167: if (runaddr && runaddr != s) ! 168: putc(runaddr=0,ofile); ! 169: if (!runaddr) { ! 170: aedout("Qx", s % Width, Height - 1 - s / Width); ! 171: aedout("s"); ! 172: } ! 173: runaddr = s + n; ! 174: if (b >= 0) ! 175: n--; ! 176: while (n > 254) { ! 177: putc(254,ofile); ! 178: putc(c,ofile); ! 179: n -= 254; ! 180: } ! 181: if (n > 0) { ! 182: putc(n,ofile); ! 183: putc(c,ofile); ! 184: } ! 185: if (b >= 0) { ! 186: putc(1,ofile); ! 187: putc(b,ofile); ! 188: } ! 189: } ! 190: ! 191: /* ! 192: * gdflush() - flush output. ! 193: */ ! 194: ! 195: gdflush() ! 196: { ! 197: fflush(ofile); ! 198: } ! 199: ! 200: /* ! 201: * gdpause(color) - pause for acknowledgement, showing color to hint at reason. ! 202: * Return last character before '\n', 0 if none, or EOF if not interactive. ! 203: */ ! 204: ! 205: gdpause(color) ! 206: int color; ! 207: { ! 208: int c1, c2, pline; ! 209: ! 210: if (!ifile) ! 211: return EOF; ! 212: EndRun(); ! 213: fputs("\r\007\033",ofile); /* ring bell */ ! 214: pline = Height - Height / yscale; ! 215: aedout("Qx",Width-PromptSize,pline); ! 216: aedout("sbbb",PromptSize,color,0); ! 217: fflush(ofile); ! 218: c1 = 0; ! 219: while ((c2 = getc(ifile)) != '\n') ! 220: if (c2 == EOF) { ! 221: ifile = 0; ! 222: c1 = EOF; ! 223: break; ! 224: } ! 225: else ! 226: c1 = c2; ! 227: aedout("Qx",Width-PromptSize,pline); ! 228: aedout("sbbb",PromptSize,bgcolor,0); ! 229: return c1; ! 230: } ! 231: ! 232: /* ! 233: * gdterm() - terminate graphics ! 234: */ ! 235: ! 236: gdterm() ! 237: { ! 238: if (!ofile) ! 239: return; /* if no file, just return */ ! 240: EndRun(); ! 241: aedout("Gs","3DNNN"); /* reset encoding */ ! 242: aedout("\r"); /* exit graphics mode */ ! 243: } ! 244: ! 245: /* ! 246: * aedout(s,args) - output command to the AED. ! 247: * s is a string specifying the command format a la printf. The first ! 248: * character (or two chars if first is '+') are the AED command. Additional ! 249: * characters specify formats for outputting additional arguments (see below). ! 250: */ ! 251: ! 252: /*VARARGS1*/ ! 253: static aedout (s, va_alist) ! 254: char *s; ! 255: va_dcl ! 256: { ! 257: va_list ap; ! 258: char c; ! 259: unsigned int n, x, y; ! 260: ! 261: va_start(ap); ! 262: if (putc(*s++,ofile) == '+') ! 263: putc(*s++,ofile); ! 264: while (c = *s++) ! 265: switch (c) { /* Output formats for add'l args: */ ! 266: case 'b': /* b - single byte unaltered */ ! 267: case 'c': /* c - single char unaltered */ ! 268: n = va_arg(ap,int); ! 269: putc(n, ofile); ! 270: break; ! 271: case 'i': /* i - 16-bit integer as two bytes */ ! 272: n = va_arg(ap,int); ! 273: putc(n>>8, ofile); ! 274: putc(n, ofile); ! 275: break; ! 276: case 's': /* s - string terminated by '\0' */ ! 277: fputs(va_arg(ap,int),ofile); ! 278: break; ! 279: case 'x': /* x - two args give x and y coords */ ! 280: x = va_arg(ap,int); ! 281: y = va_arg(ap,int); ! 282: putc(((x>>4)&0xF0) | (y>>8), ofile); ! 283: putc(x, ofile); ! 284: putc(y, ofile); ! 285: break; ! 286: default: /* unrecognized - just echoed */ ! 287: putc(c, ofile); ! 288: } ! 289: va_end(ap); ! 290: } ! 291: ! 292: ! 293: /* ! 294: * memmon.c - memory monitoring code excluding the device driver. ! 295: * When MemMon is undefined, gc.h defines these entrypoints ! 296: * as null macros. ! 297: */ ! 298: ! 299: /* ! 300: * Color list, indexed by block type or defined symbol. ! 301: * Every entry has 3 bits each (left to right) for red, green, blue. ! 302: * White is used for blocks not expected in the block region. ! 303: */ ! 304: ! 305: static int clist[] = { ! 306: /* --- these entries change color in marking phase --- */ ! 307: 0777, /* 0. T_Null white null value */ ! 308: 0777, /* 1. T_Integer white integer */ ! 309: 0777, /* 2. T_Longint white long integer */ ! 310: 0007, /* 3. T_Real blue real number */ ! 311: 0540, /* 4. T_Cset brown cset */ ! 312: 0405, /* 5. T_File purple file block */ ! 313: 0777, /* 6. T_Proc white procedure block */ ! 314: 0060, /* 7. T_List green list header block */ ! 315: 0770, /* 8. T_Table yellow table header block */ ! 316: 0077, /* 9. T_Record cyan record block */ ! 317: 0773, /* 10. T_Telem lt yel table element block */ ! 318: 0272, /* 11. T_Lelem lt grn list element block */ ! 319: 0756, /* 12. T_Tvsubs pink substring trapped variable */ ! 320: 0777, /* 13. T_Tvkywd white keyword trapped variable */ ! 321: 0751, /* 14. T_Tvtbl orange table elem trapped variable */ ! 322: 0600, /* 15. T_Set red set header block */ ! 323: 0700, /* 16. T_Selem brt red set element block */ ! 324: 0004, /* 17. T_Refresh navy refresh block */ ! 325: 0777, /* 18. T_Coexpr white co-expression block */ ! 326: 0777, /* 19. white unused */ ! 327: 0777, /* 20. white unused */ ! 328: 0777, /* 21. white unused */ ! 329: 0777, /* 22. UNcolr white unknown type */ ! 330: 0776, /* 23. STcolr ivory unbroken string */ ! 331: 0344, /* 24. STBcolr blue string separator */ ! 332: /* --- these entries remain constant --- */ ! 333: 0000, /* 25. BGcolr black background */ ! 334: 0222, /* 26. AVcolr med gry available space */ ! 335: 0000, /* 27. BKBcolr black block border */ ! 336: 0700, /* 28. GCcolr red begin garbage collection */ ! 337: 0770, /* 29. GARcolr yellow screen contents are garbage */ ! 338: 0007, /* 30. VALcolr blue screen contents are valid data */ ! 339: 0070, /* 31. GOcolr green ready to go after garb coll */ ! 340: /* --- these entries are used for color changes --- */ ! 341: 0222, /* 32. MKcolr med gry marked block */ ! 342: 0000, /* 33. UMcolr black unmarked block */ ! 343: 0222, /* 34. UMBcolr med gry unmarked block border */ ! 344: }; ! 345: ! 346: #define NColors 33 /* number of colors copied directly to color map */ ! 347: #define TColors 25 /* number of those which are transmutable */ ! 348: ! 349: #define UNcolr 22 ! 350: #define STcolr 23 ! 351: #define STBcolr 24 ! 352: #define BGcolr 25 ! 353: #define AVcolr 26 ! 354: #define BKBcolr 27 ! 355: #define GCcolr 28 ! 356: #define GARcolr 29 ! 357: #define VALcolr 30 ! 358: #define GOcolr 31 ! 359: #define MKcolr 32 ! 360: #define UMcolr 33 ! 361: #define UMBcolr 34 ! 362: ! 363: /* ! 364: * Color map buffer, initialized in MMInit and thereafter unaltered. ! 365: * The color map downloaded to the display is always NColors+Bcolors ! 366: * long and normally starts at cbuff+NColors. After marking and before ! 367: * compaction, marked blocks are shown in color by downloading a map ! 368: * beginning at the front of cbuff. ! 369: */ ! 370: ! 371: int cbuff[3*NColors]; ! 372: ! 373: /* ! 374: * Miscellaney. ! 375: */ ! 376: ! 377: static char *mmdev; /* name of monitoring device, if used */ ! 378: static int currcolor = UNcolr; /* current block output color */ ! 379: static int sstart; /* origin of string space display */ ! 380: static int scale = 16; /* initial scaling; may decrease */ ! 381: ! 382: #define NSkip 4 /* empty lines between blocks and strings */ ! 383: #define Gran 4 /* granularity of display (in bytes) */ ! 384: #define PaintBlk(addr,size,color,b) \ ! 385: gdpaint(((addr)-blkbase)/Gran,(size)/Gran,color,b) ! 386: #define PaintStr(addr,size,color,b) \ ! 387: gdpaint(sstart+((addr)-strbase)/Gran,(size)/Gran,color,b) ! 388: ! 389: /* ! 390: * MMInit() - initialization. ! 391: */ ! 392: ! 393: MMInit() ! 394: { ! 395: int i; ! 396: extern char *getenv(); ! 397: ! 398: if (!(mmdev = getenv("MEMMON"))) ! 399: return; ! 400: for (i=0; i<TColors; i++) { ! 401: cbuff[i] = clist[UMcolr]; ! 402: cbuff[i+NColors] = clist[i]; ! 403: cbuff[i+2*NColors] = clist[MKcolr]; ! 404: } ! 405: for (i=TColors; i<NColors; i++) ! 406: cbuff[i] = cbuff[i+NColors] = clist[i]; ! 407: cbuff[BKBcolr] = clist[UMBcolr]; ! 408: gdinit(mmdev); ! 409: } ! 410: ! 411: /* ! 412: * MMType(t) - set type for subsequent block allocation. ! 413: */ ! 414: ! 415: MMType(t) ! 416: int t; ! 417: { ! 418: currcolor = t; ! 419: } ! 420: ! 421: /* ! 422: * MMAlc(n) - show allocation of n block bytes at blkfree. ! 423: */ ! 424: ! 425: MMAlc(n) ! 426: int n; ! 427: { ! 428: if (!mmdev) ! 429: return; ! 430: if (!sstart) ! 431: refresh(); ! 432: PaintBlk(blkfree,n,currcolor,BKBcolr); ! 433: gdflush(); ! 434: currcolor = UNcolr; ! 435: } ! 436: ! 437: /* ! 438: * MMStr(n) - show allocation of n string bytes at strfree. ! 439: * Each pixel on the display represents multiple bytes. A pixel in which any ! 440: * string ends will be STBcolr; pixels corresponding to nonterminal characters ! 441: * of one string will be STcolr. This method makes long strings individually ! 442: * distinguishable from each other and from runs of short strings, and allows ! 443: * continuous output with no backtracking as the string space is allocated. ! 444: */ ! 445: ! 446: MMStr(slen) ! 447: int slen; ! 448: { ! 449: int s, e; ! 450: ! 451: if (!mmdev) ! 452: return; ! 453: if (!sstart) ! 454: refresh(); ! 455: s = (strfree-strbase+Gran-1) / Gran; /* start (first pixel wholly owned) */ ! 456: e = (strfree-strbase+slen-1) / Gran; /* end pixel */ ! 457: if (e < s) /* if no new pixels, return */ ! 458: return; ! 459: gdpaint(sstart+s,e-s+1,STcolr,STBcolr); ! 460: gdflush(); ! 461: } ! 462: ! 463: /* ! 464: * MMBGC() - begin garbage collection. ! 465: */ ! 466: ! 467: MMBGC() ! 468: { ! 469: if (!mmdev) ! 470: return; ! 471: gdpause(GCcolr); ! 472: } ! 473: ! 474: /* ! 475: * MMMark(block,type) - mark indicated block during garbage collection. ! 476: */ ! 477: ! 478: MMMark(block,type) ! 479: char *block; ! 480: int type; ! 481: { ! 482: if (mmdev) ! 483: PaintBlk(block,BlkSize(block),NColors+type,BKBcolr); ! 484: } ! 485: ! 486: /* ! 487: * MMSMark - Mark String. ! 488: */ ! 489: ! 490: MMSMark(saddr,slen) ! 491: char *saddr; ! 492: int slen; ! 493: { ! 494: int s, e; ! 495: ! 496: if (!mmdev) ! 497: return; ! 498: s = (saddr-strbase+Gran-1) / Gran; /* start (first pixel wholly owned) */ ! 499: e = (saddr-strbase+slen-1) / Gran; /* end pixel */ ! 500: if (e >= s) /* if anything to paint... */ ! 501: gdpaint(sstart+s,e-s+1,NColors+STcolr,NColors+STBcolr); ! 502: } ! 503: ! 504: /* ! 505: * MMEGC() - end garbage collection. ! 506: */ ! 507: ! 508: MMEGC() ! 509: { ! 510: if (!mmdev) ! 511: return; ! 512: if (gdpause(GARcolr) != EOF) ! 513: gdmap(cbuff,NColors+TColors); ! 514: while (gdpause(VALcolr) == '-') { ! 515: gdmap(cbuff+NColors,NColors+TColors); ! 516: gdpause(GARcolr); ! 517: gdmap(cbuff,NColors+TColors); ! 518: } ! 519: refresh(); ! 520: gdpause(GOcolr); ! 521: } ! 522: ! 523: /* ! 524: * MMTerm() - terminate memory monitoring. ! 525: */ ! 526: ! 527: MMTerm() ! 528: { ! 529: if (mmdev) ! 530: gdterm(); ! 531: } ! 532: ! 533: /* ! 534: * refresh() - redraw screen, initially or after garbage collection. ! 535: */ ! 536: ! 537: static refresh() ! 538: { ! 539: char *p; ! 540: int n; ! 541: ! 542: if (layout()) ! 543: gdflood(BGcolr); ! 544: else ! 545: PaintBlk(blkbase,blkfree-blkbase,AVcolr,-1); ! 546: PaintStr(strfree,strend-strfree,AVcolr,-1); ! 547: PaintBlk(blkfree,maxblk-blkfree,AVcolr,-1); ! 548: gdmap(cbuff+NColors,NColors+TColors); ! 549: PaintStr(strbase,strfree-strbase,STcolr,BKBcolr); ! 550: for (p = blkbase; p < blkfree; p += n) ! 551: PaintBlk(p,n=BlkSize(p),BlkType(p),BKBcolr); ! 552: } ! 553: ! 554: /* ! 555: * layout - determine screen layout. Return NZ iff different from previous. ! 556: */ ! 557: ! 558: static layout() ! 559: { ! 560: int hpixels, spixels, avail, mid, width, ideal, diff; ! 561: static int oldscale, oldss; ! 562: ! 563: hpixels = (maxblk - blkbase) / Gran + 1; ! 564: spixels = (strend - strbase) / Gran + 1; ! 565: while (scale > 1 && (hpixels + spixels > gdsize(scale))) ! 566: --scale; ! 567: gdscale(scale); ! 568: avail = gdsize(scale); ! 569: width = gdwidth(); ! 570: mid = avail / 2; ! 571: mid -= mid % width; ! 572: ideal = ((hpixels + width - 1) / width + NSkip) * width; ! 573: if (ideal <= mid && spixels <= avail - mid) ! 574: sstart = mid; ! 575: else if (ideal + spixels <= avail) ! 576: sstart = ideal; ! 577: else if (hpixels + spixels <= avail) ! 578: sstart = avail - spixels; ! 579: else ! 580: sstart = hpixels + 1; ! 581: diff = (scale != oldscale) || (sstart != oldss); ! 582: oldscale = scale; ! 583: oldss = sstart; ! 584: return diff; ! 585: } ! 586: ! 587: #else MemMon ! 588: static int x; /* prevent null module when MemMon not defined */ ! 589: #endif MemMon
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.