diff options
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/eventcnv.c | 282 |
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 | ||
| 53 | static EventClock eventTime; /* current event time */ | 53 | static EventClock eventTime; /* current event time */ |
| 54 | |||
| 55 | |||
| 56 | /* event counters */ | ||
| 57 | |||
| 58 | typedef unsigned long eventCountArray[EventCodeMAX+1]; | ||
| 59 | static unsigned long bucketEventCount[EventCodeMAX+1]; | ||
| 60 | static unsigned long totalEventCount[EventCodeMAX+1]; | ||
| 61 | |||
| 62 | |||
| 63 | static char *prog; /* program name */ | 54 | static char *prog; /* program name */ |
| 64 | 55 | ||
| 65 | 56 | ||
| 66 | /* command-line arguments */ | ||
| 67 | |||
| 68 | static 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. */ |
| 70 | static char style = '\0'; | 58 | static char style = '\0'; |
| 71 | static Bool reportStats = FALSE; | ||
| 72 | static Bool eventEnabled[EventCodeMAX+1]; | ||
| 73 | static 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, ...) | |||
| 95 | static void usage(void) | 80 | static 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 | |||
| 119 | static 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 | ||
| 145 | static char *parseArgs(int argc, char *argv[]) | 100 | static 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 | |||
| 216 | static 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 | ||
| 251 | static void printAddr(EventProc proc, Addr addr) | 157 | static 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 | |||
| 278 | static 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 | |||
| 314 | static 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 | |||
| 337 | static 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) | |||
| 398 | static void printParamB(EventProc proc, char *styleConv, Bool b) | 219 | static 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 | ||
| 415 | static void readLog(EventProc proc) | 235 | static 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 | * |