|
|
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.