aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorNick Barnes2012-10-24 11:12:17 +0100
committerNick Barnes2012-10-24 11:12:17 +0100
commitec8692c49cfea149d977d4bb70bcd4c09bbc30ce (patch)
tree1adcd5a782ac97e9337ba193501be3de603dcb38 /mps/code
parent1822b236377d1801c141b19014e751046e596a84 (diff)
parent07d0aaf1135294adad13d66c2636c7bc9392a7b6 (diff)
downloademacs-ec8692c49cfea149d977d4bb70bcd4c09bbc30ce.tar.gz
emacs-ec8692c49cfea149d977d4bb70bcd4c09bbc30ce.zip
Integrate gdr's somewhat cut-down eventcnv code.
Copied from Perforce Change: 180046 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
-rw-r--r--mps/code/eventcnv.c282
1 files changed, 16 insertions, 266 deletions
diff --git a/mps/code/eventcnv.c b/mps/code/eventcnv.c
index 42c84c376df..b1535ace624 100644
--- a/mps/code/eventcnv.c
+++ b/mps/code/eventcnv.c
@@ -13,7 +13,7 @@
13 * will run the amcss test program and emit a file with event kinds 0, 1, 2. 13 * will run the amcss test program and emit a file with event kinds 0, 1, 2.
14 * The file can then be converted into text format with a command like: 14 * The file can then be converted into text format with a command like:
15 * 15 *
16 * eventcnv -v | sort 16 * eventcnv | sort
17 * 17 *
18 * Note that the eventcnv program can only read streams that come from an 18 * Note that the eventcnv program can only read streams that come from an
19 * MPS compiled on the same platform. 19 * MPS compiled on the same platform.
@@ -51,26 +51,11 @@ typedef unsigned long ulong;
51 51
52 52
53static EventClock eventTime; /* current event time */ 53static EventClock eventTime; /* current event time */
54
55
56/* event counters */
57
58typedef unsigned long eventCountArray[EventCodeMAX+1];
59static unsigned long bucketEventCount[EventCodeMAX+1];
60static unsigned long totalEventCount[EventCodeMAX+1];
61
62
63static char *prog; /* program name */ 54static char *prog; /* program name */
64 55
65 56
66/* command-line arguments */
67
68static Bool verbose = FALSE;
69/* style: '\0' for human-readable, 'L' for Lisp, 'C' for CDF. */ 57/* style: '\0' for human-readable, 'L' for Lisp, 'C' for CDF. */
70static char style = '\0'; 58static char style = '\0';
71static Bool reportStats = FALSE;
72static Bool eventEnabled[EventCodeMAX+1];
73static Word bucketSize = 0;
74 59
75 60
76/* everror -- error signalling */ 61/* everror -- error signalling */
@@ -95,8 +80,8 @@ static void everror(const char *format, ...)
95static void usage(void) 80static void usage(void)
96{ 81{
97 fprintf(stderr, 82 fprintf(stderr,
98 "Usage: %s [-f logfile] [-p] [-v] [-e events] [-b size]" 83 "Usage: %s [-f logfile] [-S[LC]] [-h]\n"
99 " [-S[LC]] [-?]\nSee guide.mps.telemetry for instructions.\n", 84 "See \"Telemetry\" in the reference manual for instructions.\n",
100 prog); 85 prog);
101} 86}
102 87
@@ -110,36 +95,6 @@ static void usageError(void)
110} 95}
111 96
112 97
113/* parseEventSpec -- parses an event spec
114 *
115 * The spec is of the form: <name>[(+|-)<name>]...
116 * The first name can be 'all'.
117 */
118
119static void parseEventSpec(const char *arg)
120{
121 size_t arglen;
122 EventCode i;
123 const char *end;
124 char name[EventNameMAX+1];
125 Bool enabled = TRUE;
126
127 end = arg + strlen(arg);
128 for(i = 0; i <= EventCodeMAX; ++i)
129 eventEnabled[i] = FALSE;
130 do {
131 arglen = strcspn(arg, "+-");
132 strncpy(name, arg, arglen); name[arglen] = '\0';
133 if (strcmp(name, "all") == 0) {
134 for(i = 0; i <= EventCodeMAX; ++i)
135 eventEnabled[i] = EventCodeIsValid(i);
136 } else
137 eventEnabled[EventName2Code(name)] = enabled;
138 enabled = (arg[arglen] == '+'); arg += arglen + 1;
139 } while (arg < end);
140}
141
142
143/* parseArgs -- parse command line arguments, return log file name */ 98/* parseArgs -- parse command line arguments, return log file name */
144 99
145static char *parseArgs(int argc, char *argv[]) 100static char *parseArgs(int argc, char *argv[])
@@ -162,34 +117,12 @@ static char *parseArgs(int argc, char *argv[])
162 else 117 else
163 name = argv[i]; 118 name = argv[i];
164 break; 119 break;
165 case 'v': /* verbosity */
166 verbose = TRUE;
167 break;
168 case 'e': { /* event statistics */
169 reportStats = TRUE;
170 ++ i;
171 if (i == argc)
172 usageError();
173 else
174 parseEventSpec(argv[i]);
175 } break;
176 case 'b': { /* bucket size */
177 ++ i;
178 if (i == argc)
179 usageError();
180 else {
181 int n;
182
183 n = sscanf(argv[i], "%lu", &bucketSize);
184 if (n != 1) usageError();
185 }
186 } break;
187 case 'S': /* style */ 120 case 'S': /* style */
188 style = argv[i][2]; /* '\0' for human-readable, 'L' for Lisp, */ 121 style = argv[i][2]; /* '\0' for human-readable, 'L' for Lisp, */
189 break; /* 'C' for CDF. */ 122 break; /* 'C' for CDF. */
190 case '?': case 'h': /* help */ 123 case '?': case 'h': /* help */
191 usage(); 124 usage();
192 break; 125 exit(EXIT_SUCCESS);
193 default: 126 default:
194 usageError(); 127 usageError();
195 } 128 }
@@ -200,33 +133,6 @@ static char *parseArgs(int argc, char *argv[])
200} 133}
201 134
202 135
203/* recordEvent -- record event
204 *
205 * This is the beginning of a system to model MPS state as events are read,
206 * but for the moment it just records which strings have been interned
207 * and which addresses have been labelled with them.
208 *
209 * NOTE: Since branch/2012-08-21/diagnostic-telemetry events are no longer
210 * in order in the event stream, so eventcnv would need some serious
211 * rethinking to model state. It's questionable that it should attempt it
212 * or event try to label addresses, but instead leave that to later stages of
213 * processing. RB 2012-09-07
214 */
215
216static void recordEvent(EventProc proc, Event event, EventClock etime)
217{
218 Res res;
219
220 res = EventRecord(proc, event, etime);
221 if (res != ResOK)
222 everror("Can't record event: error %d.", res);
223 switch(event->any.code) {
224 default:
225 break;
226 }
227}
228
229
230/* Printing routines */ 136/* Printing routines */
231 137
232 138
@@ -250,96 +156,11 @@ static void printStr(const char *str, Bool quotes)
250 156
251static void printAddr(EventProc proc, Addr addr) 157static void printAddr(EventProc proc, Addr addr)
252{ 158{
253 Word label; 159 UNUSED(proc);
254 160 printf(style != 'C' ?
255 label = AddrLabel(proc, addr); 161 " %0"PRIwWORD PRIXLONGEST :
256 if (label != 0 && addr != 0) { 162 " %"PRIuLONGEST,
257 /* We assume labelling zero is meant to record a point in time */ 163 (ulongest_t)addr);
258 const char *sym = LabelText(proc, label);
259 if (sym != NULL) {
260 putchar(' ');
261 printStr(sym, (style == 'C'));
262 } else {
263 printf((style == '\0') ?
264 " sym%05"PRIXLONGEST :
265 " \"sym %"PRIXLONGEST"\"",
266 (ulongest_t)label);
267 }
268 } else
269 printf(style != 'C' ?
270 " %0"PRIwWORD PRIXLONGEST :
271 " %"PRIuLONGEST,
272 (ulongest_t)addr);
273}
274
275
276/* reportEventResults -- report event counts from a count array */
277
278static void reportEventResults(eventCountArray eventCounts)
279{
280 EventCode i;
281 unsigned long total = 0;
282
283 for(i = 0; i <= EventCodeMAX; ++i) {
284 total += eventCounts[i];
285 if (eventEnabled[i])
286 switch (style) {
287 case '\0':
288 printf(" %5lu", eventCounts[i]);
289 break;
290 case 'L':
291 printf(" %lX", eventCounts[i]);
292 break;
293 case 'C':
294 printf(", %lu", eventCounts[i]);
295 break;
296 }
297 }
298 switch (style) {
299 case '\0':
300 printf(" %5lu\n", total);
301 break;
302 case 'L':
303 printf(" %lX)\n", total);
304 break;
305 case 'C':
306 printf(", %lu\n", total);
307 break;
308 }
309}
310
311
312/* reportBucketResults -- report results of the current bucket */
313
314static void reportBucketResults(EventClock bucketLimit)
315{
316 switch (style) {
317 case '\0':
318 EVENT_CLOCK_PRINT(stdout, bucketLimit);
319 putchar(':');
320 break;
321 case 'L':
322 putchar('(');
323 EVENT_CLOCK_PRINT(stdout, bucketLimit);
324 break;
325 case 'C':
326 EVENT_CLOCK_PRINT(stdout, bucketLimit);
327 break;
328 }
329 if (reportStats) {
330 reportEventResults(bucketEventCount);
331 }
332}
333
334
335/* clearBucket -- clear bucket */
336
337static void clearBucket(void)
338{
339 EventCode i;
340
341 for(i = 0; i <= EventCodeMAX; ++i)
342 bucketEventCount[i] = 0;
343} 164}
344 165
345 166
@@ -398,42 +219,23 @@ static void printParamS(EventProc proc, char *styleConv, const char *s)
398static void printParamB(EventProc proc, char *styleConv, Bool b) 219static void printParamB(EventProc proc, char *styleConv, Bool b)
399{ 220{
400 UNUSED(proc); 221 UNUSED(proc);
401 UNUSED(proc);
402 printf(styleConv, (ulongest_t)b); 222 printf(styleConv, (ulongest_t)b);
403} 223}
404 224
405 225
406/* readLog -- read and parse log 226/* readLog -- read and parse log
407 * 227 *
408 * This is the heart of eventcnv: It reads an event log using EventRead. 228 * This is the heart of eventcnv: It reads an event log using
409 * It updates the counters. If verbose is true, it looks up the format, 229 * EventRead. It updates the counters. It looks up the format,
410 * parses the arguments, and prints a representation of the event. Each 230 * parses the arguments, and prints a representation of the event.
411 * argument is printed using printArg (see RELATION, below), except for 231 * Each argument is printed using printArg (see RELATION, below),
412 * some event types that are handled specially. 232 * except for some event types that are handled specially.
413 */ 233 */
414 234
415static void readLog(EventProc proc) 235static void readLog(EventProc proc)
416{ 236{
417 EventCode c;
418 Word bucketLimit = bucketSize;
419 char *styleConv = NULL; /* suppress uninit warning */ 237 char *styleConv = NULL; /* suppress uninit warning */
420 238
421 /* Print event count header. */
422 if (reportStats) {
423 if (style == '\0') {
424 printf(" bucket:");
425 for(c = 0; c <= EventCodeMAX; ++c)
426 if (eventEnabled[c])
427 printf(" %04X", (unsigned)c);
428 printf(" all\n");
429 }
430 }
431
432 /* Init event counts. */
433 for(c = 0; c <= EventCodeMAX; ++c)
434 totalEventCount[c] = 0;
435 clearBucket();
436
437 /* Init style. */ 239 /* Init style. */
438 switch (style) { 240 switch (style) {
439 case '\0': 241 case '\0':
@@ -458,21 +260,8 @@ static void readLog(EventProc proc)
458 eventTime = event->any.clock; 260 eventTime = event->any.clock;
459 code = event->any.code; 261 code = event->any.code;
460 262
461 /* Output bucket, if necessary, and update counters */
462 if (bucketSize != 0 && eventTime >= bucketLimit) {
463 reportBucketResults(bucketLimit-1);
464 clearBucket();
465 do {
466 bucketLimit += bucketSize;
467 } while (eventTime >= bucketLimit);
468 }
469 if (reportStats) {
470 ++bucketEventCount[code];
471 ++totalEventCount[code];
472 }
473
474 /* Output event. */ 263 /* Output event. */
475 if (verbose) { 264 {
476 if (style == 'L') putchar('('); 265 if (style == 'L') putchar('(');
477 266
478 switch (style) { 267 switch (style) {
@@ -591,47 +380,8 @@ static void readLog(EventProc proc)
591 putchar('\n'); 380 putchar('\n');
592 fflush(stdout); 381 fflush(stdout);
593 } 382 }
594 recordEvent(proc, event, eventTime);
595 EventDestroy(proc, event); 383 EventDestroy(proc, event);
596 } /* while(!feof(input)) */ 384 } /* while(!feof(input)) */
597
598 /* report last bucket (partial) */
599 if (bucketSize != 0) {
600 reportBucketResults(eventTime);
601 }
602 if (reportStats) {
603 /* report totals */
604 switch (style) {
605 case '\0':
606 printf("\n run:");
607 break;
608 case 'L':
609 printf("(t");
610 break;
611 case 'C':
612 {
613 /* FIXME: This attempted to print the event stats on a row that
614 resembled a kind of final event, but the event clock no longer runs
615 monotonically upwards. */
616 EventClock last = eventTime + 1;
617 EVENT_CLOCK_PRINT(stdout, last);
618 }
619 break;
620 }
621 reportEventResults(totalEventCount);
622
623 /* explain event codes */
624 if (style == '\0') {
625 printf("\n");
626 for(c = 0; c <= EventCodeMAX; ++c)
627 if (eventEnabled[c])
628 printf(" %04X %s\n", (unsigned)c, EventCode2Name(c));
629 if (bucketSize == 0)
630 printf("\nevent clock stopped at ");
631 EVENT_CLOCK_PRINT(stdout, eventTime);
632 printf("\n");
633 }
634 }
635} 385}
636 386
637 387
@@ -691,7 +441,7 @@ int main(int argc, char *argv[])
691 441
692/* C. COPYRIGHT AND LICENSE 442/* C. COPYRIGHT AND LICENSE
693 * 443 *
694 * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. 444 * Copyright (C) 2001-2012 Ravenbrook Limited <http://www.ravenbrook.com/>.
695 * All rights reserved. This is an open source license. Contact 445 * All rights reserved. This is an open source license. Contact
696 * Ravenbrook for commercial licensing options. 446 * Ravenbrook for commercial licensing options.
697 * 447 *