diff options
| author | Richard Brooksby | 2013-02-08 16:17:34 +0000 |
|---|---|---|
| committer | Richard Brooksby | 2013-02-08 16:17:34 +0000 |
| commit | 2706097eab7b3d1aa9429ef0e4ea1ac9f3c6edbe (patch) | |
| tree | 01b97e7abdada2c711cf5139952feee4ec71ba97 /mps/code | |
| parent | ab2c28cae42410c7b5edca80f1de8a9789494b52 (diff) | |
| parent | b31cda511d16f6a9947cead9341a1dfff5524cce (diff) | |
| download | emacs-2706097eab7b3d1aa9429ef0e4ea1ac9f3c6edbe.tar.gz emacs-2706097eab7b3d1aa9429ef0e4ea1ac9f3c6edbe.zip | |
Integrating branch/2012-10-09/user-guide back to master.
Copied from Perforce
Change: 180943
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/buffer.c | 2 | ||||
| -rw-r--r-- | mps/code/clock.h | 9 | ||||
| -rw-r--r-- | mps/code/comm.gmk | 46 | ||||
| -rw-r--r-- | mps/code/commpost.nmk | 18 | ||||
| -rw-r--r-- | mps/code/commpre.nmk | 2 | ||||
| -rw-r--r-- | mps/code/event.c | 40 | ||||
| -rw-r--r-- | mps/code/eventcnv.c | 616 | ||||
| -rw-r--r-- | mps/code/eventdef.h | 40 | ||||
| -rw-r--r-- | mps/code/eventsql.c | 1004 | ||||
| -rw-r--r-- | mps/code/eventtxt.c | 540 | ||||
| -rw-r--r-- | mps/code/fri3gc.gmk | 3 | ||||
| -rw-r--r-- | mps/code/gc.gmk | 13 | ||||
| -rw-r--r-- | mps/code/global.c | 13 | ||||
| -rw-r--r-- | mps/code/mpmtypes.h | 2 | ||||
| -rw-r--r-- | mps/code/mps.h | 11 | ||||
| -rw-r--r-- | mps/code/mps.xcodeproj/project.pbxproj | 235 | ||||
| -rw-r--r-- | mps/code/mpscamc.h | 4 | ||||
| -rw-r--r-- | mps/code/mpscmfs.h | 56 | ||||
| -rw-r--r-- | mps/code/mpscmvt.h | 77 | ||||
| -rw-r--r-- | mps/code/mpsi.c | 35 | ||||
| -rw-r--r-- | mps/code/mpsliban.c | 56 | ||||
| -rw-r--r-- | mps/code/mpstd.h | 1 | ||||
| -rw-r--r-- | mps/code/mv2test.c | 2 | ||||
| -rw-r--r-- | mps/code/poolamc.c | 27 | ||||
| -rw-r--r-- | mps/code/poolmfs.c | 11 | ||||
| -rw-r--r-- | mps/code/poolmv2.c | 2 | ||||
| -rw-r--r-- | mps/code/seg.c | 2 | ||||
| -rw-r--r-- | mps/code/testlib.h | 24 | ||||
| -rw-r--r-- | mps/code/w3i3mv.nmk | 5 | ||||
| -rw-r--r-- | mps/code/w3i6mv.nmk | 5 |
30 files changed, 2318 insertions, 583 deletions
diff --git a/mps/code/buffer.c b/mps/code/buffer.c index 2128ffda0cf..f911a28c6b9 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c | |||
| @@ -1494,8 +1494,6 @@ DEFINE_CLASS(SegBufClass, class) | |||
| 1494 | 1494 | ||
| 1495 | static Res rankBufInit (Buffer buffer, Pool pool, va_list args) | 1495 | static Res rankBufInit (Buffer buffer, Pool pool, va_list args) |
| 1496 | { | 1496 | { |
| 1497 | /* Assumes pun compatibility between Rank and mps_rank_t */ | ||
| 1498 | /* Which is checked by mpsi_check in <code/mpsi.c> */ | ||
| 1499 | Rank rank = va_arg(args, Rank); | 1497 | Rank rank = va_arg(args, Rank); |
| 1500 | BufferClass super; | 1498 | BufferClass super; |
| 1501 | Res res; | 1499 | Res res; |
diff --git a/mps/code/clock.h b/mps/code/clock.h index 881d74e2715..b9205f2e9be 100644 --- a/mps/code/clock.h +++ b/mps/code/clock.h | |||
| @@ -21,14 +21,13 @@ | |||
| 21 | * RB 2012-09-11 | 21 | * RB 2012-09-11 |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | /* TODO: Clang supposedly provides a cross-platform builtin for a fast | 24 | /* Clang provides a cross-platform builtin for a fast timer, but it |
| 25 | timer, but it doesn't seem to be present on Mac OS X 10.8. We should | 25 | was not available on Mac OS X 10.8 until the release of XCode 4.6. |
| 26 | use it if it ever appears. | ||
| 27 | <http://clang.llvm.org/docs/LanguageExtensions.html#builtins> */ | 26 | <http://clang.llvm.org/docs/LanguageExtensions.html#builtins> */ |
| 28 | #if defined(MPS_BUILD_LL) | 27 | #if defined(MPS_BUILD_LL) |
| 29 | 28 | ||
| 30 | #if __has_builtin(__builtin_readcyclecounter) | 29 | #if __has_builtin(__builtin_readcyclecounter) |
| 31 | #error "__builtin_readcyclecounter is available but not used" | 30 | /* TODO: use this for EVENT_CLOCK. See job003411. */ |
| 32 | #endif /* __has_builtin(__builtin_readcyclecounter) */ | 31 | #endif /* __has_builtin(__builtin_readcyclecounter) */ |
| 33 | 32 | ||
| 34 | #endif | 33 | #endif |
| @@ -120,7 +119,7 @@ __extension__ typedef unsigned long long EventClock; | |||
| 120 | #define EVENT_CLOCK_PRINT(stream, clock) \ | 119 | #define EVENT_CLOCK_PRINT(stream, clock) \ |
| 121 | fprintf(stream, "%08lX%08lX", \ | 120 | fprintf(stream, "%08lX%08lX", \ |
| 122 | (unsigned long)((clock) >> 32), \ | 121 | (unsigned long)((clock) >> 32), \ |
| 123 | (unsigned long)(clock)) | 122 | (unsigned long)((clock) & 0xffffffff)) |
| 124 | 123 | ||
| 125 | #define EVENT_CLOCK_WRITE(stream, clock) \ | 124 | #define EVENT_CLOCK_WRITE(stream, clock) \ |
| 126 | WriteF(stream, "$W$W", (WriteFW)((clock) >> 32), (WriteFW)clock, NULL) | 125 | WriteF(stream, "$W$W", (WriteFW)((clock) >> 32), (WriteFW)clock, NULL) |
diff --git a/mps/code/comm.gmk b/mps/code/comm.gmk index 2e16905eab7..bfdf9a20c7a 100644 --- a/mps/code/comm.gmk +++ b/mps/code/comm.gmk | |||
| @@ -11,7 +11,12 @@ | |||
| 11 | # PARAMETERS | 11 | # PARAMETERS |
| 12 | # | 12 | # |
| 13 | # Assumes the following variables and definitions: | 13 | # Assumes the following variables and definitions: |
| 14 | # EXTRA_TARGETS a list of extra targets to build | ||
| 14 | # CFLAGSCOMPILER a list of flags for all compilations | 15 | # CFLAGSCOMPILER a list of flags for all compilations |
| 16 | # CFLAGSSTRICT a list of flags for almost all compilations | ||
| 17 | # CFLAGSLAX a list of flags for compilations which can't be as | ||
| 18 | # strict (e.g. because they have to include a third- | ||
| 19 | # party header file that isn't -ansi -pedantic). | ||
| 15 | # CFLAGSDEBUG a list of flags for compilations with maximum debug | 20 | # CFLAGSDEBUG a list of flags for compilations with maximum debug |
| 16 | # information, and any optimization possible | 21 | # information, and any optimization possible |
| 17 | # CFLAGSOPT a list of flags for compilations with maximum | 22 | # CFLAGSOPT a list of flags for compilations with maximum |
| @@ -63,6 +68,15 @@ ifndef CFLAGSOPT | |||
| 63 | error "comm.gmk: CFLAGSOPT not defined" | 68 | error "comm.gmk: CFLAGSOPT not defined" |
| 64 | endif | 69 | endif |
| 65 | 70 | ||
| 71 | |||
| 72 | # EXTRA TARGETS | ||
| 73 | # | ||
| 74 | # Don't build mpseventsql by default (might not have sqlite3 installed), | ||
| 75 | # but do build mpseventcnv and mpseventtxt. | ||
| 76 | |||
| 77 | EXTRA_TARGETS ?= mpseventcnv mpseventtxt | ||
| 78 | |||
| 79 | |||
| 66 | # | 80 | # |
| 67 | # %%PART: When adding a new part, add checks for the parameter with the | 81 | # %%PART: When adding a new part, add checks for the parameter with the |
| 68 | # sources for the new part. | 82 | # sources for the new part. |
| @@ -92,7 +106,8 @@ endif | |||
| 92 | # These flags are included in all compilations. | 106 | # These flags are included in all compilations. |
| 93 | # Avoid using PFMDEFS in platform makefiles, as they prevent the MPS being | 107 | # Avoid using PFMDEFS in platform makefiles, as they prevent the MPS being |
| 94 | # built with a simple command like "cc -c mps.c". | 108 | # built with a simple command like "cc -c mps.c". |
| 95 | CFLAGSCOMMON = $(PFMDEFS) $(CFLAGSCOMPILER) | 109 | CFLAGSCOMMON = $(PFMDEFS) $(CFLAGSCOMPILER) $(CFLAGSCOMPILERSTRICT) |
| 110 | CFLAGSCOMMONLAX = $(PFMDEFS) $(CFLAGSCOMPILER) $(CFLAGSCOMPILERLAX) | ||
| 96 | 111 | ||
| 97 | # %%VARIETY: When adding a new variety, define a macro containing the set | 112 | # %%VARIETY: When adding a new variety, define a macro containing the set |
| 98 | # of flags for the new variety. | 113 | # of flags for the new variety. |
| @@ -108,15 +123,19 @@ CFCOOL = -DCONFIG_VAR_COOL $(CFLAGSDEBUG) | |||
| 108 | # CFLAGS here. | 123 | # CFLAGS here. |
| 109 | ifeq ($(VARIETY),rash) | 124 | ifeq ($(VARIETY),rash) |
| 110 | CFLAGS=$(CFLAGSCOMMON) $(CFRASH) | 125 | CFLAGS=$(CFLAGSCOMMON) $(CFRASH) |
| 126 | CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFRASH) | ||
| 111 | else | 127 | else |
| 112 | ifeq ($(VARIETY),hot) | 128 | ifeq ($(VARIETY),hot) |
| 113 | CFLAGS=$(CFLAGSCOMMON) $(CFHOT) | 129 | CFLAGS=$(CFLAGSCOMMON) $(CFHOT) |
| 130 | CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFHOT) | ||
| 114 | else | 131 | else |
| 115 | ifeq ($(VARIETY),diag) | 132 | ifeq ($(VARIETY),diag) |
| 116 | CFLAGS=$(CFLAGSCOMMON) $(CFDIAG) | 133 | CFLAGS=$(CFLAGSCOMMON) $(CFDIAG) |
| 134 | CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFDIAG) | ||
| 117 | else | 135 | else |
| 118 | ifeq ($(VARIETY),cool) | 136 | ifeq ($(VARIETY),cool) |
| 119 | CFLAGS=$(CFLAGSCOMMON) $(CFCOOL) | 137 | CFLAGS=$(CFLAGSCOMMON) $(CFCOOL) |
| 138 | CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFCOOL) | ||
| 120 | else | 139 | else |
| 121 | endif | 140 | endif |
| 122 | endif | 141 | endif |
| @@ -203,7 +222,7 @@ all: mpmss sacss amcss amcsshe amsss amssshe segsmss awlut awluthe \ | |||
| 203 | finalcv finaltest arenacv bttest teletest \ | 222 | finalcv finaltest arenacv bttest teletest \ |
| 204 | abqtest cbstest btcv mv2test messtest steptest \ | 223 | abqtest cbstest btcv mv2test messtest steptest \ |
| 205 | walkt0 zcoll zmess \ | 224 | walkt0 zcoll zmess \ |
| 206 | eventcnv \ | 225 | $(EXTRA_TARGETS) \ |
| 207 | mps.a mpsplan.a | 226 | mps.a mpsplan.a |
| 208 | 227 | ||
| 209 | 228 | ||
| @@ -232,7 +251,7 @@ mpmss sacss amcss amcssth amcsshe amsss amssshe segsmss awlut awlutth \ | |||
| 232 | walkt0 \ | 251 | walkt0 \ |
| 233 | exposet0 \ | 252 | exposet0 \ |
| 234 | zcoll zmess \ | 253 | zcoll zmess \ |
| 235 | eventcnv replay replaysw \ | 254 | $(EXTRA_TARGETS) replay replaysw \ |
| 236 | mps.a mpsplan.a: phony | 255 | mps.a mpsplan.a: phony |
| 237 | ifdef VARIETY | 256 | ifdef VARIETY |
| 238 | $(MAKE) -f $(PFM).gmk TARGET=$@ variety | 257 | $(MAKE) -f $(PFM).gmk TARGET=$@ variety |
| @@ -414,9 +433,15 @@ $(PFM)/$(VARIETY)/zcoll: $(PFM)/$(VARIETY)/zcoll.o \ | |||
| 414 | $(PFM)/$(VARIETY)/zmess: $(PFM)/$(VARIETY)/zmess.o \ | 433 | $(PFM)/$(VARIETY)/zmess: $(PFM)/$(VARIETY)/zmess.o \ |
| 415 | $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a | 434 | $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a |
| 416 | 435 | ||
| 417 | $(PFM)/$(VARIETY)/eventcnv: $(PFM)/$(VARIETY)/eventcnv.o \ | 436 | $(PFM)/$(VARIETY)/mpseventcnv: $(PFM)/$(VARIETY)/eventcnv.o \ |
| 418 | $(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/mps.a | 437 | $(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/mps.a |
| 419 | 438 | ||
| 439 | $(PFM)/$(VARIETY)/mpseventtxt: $(PFM)/$(VARIETY)/eventtxt.o \ | ||
| 440 | $(PFM)/$(VARIETY)/mps.a | ||
| 441 | |||
| 442 | $(PFM)/$(VARIETY)/mpseventsql: $(PFM)/$(VARIETY)/eventsql.o \ | ||
| 443 | $(PFM)/$(VARIETY)/mps.a | ||
| 444 | |||
| 420 | $(PFM)/$(VARIETY)/replay: $(PFM)/$(VARIETY)/replay.o \ | 445 | $(PFM)/$(VARIETY)/replay: $(PFM)/$(VARIETY)/replay.o \ |
| 421 | $(PFM)/$(VARIETY)/eventrep.o \ | 446 | $(PFM)/$(VARIETY)/eventrep.o \ |
| 422 | $(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/table.o \ | 447 | $(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/table.o \ |
| @@ -440,10 +465,20 @@ mkdir -p $(PFM)/$(VARIETY) | |||
| 440 | $(CC) $(CFLAGS) -c -o $@ $< | 465 | $(CC) $(CFLAGS) -c -o $@ $< |
| 441 | endef | 466 | endef |
| 442 | 467 | ||
| 468 | define run-cc-lax | ||
| 469 | $(ECHO) "$(PFM): $@ - compiling with lax flags." | ||
| 470 | mkdir -p $(PFM) | ||
| 471 | mkdir -p $(PFM)/$(VARIETY) | ||
| 472 | $(CC) $(CFLAGSLAX) -c -o $@ $< | ||
| 473 | endef | ||
| 474 | |||
| 443 | # .rule.c-to-o: | 475 | # .rule.c-to-o: |
| 444 | $(PFM)/$(VARIETY)/%.o: %.c | 476 | $(PFM)/$(VARIETY)/%.o: %.c |
| 445 | $(run-cc) | 477 | $(run-cc) |
| 446 | 478 | ||
| 479 | $(PFM)/$(VARIETY)/eventsql.o: eventsql.c | ||
| 480 | $(run-cc-lax) | ||
| 481 | |||
| 447 | $(PFM)/$(VARIETY)/%.o: %.s | 482 | $(PFM)/$(VARIETY)/%.o: %.s |
| 448 | $(run-cc) | 483 | $(run-cc) |
| 449 | 484 | ||
| @@ -507,6 +542,9 @@ $(PFM)/$(VARIETY)/%: | |||
| 507 | $(ECHO) "$(PFM): $@" | 542 | $(ECHO) "$(PFM): $@" |
| 508 | $(CC) $(CFLAGS) $(LINKFLAGS) -o $@ $^ $(LIBS) | 543 | $(CC) $(CFLAGS) $(LINKFLAGS) -o $@ $^ $(LIBS) |
| 509 | 544 | ||
| 545 | $(PFM)/$(VARIETY)/mpseventsql: | ||
| 546 | $(ECHO) "$(PFM): $@" | ||
| 547 | $(CC) $(CFLAGS) $(LINKFLAGS) -o $@ $^ $(LIBS) -lsqlite3 | ||
| 510 | 548 | ||
| 511 | # Special targets for development | 549 | # Special targets for development |
| 512 | 550 | ||
diff --git a/mps/code/commpost.nmk b/mps/code/commpost.nmk index 15b77940b29..793ec8e6035 100644 --- a/mps/code/commpost.nmk +++ b/mps/code/commpost.nmk | |||
| @@ -19,7 +19,7 @@ all: mpmss.exe amcss.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awluthe.exe | |||
| 19 | arenacv.exe bttest.exe teletest.exe \ | 19 | arenacv.exe bttest.exe teletest.exe \ |
| 20 | abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \ | 20 | abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \ |
| 21 | locbwcss.exe locusss.exe zcoll.exe zmess.exe \ | 21 | locbwcss.exe locusss.exe zcoll.exe zmess.exe \ |
| 22 | eventcnv.exe \ | 22 | mpseventcnv.exe mpseventtxt.exe \ |
| 23 | mps.lib | 23 | mps.lib |
| 24 | 24 | ||
| 25 | 25 | ||
| @@ -37,7 +37,7 @@ mpmss.exe amcss.exe amcsshe.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awlu | |||
| 37 | abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \ | 37 | abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \ |
| 38 | walkt0.exe locbwcss.exe locusss.exe \ | 38 | walkt0.exe locbwcss.exe locusss.exe \ |
| 39 | exposet0.exe zcoll.exe zmess.exe \ | 39 | exposet0.exe zcoll.exe zmess.exe \ |
| 40 | replay.exe replaysw.exe eventcnv.exe \ | 40 | replay.exe replaysw.exe mpseventcnv.exe mpseventtxt.exe mpseventsql.exe \ |
| 41 | mps.lib: | 41 | mps.lib: |
| 42 | !IFDEF VARIETY | 42 | !IFDEF VARIETY |
| 43 | $(MAKE) /nologo /f $(PFM).nmk TARGET=$@ variety | 43 | $(MAKE) /nologo /f $(PFM).nmk TARGET=$@ variety |
| @@ -231,9 +231,15 @@ $(PFM)\$(VARIETY)\zmess.exe: $(PFM)\$(VARIETY)\zmess.obj \ | |||
| 231 | $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) \ | 231 | $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) \ |
| 232 | $(TESTLIBOBJ) | 232 | $(TESTLIBOBJ) |
| 233 | 233 | ||
| 234 | $(PFM)\$(VARIETY)\eventcnv.exe: $(PFM)\$(VARIETY)\eventcnv.obj \ | 234 | $(PFM)\$(VARIETY)\mpseventcnv.exe: $(PFM)\$(VARIETY)\eventcnv.obj \ |
| 235 | $(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\mps.lib | 235 | $(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\mps.lib |
| 236 | 236 | ||
| 237 | $(PFM)\$(VARIETY)\mpseventtxt.exe: $(PFM)\$(VARIETY)\eventtxt.obj \ | ||
| 238 | $(PFM)\$(VARIETY)\mps.lib | ||
| 239 | |||
| 240 | $(PFM)\$(VARIETY)\mpseventsql.exe: $(PFM)\$(VARIETY)\eventsql.obj \ | ||
| 241 | $(PFM)\$(VARIETY)\sqlite3.obj $(PFM)\$(VARIETY)\mps.lib | ||
| 242 | |||
| 237 | $(PFM)\$(VARIETY)\replay.exe: $(PFM)\$(VARIETY)\replay.obj \ | 243 | $(PFM)\$(VARIETY)\replay.exe: $(PFM)\$(VARIETY)\replay.obj \ |
| 238 | $(PFM)\$(VARIETY)\eventrep.obj \ | 244 | $(PFM)\$(VARIETY)\eventrep.obj \ |
| 239 | $(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\table.obj \ | 245 | $(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\table.obj \ |
| @@ -270,6 +276,12 @@ $(PFM)\$(VARIETY)\exposet0.exe: $(PFM)\$(VARIETY)\exposet0.obj \ | |||
| 270 | @if not exist $(PFM)\$(VARIETY) mkdir $(PFM)\$(VARIETY) | 276 | @if not exist $(PFM)\$(VARIETY) mkdir $(PFM)\$(VARIETY) |
| 271 | cl /c $(CFLAGS) /Fd$(PFM)\$(VARIETY)\ /Fo$@ $< | 277 | cl /c $(CFLAGS) /Fd$(PFM)\$(VARIETY)\ /Fo$@ $< |
| 272 | 278 | ||
| 279 | $(PFM)\$(VARIETY)\sqlite3.obj: | ||
| 280 | $(ECHO) $@ | ||
| 281 | @if not exist $(PFM) mkdir $(PFM) | ||
| 282 | @if not exist $(PFM)\$(VARIETY) mkdir $(PFM)\$(VARIETY) | ||
| 283 | cl /c $(CFLAGSSQL) /Fd$(PFM)\$(VARIETY)\ /Fo$@ sqlite3.c | ||
| 284 | |||
| 273 | {}.asm{$(PFM)\$(VARIETY)}.obj: | 285 | {}.asm{$(PFM)\$(VARIETY)}.obj: |
| 274 | $(ECHO) $@ | 286 | $(ECHO) $@ |
| 275 | @if not exist $(PFM) mkdir $(PFM) | 287 | @if not exist $(PFM) mkdir $(PFM) |
diff --git a/mps/code/commpre.nmk b/mps/code/commpre.nmk index 0afcab6fe96..5ae4ffb49aa 100644 --- a/mps/code/commpre.nmk +++ b/mps/code/commpre.nmk | |||
| @@ -95,7 +95,9 @@ CRTFLAGSCOOL = /MTd | |||
| 95 | LINKFLAGSHOT = libcmt.lib | 95 | LINKFLAGSHOT = libcmt.lib |
| 96 | LINKFLAGSCOOL = libcmtd.lib | 96 | LINKFLAGSCOOL = libcmtd.lib |
| 97 | 97 | ||
| 98 | CFLAGSSQLPRE = /nologo $(PFMDEFS) | ||
| 98 | CFLAGSCOMMONPRE = /nologo /W4 /WX $(PFMDEFS) $(CFLAGSTARGETPRE) | 99 | CFLAGSCOMMONPRE = /nologo /W4 /WX $(PFMDEFS) $(CFLAGSTARGETPRE) |
| 100 | CFLAGSSQLPOST = | ||
| 99 | CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST) | 101 | CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST) |
| 100 | 102 | ||
| 101 | # Flags for use in the variety combinations | 103 | # Flags for use in the variety combinations |
diff --git a/mps/code/event.c b/mps/code/event.c index a3331d18c18..1bdbafb34f6 100644 --- a/mps/code/event.c +++ b/mps/code/event.c | |||
| @@ -46,6 +46,31 @@ char *EventLast[EventKindLIMIT]; | |||
| 46 | EventControlSet EventKindControl; /* Bit set used to control output. */ | 46 | EventControlSet EventKindControl; /* Bit set used to control output. */ |
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | /* A single event structure output once per buffer flush. */ | ||
| 50 | EventEventClockSyncStruct eventClockSyncStruct; | ||
| 51 | |||
| 52 | |||
| 53 | /* eventClockSync -- Populate and write the clock sync event. */ | ||
| 54 | |||
| 55 | static Res eventClockSync(void) | ||
| 56 | { | ||
| 57 | Res res; | ||
| 58 | size_t size; | ||
| 59 | |||
| 60 | size= size_tAlignUp(sizeof(eventClockSyncStruct), MPS_PF_ALIGN); | ||
| 61 | eventClockSyncStruct.code = EventEventClockSyncCode; | ||
| 62 | eventClockSyncStruct.size = (EventSize)size; | ||
| 63 | EVENT_CLOCK(eventClockSyncStruct.clock); | ||
| 64 | eventClockSyncStruct.f0 = (Word)mps_clock(); | ||
| 65 | res = (Res)mps_io_write(eventIO, (void *)&eventClockSyncStruct, size); | ||
| 66 | if (res != ResOK) | ||
| 67 | goto failWrite; | ||
| 68 | |||
| 69 | res = ResOK; | ||
| 70 | failWrite: | ||
| 71 | return res; | ||
| 72 | } | ||
| 73 | |||
| 49 | /* EventFlush -- flush event buffer to the event stream */ | 74 | /* EventFlush -- flush event buffer to the event stream */ |
| 50 | 75 | ||
| 51 | Res EventFlush(EventKind kind) | 76 | Res EventFlush(EventKind kind) |
| @@ -78,7 +103,12 @@ Res EventFlush(EventKind kind) | |||
| 78 | goto failCreate; | 103 | goto failCreate; |
| 79 | eventIOInited = TRUE; | 104 | eventIOInited = TRUE; |
| 80 | } | 105 | } |
| 81 | 106 | ||
| 107 | /* Send an EventClockSync event */ | ||
| 108 | res = eventClockSync(); | ||
| 109 | if (res != ResOK) | ||
| 110 | goto failClockSync; | ||
| 111 | |||
| 82 | /* Writing might be faster if the size is aligned to a multiple of the | 112 | /* Writing might be faster if the size is aligned to a multiple of the |
| 83 | C library or kernel's buffer size. We could pad out the buffer with | 113 | C library or kernel's buffer size. We could pad out the buffer with |
| 84 | a marker for this purpose. */ | 114 | a marker for this purpose. */ |
| @@ -88,9 +118,10 @@ Res EventFlush(EventKind kind) | |||
| 88 | goto failWrite; | 118 | goto failWrite; |
| 89 | 119 | ||
| 90 | } | 120 | } |
| 91 | 121 | ||
| 92 | res = ResOK; | 122 | res = ResOK; |
| 93 | 123 | ||
| 124 | failClockSync: | ||
| 94 | failWrite: | 125 | failWrite: |
| 95 | failCreate: | 126 | failCreate: |
| 96 | 127 | ||
| @@ -178,6 +209,11 @@ void EventInit(void) | |||
| 178 | EventKindControl = (Word)mps_lib_telemetry_control(); | 209 | EventKindControl = (Word)mps_lib_telemetry_control(); |
| 179 | EventInternSerial = (Serial)1; /* 0 is reserved */ | 210 | EventInternSerial = (Serial)1; /* 0 is reserved */ |
| 180 | (void)EventInternString(MPSVersion()); /* emit version */ | 211 | (void)EventInternString(MPSVersion()); /* emit version */ |
| 212 | EVENT7(EventInit, EVENT_VERSION_MAJOR, EVENT_VERSION_MEDIAN, | ||
| 213 | EVENT_VERSION_MINOR, EventCodeMAX, EventNameMAX, MPS_WORD_WIDTH, | ||
| 214 | mps_clocks_per_sec()); | ||
| 215 | /* flush these initial events to get the first ClockSync out. */ | ||
| 216 | EventSync(); | ||
| 181 | } else { | 217 | } else { |
| 182 | ++eventUserCount; | 218 | ++eventUserCount; |
| 183 | } | 219 | } |
diff --git a/mps/code/eventcnv.c b/mps/code/eventcnv.c index fcd569add74..99974831908 100644 --- a/mps/code/eventcnv.c +++ b/mps/code/eventcnv.c | |||
| @@ -2,40 +2,49 @@ | |||
| 2 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | 2 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. |
| 3 | * | 3 | * |
| 4 | * This is a command-line tool that converts a binary format telemetry output | 4 | * This is a command-line tool that converts a binary format telemetry output |
| 5 | * stream from the MPS into several textual formats. | 5 | * stream from the MPS into a more-portable textual format. |
| 6 | * | 6 | * |
| 7 | * The default MPS library will write a telemetry stream to a file called | 7 | * eventcnv can only read binary-format files that come from an MPS |
| 8 | * "mpsio.log" when the environment variable MPS_TELEMETRY_CONTROL is set | 8 | * compiled on the same platform, whereas the text-format files it |
| 9 | * to an integer whose bits select event kinds. For example: | 9 | * produces can be processed on any platform. |
| 10 | * | 10 | * |
| 11 | * MPS_TELEMETRY_CONTROL=7 amcss | 11 | * The default MPS library will write a telemetry stream to a file |
| 12 | * when the environment variable MPS_TELEMETRY_CONTROL is set to an | ||
| 13 | * integer whose bits select event kinds. For example: | ||
| 12 | * | 14 | * |
| 13 | * will run the amcss test program and emit a file with event kinds 0, 1, 2. | 15 | * MPS_TELEMETRY_CONTROL=7 amcss |
| 14 | * The file can then be converted into text format with a command like: | ||
| 15 | * | 16 | * |
| 16 | * eventcnv -v | sort | 17 | * will run the amcss test program and emit a telemetry file with |
| 18 | * event kinds 0, 1, 2. The file can then be converted into a sorted | ||
| 19 | * text format log with a command like: | ||
| 17 | * | 20 | * |
| 18 | * Note that the eventcnv program can only read streams that come from an | 21 | * eventcnv | sort > mps-events.txt |
| 19 | * MPS compiled on the same platform. | ||
| 20 | * | 22 | * |
| 23 | * These text-format files have one line per event, and can be | ||
| 24 | * manipulated by various programs systems in the usual Unix way. | ||
| 25 | * | ||
| 26 | * The binary telemetry filename can be specified with a -f | ||
| 27 | * command-line argument (use -f - to specify standard input). If no | ||
| 28 | * filename is specified on the command line, the environment variable | ||
| 29 | * MPS_TELEMETRY_FILENAME is consulted (this is the same environment | ||
| 30 | * variable used to specify the telemetry file to the MPS library). | ||
| 31 | * If the environment variable does not exist, the default filename of | ||
| 32 | * "mpsio.log" is used. | ||
| 33 | * | ||
| 21 | * $Id$ | 34 | * $Id$ |
| 22 | */ | 35 | */ |
| 23 | 36 | ||
| 24 | #include "config.h" | 37 | #include "config.h" |
| 25 | |||
| 26 | #include "eventdef.h" | 38 | #include "eventdef.h" |
| 27 | #include "eventcom.h" | 39 | #include "eventcom.h" |
| 28 | #include "eventpro.h" | 40 | #include "eventpro.h" |
| 29 | #include "mpmtypes.h" | ||
| 30 | #include "testlib.h" /* for ulongest_t and associated print formats */ | 41 | #include "testlib.h" /* for ulongest_t and associated print formats */ |
| 31 | 42 | ||
| 32 | #include <stddef.h> /* for size_t */ | 43 | #include <stddef.h> /* for size_t */ |
| 33 | #include <stdio.h> /* for printf */ | 44 | #include <stdio.h> /* for printf */ |
| 34 | #include <stdarg.h> /* for va_list */ | ||
| 35 | #include <stdlib.h> /* for EXIT_FAILURE */ | 45 | #include <stdlib.h> /* for EXIT_FAILURE */ |
| 36 | #include <assert.h> /* for assert */ | 46 | #include <assert.h> /* for assert */ |
| 37 | #include <string.h> /* for strcmp */ | 47 | #include <string.h> /* for strcmp */ |
| 38 | #include <math.h> /* for sqrt */ | ||
| 39 | #include "mpstd.h" | 48 | #include "mpstd.h" |
| 40 | 49 | ||
| 41 | #ifdef MPS_BUILD_MV | 50 | #ifdef MPS_BUILD_MV |
| @@ -44,47 +53,45 @@ | |||
| 44 | #pragma warning( disable : 4996 ) | 53 | #pragma warning( disable : 4996 ) |
| 45 | #endif | 54 | #endif |
| 46 | 55 | ||
| 47 | 56 | #define DEFAULT_TELEMETRY_FILENAME "mpsio.log" | |
| 48 | 57 | #define TELEMETRY_FILENAME_ENVAR "MPS_TELEMETRY_FILENAME" | |
| 49 | typedef unsigned int uint; | ||
| 50 | typedef unsigned long ulong; | ||
| 51 | |||
| 52 | 58 | ||
| 53 | static EventClock eventTime; /* current event time */ | 59 | static EventClock eventTime; /* current event time */ |
| 60 | static char *prog; /* program name */ | ||
| 54 | 61 | ||
| 62 | /* Errors and Warnings */ | ||
| 55 | 63 | ||
| 56 | /* event counters */ | 64 | /* fevwarn -- flush stdout, write message to stderr */ |
| 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 */ | ||
| 64 | 65 | ||
| 66 | static void fevwarn(const char *prefix, const char *format, va_list args) | ||
| 67 | { | ||
| 68 | fflush(stdout); /* sync */ | ||
| 69 | fprintf(stderr, "%s: %s @", prog, prefix); | ||
| 70 | EVENT_CLOCK_PRINT(stderr, eventTime); | ||
| 71 | fprintf(stderr, " "); | ||
| 72 | vfprintf(stderr, format, args); | ||
| 73 | fprintf(stderr, "\n"); | ||
| 74 | } | ||
| 65 | 75 | ||
| 66 | /* command-line arguments */ | 76 | /* evwarn -- flush stdout, warn to stderr */ |
| 67 | 77 | ||
| 68 | static Bool verbose = FALSE; | 78 | static void evwarn(const char *format, ...) |
| 69 | /* style: '\0' for human-readable, 'L' for Lisp, 'C' for CDF. */ | 79 | { |
| 70 | static char style = '\0'; | 80 | va_list args; |
| 71 | static Bool reportStats = FALSE; | ||
| 72 | static Bool eventEnabled[EventCodeMAX+1]; | ||
| 73 | static Word bucketSize = 0; | ||
| 74 | 81 | ||
| 82 | va_start(args, format); | ||
| 83 | fevwarn("Warning", format, args); | ||
| 84 | va_end(args); | ||
| 85 | } | ||
| 75 | 86 | ||
| 76 | /* everror -- error signalling */ | 87 | /* everror -- flush stdout, mesage to stderr, exit */ |
| 77 | 88 | ||
| 78 | static void everror(const char *format, ...) | 89 | static void everror(const char *format, ...) |
| 79 | { | 90 | { |
| 80 | va_list args; | 91 | va_list args; |
| 81 | 92 | ||
| 82 | fflush(stdout); /* sync */ | ||
| 83 | fprintf(stderr, "%s: @", prog); | ||
| 84 | EVENT_CLOCK_PRINT(stderr, eventTime); | ||
| 85 | va_start(args, format); | 93 | va_start(args, format); |
| 86 | vfprintf(stderr, format, args); | 94 | fevwarn("Error", format, args); |
| 87 | fprintf(stderr, "\n"); | ||
| 88 | va_end(args); | 95 | va_end(args); |
| 89 | exit(EXIT_FAILURE); | 96 | exit(EXIT_FAILURE); |
| 90 | } | 97 | } |
| @@ -95,8 +102,8 @@ static void everror(const char *format, ...) | |||
| 95 | static void usage(void) | 102 | static void usage(void) |
| 96 | { | 103 | { |
| 97 | fprintf(stderr, | 104 | fprintf(stderr, |
| 98 | "Usage: %s [-f logfile] [-p] [-v] [-e events] [-b size]" | 105 | "Usage: %s [-f logfile] [-h]\n" |
| 99 | " [-S[LC]] [-?]\nSee guide.mps.telemetry for instructions.\n", | 106 | "See \"Telemetry\" in the reference manual for instructions.\n", |
| 100 | prog); | 107 | prog); |
| 101 | } | 108 | } |
| 102 | 109 | ||
| @@ -110,41 +117,11 @@ static void usageError(void) | |||
| 110 | } | 117 | } |
| 111 | 118 | ||
| 112 | 119 | ||
| 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 */ | 120 | /* parseArgs -- parse command line arguments, return log file name */ |
| 144 | 121 | ||
| 145 | static char *parseArgs(int argc, char *argv[]) | 122 | static char *parseArgs(int argc, char *argv[]) |
| 146 | { | 123 | { |
| 147 | char *name = "mpsio.log"; | 124 | char *name = NULL; |
| 148 | int i = 1; | 125 | int i = 1; |
| 149 | 126 | ||
| 150 | if (argc >= 1) | 127 | if (argc >= 1) |
| @@ -162,34 +139,9 @@ static char *parseArgs(int argc, char *argv[]) | |||
| 162 | else | 139 | else |
| 163 | name = argv[i]; | 140 | name = argv[i]; |
| 164 | break; | 141 | 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 */ | ||
| 188 | style = argv[i][2]; /* '\0' for human-readable, 'L' for Lisp, */ | ||
| 189 | break; /* 'C' for CDF. */ | ||
| 190 | case '?': case 'h': /* help */ | 142 | case '?': case 'h': /* help */ |
| 191 | usage(); | 143 | usage(); |
| 192 | break; | 144 | exit(EXIT_SUCCESS); |
| 193 | default: | 145 | default: |
| 194 | usageError(); | 146 | usageError(); |
| 195 | } | 147 | } |
| @@ -200,252 +152,41 @@ static char *parseArgs(int argc, char *argv[]) | |||
| 200 | } | 152 | } |
| 201 | 153 | ||
| 202 | 154 | ||
| 203 | /* recordEvent -- record event | 155 | /* Printing routines */ |
| 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 | 156 | ||
| 216 | static void recordEvent(EventProc proc, Event event, EventClock etime) | 157 | static void printHex(ulongest_t val) |
| 217 | { | 158 | { |
| 218 | Res res; | 159 | printf(" %"PRIXLONGEST, (ulongest_t)val); |
| 219 | 160 | } | |
| 220 | res = EventRecord(proc, event, etime); | 161 | |
| 221 | if (res != ResOK) | 162 | #define printParamP(p) printHex((ulongest_t)p) |
| 222 | everror("Can't record event: error %d.", res); | 163 | #define printParamA(a) printHex((ulongest_t)a) |
| 223 | switch(event->any.code) { | 164 | #define printParamU(u) printHex((ulongest_t)u) |
| 224 | default: | 165 | #define printParamW(w) printHex((ulongest_t)w) |
| 225 | break; | 166 | #define printParamB(b) printHex((ulongest_t)b) |
| 226 | } | 167 | |
| 168 | static void printParamD(double d) | ||
| 169 | { | ||
| 170 | printf(" %.10G", d); | ||
| 227 | } | 171 | } |
| 228 | 172 | ||
| 229 | 173 | static void printParamS(const char *str) | |
| 230 | /* Printing routines */ | ||
| 231 | |||
| 232 | |||
| 233 | /* printStr -- print an EventString */ | ||
| 234 | |||
| 235 | static void printStr(const char *str, Bool quotes) | ||
| 236 | { | 174 | { |
| 237 | size_t i; | 175 | size_t i; |
| 238 | 176 | putchar(' '); | |
| 239 | if (quotes) putchar('"'); | 177 | putchar('"'); |
| 240 | for (i = 0; str[i] != '\0'; ++i) { | 178 | for (i = 0; str[i] != '\0'; ++i) { |
| 241 | char c = str[i]; | 179 | char c = str[i]; |
| 242 | if (quotes && (c == '"' || c == '\\')) putchar('\\'); | 180 | if (c == '"' || c == '\\') putchar('\\'); |
| 243 | putchar(c); | 181 | putchar(c); |
| 244 | } | 182 | } |
| 245 | if (quotes) putchar('"'); | 183 | putchar('"'); |
| 246 | } | ||
| 247 | |||
| 248 | |||
| 249 | /* printAddr -- print an Addr or its label */ | ||
| 250 | |||
| 251 | static void printAddr(EventProc proc, Addr addr) | ||
| 252 | { | ||
| 253 | Word label; | ||
| 254 | |||
| 255 | label = AddrLabel(proc, addr); | ||
| 256 | if (label != 0 && addr != 0) { | ||
| 257 | /* We assume labelling zero is meant to record a point in time */ | ||
| 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 | } | 184 | } |
| 274 | 185 | ||
| 275 | 186 | /* readLog -- read and parse log */ | |
| 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 | } | ||
| 344 | |||
| 345 | |||
| 346 | /* printParam* -- printing functions for event parameter types */ | ||
| 347 | |||
| 348 | static void printParamA(EventProc proc, char *styleConv, Addr addr) | ||
| 349 | { | ||
| 350 | if (style != 'L') { | ||
| 351 | if (style == 'C') putchar(','); | ||
| 352 | printAddr(proc, addr); | ||
| 353 | } else | ||
| 354 | printf(styleConv, (ulongest_t)addr); | ||
| 355 | } | ||
| 356 | |||
| 357 | static void printParamP(EventProc proc, char *styleConv, void *p) | ||
| 358 | { | ||
| 359 | UNUSED(proc); | ||
| 360 | printf(styleConv, (ulongest_t)p); | ||
| 361 | } | ||
| 362 | |||
| 363 | static void printParamU(EventProc proc, char *styleConv, unsigned u) | ||
| 364 | { | ||
| 365 | UNUSED(proc); | ||
| 366 | printf(styleConv, (ulongest_t)u); | ||
| 367 | } | ||
| 368 | |||
| 369 | static void printParamW(EventProc proc, char *styleConv, Word w) | ||
| 370 | { | ||
| 371 | UNUSED(proc); | ||
| 372 | printf(styleConv, (ulongest_t)w); | ||
| 373 | } | ||
| 374 | |||
| 375 | static void printParamD(EventProc proc, char *styleConv, double d) | ||
| 376 | { | ||
| 377 | UNUSED(proc); | ||
| 378 | UNUSED(styleConv); | ||
| 379 | switch (style) { | ||
| 380 | case '\0': | ||
| 381 | printf(" %#8.3g", d); break; | ||
| 382 | case 'C': | ||
| 383 | printf(", %.10G", d); break; | ||
| 384 | case 'L': | ||
| 385 | printf(" %#.10G", d); break; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | static void printParamS(EventProc proc, char *styleConv, const char *s) | ||
| 390 | { | ||
| 391 | UNUSED(proc); | ||
| 392 | UNUSED(styleConv); | ||
| 393 | if (style == 'C') putchar(','); | ||
| 394 | putchar(' '); | ||
| 395 | printStr(s, (style == 'C' || style == 'L')); | ||
| 396 | } | ||
| 397 | |||
| 398 | static void printParamB(EventProc proc, char *styleConv, Bool b) | ||
| 399 | { | ||
| 400 | UNUSED(proc); | ||
| 401 | UNUSED(proc); | ||
| 402 | printf(styleConv, (ulongest_t)b); | ||
| 403 | } | ||
| 404 | |||
| 405 | |||
| 406 | /* readLog -- read and parse log | ||
| 407 | * | ||
| 408 | * This is the heart of eventcnv: It reads an event log using EventRead. | ||
| 409 | * It updates the counters. If verbose is true, it looks up the format, | ||
| 410 | * parses the arguments, and prints a representation of the event. Each | ||
| 411 | * argument is printed using printArg (see RELATION, below), except for | ||
| 412 | * some event types that are handled specially. | ||
| 413 | */ | ||
| 414 | 187 | ||
| 415 | static void readLog(EventProc proc) | 188 | static void readLog(EventProc proc) |
| 416 | { | 189 | { |
| 417 | EventCode c; | ||
| 418 | Word bucketLimit = bucketSize; | ||
| 419 | char *styleConv = NULL; /* suppress uninit warning */ | ||
| 420 | |||
| 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. */ | ||
| 438 | switch (style) { | ||
| 439 | case '\0': | ||
| 440 | styleConv = " %8"PRIXLONGEST; break; | ||
| 441 | case 'C': | ||
| 442 | styleConv = ", %"PRIuLONGEST; break; | ||
| 443 | case 'L': | ||
| 444 | styleConv = " %"PRIXLONGEST; break; | ||
| 445 | default: | ||
| 446 | everror("Unknown style code '%c'", style); | ||
| 447 | } | ||
| 448 | |||
| 449 | while (TRUE) { /* loop for each event */ | 190 | while (TRUE) { /* loop for each event */ |
| 450 | Event event; | 191 | Event event; |
| 451 | EventCode code; | 192 | EventCode code; |
| @@ -457,181 +198,56 @@ static void readLog(EventProc proc) | |||
| 457 | if (res != ResOK) everror("Truncated log"); | 198 | if (res != ResOK) everror("Truncated log"); |
| 458 | eventTime = event->any.clock; | 199 | eventTime = event->any.clock; |
| 459 | code = event->any.code; | 200 | code = event->any.code; |
| 460 | 201 | ||
| 461 | /* Output bucket, if necessary, and update counters */ | 202 | /* Special handling for some events, prior to text output */ |
| 462 | if (bucketSize != 0 && eventTime >= bucketLimit) { | 203 | |
| 463 | reportBucketResults(bucketLimit-1); | 204 | switch(code) { |
| 464 | clearBucket(); | 205 | case EventEventInitCode: |
| 465 | do { | 206 | if ((event->EventInit.f0 != EVENT_VERSION_MAJOR) || |
| 466 | bucketLimit += bucketSize; | 207 | (event->EventInit.f1 != EVENT_VERSION_MEDIAN) || |
| 467 | } while (eventTime >= bucketLimit); | 208 | (event->EventInit.f2 != EVENT_VERSION_MINOR)) |
| 468 | } | 209 | evwarn("Event log version does not match: %d.%d.%d vs %d.%d.%d", |
| 469 | if (reportStats) { | 210 | event->EventInit.f0, |
| 470 | ++bucketEventCount[code]; | 211 | event->EventInit.f1, |
| 471 | ++totalEventCount[code]; | 212 | event->EventInit.f2, |
| 213 | EVENT_VERSION_MAJOR, | ||
| 214 | EVENT_VERSION_MEDIAN, | ||
| 215 | EVENT_VERSION_MINOR); | ||
| 216 | |||
| 217 | if (event->EventInit.f3 > EventCodeMAX) | ||
| 218 | evwarn("Event log may contain unknown events with codes from %d to %d", | ||
| 219 | EventCodeMAX+1, event->EventInit.f3); | ||
| 220 | |||
| 221 | if (event->EventInit.f5 != MPS_WORD_WIDTH) | ||
| 222 | /* This probably can't happen; other things will break | ||
| 223 | * before we get here */ | ||
| 224 | evwarn("Event log has incompatible word width: %d instead of %d", | ||
| 225 | event->EventInit.f5, | ||
| 226 | MPS_WORD_WIDTH); | ||
| 227 | break; | ||
| 472 | } | 228 | } |
| 473 | 229 | ||
| 474 | /* Output event. */ | 230 | EVENT_CLOCK_PRINT(stdout, eventTime); |
| 475 | if (verbose) { | 231 | printf(" %4X", (unsigned)code); |
| 476 | if (style == 'L') putchar('('); | ||
| 477 | 232 | ||
| 478 | switch (style) { | 233 | switch (code) { |
| 479 | case '\0': case 'L': | 234 | #define EVENT_PARAM_PRINT(name, index, sort, ident) \ |
| 480 | EVENT_CLOCK_PRINT(stdout, eventTime); | 235 | printParam##sort(event->name.f##index); |
| 481 | putchar(' '); | 236 | #define EVENT_PRINT(X, name, code, always, kind) \ |
| 237 | case code: \ | ||
| 238 | EVENT_##name##_PARAMS(EVENT_PARAM_PRINT, name) \ | ||
| 482 | break; | 239 | break; |
| 483 | case 'C': | 240 | EVENT_LIST(EVENT_PRINT, X) |
| 484 | EVENT_CLOCK_PRINT(stdout, eventTime); | 241 | default: |
| 485 | fputs(", ", stdout); | 242 | evwarn("Unknown event code %d", code); |
| 486 | break; | ||
| 487 | } | ||
| 488 | |||
| 489 | switch (style) { | ||
| 490 | case '\0': case 'L': { | ||
| 491 | printf("%-19s ", EventCode2Name(code)); | ||
| 492 | } break; | ||
| 493 | case 'C': | ||
| 494 | printf("%u", (unsigned)code); | ||
| 495 | break; | ||
| 496 | } | ||
| 497 | |||
| 498 | switch (code) { | ||
| 499 | |||
| 500 | case EventLabelCode: | ||
| 501 | switch (style) { | ||
| 502 | case '\0': case 'C': | ||
| 503 | { | ||
| 504 | const char *sym = LabelText(proc, event->Label.f1); | ||
| 505 | printf(style == '\0' ? | ||
| 506 | " %08"PRIXLONGEST" " : | ||
| 507 | ", %"PRIuLONGEST", ", | ||
| 508 | (ulongest_t)event->Label.f0); | ||
| 509 | if (sym != NULL) { | ||
| 510 | printStr(sym, (style == 'C')); | ||
| 511 | } else { | ||
| 512 | printf(style == '\0' ? | ||
| 513 | "sym %05"PRIXLONGEST : | ||
| 514 | "sym %"PRIXLONGEST"\"", | ||
| 515 | (ulongest_t)event->Label.f1); | ||
| 516 | } | ||
| 517 | } | ||
| 518 | break; | ||
| 519 | case 'L': | ||
| 520 | printf(" %"PRIXLONGEST" %"PRIXLONGEST, | ||
| 521 | (ulongest_t)event->Label.f0, | ||
| 522 | (ulongest_t)event->Label.f1); | ||
| 523 | break; | ||
| 524 | } | ||
| 525 | break; | ||
| 526 | |||
| 527 | case EventMeterValuesCode: | ||
| 528 | switch (style) { | ||
| 529 | case '\0': | ||
| 530 | if (event->MeterValues.f3 == 0) { | ||
| 531 | printf(" %08"PRIXLONGEST" 0 N/A N/A N/A N/A", | ||
| 532 | (ulongest_t)event->MeterValues.f0); | ||
| 533 | } else { | ||
| 534 | double mean = event->MeterValues.f1 / (double)event->MeterValues.f3; | ||
| 535 | /* .stddev: stddev = sqrt(meanSquared - mean^2), but see */ | ||
| 536 | /* <code/meter.c#limitation.variance>. */ | ||
| 537 | double stddev = sqrt(fabs(event->MeterValues.f2 | ||
| 538 | - (mean * mean))); | ||
| 539 | printf(" %08"PRIXLONGEST" %8u %8u %8u %#8.3g %#8.3g", | ||
| 540 | (ulongest_t)event->MeterValues.f0, (uint)event->MeterValues.f3, | ||
| 541 | (uint)event->MeterValues.f4, (uint)event->MeterValues.f5, | ||
| 542 | mean, stddev); | ||
| 543 | } | ||
| 544 | printAddr(proc, (Addr)event->MeterValues.f0); | ||
| 545 | break; | ||
| 546 | |||
| 547 | case 'C': | ||
| 548 | putchar(','); | ||
| 549 | printAddr(proc, (Addr)event->MeterValues.f0); | ||
| 550 | printf(", %.10G, %.10G, %u, %u, %u", | ||
| 551 | event->MeterValues.f1, event->MeterValues.f2, | ||
| 552 | (uint)event->MeterValues.f3, (uint)event->MeterValues.f4, | ||
| 553 | (uint)event->MeterValues.f5); | ||
| 554 | break; | ||
| 555 | |||
| 556 | case 'L': | ||
| 557 | printf(" %"PRIXLONGEST" %#.10G %#.10G %X %X %X", | ||
| 558 | (ulongest_t)event->MeterValues.f0, | ||
| 559 | event->MeterValues.f1, event->MeterValues.f2, | ||
| 560 | (uint)event->MeterValues.f3, (uint)event->MeterValues.f4, | ||
| 561 | (uint)event->MeterValues.f5); | ||
| 562 | break; | ||
| 563 | } | ||
| 564 | break; | ||
| 565 | |||
| 566 | case EventPoolInitCode: /* pool, arena, class */ | ||
| 567 | printf(styleConv, (ulongest_t)event->PoolInit.f0); | ||
| 568 | printf(styleConv, (ulongest_t)event->PoolInit.f1); | ||
| 569 | /* class is a Pointer, but we label them, so call printAddr */ | ||
| 570 | if (style != 'L') { | ||
| 571 | if (style == 'C') putchar(','); | ||
| 572 | printAddr(proc, (Addr)event->PoolInit.f2); | ||
| 573 | } else | ||
| 574 | printf(styleConv, (ulongest_t)event->PoolInit.f2); | ||
| 575 | break; | ||
| 576 | |||
| 577 | default: | ||
| 578 | #define EVENT_PARAM_PRINT(name, index, sort, ident) \ | ||
| 579 | printParam##sort(proc, styleConv, event->name.f##index); | ||
| 580 | #define EVENT_PRINT(X, name, code, always, kind) \ | ||
| 581 | case code: \ | ||
| 582 | EVENT_##name##_PARAMS(EVENT_PARAM_PRINT, name) \ | ||
| 583 | break; | ||
| 584 | switch (code) { EVENT_LIST(EVENT_PRINT, X) } | ||
| 585 | } | ||
| 586 | |||
| 587 | if (style == 'L') putchar(')'); | ||
| 588 | putchar('\n'); | ||
| 589 | fflush(stdout); | ||
| 590 | } | 243 | } |
| 591 | recordEvent(proc, event, eventTime); | 244 | |
| 245 | putchar('\n'); | ||
| 246 | fflush(stdout); | ||
| 592 | EventDestroy(proc, event); | 247 | EventDestroy(proc, event); |
| 593 | } /* while(!feof(input)) */ | 248 | } /* while(!feof(input)) */ |
| 594 | |||
| 595 | /* report last bucket (partial) */ | ||
| 596 | if (bucketSize != 0) { | ||
| 597 | reportBucketResults(eventTime); | ||
| 598 | } | ||
| 599 | if (reportStats) { | ||
| 600 | /* report totals */ | ||
| 601 | switch (style) { | ||
| 602 | case '\0': | ||
| 603 | printf("\n run:"); | ||
| 604 | break; | ||
| 605 | case 'L': | ||
| 606 | printf("(t"); | ||
| 607 | break; | ||
| 608 | case 'C': | ||
| 609 | { | ||
| 610 | /* FIXME: This attempted to print the event stats on a row that | ||
| 611 | resembled a kind of final event, but the event clock no longer runs | ||
| 612 | monotonically upwards. */ | ||
| 613 | EventClock last = eventTime + 1; | ||
| 614 | EVENT_CLOCK_PRINT(stdout, last); | ||
| 615 | } | ||
| 616 | break; | ||
| 617 | } | ||
| 618 | reportEventResults(totalEventCount); | ||
| 619 | |||
| 620 | /* explain event codes */ | ||
| 621 | if (style == '\0') { | ||
| 622 | printf("\n"); | ||
| 623 | for(c = 0; c <= EventCodeMAX; ++c) | ||
| 624 | if (eventEnabled[c]) | ||
| 625 | printf(" %04X %s\n", (unsigned)c, EventCode2Name(c)); | ||
| 626 | if (bucketSize == 0) | ||
| 627 | printf("\nevent clock stopped at "); | ||
| 628 | EVENT_CLOCK_PRINT(stdout, eventTime); | ||
| 629 | printf("\n"); | ||
| 630 | } | ||
| 631 | } | ||
| 632 | } | 249 | } |
| 633 | 250 | ||
| 634 | |||
| 635 | /* logReader -- reader function for a file log */ | 251 | /* logReader -- reader function for a file log */ |
| 636 | 252 | ||
| 637 | static FILE *input; | 253 | static FILE *input; |
| @@ -663,9 +279,13 @@ int main(int argc, char *argv[]) | |||
| 663 | assert(CHECKCONV(ulongest_t, Addr)); | 279 | assert(CHECKCONV(ulongest_t, Addr)); |
| 664 | assert(CHECKCONV(ulongest_t, void *)); | 280 | assert(CHECKCONV(ulongest_t, void *)); |
| 665 | assert(CHECKCONV(ulongest_t, EventCode)); | 281 | assert(CHECKCONV(ulongest_t, EventCode)); |
| 666 | assert(CHECKCONV(Addr, void *)); /* for labelled pointers */ | ||
| 667 | 282 | ||
| 668 | filename = parseArgs(argc, argv); | 283 | filename = parseArgs(argc, argv); |
| 284 | if (!filename) { | ||
| 285 | filename = getenv(TELEMETRY_FILENAME_ENVAR); | ||
| 286 | if(!filename) | ||
| 287 | filename = DEFAULT_TELEMETRY_FILENAME; | ||
| 288 | } | ||
| 669 | 289 | ||
| 670 | if (strcmp(filename, "-") == 0) | 290 | if (strcmp(filename, "-") == 0) |
| 671 | input = stdin; | 291 | input = stdin; |
| @@ -688,7 +308,7 @@ int main(int argc, char *argv[]) | |||
| 688 | 308 | ||
| 689 | /* C. COPYRIGHT AND LICENSE | 309 | /* C. COPYRIGHT AND LICENSE |
| 690 | * | 310 | * |
| 691 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. | 311 | * Copyright (C) 2001-2012 Ravenbrook Limited <http://www.ravenbrook.com/>. |
| 692 | * All rights reserved. This is an open source license. Contact | 312 | * All rights reserved. This is an open source license. Contact |
| 693 | * Ravenbrook for commercial licensing options. | 313 | * Ravenbrook for commercial licensing options. |
| 694 | * | 314 | * |
diff --git a/mps/code/eventdef.h b/mps/code/eventdef.h index df80bb6d1c2..70a32393d3d 100644 --- a/mps/code/eventdef.h +++ b/mps/code/eventdef.h | |||
| @@ -37,8 +37,8 @@ | |||
| 37 | */ | 37 | */ |
| 38 | 38 | ||
| 39 | #define EVENT_VERSION_MAJOR ((unsigned)1) | 39 | #define EVENT_VERSION_MAJOR ((unsigned)1) |
| 40 | #define EVENT_VERSION_MEDIAN ((unsigned)0) | 40 | #define EVENT_VERSION_MEDIAN ((unsigned)1) |
| 41 | #define EVENT_VERSION_MINOR ((unsigned)0) | 41 | #define EVENT_VERSION_MINOR ((unsigned)3) |
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | /* EVENT_LIST -- list of event types and general properties | 44 | /* EVENT_LIST -- list of event types and general properties |
| @@ -68,7 +68,7 @@ | |||
| 68 | */ | 68 | */ |
| 69 | 69 | ||
| 70 | #define EventNameMAX ((size_t)19) | 70 | #define EventNameMAX ((size_t)19) |
| 71 | #define EventCodeMAX ((EventCode)0x0073) | 71 | #define EventCodeMAX ((EventCode)0x0078) |
| 72 | 72 | ||
| 73 | #define EVENT_LIST(EVENT, X) \ | 73 | #define EVENT_LIST(EVENT, X) \ |
| 74 | /* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \ | 74 | /* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \ |
| @@ -179,7 +179,13 @@ | |||
| 179 | EVENT(X, TraceFindGrey , 0x0070, TRUE, Trace) \ | 179 | EVENT(X, TraceFindGrey , 0x0070, TRUE, Trace) \ |
| 180 | EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace) \ | 180 | EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace) \ |
| 181 | EVENT(X, AWLDeclineTotal , 0x0072, TRUE, Trace) \ | 181 | EVENT(X, AWLDeclineTotal , 0x0072, TRUE, Trace) \ |
| 182 | EVENT(X, AWLDeclineSeg , 0x0073, TRUE, Trace) | 182 | EVENT(X, AWLDeclineSeg , 0x0073, TRUE, Trace) \ |
| 183 | EVENT(X, EventInit , 0x0074, TRUE, Arena) \ | ||
| 184 | EVENT(X, EventClockSync , 0x0075, TRUE, Arena) \ | ||
| 185 | EVENT(X, ArenaAccess , 0x0076, TRUE, Arena) \ | ||
| 186 | EVENT(X, ArenaPoll , 0x0077, TRUE, Arena) \ | ||
| 187 | EVENT(X, ArenaSetEmergency , 0x0078, TRUE, Arena) | ||
| 188 | |||
| 183 | 189 | ||
| 184 | 190 | ||
| 185 | /* Remember to update EventNameMAX and EventCodeMAX in eventcom.h! | 191 | /* Remember to update EventNameMAX and EventCodeMAX in eventcom.h! |
| @@ -620,6 +626,32 @@ | |||
| 620 | PARAM(X, 0, P, seg) /* segment declined single access */ \ | 626 | PARAM(X, 0, P, seg) /* segment declined single access */ \ |
| 621 | PARAM(X, 1, W, singleAccesses) /* single accesses this cycle */ | 627 | PARAM(X, 1, W, singleAccesses) /* single accesses this cycle */ |
| 622 | 628 | ||
| 629 | #define EVENT_EventInit_PARAMS(PARAM, X) \ | ||
| 630 | PARAM(X, 0, U, major) /* EVENT_VERSION_MAJOR */ \ | ||
| 631 | PARAM(X, 1, U, median) /* EVENT_VERSION_MEDIAN */ \ | ||
| 632 | PARAM(X, 2, U, minor) /* EVENT_VERSION_MINOR */ \ | ||
| 633 | PARAM(X, 3, U, maxCode) /* EventCodeMAX */ \ | ||
| 634 | PARAM(X, 4, U, maxNameLen) /* EventNameMAX */ \ | ||
| 635 | PARAM(X, 5, U, wordWidth) /* MPS_WORD_WIDTH */ \ | ||
| 636 | PARAM(X, 6, W, clocksPerSec) /* mps_clocks_per_sec() */ | ||
| 637 | |||
| 638 | #define EVENT_EventClockSync_PARAMS(PARAM, X) \ | ||
| 639 | PARAM(X, 0, W, clock) /* mps_clock() value */ | ||
| 640 | |||
| 641 | #define EVENT_ArenaAccess_PARAMS(PARAM, X) \ | ||
| 642 | PARAM(X, 0, P, arena) \ | ||
| 643 | PARAM(X, 1, W, count) \ | ||
| 644 | PARAM(X, 2, P, addr) \ | ||
| 645 | PARAM(X, 3, U, mode) | ||
| 646 | |||
| 647 | #define EVENT_ArenaPoll_PARAMS(PARAM, X) \ | ||
| 648 | PARAM(X, 0, P, arena) \ | ||
| 649 | PARAM(X, 1, W, start) \ | ||
| 650 | PARAM(X, 2, W, quanta) | ||
| 651 | |||
| 652 | #define EVENT_ArenaSetEmergency_PARAMS(PARAM, X) \ | ||
| 653 | PARAM(X, 0, P, arena) \ | ||
| 654 | PARAM(X, 1, B, emergency) | ||
| 623 | 655 | ||
| 624 | #endif /* eventdef_h */ | 656 | #endif /* eventdef_h */ |
| 625 | 657 | ||
diff --git a/mps/code/eventsql.c b/mps/code/eventsql.c new file mode 100644 index 00000000000..1fdafe4624e --- /dev/null +++ b/mps/code/eventsql.c | |||
| @@ -0,0 +1,1004 @@ | |||
| 1 | /* eventsql.c: event log to SQLite importer. | ||
| 2 | * | ||
| 3 | * $Id$ | ||
| 4 | * | ||
| 5 | * Copyright (c) 2012 Ravenbrook Limited. See end of file for license. | ||
| 6 | * | ||
| 7 | * This is a command-line tool that imports events from a text-format | ||
| 8 | * MPS telemetry file into a SQLite database file. | ||
| 9 | * | ||
| 10 | * The default MPS library will write a binary-format telemetry file | ||
| 11 | * which can be converted into a text-format file using the eventcnv | ||
| 12 | * program (q.v.). | ||
| 13 | * | ||
| 14 | * Each event type gets its own table in the database. These tables | ||
| 15 | * are created from the definitions in eventdef.h if they don't | ||
| 16 | * already exist. Each event becomes a single row in the appropriate | ||
| 17 | * table, which has a column for each event parameter, a time column | ||
| 18 | * for the event time field, and a log_serial column to identify the | ||
| 19 | * source log file. Because the database schema depends on the event | ||
| 20 | * definitions in eventdef.h, eventsql has to be compiled using the | ||
| 21 | * same event header files as those used to compile the MPS and | ||
| 22 | * eventcnv which generated and processed the telemetry output. | ||
| 23 | * | ||
| 24 | * The program also creates several other tables: three 'glue' tables | ||
| 25 | * containing event metadata - event_kind (one row per kind), | ||
| 26 | * event_type (one row per type), and event_param (one row per | ||
| 27 | * parameter), all derived from eventdef.h - and the event_log table | ||
| 28 | * which has one row per log file imported (the log_serial column in | ||
| 29 | * the event tables is a primary key to this event_log table). | ||
| 30 | * | ||
| 31 | * No tables are created if they already exist, unless the -r | ||
| 32 | * (rebuild) switch is given. | ||
| 33 | * | ||
| 34 | * Options: | ||
| 35 | * | ||
| 36 | * -v (verbose): Increase verbosity. eventsql logs to stderr. By | ||
| 37 | * default, it doesn't log much; it can be made more and more | ||
| 38 | * loquacious by adding more -v switches. | ||
| 39 | * | ||
| 40 | * -p (progress): Show progress with a series of dots written to | ||
| 41 | * standard output (one dot per 100,000 events processed). Defaults | ||
| 42 | * on if -v specified, off otherwise. | ||
| 43 | * | ||
| 44 | * -t (test): Run unit tests on parts of eventsql. There aren't many | ||
| 45 | * of these. TODO: write more unit tests. | ||
| 46 | * | ||
| 47 | * -d (delete): Delete the SQL file before importing. | ||
| 48 | * | ||
| 49 | * -f (force): Import the events to SQL even if the SQL database | ||
| 50 | * already includes a record of importing a matching log file. | ||
| 51 | * | ||
| 52 | * -r (rebuild): Drop the glue tables from SQL, which will force them | ||
| 53 | * to be recreated. Important if you change event types or kinds in | ||
| 54 | * eventdef.h. | ||
| 55 | * | ||
| 56 | * -i <logfile>: Import events from the named logfile. Defaults to | ||
| 57 | * standard input. If the specified file (matched by size and | ||
| 58 | * modtime) has previously been imported to the same database, it will | ||
| 59 | * not be imported again unless -f is specified. | ||
| 60 | * | ||
| 61 | * -o <database>: Import events to the named database file. If not | ||
| 62 | * specified, eventsql will use the MPS_TELEMETRY_DATABASE environment | ||
| 63 | * variable, and default to "mpsevent.db". | ||
| 64 | * | ||
| 65 | * $Id$ | ||
| 66 | */ | ||
| 67 | |||
| 68 | #include "misc.h" | ||
| 69 | #include "config.h" | ||
| 70 | #include "eventdef.h" | ||
| 71 | #include "eventcom.h" | ||
| 72 | |||
| 73 | #include <stdio.h> | ||
| 74 | #include <stdlib.h> | ||
| 75 | #include <string.h> | ||
| 76 | #include <sys/stat.h> | ||
| 77 | |||
| 78 | /* on Windows, we build SQLite locally from the amalgamated sources */ | ||
| 79 | #ifdef MPS_BUILD_MV | ||
| 80 | #include "sqlite3.h" | ||
| 81 | #else | ||
| 82 | #include <sqlite3.h> | ||
| 83 | #endif | ||
| 84 | |||
| 85 | #define DATABASE_NAME_ENVAR "MPS_TELEMETRY_DATABASE" | ||
| 86 | #define DEFAULT_DATABASE_NAME "mpsevent.db" | ||
| 87 | |||
| 88 | #ifdef MPS_BUILD_MV | ||
| 89 | /* MSVC warning 4996 = stdio / C runtime 'unsafe' */ | ||
| 90 | /* Objects to: getenv, sprintf. See job001934. */ | ||
| 91 | #pragma warning( disable : 4996 ) | ||
| 92 | #define strtoll _strtoi64 | ||
| 93 | #endif | ||
| 94 | |||
| 95 | |||
| 96 | typedef sqlite3_int64 int64; | ||
| 97 | |||
| 98 | /* At non-zero verbosity levels we output rows of dots. One dot per | ||
| 99 | * SMALL_TICK events, BIG_TICK dots per row. */ | ||
| 100 | |||
| 101 | #define SMALL_TICK 100000 | ||
| 102 | #define BIG_TICK 50 | ||
| 103 | |||
| 104 | /* Utility code for logging to stderr with multiple log levels, | ||
| 105 | * and for reporting errors. | ||
| 106 | */ | ||
| 107 | |||
| 108 | unsigned int verbosity = 0; | ||
| 109 | |||
| 110 | #define LOG_ALWAYS 0 | ||
| 111 | #define LOG_OFTEN 1 | ||
| 112 | #define LOG_SOMETIMES 2 | ||
| 113 | #define LOG_SELDOM 3 | ||
| 114 | #define LOG_RARELY 4 | ||
| 115 | |||
| 116 | static void vlog(unsigned int level, const char *format, va_list args) | ||
| 117 | { | ||
| 118 | if (level <= verbosity) { | ||
| 119 | fflush(stderr); /* sync */ | ||
| 120 | fprintf(stderr, "log %d: ", level); | ||
| 121 | vfprintf(stderr, format, args); | ||
| 122 | fprintf(stderr, "\n"); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | static void evlog(unsigned int level, const char *format, ...) | ||
| 127 | { | ||
| 128 | va_list args; | ||
| 129 | va_start(args, format); | ||
| 130 | vlog(level, format, args); | ||
| 131 | va_end(args); | ||
| 132 | } | ||
| 133 | |||
| 134 | static void error(const char *format, ...) | ||
| 135 | { | ||
| 136 | va_list args; | ||
| 137 | fprintf(stderr, "Fatal error: "); | ||
| 138 | va_start(args, format); | ||
| 139 | vlog(LOG_ALWAYS, format, args); | ||
| 140 | va_end(args); | ||
| 141 | exit(1); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void sqlite_error(int res, sqlite3 *db, const char *format, ...) | ||
| 145 | { | ||
| 146 | va_list args; | ||
| 147 | evlog(LOG_ALWAYS, "Fatal SQL error %d", res); | ||
| 148 | va_start(args, format); | ||
| 149 | vlog(LOG_ALWAYS, format, args); | ||
| 150 | va_end(args); | ||
| 151 | evlog(LOG_ALWAYS, "SQLite message: %s\n", sqlite3_errmsg(db)); | ||
| 152 | exit(1); | ||
| 153 | } | ||
| 154 | |||
| 155 | /* global control variables set by command-line parameters. */ | ||
| 156 | |||
| 157 | static char *prog; /* program name */ | ||
| 158 | static int rebuild = FALSE; | ||
| 159 | static int deleteDatabase = FALSE; | ||
| 160 | static int runTests = FALSE; | ||
| 161 | static int force = FALSE; | ||
| 162 | static int progress = FALSE; | ||
| 163 | static char *databaseName = NULL; | ||
| 164 | static char *logFileName = NULL; | ||
| 165 | |||
| 166 | static void usage(void) | ||
| 167 | { | ||
| 168 | fprintf(stderr, | ||
| 169 | "Usage: %s [-rfdvt] [-i <logfile>] [-o <database>]\n" | ||
| 170 | " -h (help) : this message.\n" | ||
| 171 | " -r (rebuild) : re-create glue tables.\n" | ||
| 172 | " -f (force) : ignore previous import of same logfile.\n" | ||
| 173 | " -d (delete) : delete and recreate database file.\n" | ||
| 174 | " -v (verbose) : increase logging to stderr.\n" | ||
| 175 | " -p (progress): show progress with dots to stdout.\n" | ||
| 176 | " -t (test) : run self-tests.\n" | ||
| 177 | " -i <logfile> : read logfile (defaults to stdin)\n" | ||
| 178 | " -o <database>: write database (defaults to\n" | ||
| 179 | " " | ||
| 180 | DATABASE_NAME_ENVAR " or " DEFAULT_DATABASE_NAME ").\n", | ||
| 181 | prog); | ||
| 182 | } | ||
| 183 | |||
| 184 | static void usageError(void) | ||
| 185 | { | ||
| 186 | usage(); | ||
| 187 | error("Bad usage"); | ||
| 188 | } | ||
| 189 | |||
| 190 | /* parseArgs -- parse command line arguments */ | ||
| 191 | |||
| 192 | static void parseArgs(int argc, char *argv[]) | ||
| 193 | { | ||
| 194 | int i = 1; | ||
| 195 | |||
| 196 | if (argc >= 1) | ||
| 197 | prog = argv[0]; | ||
| 198 | else | ||
| 199 | prog = "unknown"; | ||
| 200 | |||
| 201 | while(i < argc) { /* consider argument i */ | ||
| 202 | if (argv[i][0] == '-') { /* it's an option argument */ | ||
| 203 | char *p = argv[i] + 1; | ||
| 204 | while(*p) { | ||
| 205 | switch (*p) { | ||
| 206 | case 'v': /* verbosity */ | ||
| 207 | ++ verbosity; | ||
| 208 | break; | ||
| 209 | case 'p': /* progress */ | ||
| 210 | progress = TRUE; | ||
| 211 | break; | ||
| 212 | case 'r': /* rebuild */ | ||
| 213 | rebuild = TRUE; | ||
| 214 | break; | ||
| 215 | case 'd': /* rebuild */ | ||
| 216 | deleteDatabase = TRUE; | ||
| 217 | break; | ||
| 218 | case 'f': /* force */ | ||
| 219 | force = TRUE; | ||
| 220 | break; | ||
| 221 | case 't': /* run tests */ | ||
| 222 | runTests = TRUE; | ||
| 223 | break; | ||
| 224 | case 'i': /* input (log file) name */ | ||
| 225 | if (p[1] == '\0') { /* last character in this arg; name is next arg */ | ||
| 226 | logFileName = argv[i+1]; | ||
| 227 | ++ i; | ||
| 228 | } else { /* not last character in arg; name is rest of arg */ | ||
| 229 | logFileName = p+1; | ||
| 230 | } | ||
| 231 | continue; | ||
| 232 | case 'o': /* output (database file) name */ | ||
| 233 | if (p[1] == '\0') { /* last character in this arg; name is next arg */ | ||
| 234 | databaseName = argv[i+1]; | ||
| 235 | ++ i; | ||
| 236 | } else { /* not last character in arg; name is rest of arg */ | ||
| 237 | databaseName = p+1; | ||
| 238 | } | ||
| 239 | continue; | ||
| 240 | case 'h': | ||
| 241 | usage(); | ||
| 242 | exit(EXIT_SUCCESS); | ||
| 243 | default: | ||
| 244 | usageError(); | ||
| 245 | } | ||
| 246 | ++ p; | ||
| 247 | } | ||
| 248 | } else { /* not an option argument */ | ||
| 249 | usageError(); | ||
| 250 | } | ||
| 251 | ++ i; | ||
| 252 | } | ||
| 253 | if (verbosity > LOG_ALWAYS) | ||
| 254 | progress = TRUE; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* openDatabase(p) opens the database file and returns a SQLite 3 | ||
| 258 | * database connection object. */ | ||
| 259 | |||
| 260 | static sqlite3 *openDatabase(void) | ||
| 261 | { | ||
| 262 | sqlite3 *db; | ||
| 263 | int res; | ||
| 264 | |||
| 265 | if (!databaseName) { | ||
| 266 | databaseName = getenv(DATABASE_NAME_ENVAR); | ||
| 267 | if(!databaseName) | ||
| 268 | databaseName = DEFAULT_DATABASE_NAME; | ||
| 269 | } | ||
| 270 | |||
| 271 | if (deleteDatabase) { | ||
| 272 | res = remove(databaseName); | ||
| 273 | if (res) | ||
| 274 | evlog(LOG_ALWAYS, "Could not remove database file %s", databaseName); | ||
| 275 | else | ||
| 276 | evlog(LOG_OFTEN, "Removed database file %s", databaseName); | ||
| 277 | } | ||
| 278 | |||
| 279 | res = sqlite3_open_v2(databaseName, | ||
| 280 | &db, | ||
| 281 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, | ||
| 282 | NULL); /* use default sqlite_vfs object */ | ||
| 283 | |||
| 284 | if (res != SQLITE_OK) | ||
| 285 | sqlite_error(res, db, "Opening %s failed", databaseName); | ||
| 286 | |||
| 287 | evlog(LOG_OFTEN, "Writing to %s.",databaseName); | ||
| 288 | |||
| 289 | return db; | ||
| 290 | } | ||
| 291 | |||
| 292 | /* closeDatabase(db) closes the database opened by openDatabase(). */ | ||
| 293 | |||
| 294 | static void closeDatabase(sqlite3 *db) | ||
| 295 | { | ||
| 296 | int res = sqlite3_close(db); | ||
| 297 | if (res != SQLITE_OK) | ||
| 298 | sqlite_error(res, db, "Closing database failed"); | ||
| 299 | evlog(LOG_SOMETIMES, "Closed %s.", databaseName); | ||
| 300 | } | ||
| 301 | |||
| 302 | /* Utility functions for SQLite statements. */ | ||
| 303 | |||
| 304 | static sqlite3_stmt *prepareStatement(sqlite3 *db, | ||
| 305 | const char *sql) | ||
| 306 | { | ||
| 307 | int res; | ||
| 308 | sqlite3_stmt *statement; | ||
| 309 | evlog(LOG_SELDOM, "Preparing statement %s", sql); | ||
| 310 | res = sqlite3_prepare_v2(db, sql, | ||
| 311 | -1, /* prepare whole string as statement */ | ||
| 312 | &statement, | ||
| 313 | NULL); | ||
| 314 | if (res != SQLITE_OK) | ||
| 315 | sqlite_error(res, db, "statement preparation failed: %s", sql); | ||
| 316 | return statement; | ||
| 317 | } | ||
| 318 | |||
| 319 | static void finalizeStatement(sqlite3 *db, | ||
| 320 | sqlite3_stmt *statement) | ||
| 321 | { | ||
| 322 | int res; | ||
| 323 | res = sqlite3_finalize(statement); | ||
| 324 | if (res != SQLITE_OK) | ||
| 325 | sqlite_error(res, db, "statement finalize failed"); | ||
| 326 | } | ||
| 327 | |||
| 328 | static void runStatement(sqlite3 *db, | ||
| 329 | const char *sql, | ||
| 330 | const char *description) | ||
| 331 | { | ||
| 332 | int res; | ||
| 333 | evlog(LOG_SELDOM, "%s: %s", description, sql); | ||
| 334 | res = sqlite3_exec(db, | ||
| 335 | sql, | ||
| 336 | NULL, /* No callback */ | ||
| 337 | NULL, /* No callback closure */ | ||
| 338 | NULL); /* error messages handled by sqlite_error */ | ||
| 339 | if (res != SQLITE_OK) | ||
| 340 | sqlite_error(res, db, "%s failed - statement %s", description, sql); | ||
| 341 | } | ||
| 342 | |||
| 343 | /* Test for the existence of a table using sqlite_master table. | ||
| 344 | */ | ||
| 345 | |||
| 346 | static int tableExists(sqlite3* db, const char *tableName) | ||
| 347 | { | ||
| 348 | int res; | ||
| 349 | int exists = 0; | ||
| 350 | sqlite3_stmt *statement = NULL; | ||
| 351 | |||
| 352 | statement = prepareStatement(db, | ||
| 353 | "SELECT 1 FROM sqlite_master WHERE type='table' AND name=?"); | ||
| 354 | res = sqlite3_bind_text(statement, 1, tableName, -1, SQLITE_STATIC); | ||
| 355 | if (res != SQLITE_OK) | ||
| 356 | sqlite_error(res, db, "table existence bind of name failed."); | ||
| 357 | res = sqlite3_step(statement); | ||
| 358 | switch(res) { | ||
| 359 | case SQLITE_DONE: | ||
| 360 | exists = 0; | ||
| 361 | break; | ||
| 362 | case SQLITE_ROW: | ||
| 363 | exists = 1; | ||
| 364 | break; | ||
| 365 | default: | ||
| 366 | sqlite_error(res, db, "select from sqlite_master failed."); | ||
| 367 | } | ||
| 368 | finalizeStatement(db, statement); | ||
| 369 | return exists; | ||
| 370 | } | ||
| 371 | |||
| 372 | /* Unit test for tableExists() */ | ||
| 373 | |||
| 374 | static struct { | ||
| 375 | const char* name; | ||
| 376 | int exists; | ||
| 377 | } tableTests[] = { | ||
| 378 | {"event_kind", TRUE}, | ||
| 379 | {"spong", FALSE}, | ||
| 380 | {"EVENT_SegSplit", TRUE} | ||
| 381 | }; | ||
| 382 | |||
| 383 | static void testTableExists(sqlite3 *db) | ||
| 384 | { | ||
| 385 | size_t i; | ||
| 386 | int defects = 0; | ||
| 387 | int tests = 0; | ||
| 388 | for (i=0; i < (sizeof(tableTests)/sizeof(tableTests[0])); ++i) { | ||
| 389 | const char *name = tableTests[i].name; | ||
| 390 | int exists = tableExists(db, name); | ||
| 391 | if (exists) | ||
| 392 | evlog(LOG_OFTEN, "Table exists: %s", name); | ||
| 393 | else | ||
| 394 | evlog(LOG_OFTEN, "Table does not exist: %s", name); | ||
| 395 | if (exists != tableTests[i].exists) { | ||
| 396 | evlog(LOG_ALWAYS, "tableExists test failed on table %s", name); | ||
| 397 | ++ defects; | ||
| 398 | } | ||
| 399 | ++ tests; | ||
| 400 | } | ||
| 401 | evlog(LOG_ALWAYS, "%d tests, %d defects found.", tests, defects); | ||
| 402 | } | ||
| 403 | |||
| 404 | /* Every time we put events from a log file into a database file, we | ||
| 405 | * add the log file to the event_log table, and get a serial number | ||
| 406 | * from SQL which is then attached to all event rows from that log. | ||
| 407 | * We use this to record overall SQL activity, to deter mistaken | ||
| 408 | * attempts to add the same log file twice, and to allow events from | ||
| 409 | * several different log files to share the same SQL file. | ||
| 410 | * | ||
| 411 | * When reading events from stdin, we can't so easily avoid the | ||
| 412 | * duplication (unless we, e.g., take a hash of the event set); we | ||
| 413 | * have to assume that the user is smart enough not to do that. | ||
| 414 | */ | ||
| 415 | |||
| 416 | static int64 logSerial = 0; | ||
| 417 | |||
| 418 | static void registerLogFile(sqlite3 *db, | ||
| 419 | const char *filename) | ||
| 420 | { | ||
| 421 | sqlite3_stmt *statement; | ||
| 422 | int res; | ||
| 423 | const unsigned char *name; | ||
| 424 | int64 completed; | ||
| 425 | int64 file_size; | ||
| 426 | int64 file_modtime; | ||
| 427 | |||
| 428 | if (filename) { | ||
| 429 | struct stat st; | ||
| 430 | res = stat(filename, &st); | ||
| 431 | if (res != 0) | ||
| 432 | error("Couldn't stat() %s", filename); | ||
| 433 | file_size = st.st_size; | ||
| 434 | file_modtime = st.st_mtime; | ||
| 435 | |||
| 436 | statement = prepareStatement(db, | ||
| 437 | "SELECT name, serial, completed FROM event_log" | ||
| 438 | " WHERE size = ? AND modtime = ?"); | ||
| 439 | res = sqlite3_bind_int64(statement, 1, file_size); | ||
| 440 | if (res != SQLITE_OK) | ||
| 441 | sqlite_error(res, db, "event_log bind of size failed."); | ||
| 442 | res = sqlite3_bind_int64(statement, 2, file_modtime); | ||
| 443 | if (res != SQLITE_OK) | ||
| 444 | sqlite_error(res, db, "event_log bind of modtime failed."); | ||
| 445 | res = sqlite3_step(statement); | ||
| 446 | switch(res) { | ||
| 447 | case SQLITE_DONE: | ||
| 448 | evlog(LOG_SOMETIMES, "No log file matching '%s' found in database.", filename); | ||
| 449 | break; | ||
| 450 | case SQLITE_ROW: | ||
| 451 | name = sqlite3_column_text(statement, 0); | ||
| 452 | logSerial = sqlite3_column_int64(statement, 1); | ||
| 453 | completed = sqlite3_column_int64(statement, 2); | ||
| 454 | evlog(force ? LOG_OFTEN : LOG_ALWAYS, "Log file matching '%s' already in event_log, named \"%s\" (serial %lu, completed %lu).", | ||
| 455 | filename, name, logSerial, completed); | ||
| 456 | if (force) { | ||
| 457 | evlog(LOG_OFTEN, "Continuing anyway because -f specified."); | ||
| 458 | } else { | ||
| 459 | evlog(LOG_ALWAYS, "Exiting. Specify -f to force events into SQL anyway."); | ||
| 460 | exit(0); | ||
| 461 | } | ||
| 462 | break; | ||
| 463 | default: | ||
| 464 | sqlite_error(res, db, "select from event_log failed."); | ||
| 465 | } | ||
| 466 | finalizeStatement(db, statement); | ||
| 467 | } else { /* stdin */ | ||
| 468 | filename = "<stdin>"; | ||
| 469 | file_size = 0; | ||
| 470 | file_modtime = 0; | ||
| 471 | } | ||
| 472 | statement = prepareStatement(db, | ||
| 473 | "INSERT into event_log (name, size, modtime, completed)" | ||
| 474 | " VALUES (?, ?, ?, 0)"); | ||
| 475 | res = sqlite3_bind_text(statement, 1, filename, -1, SQLITE_STATIC); | ||
| 476 | if (res != SQLITE_OK) | ||
| 477 | sqlite_error(res, db, "event_log insert bind of name failed."); | ||
| 478 | res = sqlite3_bind_int64(statement, 2, file_size); | ||
| 479 | if (res != SQLITE_OK) | ||
| 480 | sqlite_error(res, db, "event_log insert bind of size failed."); | ||
| 481 | res = sqlite3_bind_int64(statement, 3, file_modtime); | ||
| 482 | if (res != SQLITE_OK) | ||
| 483 | sqlite_error(res, db, "event_log insert bind of modtime failed."); | ||
| 484 | res = sqlite3_step(statement); | ||
| 485 | if (res != SQLITE_DONE) | ||
| 486 | sqlite_error(res, db, "insert into event_log failed."); | ||
| 487 | logSerial = sqlite3_last_insert_rowid(db); | ||
| 488 | evlog(LOG_SOMETIMES, "Log file %s added to event_log with serial %lu", | ||
| 489 | filename, logSerial); | ||
| 490 | finalizeStatement(db, statement); | ||
| 491 | } | ||
| 492 | |||
| 493 | static void logFileCompleted(sqlite3 *db, | ||
| 494 | int64 completed) | ||
| 495 | { | ||
| 496 | sqlite3_stmt *statement; | ||
| 497 | int res; | ||
| 498 | |||
| 499 | statement = prepareStatement(db, | ||
| 500 | "UPDATE event_log SET completed=? WHERE serial=?"); | ||
| 501 | res = sqlite3_bind_int64(statement, 2, logSerial); | ||
| 502 | if (res != SQLITE_OK) | ||
| 503 | sqlite_error(res, db, "event_log update bind of serial failed."); | ||
| 504 | res = sqlite3_bind_int64(statement, 1, completed); | ||
| 505 | if (res != SQLITE_OK) | ||
| 506 | sqlite_error(res, db, "event_log update bind of completed failed."); | ||
| 507 | res = sqlite3_step(statement); | ||
| 508 | if (res != SQLITE_DONE) | ||
| 509 | sqlite_error(res, db, "insert into event_log failed."); | ||
| 510 | evlog(LOG_SOMETIMES, "Marked in event_log: %lu events", completed); | ||
| 511 | finalizeStatement(db, statement); | ||
| 512 | } | ||
| 513 | |||
| 514 | /* Macro magic to make a CREATE TABLE statement for each event type. */ | ||
| 515 | |||
| 516 | #define EVENT_PARAM_SQL_TYPE_A "INTEGER" | ||
| 517 | #define EVENT_PARAM_SQL_TYPE_P "INTEGER" | ||
| 518 | #define EVENT_PARAM_SQL_TYPE_U "INTEGER" | ||
| 519 | #define EVENT_PARAM_SQL_TYPE_W "INTEGER" | ||
| 520 | #define EVENT_PARAM_SQL_TYPE_D "REAL " | ||
| 521 | #define EVENT_PARAM_SQL_TYPE_S "TEXT " | ||
| 522 | #define EVENT_PARAM_SQL_TYPE_B "INTEGER" | ||
| 523 | |||
| 524 | #define EVENT_PARAM_SQL_COLUMN(X, index, sort, ident) \ | ||
| 525 | "\"" #ident "\" " EVENT_PARAM_SQL_TYPE_##sort ", " | ||
| 526 | |||
| 527 | #define EVENT_TABLE_CREATE(X, name, code, always, kind) \ | ||
| 528 | "CREATE TABLE IF NOT EXISTS EVENT_" #name " ( " \ | ||
| 529 | EVENT_##name##_PARAMS(EVENT_PARAM_SQL_COLUMN, X) \ | ||
| 530 | "time INTEGER, " \ | ||
| 531 | "log_serial INTEGER)", | ||
| 532 | |||
| 533 | /* An array of table-creation statement strings. */ | ||
| 534 | |||
| 535 | const char *createStatements[] = { | ||
| 536 | "CREATE TABLE IF NOT EXISTS event_kind (name TEXT," | ||
| 537 | " description TEXT," | ||
| 538 | " enum INTEGER PRIMARY KEY)", | ||
| 539 | |||
| 540 | "CREATE TABLE IF NOT EXISTS event_type (name TEXT," | ||
| 541 | " code INTEGER PRIMARY KEY," | ||
| 542 | " always INTEGER," | ||
| 543 | " kind INTEGER," | ||
| 544 | " FOREIGN KEY (kind) REFERENCES event_kind(enum));", | ||
| 545 | |||
| 546 | "CREATE TABLE IF NOT EXISTS event_param (type INTEGER," | ||
| 547 | " param_index INTEGER," | ||
| 548 | " sort TEXT," | ||
| 549 | " ident TEXT," | ||
| 550 | " FOREIGN KEY (type) REFERENCES event_type(code));", | ||
| 551 | |||
| 552 | "CREATE TABLE IF NOT EXISTS event_log (name TEXT," | ||
| 553 | " size INTEGER," | ||
| 554 | " modtime INTEGER," | ||
| 555 | " completed INTEGER," | ||
| 556 | " serial INTEGER PRIMARY KEY AUTOINCREMENT)", | ||
| 557 | |||
| 558 | EVENT_LIST(EVENT_TABLE_CREATE, X) | ||
| 559 | }; | ||
| 560 | |||
| 561 | /* makeTables makes all the tables. */ | ||
| 562 | |||
| 563 | static void makeTables(sqlite3 *db) | ||
| 564 | { | ||
| 565 | size_t i; | ||
| 566 | evlog(LOG_SOMETIMES, "Creating tables."); | ||
| 567 | |||
| 568 | for (i=0; i < (sizeof(createStatements)/sizeof(createStatements[0])); ++i) { | ||
| 569 | runStatement(db, createStatements[i], "Table creation"); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | const char *glueTables[] = { | ||
| 574 | "event_kind", | ||
| 575 | "event_type", | ||
| 576 | "event_param", | ||
| 577 | }; | ||
| 578 | |||
| 579 | static void dropGlueTables(sqlite3 *db) | ||
| 580 | { | ||
| 581 | size_t i; | ||
| 582 | int res; | ||
| 583 | char sql[1024]; | ||
| 584 | |||
| 585 | evlog(LOG_ALWAYS, "Dropping glue tables so they are rebuilt."); | ||
| 586 | |||
| 587 | for (i=0; i < (sizeof(glueTables)/sizeof(glueTables[0])); ++i) { | ||
| 588 | evlog(LOG_SOMETIMES, "Dropping table %s", glueTables[i]); | ||
| 589 | sprintf(sql, "DROP TABLE %s", glueTables[i]); | ||
| 590 | res = sqlite3_exec(db, | ||
| 591 | sql, | ||
| 592 | NULL, /* No callback */ | ||
| 593 | NULL, /* No callback closure */ | ||
| 594 | NULL); /* error messages handled by sqlite_error */ | ||
| 595 | /* Don't check for errors. */ | ||
| 596 | (void)res; | ||
| 597 | } | ||
| 598 | } | ||
| 599 | |||
| 600 | /* Populate the metadata "glue" tables event_kind, event_type, and | ||
| 601 | * event_param. */ | ||
| 602 | |||
| 603 | #define EVENT_KIND_DO_INSERT(X, name, description) \ | ||
| 604 | res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ | ||
| 605 | if (res != SQLITE_OK) \ | ||
| 606 | sqlite_error(res, db, "event_kind bind of name \"" #name "\" failed."); \ | ||
| 607 | res = sqlite3_bind_text(statement, 2, description, -1, SQLITE_STATIC); \ | ||
| 608 | if (res != SQLITE_OK) \ | ||
| 609 | sqlite_error(res, db, "event_kind bind of description \"" description "\" failed."); \ | ||
| 610 | res = sqlite3_bind_int(statement, 3, i); \ | ||
| 611 | if (res != SQLITE_OK) \ | ||
| 612 | sqlite_error(res, db, "event_kind bind of enum %d failed.", i); \ | ||
| 613 | ++i; \ | ||
| 614 | res = sqlite3_step(statement); \ | ||
| 615 | if (res != SQLITE_DONE) \ | ||
| 616 | sqlite_error(res, db, "event_kind insert of name \"" #name "\" failed."); \ | ||
| 617 | if (sqlite3_changes(db) != 0) \ | ||
| 618 | evlog(LOG_SOMETIMES, "Insert of event_kind row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ | ||
| 619 | res = sqlite3_reset(statement); \ | ||
| 620 | if (res != SQLITE_OK) \ | ||
| 621 | sqlite_error(res, db, "Couldn't reset event_kind insert statement."); | ||
| 622 | |||
| 623 | #define EVENT_TYPE_DO_INSERT(X, name, code, always, kind) \ | ||
| 624 | res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ | ||
| 625 | if (res != SQLITE_OK) \ | ||
| 626 | sqlite_error(res, db, "event_type bind of name \"" #name "\" failed."); \ | ||
| 627 | res = sqlite3_bind_int(statement, 2, code); \ | ||
| 628 | if (res != SQLITE_OK) \ | ||
| 629 | sqlite_error(res, db, "event_type bind of code %d failed.", code); \ | ||
| 630 | res = sqlite3_bind_int(statement, 3, always); \ | ||
| 631 | if (res != SQLITE_OK) \ | ||
| 632 | sqlite_error(res, db, "event_type bind of always for name \"" #name "\" failed."); \ | ||
| 633 | res = sqlite3_bind_int(statement, 4, EventKind##kind); \ | ||
| 634 | if (res != SQLITE_OK) \ | ||
| 635 | sqlite_error(res, db, "event_type bind of kind for name \"" #name "\" failed."); \ | ||
| 636 | res = sqlite3_step(statement); \ | ||
| 637 | if (res != SQLITE_DONE) \ | ||
| 638 | sqlite_error(res, db, "event_type insert of name \"" #name "\" failed."); \ | ||
| 639 | if (sqlite3_changes(db) != 0) \ | ||
| 640 | evlog(LOG_SOMETIMES, "Insert of event_type row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ | ||
| 641 | res = sqlite3_reset(statement); \ | ||
| 642 | if (res != SQLITE_OK) \ | ||
| 643 | sqlite_error(res, db, "Couldn't reset event_type insert statement."); | ||
| 644 | |||
| 645 | #define EVENT_PARAM_DO_INSERT(code, index, sort, ident) \ | ||
| 646 | res = sqlite3_bind_int(statement, 1, code); \ | ||
| 647 | if (res != SQLITE_OK) \ | ||
| 648 | sqlite_error(res, db, "event_param bind of code %d failed.", code); \ | ||
| 649 | res = sqlite3_bind_int(statement, 2, index); \ | ||
| 650 | if (res != SQLITE_OK) \ | ||
| 651 | sqlite_error(res, db, "event_param bind of index %d failed.", index); \ | ||
| 652 | res = sqlite3_bind_text(statement, 3, #sort, -1, SQLITE_STATIC); \ | ||
| 653 | if (res != SQLITE_OK) \ | ||
| 654 | sqlite_error(res, db, "event_type bind of sort \"" #sort "\" failed."); \ | ||
| 655 | res = sqlite3_bind_text(statement, 4, #ident, -1, SQLITE_STATIC); \ | ||
| 656 | if (res != SQLITE_OK) \ | ||
| 657 | sqlite_error(res, db, "event_type bind of ident \"" #ident "\" failed."); \ | ||
| 658 | res = sqlite3_step(statement); \ | ||
| 659 | if (res != SQLITE_DONE) \ | ||
| 660 | sqlite_error(res, db, "event_param insert of ident \"" #ident "\" for code %d failed.", code); \ | ||
| 661 | if (sqlite3_changes(db) != 0) \ | ||
| 662 | evlog(LOG_SOMETIMES, "Insert of event_param row for code %d, ident \"" #ident "\" affected %d rows.", code, sqlite3_changes(db)); \ | ||
| 663 | res = sqlite3_reset(statement); \ | ||
| 664 | if (res != SQLITE_OK) \ | ||
| 665 | sqlite_error(res, db, "Couldn't reset event_param insert statement."); | ||
| 666 | |||
| 667 | #define EVENT_TYPE_INSERT_PARAMS(X, name, code, always, kind) \ | ||
| 668 | EVENT_##name##_PARAMS(EVENT_PARAM_DO_INSERT, code) | ||
| 669 | |||
| 670 | static void fillGlueTables(sqlite3 *db) | ||
| 671 | { | ||
| 672 | int i; | ||
| 673 | sqlite3_stmt *statement; | ||
| 674 | int res; | ||
| 675 | |||
| 676 | statement = prepareStatement(db, | ||
| 677 | "INSERT OR IGNORE INTO event_kind (name, description, enum)" | ||
| 678 | "VALUES (?, ?, ?)"); | ||
| 679 | |||
| 680 | i = 0; | ||
| 681 | EventKindENUM(EVENT_KIND_DO_INSERT, X); | ||
| 682 | |||
| 683 | finalizeStatement(db, statement); | ||
| 684 | |||
| 685 | statement = prepareStatement(db, | ||
| 686 | "INSERT OR IGNORE INTO event_type (name, code, always, kind)" | ||
| 687 | "VALUES (?, ?, ?, ?)"); | ||
| 688 | EVENT_LIST(EVENT_TYPE_DO_INSERT, X); | ||
| 689 | |||
| 690 | finalizeStatement(db, statement); | ||
| 691 | |||
| 692 | statement = prepareStatement(db, | ||
| 693 | "INSERT OR IGNORE INTO event_param (type, param_index, sort, ident)" | ||
| 694 | "VALUES (?, ?, ?, ?)"); | ||
| 695 | EVENT_LIST(EVENT_TYPE_INSERT_PARAMS, X); | ||
| 696 | |||
| 697 | finalizeStatement(db, statement); | ||
| 698 | } | ||
| 699 | |||
| 700 | /* Populate the actual event tables. */ | ||
| 701 | |||
| 702 | #define EVENT_TYPE_DECLARE_STATEMENT(X, name, code, always, kind) \ | ||
| 703 | sqlite3_stmt *stmt_##name; | ||
| 704 | |||
| 705 | #define EVENT_PARAM_PREPARE_IDENT(X, index, sort, ident) "\"" #ident "\", " | ||
| 706 | |||
| 707 | #define EVENT_PARAM_PREPARE_PLACE(X, index, sort, ident) "?, " | ||
| 708 | |||
| 709 | #define EVENT_TYPE_PREPARE_STATEMENT(X, name, code, always, kind) \ | ||
| 710 | stmt_##name = \ | ||
| 711 | prepareStatement(db, \ | ||
| 712 | "INSERT INTO EVENT_" #name " (" \ | ||
| 713 | EVENT_##name##_PARAMS(EVENT_PARAM_PREPARE_IDENT, X) \ | ||
| 714 | "log_serial, time) VALUES (" \ | ||
| 715 | EVENT_##name##_PARAMS(EVENT_PARAM_PREPARE_PLACE,X) \ | ||
| 716 | "?, ?)"); | ||
| 717 | |||
| 718 | #define EVENT_TYPE_FINALIZE_STATEMENT(X, name, code, always, kind) \ | ||
| 719 | finalizeStatement(db, stmt_##name); | ||
| 720 | |||
| 721 | #define EVENT_PARAM_BIND_A bind_int | ||
| 722 | #define EVENT_PARAM_BIND_P bind_int | ||
| 723 | #define EVENT_PARAM_BIND_U bind_int | ||
| 724 | #define EVENT_PARAM_BIND_W bind_int | ||
| 725 | #define EVENT_PARAM_BIND_D bind_real | ||
| 726 | #define EVENT_PARAM_BIND_S bind_text | ||
| 727 | #define EVENT_PARAM_BIND_B bind_int | ||
| 728 | |||
| 729 | #define EVENT_PARAM_BIND(X, index, sort, ident) \ | ||
| 730 | p = EVENT_PARAM_BIND_##sort (db, statement, eventCount, index+1, p); \ | ||
| 731 | last_index = index+1; | ||
| 732 | |||
| 733 | #define EVENT_TYPE_WRITE_SQL(X, name, code, always, kind) \ | ||
| 734 | case code: \ | ||
| 735 | statement = stmt_##name; \ | ||
| 736 | /* bind all the parameters of this particular event with macro magic. */ \ | ||
| 737 | EVENT_##name##_PARAMS(EVENT_PARAM_BIND, X) \ | ||
| 738 | break; | ||
| 739 | |||
| 740 | static char *bind_int(sqlite3 *db, sqlite3_stmt *stmt, int64 count, int field, char *p) | ||
| 741 | { | ||
| 742 | char *q; | ||
| 743 | long long val; | ||
| 744 | int res; | ||
| 745 | |||
| 746 | while(*p == ' ') | ||
| 747 | ++p; | ||
| 748 | |||
| 749 | val = strtoll(p, &q, 16); | ||
| 750 | if (q == p) | ||
| 751 | error("event %llu field %d not an integer: %s", | ||
| 752 | count, field, p); | ||
| 753 | |||
| 754 | res = sqlite3_bind_int64(stmt, field, val); | ||
| 755 | if (res != SQLITE_OK) | ||
| 756 | sqlite_error(res, db, "event %llu field %d bind failed", count, field); | ||
| 757 | return q; | ||
| 758 | } | ||
| 759 | |||
| 760 | static char *bind_real(sqlite3 *db, sqlite3_stmt *stmt, int64 count, int field, char *p) | ||
| 761 | { | ||
| 762 | char *q; | ||
| 763 | double val; | ||
| 764 | int res; | ||
| 765 | |||
| 766 | while(*p == ' ') | ||
| 767 | ++p; | ||
| 768 | |||
| 769 | val = strtod(p, &q); | ||
| 770 | if (q == p) | ||
| 771 | error("event %llu field %d not a floating-point value: %s", | ||
| 772 | count, field, p); | ||
| 773 | |||
| 774 | res = sqlite3_bind_double(stmt, field, val); | ||
| 775 | if (res != SQLITE_OK) | ||
| 776 | sqlite_error(res, db, "event %llu field %d bind failed", count, field); | ||
| 777 | return q; | ||
| 778 | } | ||
| 779 | |||
| 780 | static char *bind_text(sqlite3 *db, sqlite3_stmt *stmt, int64 count, int field, char *p) | ||
| 781 | { | ||
| 782 | char *q; | ||
| 783 | int res; | ||
| 784 | |||
| 785 | while(*p == ' ') | ||
| 786 | ++p; | ||
| 787 | |||
| 788 | q = p; | ||
| 789 | while((*q != '\n') && (*q != '\0')) { | ||
| 790 | ++ q; | ||
| 791 | } | ||
| 792 | if ((q == p) || (q[-1] != '"')) | ||
| 793 | error("event %llu string field %d has no closing quote mark.", | ||
| 794 | count, field); | ||
| 795 | |||
| 796 | res = sqlite3_bind_text(stmt, field, p, (int)(q-p-1), SQLITE_STATIC); | ||
| 797 | if (res != SQLITE_OK) | ||
| 798 | sqlite_error(res, db, "event %llu field %d bind failed", count, field); | ||
| 799 | return q; | ||
| 800 | } | ||
| 801 | |||
| 802 | /* this is overkill, at present. */ | ||
| 803 | |||
| 804 | #define MAX_LOG_LINE_LENGTH 1024 | ||
| 805 | |||
| 806 | /* readLog -- read and parse log. Returns the number of events written. | ||
| 807 | */ | ||
| 808 | |||
| 809 | static int64 readLog(FILE *input, | ||
| 810 | sqlite3 *db) | ||
| 811 | { | ||
| 812 | int64 eventCount = 0; | ||
| 813 | |||
| 814 | /* declare statements for every event type */ | ||
| 815 | EVENT_LIST(EVENT_TYPE_DECLARE_STATEMENT, X); | ||
| 816 | |||
| 817 | /* prepare statements for every event type */ | ||
| 818 | EVENT_LIST(EVENT_TYPE_PREPARE_STATEMENT, X); | ||
| 819 | |||
| 820 | runStatement(db, "BEGIN", "Transaction start"); | ||
| 821 | |||
| 822 | while (TRUE) { /* loop for each event */ | ||
| 823 | char line[MAX_LOG_LINE_LENGTH]; | ||
| 824 | char *p; | ||
| 825 | char *q; | ||
| 826 | int last_index=0; | ||
| 827 | sqlite3_stmt *statement = NULL; | ||
| 828 | int res; | ||
| 829 | int64 clock_field; | ||
| 830 | long code; | ||
| 831 | |||
| 832 | p = fgets(line, MAX_LOG_LINE_LENGTH, input); | ||
| 833 | if (!p) { | ||
| 834 | if (feof(input)) | ||
| 835 | break; | ||
| 836 | else | ||
| 837 | error("Couldn't read line after event %llu", eventCount); | ||
| 838 | } | ||
| 839 | |||
| 840 | eventCount++; | ||
| 841 | |||
| 842 | clock_field = strtoll(p, &q, 16); | ||
| 843 | |||
| 844 | if (q == p) | ||
| 845 | error("event %llu clock field not a hex integer: %s", | ||
| 846 | eventCount, p); | ||
| 847 | |||
| 848 | if (*q != ' ') | ||
| 849 | error("event %llu code field not preceded by ' ': %s", | ||
| 850 | eventCount, q); | ||
| 851 | while(*q == ' ') | ||
| 852 | ++q; | ||
| 853 | |||
| 854 | p = q; | ||
| 855 | code = strtol(p, &q, 16); | ||
| 856 | if (q == p) | ||
| 857 | error("event %llu code field not an integer: %s", | ||
| 858 | eventCount, p); | ||
| 859 | p = q; | ||
| 860 | |||
| 861 | /* Write event to SQLite. */ | ||
| 862 | switch (code) { | ||
| 863 | /* this macro sets statement and last_index */ | ||
| 864 | EVENT_LIST(EVENT_TYPE_WRITE_SQL, X); | ||
| 865 | default: | ||
| 866 | error("Event %llu has Unknown event code %d", eventCount, code); | ||
| 867 | } | ||
| 868 | /* bind the fields we store for every event */ \ | ||
| 869 | res = sqlite3_bind_int64(statement, last_index+1, logSerial); | ||
| 870 | if (res != SQLITE_OK) | ||
| 871 | sqlite_error(res, db, "Event %llu bind of log_serial failed.", eventCount); | ||
| 872 | res = sqlite3_bind_int64(statement, last_index+2, clock_field); | ||
| 873 | if (res != SQLITE_OK) | ||
| 874 | sqlite_error(res, db, "Event %llu bind of clock failed.", eventCount); | ||
| 875 | res = sqlite3_step(statement); | ||
| 876 | if (res != SQLITE_DONE) | ||
| 877 | sqlite_error(res, db, "insert of event %llu failed.", eventCount); | ||
| 878 | res = sqlite3_reset(statement); | ||
| 879 | if (res != SQLITE_OK) | ||
| 880 | sqlite_error(res, db, "Couldn't reset insert statement of event %llu", eventCount); | ||
| 881 | |||
| 882 | if (progress) { | ||
| 883 | if ((eventCount % SMALL_TICK) == 0) { | ||
| 884 | printf("."); | ||
| 885 | fflush(stdout); | ||
| 886 | if (((eventCount / SMALL_TICK) % BIG_TICK) == 0) { | ||
| 887 | printf("\n"); | ||
| 888 | fflush(stdout); | ||
| 889 | evlog(LOG_SOMETIMES, "%lu events.", (unsigned long)eventCount); | ||
| 890 | } | ||
| 891 | } | ||
| 892 | } | ||
| 893 | } | ||
| 894 | if (progress) { | ||
| 895 | printf("\n"); | ||
| 896 | fflush(stdout); | ||
| 897 | } | ||
| 898 | runStatement(db, "COMMIT", "Transaction finish"); | ||
| 899 | logFileCompleted(db, eventCount); | ||
| 900 | |||
| 901 | /* finalize all the statements */ | ||
| 902 | EVENT_LIST(EVENT_TYPE_FINALIZE_STATEMENT, X); | ||
| 903 | |||
| 904 | return eventCount; | ||
| 905 | } | ||
| 906 | |||
| 907 | /* openLog -- open the log file doors, HAL */ | ||
| 908 | |||
| 909 | static FILE *openLog(sqlite3 *db) | ||
| 910 | { | ||
| 911 | FILE *input; | ||
| 912 | |||
| 913 | registerLogFile(db, logFileName); | ||
| 914 | if (!logFileName) { | ||
| 915 | input = stdin; | ||
| 916 | logFileName = "<stdin>"; | ||
| 917 | } else { | ||
| 918 | input = fopen(logFileName, "r"); | ||
| 919 | if (input == NULL) | ||
| 920 | error("unable to open %s", logFileName); | ||
| 921 | } | ||
| 922 | |||
| 923 | evlog(LOG_OFTEN, "Reading %s.", logFileName ? logFileName : "standard input"); | ||
| 924 | |||
| 925 | return input; | ||
| 926 | } | ||
| 927 | |||
| 928 | static int64 writeEventsToSQL(sqlite3 *db) | ||
| 929 | { | ||
| 930 | FILE *input; | ||
| 931 | int64 count; | ||
| 932 | input = openLog(db); | ||
| 933 | count = readLog(input, db); | ||
| 934 | (void)fclose(input); | ||
| 935 | return count; | ||
| 936 | } | ||
| 937 | |||
| 938 | |||
| 939 | int main(int argc, char *argv[]) | ||
| 940 | { | ||
| 941 | sqlite3 *db; | ||
| 942 | int64 count; | ||
| 943 | |||
| 944 | parseArgs(argc, argv); | ||
| 945 | |||
| 946 | db = openDatabase(); | ||
| 947 | if (rebuild) { | ||
| 948 | dropGlueTables(db); | ||
| 949 | } | ||
| 950 | makeTables(db); | ||
| 951 | fillGlueTables(db); | ||
| 952 | count = writeEventsToSQL(db); | ||
| 953 | evlog(LOG_ALWAYS, "Imported %llu events from %s to %s, serial %lu.", | ||
| 954 | count, logFileName, databaseName, logSerial); | ||
| 955 | |||
| 956 | if (runTests) { | ||
| 957 | /* TODO: more unit tests in here */ | ||
| 958 | testTableExists(db); | ||
| 959 | } | ||
| 960 | |||
| 961 | closeDatabase(db); | ||
| 962 | return 0; | ||
| 963 | } | ||
| 964 | |||
| 965 | /* COPYRIGHT AND LICENSE | ||
| 966 | * | ||
| 967 | * Copyright (C) 2012 Ravenbrook Limited <http://www.ravenbrook.com/>. | ||
| 968 | * All rights reserved. This is an open source license. Contact | ||
| 969 | * Ravenbrook for commercial licensing options. | ||
| 970 | * | ||
| 971 | * Redistribution and use in source and binary forms, with or without | ||
| 972 | * modification, are permitted provided that the following conditions are | ||
| 973 | * met: | ||
| 974 | * | ||
| 975 | * 1. Redistributions of source code must retain the above copyright | ||
| 976 | * notice, this list of conditions and the following disclaimer. | ||
| 977 | * | ||
| 978 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 979 | * notice, this list of conditions and the following disclaimer in the | ||
| 980 | * documentation and/or other materials provided with the distribution. | ||
| 981 | * | ||
| 982 | * 3. Redistributions in any form must be accompanied by information on how | ||
| 983 | * to obtain complete source code for this software and any accompanying | ||
| 984 | * software that uses this software. The source code must either be | ||
| 985 | * included in the distribution or be available for no more than the cost | ||
| 986 | * of distribution plus a nominal fee, and must be freely redistributable | ||
| 987 | * under reasonable conditions. For an executable file, complete source | ||
| 988 | * code means the source code for all modules it contains. It does not | ||
| 989 | * include source code for modules or files that typically accompany the | ||
| 990 | * major components of the operating system on which the executable file | ||
| 991 | * runs. | ||
| 992 | * | ||
| 993 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 994 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
| 995 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
| 996 | * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 997 | * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 998 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 999 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 1000 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 1001 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 1002 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 1003 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 1004 | */ | ||
diff --git a/mps/code/eventtxt.c b/mps/code/eventtxt.c new file mode 100644 index 00000000000..77c3100131a --- /dev/null +++ b/mps/code/eventtxt.c | |||
| @@ -0,0 +1,540 @@ | |||
| 1 | /* eventtxt.c: event text log to human-friendly format. | ||
| 2 | * | ||
| 3 | * $Id$ | ||
| 4 | * | ||
| 5 | * Copyright (c) 2012 Ravenbrook Limited. See end of file for license. | ||
| 6 | * | ||
| 7 | * This is a command-line tool that converts events from a text-format | ||
| 8 | * MPS telemetry file into a more human-readable format. | ||
| 9 | * | ||
| 10 | * The default MPS library will write a binary-format telemetry file | ||
| 11 | * which can be converted into a text-format file using the eventcnv | ||
| 12 | * program (q.v.). | ||
| 13 | * | ||
| 14 | * For efficiency, eventcnv writes all event times, codes, and | ||
| 15 | * parameters (apart from EventFS - strings - and EventFD - | ||
| 16 | * floating-point) as hexadecimal strings, separated by single spaces. | ||
| 17 | * For human-readable purposes, we'd prefer a format in which | ||
| 18 | * parameters are named; event codes are converted to event type | ||
| 19 | * names; integers are in decimal; booleans are 'True ' or 'False'; | ||
| 20 | * pointers, addresses, and words are in hex; and labelled addresses | ||
| 21 | * are shown with their label strings. This program performs that | ||
| 22 | * conversion. | ||
| 23 | * | ||
| 24 | * Options: | ||
| 25 | * | ||
| 26 | * -l <logfile>: Import events from the named logfile. Defaults to | ||
| 27 | * stdin. | ||
| 28 | * | ||
| 29 | * $Id$ | ||
| 30 | */ | ||
| 31 | |||
| 32 | #include "config.h" | ||
| 33 | #include "eventdef.h" | ||
| 34 | #include "eventcom.h" | ||
| 35 | #include "table.h" | ||
| 36 | #include "testlib.h" /* for ulongest_t and associated print formats */ | ||
| 37 | |||
| 38 | #include <stdio.h> | ||
| 39 | #include <stdlib.h> | ||
| 40 | #include <string.h> | ||
| 41 | |||
| 42 | #ifdef MPS_BUILD_MV | ||
| 43 | /* MSVC warning 4996 = stdio / C runtime 'unsafe' */ | ||
| 44 | /* Objects to: strncpy, sscanf, fopen. See job001934. */ | ||
| 45 | #pragma warning( disable : 4996 ) | ||
| 46 | #endif | ||
| 47 | |||
| 48 | static char *prog; /* program name */ | ||
| 49 | static char *logFileName = NULL; | ||
| 50 | |||
| 51 | /* everror -- error signalling */ | ||
| 52 | |||
| 53 | static void everror(const char *format, ...) | ||
| 54 | { | ||
| 55 | va_list args; | ||
| 56 | |||
| 57 | fflush(stdout); /* sync */ | ||
| 58 | fprintf(stderr, "%s: ", prog); | ||
| 59 | va_start(args, format); | ||
| 60 | vfprintf(stderr, format, args); | ||
| 61 | fprintf(stderr, "\n"); | ||
| 62 | va_end(args); | ||
| 63 | exit(EXIT_FAILURE); | ||
| 64 | } | ||
| 65 | |||
| 66 | static void usage(void) | ||
| 67 | { | ||
| 68 | fprintf(stderr, | ||
| 69 | "Usage: %s [-l <logfile>]\n", | ||
| 70 | prog); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void usageError(void) | ||
| 74 | { | ||
| 75 | usage(); | ||
| 76 | everror("Bad usage"); | ||
| 77 | } | ||
| 78 | |||
| 79 | /* parseArgs -- parse command line arguments */ | ||
| 80 | |||
| 81 | static void parseArgs(int argc, char *argv[]) | ||
| 82 | { | ||
| 83 | int i = 1; | ||
| 84 | |||
| 85 | if (argc >= 1) | ||
| 86 | prog = argv[0]; | ||
| 87 | else | ||
| 88 | prog = "unknown"; | ||
| 89 | |||
| 90 | while (i < argc) { /* consider argument i */ | ||
| 91 | if (argv[i][0] == '-') { /* it's an option argument */ | ||
| 92 | switch (argv[i][1]) { | ||
| 93 | case 'l': /* log file name */ | ||
| 94 | ++ i; | ||
| 95 | if (i == argc) | ||
| 96 | usageError(); | ||
| 97 | else | ||
| 98 | logFileName = argv[i]; | ||
| 99 | break; | ||
| 100 | case '?': case 'h': /* help */ | ||
| 101 | usage(); | ||
| 102 | exit(EXIT_SUCCESS); | ||
| 103 | default: | ||
| 104 | usageError(); | ||
| 105 | } | ||
| 106 | } /* if option */ | ||
| 107 | ++ i; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | /* table methods for a table of interned strings, and another of | ||
| 112 | * labelled addresses. */ | ||
| 113 | |||
| 114 | static void *tableAlloc(void *closure, size_t size) | ||
| 115 | { | ||
| 116 | UNUSED(closure); | ||
| 117 | return malloc(size); | ||
| 118 | } | ||
| 119 | |||
| 120 | static void tableFree(void *closure, void *p, size_t size) | ||
| 121 | { | ||
| 122 | UNUSED(closure); | ||
| 123 | UNUSED(size); | ||
| 124 | free(p); | ||
| 125 | } | ||
| 126 | |||
| 127 | /* Printing routines */ | ||
| 128 | |||
| 129 | /* printStr -- print an EventString */ | ||
| 130 | |||
| 131 | static void printStr(const char *str) | ||
| 132 | { | ||
| 133 | size_t i; | ||
| 134 | |||
| 135 | putchar('"'); | ||
| 136 | for (i = 0; str[i] != '\0'; ++i) { | ||
| 137 | char c = str[i]; | ||
| 138 | if (c == '"' || c == '\\') putchar('\\'); | ||
| 139 | putchar(c); | ||
| 140 | } | ||
| 141 | putchar('"'); | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | /* Reading hex numbers, and doubles, and quoted-and-escaped | ||
| 146 | * strings. */ | ||
| 147 | |||
| 148 | static ulongest_t parseHex(char **pInOut) | ||
| 149 | { | ||
| 150 | ulongest_t val; | ||
| 151 | int i, l; | ||
| 152 | char *p = *pInOut; | ||
| 153 | |||
| 154 | i = sscanf(p, "%" SCNXLONGEST "%n", &val, &l); | ||
| 155 | if (i != 1) | ||
| 156 | everror("Couldn't read a hex number from '%s'", p); | ||
| 157 | *pInOut = p + l; | ||
| 158 | return val; | ||
| 159 | } | ||
| 160 | |||
| 161 | static double parseDouble(char **pInOut) | ||
| 162 | { | ||
| 163 | double val; | ||
| 164 | int i, l; | ||
| 165 | char *p = *pInOut; | ||
| 166 | |||
| 167 | i = sscanf(p, "%lg%n", &val, &l); | ||
| 168 | if (i != 1) | ||
| 169 | everror("Couldn't read a float from '%s'", p); | ||
| 170 | *pInOut = p + l; | ||
| 171 | return val; | ||
| 172 | } | ||
| 173 | |||
| 174 | /* parseString checks string syntax (opening and closing quotation | ||
| 175 | * marks) and takes a copy (stripping escaping backslashes) into a | ||
| 176 | * static buffer (callers must "use it or lose it"; the next | ||
| 177 | * invocation will over-write it). Probably not bullet-proof. */ | ||
| 178 | |||
| 179 | #define MAX_STRING_LENGTH 1024 | ||
| 180 | |||
| 181 | char strBuf[MAX_STRING_LENGTH]; | ||
| 182 | |||
| 183 | static char *parseString(char **pInOut) | ||
| 184 | { | ||
| 185 | char *p = *pInOut; | ||
| 186 | char *q = strBuf; | ||
| 187 | while(*p == ' ') | ||
| 188 | ++p; | ||
| 189 | |||
| 190 | if (*p != '"') | ||
| 191 | everror("String has no opening quotation mark: '%s'", p); | ||
| 192 | ++p; | ||
| 193 | |||
| 194 | while(1) { | ||
| 195 | if (q - strBuf >= MAX_STRING_LENGTH) { | ||
| 196 | everror("String length exceeds %d", MAX_STRING_LENGTH); | ||
| 197 | } | ||
| 198 | if (*p == '\\') { /* escaped character */ | ||
| 199 | ++p; | ||
| 200 | if (*p == '\0') | ||
| 201 | everror("Closing NUL byte escaped by backslash."); | ||
| 202 | *q++ = *p++; | ||
| 203 | } else if (*p == '"') { /* end of string */ | ||
| 204 | *q = '\0'; | ||
| 205 | ++p; | ||
| 206 | *pInOut = p; | ||
| 207 | return strBuf; | ||
| 208 | } else if (*p == '\0') | ||
| 209 | everror("Unexpected closing NUL byte."); | ||
| 210 | else | ||
| 211 | *q++ = *p++; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | /* Event logs have interned strings (i.e. they construct a partial | ||
| 216 | * function from non-negatie integer IDs to strings), and can label | ||
| 217 | * addresses with intern string IDs (i.e. they construct a partial | ||
| 218 | * function from address to string ID). We need two tables to keep | ||
| 219 | * track of these. */ | ||
| 220 | |||
| 221 | static Table internTable; /* dictionary of intern ids to strings */ | ||
| 222 | |||
| 223 | static Table labelTable; /* dictionary of addrs to intern ids */ | ||
| 224 | |||
| 225 | static void createTables(void) | ||
| 226 | { | ||
| 227 | Res res; | ||
| 228 | /* MPS intern IDs are serials from zero up, so we can use -1 | ||
| 229 | * and -2 as specials. */ | ||
| 230 | res = TableCreate(&internTable, | ||
| 231 | (size_t)1<<4, | ||
| 232 | tableAlloc, tableFree, NULL, | ||
| 233 | (Word)-1, (Word)-2); | ||
| 234 | if (res != ResOK) | ||
| 235 | everror("Couldn't make intern table."); | ||
| 236 | |||
| 237 | /* We assume that 0 and 1 are invalid as Addrs. */ | ||
| 238 | res = TableCreate(&labelTable, (size_t)1<<7, | ||
| 239 | tableAlloc, tableFree, NULL, | ||
| 240 | 0, 1); | ||
| 241 | if (res != ResOK) | ||
| 242 | everror("Couldn't make label table."); | ||
| 243 | } | ||
| 244 | |||
| 245 | /* recordIntern -- record an interned string in the table. a copy of | ||
| 246 | * the string from the parsed buffer into a newly-allocated block. */ | ||
| 247 | |||
| 248 | static void recordIntern(char *p) | ||
| 249 | { | ||
| 250 | ulongest_t stringId; | ||
| 251 | char *string; | ||
| 252 | char *copy; | ||
| 253 | size_t len; | ||
| 254 | Res res; | ||
| 255 | |||
| 256 | stringId = parseHex(&p); | ||
| 257 | string = parseString(&p); | ||
| 258 | len = strlen(string); | ||
| 259 | copy = malloc(len+1); | ||
| 260 | if (copy == NULL) | ||
| 261 | everror("Couldn't allocate space for a string."); | ||
| 262 | (void)strcpy(copy, string); | ||
| 263 | res = TableDefine(internTable, (Word)stringId, (void *)copy); | ||
| 264 | if (res != ResOK) | ||
| 265 | everror("Couldn't create an intern mapping."); | ||
| 266 | } | ||
| 267 | |||
| 268 | /* recordLabel records a label (an association between an address and | ||
| 269 | * a string ID). Note that the event log may have been generated on a | ||
| 270 | * platform with addresses larger than Word on the current platform. | ||
| 271 | * If that happens then we are scuppered because our Table code uses | ||
| 272 | * Word as the key type: there's nothing we can do except detect this | ||
| 273 | * bad case (see also the EventInit handling and warning code). | ||
| 274 | * | ||
| 275 | * We can and do handle the case where string IDs (which are Words on | ||
| 276 | * the MPS platform) are larger than void* on the current platform. | ||
| 277 | * This is probably in fact the same case, because Word should be the | ||
| 278 | * same size as void*. In practice, trying to analyse a log from a | ||
| 279 | * wide platform on a narrow one (e.g. - the only case which is likely | ||
| 280 | * to occur this decade - from a 64-bit platform on a 32-bit one) is | ||
| 281 | * probably a bad idea and maybe doomed to failure. | ||
| 282 | */ | ||
| 283 | |||
| 284 | static void recordLabel(char *p) | ||
| 285 | { | ||
| 286 | ulongest_t address; | ||
| 287 | ulongest_t *stringIdP; | ||
| 288 | Res res; | ||
| 289 | |||
| 290 | address = parseHex(&p); | ||
| 291 | if (address > (Word)-1) { | ||
| 292 | printf("label address too large!"); | ||
| 293 | return; | ||
| 294 | } | ||
| 295 | |||
| 296 | stringIdP = malloc(sizeof(ulongest_t)); | ||
| 297 | if (stringIdP == NULL) | ||
| 298 | everror("Can't allocate space for a string's ID"); | ||
| 299 | *stringIdP = parseHex(&p); | ||
| 300 | res = TableDefine(labelTable, (Word)address, (void *)stringIdP); | ||
| 301 | if (res != ResOK) | ||
| 302 | everror("Couldn't create an intern mapping."); | ||
| 303 | } | ||
| 304 | |||
| 305 | /* output code */ | ||
| 306 | |||
| 307 | /* hexWordWidth is the number of characters used to output a Word | ||
| 308 | * value in hexadecimal. Note that what we really care about is the | ||
| 309 | * width of a Word on the source platform, not here. So when we see | ||
| 310 | * an EventInit event, we update this variable to the necessary | ||
| 311 | * width. */ | ||
| 312 | |||
| 313 | static int hexWordWidth = (MPS_WORD_WIDTH+3)/4; | ||
| 314 | |||
| 315 | /* printAddr -- output a ulongest_t in hex, with the interned string | ||
| 316 | * if the value is in the label table */ | ||
| 317 | |||
| 318 | static void printAddr(ulongest_t addr, const char *ident) | ||
| 319 | { | ||
| 320 | ulongest_t label; | ||
| 321 | void *alias; | ||
| 322 | |||
| 323 | printf("%s:%0*" PRIXLONGEST, ident, hexWordWidth, addr); | ||
| 324 | if (TableLookup(&alias, labelTable, addr)) { | ||
| 325 | label = *(ulongest_t*)alias; | ||
| 326 | putchar('['); | ||
| 327 | if (TableLookup(&alias, internTable, label)) | ||
| 328 | printStr((char *)alias); | ||
| 329 | else | ||
| 330 | printf("unknown label %" PRIuLONGEST, label); | ||
| 331 | putchar(']'); | ||
| 332 | } | ||
| 333 | putchar(' '); | ||
| 334 | } | ||
| 335 | |||
| 336 | /* parameter processing. For each parameter we parse it and then | ||
| 337 | * print it, preceded by its name and a colon and followed by a | ||
| 338 | * space. */ | ||
| 339 | |||
| 340 | #define processParamA(ident) \ | ||
| 341 | val_hex = parseHex(&p); \ | ||
| 342 | printAddr(val_hex, #ident); | ||
| 343 | |||
| 344 | #define processParamP processParamA | ||
| 345 | #define processParamW processParamA | ||
| 346 | |||
| 347 | #define processParamU(ident) \ | ||
| 348 | val_hex = parseHex(&p); \ | ||
| 349 | printf(#ident ":%" PRIuLONGEST " ", val_hex); | ||
| 350 | |||
| 351 | #define processParamD(ident) \ | ||
| 352 | val_float = parseDouble(&p); \ | ||
| 353 | printf(#ident ":%#8.3g ", val_float); | ||
| 354 | |||
| 355 | #define processParamS(ident) \ | ||
| 356 | val_string = parseString(&p); \ | ||
| 357 | printf(#ident ":"); \ | ||
| 358 | printStr(val_string); \ | ||
| 359 | putchar(' '); | ||
| 360 | |||
| 361 | #define processParamB(ident) \ | ||
| 362 | val_hex = parseHex(&p); \ | ||
| 363 | printf(#ident ":%s ", val_hex ? "True" : "False"); | ||
| 364 | |||
| 365 | #define EVENT_PROCESS_PARAM(X, index, sort, ident) processParam##sort(ident); | ||
| 366 | |||
| 367 | #define EVENT_PROCESS(X, name, code, always, kind) \ | ||
| 368 | case code: \ | ||
| 369 | EVENT_##name##_PARAMS(EVENT_PROCESS_PARAM, X) \ | ||
| 370 | break; | ||
| 371 | |||
| 372 | /* a table of the event names */ | ||
| 373 | |||
| 374 | static const char *eventName[EventCodeMAX+EventCodeMAX]; | ||
| 375 | |||
| 376 | #define EVENT_SET_NAME(X, name, code, always, kind) \ | ||
| 377 | eventName[code] = #name; | ||
| 378 | |||
| 379 | /* this is overkill, at present. */ | ||
| 380 | |||
| 381 | #define MAX_LOG_LINE_LENGTH 1024 | ||
| 382 | |||
| 383 | /* readLog -- read and parse log. Returns the number of events written. */ | ||
| 384 | |||
| 385 | static void readLog(FILE *input) | ||
| 386 | { | ||
| 387 | int i; | ||
| 388 | |||
| 389 | for (i=0; i <= EventCodeMAX; ++i) | ||
| 390 | eventName[i] = NULL; | ||
| 391 | |||
| 392 | EVENT_LIST(EVENT_SET_NAME, X); | ||
| 393 | |||
| 394 | while (TRUE) { /* loop for each event */ | ||
| 395 | char line[MAX_LOG_LINE_LENGTH]; | ||
| 396 | char *p, *q; | ||
| 397 | ulongest_t clock; | ||
| 398 | int code; | ||
| 399 | ulongest_t val_hex; | ||
| 400 | double val_float; | ||
| 401 | const char *val_string; | ||
| 402 | |||
| 403 | p = fgets(line, MAX_LOG_LINE_LENGTH, input); | ||
| 404 | if (!p) { | ||
| 405 | if (feof(input)) | ||
| 406 | break; | ||
| 407 | else | ||
| 408 | everror("Couldn't read line from input."); | ||
| 409 | } | ||
| 410 | |||
| 411 | clock = parseHex(&p); | ||
| 412 | code = (int)parseHex(&p); | ||
| 413 | |||
| 414 | if (eventName[code]) | ||
| 415 | printf("%0*" PRIXLONGEST " %04X %-19s ", hexWordWidth, clock, code, | ||
| 416 | eventName[code]); | ||
| 417 | else | ||
| 418 | printf("%0*" PRIXLONGEST " %04X %-19s ", hexWordWidth, clock, code, | ||
| 419 | "[Unknown]"); | ||
| 420 | |||
| 421 | q = p; | ||
| 422 | |||
| 423 | /* for a few particular codes, we do local processing. */ | ||
| 424 | if (code == EventInternCode) { | ||
| 425 | recordIntern(q); | ||
| 426 | } else if (code == EventLabelCode) { | ||
| 427 | recordLabel(q); | ||
| 428 | } else if (code == EventEventInitCode) { | ||
| 429 | ulongest_t major, median, minor, maxCode, maxNameLen, wordWidth, clocksPerSec; | ||
| 430 | major = parseHex(&q); /* EVENT_VERSION_MAJOR */ | ||
| 431 | median = parseHex(&q); /* EVENT_VERSION_MEDIAN */ | ||
| 432 | minor = parseHex(&q); /* EVENT_VERSION_MINOR */ | ||
| 433 | maxCode = parseHex(&q); /* EventCodeMAX */ | ||
| 434 | maxNameLen = parseHex(&q); /* EventNameMAX */ | ||
| 435 | wordWidth = parseHex(&q); /* MPS_WORD_WIDTH */ | ||
| 436 | clocksPerSec = parseHex(&q); /* mps_clocks_per_sec() */ | ||
| 437 | UNUSED(clocksPerSec); | ||
| 438 | UNUSED(maxNameLen); | ||
| 439 | |||
| 440 | if ((major != EVENT_VERSION_MAJOR) || | ||
| 441 | (median != EVENT_VERSION_MEDIAN) || | ||
| 442 | (minor != EVENT_VERSION_MINOR)) { | ||
| 443 | fprintf(stderr, "Event log version does not match: %d.%d.%d vs %d.%d.%d\n", | ||
| 444 | (int)major, (int)median, (int)minor, | ||
| 445 | EVENT_VERSION_MAJOR, | ||
| 446 | EVENT_VERSION_MEDIAN, | ||
| 447 | EVENT_VERSION_MINOR); | ||
| 448 | } | ||
| 449 | |||
| 450 | if (maxCode > EventCodeMAX) { | ||
| 451 | fprintf(stderr, "Event log may contain unknown events with codes from %d to %d\n", | ||
| 452 | EventCodeMAX+1, (int)maxCode); | ||
| 453 | } | ||
| 454 | |||
| 455 | if (wordWidth > MPS_WORD_WIDTH) { | ||
| 456 | int newHexWordWidth = (int)((wordWidth + 3) / 4); | ||
| 457 | if (newHexWordWidth > hexWordWidth) { | ||
| 458 | fprintf(stderr, | ||
| 459 | "Event log word width is greater than on current platform;" | ||
| 460 | "previous values may be printed too narrowly.\n"); | ||
| 461 | } | ||
| 462 | hexWordWidth = newHexWordWidth; | ||
| 463 | } | ||
| 464 | |||
| 465 | if (wordWidth > sizeof(ulongest_t) * CHAR_BIT) { | ||
| 466 | everror("Event log word width %d is too wide for the current platform.", | ||
| 467 | (int)wordWidth); | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | switch(code) { | ||
| 472 | EVENT_LIST(EVENT_PROCESS, X); | ||
| 473 | default: | ||
| 474 | printf("Unknown event."); | ||
| 475 | } | ||
| 476 | putchar('\n'); | ||
| 477 | |||
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 481 | int main(int argc, char *argv[]) | ||
| 482 | { | ||
| 483 | FILE *input; | ||
| 484 | |||
| 485 | parseArgs(argc, argv); | ||
| 486 | if (!logFileName) { | ||
| 487 | input = stdin; | ||
| 488 | logFileName = "<stdin>"; | ||
| 489 | } else { | ||
| 490 | input = fopen(logFileName, "r"); | ||
| 491 | if (input == NULL) | ||
| 492 | everror("unable to open %s", logFileName); | ||
| 493 | } | ||
| 494 | |||
| 495 | createTables(); | ||
| 496 | readLog(input); | ||
| 497 | (void)fclose(input); | ||
| 498 | return 0; | ||
| 499 | } | ||
| 500 | |||
| 501 | /* C. COPYRIGHT AND LICENSE | ||
| 502 | * | ||
| 503 | * Copyright (C) 2012 Ravenbrook Limited <http://www.ravenbrook.com/>. | ||
| 504 | * All rights reserved. This is an open source license. Contact | ||
| 505 | * Ravenbrook for commercial licensing options. | ||
| 506 | * | ||
| 507 | * Redistribution and use in source and binary forms, with or without | ||
| 508 | * modification, are permitted provided that the following conditions are | ||
| 509 | * met: | ||
| 510 | * | ||
| 511 | * 1. Redistributions of source code must retain the above copyright | ||
| 512 | * notice, this list of conditions and the following disclaimer. | ||
| 513 | * | ||
| 514 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 515 | * notice, this list of conditions and the following disclaimer in the | ||
| 516 | * documentation and/or other materials provided with the distribution. | ||
| 517 | * | ||
| 518 | * 3. Redistributions in any form must be accompanied by information on how | ||
| 519 | * to obtain complete source code for this software and any accompanying | ||
| 520 | * software that uses this software. The source code must either be | ||
| 521 | * included in the distribution or be available for no more than the cost | ||
| 522 | * of distribution plus a nominal fee, and must be freely redistributable | ||
| 523 | * under reasonable conditions. For an executable file, complete source | ||
| 524 | * code means the source code for all modules it contains. It does not | ||
| 525 | * include source code for modules or files that typically accompany the | ||
| 526 | * major components of the operating system on which the executable file | ||
| 527 | * runs. | ||
| 528 | * | ||
| 529 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 530 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
| 531 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
| 532 | * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 533 | * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 534 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 535 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 536 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 537 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 538 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 539 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 540 | */ | ||
diff --git a/mps/code/fri3gc.gmk b/mps/code/fri3gc.gmk index f2895c00404..12f0d3e7b01 100644 --- a/mps/code/fri3gc.gmk +++ b/mps/code/fri3gc.gmk | |||
| @@ -9,12 +9,13 @@ MPMPF = lockix.c thix.c pthrdext.c vmix.c \ | |||
| 9 | protix.c protsgix.c prmcan.c prmci3fr.c ssixi3.c span.c | 9 | protix.c protsgix.c prmcan.c prmci3fr.c ssixi3.c span.c |
| 10 | 10 | ||
| 11 | LIBS = -lm -pthread | 11 | LIBS = -lm -pthread |
| 12 | LINKFLAGS = -L/usr/local/lib | ||
| 12 | 13 | ||
| 13 | include gc.gmk | 14 | include gc.gmk |
| 14 | 15 | ||
| 15 | # FIXME: We pun types through the MPS interface, setting off this warning. | 16 | # FIXME: We pun types through the MPS interface, setting off this warning. |
| 16 | # Can we avoid this? The puns might indeed be dangerous. | 17 | # Can we avoid this? The puns might indeed be dangerous. |
| 17 | CFLAGSCOMPILER := $(CFLAGSCOMPILER) -Wno-strict-aliasing | 18 | CFLAGSCOMPILER := $(CFLAGSCOMPILER) -Wno-strict-aliasing -I/usr/local/include |
| 18 | 19 | ||
| 19 | CC = cc | 20 | CC = cc |
| 20 | 21 | ||
diff --git a/mps/code/gc.gmk b/mps/code/gc.gmk index 3de47e908b0..695455dbd0a 100644 --- a/mps/code/gc.gmk +++ b/mps/code/gc.gmk | |||
| @@ -8,13 +8,18 @@ | |||
| 8 | # common makefile fragment (<code/comm.gmk>) requires. | 8 | # common makefile fragment (<code/comm.gmk>) requires. |
| 9 | 9 | ||
| 10 | CC = gcc | 10 | CC = gcc |
| 11 | CFLAGSCOMPILER := \ | 11 | CFLAGSDEBUG = -O -g3 |
| 12 | -ansi -pedantic -Wall -Werror -Wpointer-arith \ | 12 | CFLAGSOPT = -O2 -g3 |
| 13 | CFLAGSCOMPILER := -Wall -Werror -Wpointer-arith \ | ||
| 13 | -Wstrict-prototypes -Wmissing-prototypes \ | 14 | -Wstrict-prototypes -Wmissing-prototypes \ |
| 14 | -Winline -Waggregate-return -Wnested-externs \ | 15 | -Winline -Waggregate-return -Wnested-externs \ |
| 15 | -Wcast-qual -Wshadow -Wstrict-aliasing=2 | 16 | -Wcast-qual -Wshadow -Wstrict-aliasing=2 |
| 16 | CFLAGSDEBUG = -O -g3 | 17 | CFLAGSCOMPILERSTRICT := -ansi -pedantic -Wshadow |
| 17 | CFLAGSOPT = -O2 -g3 | 18 | |
| 19 | # A different set of compiler flags for less strict compilation, for | ||
| 20 | # instance when we need to #include a third-party header file that | ||
| 21 | # won't fly with -ansi -pedantic. Use sparingly! | ||
| 22 | CFLAGSCOMPILERLAX := | ||
| 18 | 23 | ||
| 19 | # gcc -MM generates a dependency line of the form: | 24 | # gcc -MM generates a dependency line of the form: |
| 20 | # thing.o : thing.c ... | 25 | # thing.o : thing.c ... |
diff --git a/mps/code/global.c b/mps/code/global.c index 0f16c5e4475..ed297978d64 100644 --- a/mps/code/global.c +++ b/mps/code/global.c | |||
| @@ -584,6 +584,7 @@ MutatorFaultContext mps_exception_info = NULL; | |||
| 584 | 584 | ||
| 585 | Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context) | 585 | Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context) |
| 586 | { | 586 | { |
| 587 | static Count count = 0; /* used to match up ArenaAccess events */ | ||
| 587 | Seg seg; | 588 | Seg seg; |
| 588 | Ring node, nextNode; | 589 | Ring node, nextNode; |
| 589 | Res res; | 590 | Res res; |
| @@ -598,6 +599,8 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context) | |||
| 598 | Root root; | 599 | Root root; |
| 599 | 600 | ||
| 600 | ArenaEnter(arena); /* <design/arena/#lock.arena> */ | 601 | ArenaEnter(arena); /* <design/arena/#lock.arena> */ |
| 602 | EVENT4(ArenaAccess, arena, ++count, addr, mode); | ||
| 603 | |||
| 601 | /* @@@@ The code below assumes that Roots and Segs are disjoint. */ | 604 | /* @@@@ The code below assumes that Roots and Segs are disjoint. */ |
| 602 | /* It will fall over (in TraceSegAccess probably) if there is a */ | 605 | /* It will fall over (in TraceSegAccess probably) if there is a */ |
| 603 | /* protected root on a segment. */ | 606 | /* protected root on a segment. */ |
| @@ -613,6 +616,7 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context) | |||
| 613 | res = PoolAccess(SegPool(seg), seg, addr, mode, context); | 616 | res = PoolAccess(SegPool(seg), seg, addr, mode, context); |
| 614 | AVER(res == ResOK); /* Mutator can't continue unless this succeeds */ | 617 | AVER(res == ResOK); /* Mutator can't continue unless this succeeds */ |
| 615 | } | 618 | } |
| 619 | EVENT4(ArenaAccess, arena, count, addr, mode); | ||
| 616 | ArenaLeave(arena); | 620 | ArenaLeave(arena); |
| 617 | return TRUE; | 621 | return TRUE; |
| 618 | } else if (RootOfAddr(&root, arena, addr)) { | 622 | } else if (RootOfAddr(&root, arena, addr)) { |
| @@ -621,6 +625,7 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context) | |||
| 621 | mode &= RootPM(root); | 625 | mode &= RootPM(root); |
| 622 | if (mode != AccessSetEMPTY) | 626 | if (mode != AccessSetEMPTY) |
| 623 | RootAccess(root, mode); | 627 | RootAccess(root, mode); |
| 628 | EVENT4(ArenaAccess, arena, count, addr, mode); | ||
| 624 | ArenaLeave(arena); | 629 | ArenaLeave(arena); |
| 625 | return TRUE; | 630 | return TRUE; |
| 626 | } | 631 | } |
| @@ -680,6 +685,9 @@ void ArenaPoll(Globals globals) | |||
| 680 | arena = GlobalsArena(globals); | 685 | arena = GlobalsArena(globals); |
| 681 | start = ClockNow(); | 686 | start = ClockNow(); |
| 682 | quanta = 0; | 687 | quanta = 0; |
| 688 | |||
| 689 | EVENT3(ArenaPoll, arena, start, 0); | ||
| 690 | |||
| 683 | while(globals->pollThreshold <= globals->fillMutatorSize) { | 691 | while(globals->pollThreshold <= globals->fillMutatorSize) { |
| 684 | tracedSize = TracePoll(globals); | 692 | tracedSize = TracePoll(globals); |
| 685 | 693 | ||
| @@ -705,6 +713,8 @@ void ArenaPoll(Globals globals) | |||
| 705 | 713 | ||
| 706 | AVER(globals->fillMutatorSize < globals->pollThreshold); | 714 | AVER(globals->fillMutatorSize < globals->pollThreshold); |
| 707 | 715 | ||
| 716 | EVENT3(ArenaPoll, arena, start, quanta); | ||
| 717 | |||
| 708 | globals->insidePoll = FALSE; | 718 | globals->insidePoll = FALSE; |
| 709 | } | 719 | } |
| 710 | #endif | 720 | #endif |
| @@ -1066,7 +1076,8 @@ void ArenaSetEmergency(Arena arena, Bool emergency) | |||
| 1066 | 1076 | ||
| 1067 | DIAG_SINGLEF(( "ArenaSetEmergency", | 1077 | DIAG_SINGLEF(( "ArenaSetEmergency", |
| 1068 | "emergency: $U", (WriteFU)emergency, NULL )); | 1078 | "emergency: $U", (WriteFU)emergency, NULL )); |
| 1069 | 1079 | EVENT2(ArenaSetEmergency, arena, emergency); | |
| 1080 | |||
| 1070 | arena->emergency = emergency; | 1081 | arena->emergency = emergency; |
| 1071 | } | 1082 | } |
| 1072 | 1083 | ||
diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index 984790baf56..f7cf9a023ea 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h | |||
| @@ -41,7 +41,7 @@ typedef unsigned Shift; /* <design/type/#shift> */ | |||
| 41 | typedef unsigned Serial; /* <design/type/#serial> */ | 41 | typedef unsigned Serial; /* <design/type/#serial> */ |
| 42 | typedef Addr Ref; /* <design/type/#ref> */ | 42 | typedef Addr Ref; /* <design/type/#ref> */ |
| 43 | typedef void *Pointer; /* <design/type/#pointer> */ | 43 | typedef void *Pointer; /* <design/type/#pointer> */ |
| 44 | typedef unsigned long Clock; /* processor time */ | 44 | typedef Word Clock; /* processor time */ |
| 45 | typedef MPS_T_ULONGEST ULongest; /* <design/type/#ulongest> */ | 45 | typedef MPS_T_ULONGEST ULongest; /* <design/type/#ulongest> */ |
| 46 | 46 | ||
| 47 | typedef Word RefSet; /* design.mps.refset */ | 47 | typedef Word RefSet; /* design.mps.refset */ |
diff --git a/mps/code/mps.h b/mps/code/mps.h index 6d0edbb75d2..e47a4ca8e34 100644 --- a/mps/code/mps.h +++ b/mps/code/mps.h | |||
| @@ -70,13 +70,13 @@ typedef struct mps_frame_s | |||
| 70 | typedef MPS_T_WORD mps_word_t; /* pointer-sized word */ | 70 | typedef MPS_T_WORD mps_word_t; /* pointer-sized word */ |
| 71 | typedef int mps_bool_t; /* boolean (int) */ | 71 | typedef int mps_bool_t; /* boolean (int) */ |
| 72 | typedef int mps_res_t; /* result code (int) */ | 72 | typedef int mps_res_t; /* result code (int) */ |
| 73 | typedef unsigned mps_shift_t; /* shift amount (unsigned int) */ | ||
| 74 | typedef void *mps_addr_t; /* managed address (void *) */ | 73 | typedef void *mps_addr_t; /* managed address (void *) */ |
| 75 | typedef size_t mps_align_t; /* alignment (size_t) */ | 74 | typedef size_t mps_align_t; /* alignment (size_t) */ |
| 76 | typedef unsigned mps_rm_t; /* root mode (unsigned) */ | 75 | typedef unsigned mps_rm_t; /* root mode (unsigned) */ |
| 77 | typedef unsigned mps_rank_t; /* ranks (unsigned) */ | 76 | typedef unsigned mps_rank_t; /* ranks (unsigned) */ |
| 78 | typedef unsigned mps_message_type_t; /* message type (unsigned) */ | 77 | typedef unsigned mps_message_type_t; /* message type (unsigned) */ |
| 79 | typedef unsigned long mps_clock_t; /* processor time */ | 78 | typedef mps_word_t mps_clock_t; /* processor time */ |
| 79 | typedef mps_word_t mps_label_t; /* telemetry label */ | ||
| 80 | 80 | ||
| 81 | /* Result Codes */ | 81 | /* Result Codes */ |
| 82 | /* .result-codes: Keep in sync with <code/mpmtypes.h#result-codes> */ | 82 | /* .result-codes: Keep in sync with <code/mpmtypes.h#result-codes> */ |
| @@ -584,8 +584,11 @@ enum { | |||
| 584 | /* Telemetry */ | 584 | /* Telemetry */ |
| 585 | 585 | ||
| 586 | extern mps_word_t mps_telemetry_control(mps_word_t, mps_word_t); | 586 | extern mps_word_t mps_telemetry_control(mps_word_t, mps_word_t); |
| 587 | extern mps_word_t mps_telemetry_intern(const char *); | 587 | extern void mps_telemetry_set(mps_word_t); |
| 588 | extern void mps_telemetry_label(mps_addr_t, mps_word_t); | 588 | extern void mps_telemetry_reset(mps_word_t); |
| 589 | extern mps_word_t mps_telemetry_get(void); | ||
| 590 | extern mps_label_t mps_telemetry_intern(const char *); | ||
| 591 | extern void mps_telemetry_label(mps_addr_t, mps_label_t); | ||
| 589 | extern void mps_telemetry_flush(void); | 592 | extern void mps_telemetry_flush(void); |
| 590 | 593 | ||
| 591 | 594 | ||
diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index 207e50660e4..1b5d7700d4b 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | dependencies = ( | 15 | dependencies = ( |
| 16 | 3104AFF6156D37BC000A585A /* PBXTargetDependency */, | 16 | 3104AFF6156D37BC000A585A /* PBXTargetDependency */, |
| 17 | 3114A6D5156E9839001E0AA3 /* PBXTargetDependency */, | 17 | 3114A6D5156E9839001E0AA3 /* PBXTargetDependency */, |
| 18 | 2D07B9791636FCBD00DB751B /* PBXTargetDependency */, | ||
| 19 | 2275798916C5422900B662B0 /* PBXTargetDependency */, | ||
| 18 | 3114A6B9156E9763001E0AA3 /* PBXTargetDependency */, | 20 | 3114A6B9156E9763001E0AA3 /* PBXTargetDependency */, |
| 19 | 3114A6A7156E9739001E0AA3 /* PBXTargetDependency */, | 21 | 3114A6A7156E9739001E0AA3 /* PBXTargetDependency */, |
| 20 | 3114A68D156E9686001E0AA3 /* PBXTargetDependency */, | 22 | 3114A68D156E9686001E0AA3 /* PBXTargetDependency */, |
| @@ -51,6 +53,10 @@ | |||
| 51 | /* End PBXAggregateTarget section */ | 53 | /* End PBXAggregateTarget section */ |
| 52 | 54 | ||
| 53 | /* Begin PBXBuildFile section */ | 55 | /* Begin PBXBuildFile section */ |
| 56 | 2D07B97A1636FCCE00DB751B /* eventsql.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D07B96C1636FC7200DB751B /* eventsql.c */; }; | ||
| 57 | 2D07B97C163705E400DB751B /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D07B97B163705E400DB751B /* libsqlite3.dylib */; }; | ||
| 58 | 2D53F2E716515A63009A1829 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; | ||
| 59 | 2D604BA516514C4F003AAF46 /* eventtxt.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D604BA416514C4F003AAF46 /* eventtxt.c */; }; | ||
| 54 | 3104AFBF156D3591000A585A /* apss.c in Sources */ = {isa = PBXBuildFile; fileRef = 3104AFBE156D3591000A585A /* apss.c */; }; | 60 | 3104AFBF156D3591000A585A /* apss.c in Sources */ = {isa = PBXBuildFile; fileRef = 3104AFBE156D3591000A585A /* apss.c */; }; |
| 55 | 3104AFC2156D35B2000A585A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; | 61 | 3104AFC2156D35B2000A585A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; |
| 56 | 3104AFC3156D35C3000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; | 62 | 3104AFC3156D35C3000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; |
| @@ -196,6 +202,20 @@ | |||
| 196 | /* End PBXBuildFile section */ | 202 | /* End PBXBuildFile section */ |
| 197 | 203 | ||
| 198 | /* Begin PBXContainerItemProxy section */ | 204 | /* Begin PBXContainerItemProxy section */ |
| 205 | 2275798816C5422900B662B0 /* PBXContainerItemProxy */ = { | ||
| 206 | isa = PBXContainerItemProxy; | ||
| 207 | containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; | ||
| 208 | proxyType = 1; | ||
| 209 | remoteGlobalIDString = 2D604B9B16514B1A003AAF46; | ||
| 210 | remoteInfo = mpseventtxt; | ||
| 211 | }; | ||
| 212 | 2D07B9781636FCBD00DB751B /* PBXContainerItemProxy */ = { | ||
| 213 | isa = PBXContainerItemProxy; | ||
| 214 | containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; | ||
| 215 | proxyType = 1; | ||
| 216 | remoteGlobalIDString = 2D07B9701636FC9900DB751B; | ||
| 217 | remoteInfo = mpseventsql; | ||
| 218 | }; | ||
| 199 | 3104AFC0156D35AE000A585A /* PBXContainerItemProxy */ = { | 219 | 3104AFC0156D35AE000A585A /* PBXContainerItemProxy */ = { |
| 200 | isa = PBXContainerItemProxy; | 220 | isa = PBXContainerItemProxy; |
| 201 | containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; | 221 | containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; |
| @@ -509,7 +529,7 @@ | |||
| 509 | containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; | 529 | containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; |
| 510 | proxyType = 1; | 530 | proxyType = 1; |
| 511 | remoteGlobalIDString = 3114A6C5156E9815001E0AA3; | 531 | remoteGlobalIDString = 3114A6C5156E9815001E0AA3; |
| 512 | remoteInfo = eventcnv; | 532 | remoteInfo = mpseventcnv; |
| 513 | }; | 533 | }; |
| 514 | 31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */ = { | 534 | 31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */ = { |
| 515 | isa = PBXContainerItemProxy; | 535 | isa = PBXContainerItemProxy; |
| @@ -626,6 +646,24 @@ | |||
| 626 | /* End PBXContainerItemProxy section */ | 646 | /* End PBXContainerItemProxy section */ |
| 627 | 647 | ||
| 628 | /* Begin PBXCopyFilesBuildPhase section */ | 648 | /* Begin PBXCopyFilesBuildPhase section */ |
| 649 | 2D07B96F1636FC9900DB751B /* CopyFiles */ = { | ||
| 650 | isa = PBXCopyFilesBuildPhase; | ||
| 651 | buildActionMask = 2147483647; | ||
| 652 | dstPath = /usr/share/man/man1/; | ||
| 653 | dstSubfolderSpec = 0; | ||
| 654 | files = ( | ||
| 655 | ); | ||
| 656 | runOnlyForDeploymentPostprocessing = 1; | ||
| 657 | }; | ||
| 658 | 2D604B9A16514B1A003AAF46 /* CopyFiles */ = { | ||
| 659 | isa = PBXCopyFilesBuildPhase; | ||
| 660 | buildActionMask = 2147483647; | ||
| 661 | dstPath = /usr/share/man/man1/; | ||
| 662 | dstSubfolderSpec = 0; | ||
| 663 | files = ( | ||
| 664 | ); | ||
| 665 | runOnlyForDeploymentPostprocessing = 1; | ||
| 666 | }; | ||
| 629 | 3104AFB1156D357B000A585A /* CopyFiles */ = { | 667 | 3104AFB1156D357B000A585A /* CopyFiles */ = { |
| 630 | isa = PBXCopyFilesBuildPhase; | 668 | isa = PBXCopyFilesBuildPhase; |
| 631 | buildActionMask = 2147483647; | 669 | buildActionMask = 2147483647; |
| @@ -899,6 +937,11 @@ | |||
| 899 | /* End PBXCopyFilesBuildPhase section */ | 937 | /* End PBXCopyFilesBuildPhase section */ |
| 900 | 938 | ||
| 901 | /* Begin PBXFileReference section */ | 939 | /* Begin PBXFileReference section */ |
| 940 | 2D07B96C1636FC7200DB751B /* eventsql.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = eventsql.c; sourceTree = "<group>"; }; | ||
| 941 | 2D07B9711636FC9900DB751B /* mpseventsql */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpseventsql; sourceTree = BUILT_PRODUCTS_DIR; }; | ||
| 942 | 2D07B97B163705E400DB751B /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; | ||
| 943 | 2D604B9C16514B1A003AAF46 /* mpseventtxt */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpseventtxt; sourceTree = BUILT_PRODUCTS_DIR; }; | ||
| 944 | 2D604BA416514C4F003AAF46 /* eventtxt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventtxt.c; sourceTree = "<group>"; }; | ||
| 902 | 3104AFA5156D27E7000A585A /* ssixi6.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ssixi6.c; sourceTree = "<group>"; }; | 945 | 3104AFA5156D27E7000A585A /* ssixi6.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ssixi6.c; sourceTree = "<group>"; }; |
| 903 | 3104AFB3156D357B000A585A /* apss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apss; sourceTree = BUILT_PRODUCTS_DIR; }; | 946 | 3104AFB3156D357B000A585A /* apss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apss; sourceTree = BUILT_PRODUCTS_DIR; }; |
| 904 | 3104AFBE156D3591000A585A /* apss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = apss.c; sourceTree = "<group>"; }; | 947 | 3104AFBE156D3591000A585A /* apss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = apss.c; sourceTree = "<group>"; }; |
| @@ -939,7 +982,7 @@ | |||
| 939 | 3114A69F156E9725001E0AA3 /* messtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = messtest.c; sourceTree = "<group>"; }; | 982 | 3114A69F156E9725001E0AA3 /* messtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = messtest.c; sourceTree = "<group>"; }; |
| 940 | 3114A6AC156E9759001E0AA3 /* walkt0 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = walkt0; sourceTree = BUILT_PRODUCTS_DIR; }; | 983 | 3114A6AC156E9759001E0AA3 /* walkt0 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = walkt0; sourceTree = BUILT_PRODUCTS_DIR; }; |
| 941 | 3114A6BA156E9768001E0AA3 /* walkt0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walkt0.c; sourceTree = "<group>"; }; | 984 | 3114A6BA156E9768001E0AA3 /* walkt0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walkt0.c; sourceTree = "<group>"; }; |
| 942 | 3114A6C6156E9815001E0AA3 /* eventcnv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = eventcnv; sourceTree = BUILT_PRODUCTS_DIR; }; | 985 | 3114A6C6156E9815001E0AA3 /* mpseventcnv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpseventcnv; sourceTree = BUILT_PRODUCTS_DIR; }; |
| 943 | 3114A6D0156E9829001E0AA3 /* eventcnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventcnv.c; sourceTree = "<group>"; }; | 986 | 3114A6D0156E9829001E0AA3 /* eventcnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventcnv.c; sourceTree = "<group>"; }; |
| 944 | 3114A6D9156E9950001E0AA3 /* eventpro.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventpro.c; sourceTree = "<group>"; }; | 987 | 3114A6D9156E9950001E0AA3 /* eventpro.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventpro.c; sourceTree = "<group>"; }; |
| 945 | 3124CAB8156BE3EC00753214 /* awlut */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = awlut; sourceTree = BUILT_PRODUCTS_DIR; }; | 988 | 3124CAB8156BE3EC00753214 /* awlut */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = awlut; sourceTree = BUILT_PRODUCTS_DIR; }; |
| @@ -1026,6 +1069,22 @@ | |||
| 1026 | /* End PBXFileReference section */ | 1069 | /* End PBXFileReference section */ |
| 1027 | 1070 | ||
| 1028 | /* Begin PBXFrameworksBuildPhase section */ | 1071 | /* Begin PBXFrameworksBuildPhase section */ |
| 1072 | 2D07B96E1636FC9900DB751B /* Frameworks */ = { | ||
| 1073 | isa = PBXFrameworksBuildPhase; | ||
| 1074 | buildActionMask = 2147483647; | ||
| 1075 | files = ( | ||
| 1076 | 2D07B97C163705E400DB751B /* libsqlite3.dylib in Frameworks */, | ||
| 1077 | ); | ||
| 1078 | runOnlyForDeploymentPostprocessing = 0; | ||
| 1079 | }; | ||
| 1080 | 2D604B9916514B1A003AAF46 /* Frameworks */ = { | ||
| 1081 | isa = PBXFrameworksBuildPhase; | ||
| 1082 | buildActionMask = 2147483647; | ||
| 1083 | files = ( | ||
| 1084 | 2D53F2E716515A63009A1829 /* libmps.a in Frameworks */, | ||
| 1085 | ); | ||
| 1086 | runOnlyForDeploymentPostprocessing = 0; | ||
| 1087 | }; | ||
| 1029 | 3104AFB0156D357B000A585A /* Frameworks */ = { | 1088 | 3104AFB0156D357B000A585A /* Frameworks */ = { |
| 1030 | isa = PBXFrameworksBuildPhase; | 1089 | isa = PBXFrameworksBuildPhase; |
| 1031 | buildActionMask = 2147483647; | 1090 | buildActionMask = 2147483647; |
| @@ -1276,6 +1335,22 @@ | |||
| 1276 | /* End PBXFrameworksBuildPhase section */ | 1335 | /* End PBXFrameworksBuildPhase section */ |
| 1277 | 1336 | ||
| 1278 | /* Begin PBXGroup section */ | 1337 | /* Begin PBXGroup section */ |
| 1338 | 2D07B96A1636FC4C00DB751B /* mpseventsql */ = { | ||
| 1339 | isa = PBXGroup; | ||
| 1340 | children = ( | ||
| 1341 | 2D07B96C1636FC7200DB751B /* eventsql.c */, | ||
| 1342 | ); | ||
| 1343 | name = mpseventsql; | ||
| 1344 | sourceTree = "<group>"; | ||
| 1345 | }; | ||
| 1346 | 2D604B971651433C003AAF46 /* mpseventtxt */ = { | ||
| 1347 | isa = PBXGroup; | ||
| 1348 | children = ( | ||
| 1349 | 2D604BA416514C4F003AAF46 /* eventtxt.c */, | ||
| 1350 | ); | ||
| 1351 | name = mpseventtxt; | ||
| 1352 | sourceTree = "<group>"; | ||
| 1353 | }; | ||
| 1279 | 3114A647156E956C001E0AA3 /* Mysterious */ = { | 1354 | 3114A647156E956C001E0AA3 /* Mysterious */ = { |
| 1280 | isa = PBXGroup; | 1355 | isa = PBXGroup; |
| 1281 | children = ( | 1356 | children = ( |
| @@ -1288,18 +1363,20 @@ | |||
| 1288 | 3114A6D6156E9846001E0AA3 /* Tools */ = { | 1363 | 3114A6D6156E9846001E0AA3 /* Tools */ = { |
| 1289 | isa = PBXGroup; | 1364 | isa = PBXGroup; |
| 1290 | children = ( | 1365 | children = ( |
| 1291 | 3114A6D8156E9942001E0AA3 /* eventcnv */, | 1366 | 2D604B971651433C003AAF46 /* mpseventtxt */, |
| 1367 | 2D07B96A1636FC4C00DB751B /* mpseventsql */, | ||
| 1368 | 3114A6D8156E9942001E0AA3 /* mpseventcnv */, | ||
| 1292 | ); | 1369 | ); |
| 1293 | name = Tools; | 1370 | name = Tools; |
| 1294 | sourceTree = "<group>"; | 1371 | sourceTree = "<group>"; |
| 1295 | }; | 1372 | }; |
| 1296 | 3114A6D8156E9942001E0AA3 /* eventcnv */ = { | 1373 | 3114A6D8156E9942001E0AA3 /* mpseventcnv */ = { |
| 1297 | isa = PBXGroup; | 1374 | isa = PBXGroup; |
| 1298 | children = ( | 1375 | children = ( |
| 1299 | 3114A6D9156E9950001E0AA3 /* eventpro.c */, | 1376 | 3114A6D9156E9950001E0AA3 /* eventpro.c */, |
| 1300 | 3114A6D0156E9829001E0AA3 /* eventcnv.c */, | 1377 | 3114A6D0156E9829001E0AA3 /* eventcnv.c */, |
| 1301 | ); | 1378 | ); |
| 1302 | name = eventcnv; | 1379 | name = mpseventcnv; |
| 1303 | sourceTree = "<group>"; | 1380 | sourceTree = "<group>"; |
| 1304 | }; | 1381 | }; |
| 1305 | 3124CAB3156BE1B700753214 /* Tests */ = { | 1382 | 3124CAB3156BE1B700753214 /* Tests */ = { |
| @@ -1374,6 +1451,7 @@ | |||
| 1374 | 31EEABD8156AAE9E00714D05 = { | 1451 | 31EEABD8156AAE9E00714D05 = { |
| 1375 | isa = PBXGroup; | 1452 | isa = PBXGroup; |
| 1376 | children = ( | 1453 | children = ( |
| 1454 | 2D07B97B163705E400DB751B /* libsqlite3.dylib */, | ||
| 1377 | 3114A6D6156E9846001E0AA3 /* Tools */, | 1455 | 3114A6D6156E9846001E0AA3 /* Tools */, |
| 1378 | 3114A647156E956C001E0AA3 /* Mysterious */, | 1456 | 3114A647156E956C001E0AA3 /* Mysterious */, |
| 1379 | 31A47BA8156C1E930039B1C2 /* MPS */, | 1457 | 31A47BA8156C1E930039B1C2 /* MPS */, |
| @@ -1415,7 +1493,9 @@ | |||
| 1415 | 3114A67C156E9668001E0AA3 /* mv2test */, | 1493 | 3114A67C156E9668001E0AA3 /* mv2test */, |
| 1416 | 3114A695156E971B001E0AA3 /* messtest */, | 1494 | 3114A695156E971B001E0AA3 /* messtest */, |
| 1417 | 3114A6AC156E9759001E0AA3 /* walkt0 */, | 1495 | 3114A6AC156E9759001E0AA3 /* walkt0 */, |
| 1418 | 3114A6C6156E9815001E0AA3 /* eventcnv */, | 1496 | 3114A6C6156E9815001E0AA3 /* mpseventcnv */, |
| 1497 | 2D07B9711636FC9900DB751B /* mpseventsql */, | ||
| 1498 | 2D604B9C16514B1A003AAF46 /* mpseventtxt */, | ||
| 1419 | ); | 1499 | ); |
| 1420 | name = Products; | 1500 | name = Products; |
| 1421 | sourceTree = "<group>"; | 1501 | sourceTree = "<group>"; |
| @@ -1515,6 +1595,40 @@ | |||
| 1515 | /* End PBXHeadersBuildPhase section */ | 1595 | /* End PBXHeadersBuildPhase section */ |
| 1516 | 1596 | ||
| 1517 | /* Begin PBXNativeTarget section */ | 1597 | /* Begin PBXNativeTarget section */ |
| 1598 | 2D07B9701636FC9900DB751B /* mpseventsql */ = { | ||
| 1599 | isa = PBXNativeTarget; | ||
| 1600 | buildConfigurationList = 2D07B9741636FC9900DB751B /* Build configuration list for PBXNativeTarget "mpseventsql" */; | ||
| 1601 | buildPhases = ( | ||
| 1602 | 2D07B96D1636FC9900DB751B /* Sources */, | ||
| 1603 | 2D07B96E1636FC9900DB751B /* Frameworks */, | ||
| 1604 | 2D07B96F1636FC9900DB751B /* CopyFiles */, | ||
| 1605 | ); | ||
| 1606 | buildRules = ( | ||
| 1607 | ); | ||
| 1608 | dependencies = ( | ||
| 1609 | ); | ||
| 1610 | name = mpseventsql; | ||
| 1611 | productName = mpseventsql; | ||
| 1612 | productReference = 2D07B9711636FC9900DB751B /* mpseventsql */; | ||
| 1613 | productType = "com.apple.product-type.tool"; | ||
| 1614 | }; | ||
| 1615 | 2D604B9B16514B1A003AAF46 /* mpseventtxt */ = { | ||
| 1616 | isa = PBXNativeTarget; | ||
| 1617 | buildConfigurationList = 2D604BA216514B59003AAF46 /* Build configuration list for PBXNativeTarget "mpseventtxt" */; | ||
| 1618 | buildPhases = ( | ||
| 1619 | 2D604B9816514B1A003AAF46 /* Sources */, | ||
| 1620 | 2D604B9916514B1A003AAF46 /* Frameworks */, | ||
| 1621 | 2D604B9A16514B1A003AAF46 /* CopyFiles */, | ||
| 1622 | ); | ||
| 1623 | buildRules = ( | ||
| 1624 | ); | ||
| 1625 | dependencies = ( | ||
| 1626 | ); | ||
| 1627 | name = mpseventtxt; | ||
| 1628 | productName = mpseventtxt; | ||
| 1629 | productReference = 2D604B9C16514B1A003AAF46 /* mpseventtxt */; | ||
| 1630 | productType = "com.apple.product-type.tool"; | ||
| 1631 | }; | ||
| 1518 | 3104AFB2156D357B000A585A /* apss */ = { | 1632 | 3104AFB2156D357B000A585A /* apss */ = { |
| 1519 | isa = PBXNativeTarget; | 1633 | isa = PBXNativeTarget; |
| 1520 | buildConfigurationList = 3104AFBC156D357B000A585A /* Build configuration list for PBXNativeTarget "apss" */; | 1634 | buildConfigurationList = 3104AFBC156D357B000A585A /* Build configuration list for PBXNativeTarget "apss" */; |
| @@ -1857,9 +1971,9 @@ | |||
| 1857 | productReference = 3114A6AC156E9759001E0AA3 /* walkt0 */; | 1971 | productReference = 3114A6AC156E9759001E0AA3 /* walkt0 */; |
| 1858 | productType = "com.apple.product-type.tool"; | 1972 | productType = "com.apple.product-type.tool"; |
| 1859 | }; | 1973 | }; |
| 1860 | 3114A6C5156E9815001E0AA3 /* eventcnv */ = { | 1974 | 3114A6C5156E9815001E0AA3 /* mpseventcnv */ = { |
| 1861 | isa = PBXNativeTarget; | 1975 | isa = PBXNativeTarget; |
| 1862 | buildConfigurationList = 3114A6CD156E9815001E0AA3 /* Build configuration list for PBXNativeTarget "eventcnv" */; | 1976 | buildConfigurationList = 3114A6CD156E9815001E0AA3 /* Build configuration list for PBXNativeTarget "mpseventcnv" */; |
| 1863 | buildPhases = ( | 1977 | buildPhases = ( |
| 1864 | 3114A6C2156E9815001E0AA3 /* Sources */, | 1978 | 3114A6C2156E9815001E0AA3 /* Sources */, |
| 1865 | 3114A6C3156E9815001E0AA3 /* Frameworks */, | 1979 | 3114A6C3156E9815001E0AA3 /* Frameworks */, |
| @@ -1870,9 +1984,9 @@ | |||
| 1870 | dependencies = ( | 1984 | dependencies = ( |
| 1871 | 3114A6D3156E9834001E0AA3 /* PBXTargetDependency */, | 1985 | 3114A6D3156E9834001E0AA3 /* PBXTargetDependency */, |
| 1872 | ); | 1986 | ); |
| 1873 | name = eventcnv; | 1987 | name = mpseventcnv; |
| 1874 | productName = eventcnv; | 1988 | productName = mpseventcnv; |
| 1875 | productReference = 3114A6C6156E9815001E0AA3 /* eventcnv */; | 1989 | productReference = 3114A6C6156E9815001E0AA3 /* mpseventcnv */; |
| 1876 | productType = "com.apple.product-type.tool"; | 1990 | productType = "com.apple.product-type.tool"; |
| 1877 | }; | 1991 | }; |
| 1878 | 3124CAB7156BE3EC00753214 /* awlut */ = { | 1992 | 3124CAB7156BE3EC00753214 /* awlut */ = { |
| @@ -2123,12 +2237,30 @@ | |||
| 2123 | 3114A67B156E9668001E0AA3 /* mv2test */, | 2237 | 3114A67B156E9668001E0AA3 /* mv2test */, |
| 2124 | 3114A694156E971B001E0AA3 /* messtest */, | 2238 | 3114A694156E971B001E0AA3 /* messtest */, |
| 2125 | 3114A6AB156E9759001E0AA3 /* walkt0 */, | 2239 | 3114A6AB156E9759001E0AA3 /* walkt0 */, |
| 2126 | 3114A6C5156E9815001E0AA3 /* eventcnv */, | 2240 | 3114A6C5156E9815001E0AA3 /* mpseventcnv */, |
| 2241 | 2D07B9701636FC9900DB751B /* mpseventsql */, | ||
| 2242 | 2D604B9B16514B1A003AAF46 /* mpseventtxt */, | ||
| 2127 | ); | 2243 | ); |
| 2128 | }; | 2244 | }; |
| 2129 | /* End PBXProject section */ | 2245 | /* End PBXProject section */ |
| 2130 | 2246 | ||
| 2131 | /* Begin PBXSourcesBuildPhase section */ | 2247 | /* Begin PBXSourcesBuildPhase section */ |
| 2248 | 2D07B96D1636FC9900DB751B /* Sources */ = { | ||
| 2249 | isa = PBXSourcesBuildPhase; | ||
| 2250 | buildActionMask = 2147483647; | ||
| 2251 | files = ( | ||
| 2252 | 2D07B97A1636FCCE00DB751B /* eventsql.c in Sources */, | ||
| 2253 | ); | ||
| 2254 | runOnlyForDeploymentPostprocessing = 0; | ||
| 2255 | }; | ||
| 2256 | 2D604B9816514B1A003AAF46 /* Sources */ = { | ||
| 2257 | isa = PBXSourcesBuildPhase; | ||
| 2258 | buildActionMask = 2147483647; | ||
| 2259 | files = ( | ||
| 2260 | 2D604BA516514C4F003AAF46 /* eventtxt.c in Sources */, | ||
| 2261 | ); | ||
| 2262 | runOnlyForDeploymentPostprocessing = 0; | ||
| 2263 | }; | ||
| 2132 | 3104AFAF156D357B000A585A /* Sources */ = { | 2264 | 3104AFAF156D357B000A585A /* Sources */ = { |
| 2133 | isa = PBXSourcesBuildPhase; | 2265 | isa = PBXSourcesBuildPhase; |
| 2134 | buildActionMask = 2147483647; | 2266 | buildActionMask = 2147483647; |
| @@ -2461,6 +2593,16 @@ | |||
| 2461 | /* End PBXSourcesBuildPhase section */ | 2593 | /* End PBXSourcesBuildPhase section */ |
| 2462 | 2594 | ||
| 2463 | /* Begin PBXTargetDependency section */ | 2595 | /* Begin PBXTargetDependency section */ |
| 2596 | 2275798916C5422900B662B0 /* PBXTargetDependency */ = { | ||
| 2597 | isa = PBXTargetDependency; | ||
| 2598 | target = 2D604B9B16514B1A003AAF46 /* mpseventtxt */; | ||
| 2599 | targetProxy = 2275798816C5422900B662B0 /* PBXContainerItemProxy */; | ||
| 2600 | }; | ||
| 2601 | 2D07B9791636FCBD00DB751B /* PBXTargetDependency */ = { | ||
| 2602 | isa = PBXTargetDependency; | ||
| 2603 | target = 2D07B9701636FC9900DB751B /* mpseventsql */; | ||
| 2604 | targetProxy = 2D07B9781636FCBD00DB751B /* PBXContainerItemProxy */; | ||
| 2605 | }; | ||
| 2464 | 3104AFC1156D35AE000A585A /* PBXTargetDependency */ = { | 2606 | 3104AFC1156D35AE000A585A /* PBXTargetDependency */ = { |
| 2465 | isa = PBXTargetDependency; | 2607 | isa = PBXTargetDependency; |
| 2466 | target = 31EEABFA156AAF9D00714D05 /* mps */; | 2608 | target = 31EEABFA156AAF9D00714D05 /* mps */; |
| @@ -2683,7 +2825,7 @@ | |||
| 2683 | }; | 2825 | }; |
| 2684 | 3114A6D5156E9839001E0AA3 /* PBXTargetDependency */ = { | 2826 | 3114A6D5156E9839001E0AA3 /* PBXTargetDependency */ = { |
| 2685 | isa = PBXTargetDependency; | 2827 | isa = PBXTargetDependency; |
| 2686 | target = 3114A6C5156E9815001E0AA3 /* eventcnv */; | 2828 | target = 3114A6C5156E9815001E0AA3 /* mpseventcnv */; |
| 2687 | targetProxy = 3114A6D4156E9839001E0AA3 /* PBXContainerItemProxy */; | 2829 | targetProxy = 3114A6D4156E9839001E0AA3 /* PBXContainerItemProxy */; |
| 2688 | }; | 2830 | }; |
| 2689 | 31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = { | 2831 | 31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = { |
| @@ -2769,6 +2911,51 @@ | |||
| 2769 | /* End PBXTargetDependency section */ | 2911 | /* End PBXTargetDependency section */ |
| 2770 | 2912 | ||
| 2771 | /* Begin XCBuildConfiguration section */ | 2913 | /* Begin XCBuildConfiguration section */ |
| 2914 | 2D07B9751636FC9900DB751B /* Debug */ = { | ||
| 2915 | isa = XCBuildConfiguration; | ||
| 2916 | buildSettings = { | ||
| 2917 | GCC_C_LANGUAGE_STANDARD = c99; | ||
| 2918 | PRODUCT_NAME = "$(TARGET_NAME)"; | ||
| 2919 | }; | ||
| 2920 | name = Debug; | ||
| 2921 | }; | ||
| 2922 | 2D07B9761636FC9900DB751B /* Release */ = { | ||
| 2923 | isa = XCBuildConfiguration; | ||
| 2924 | buildSettings = { | ||
| 2925 | GCC_C_LANGUAGE_STANDARD = c99; | ||
| 2926 | PRODUCT_NAME = "$(TARGET_NAME)"; | ||
| 2927 | }; | ||
| 2928 | name = Release; | ||
| 2929 | }; | ||
| 2930 | 2D07B9771636FC9900DB751B /* WE */ = { | ||
| 2931 | isa = XCBuildConfiguration; | ||
| 2932 | buildSettings = { | ||
| 2933 | GCC_C_LANGUAGE_STANDARD = c99; | ||
| 2934 | PRODUCT_NAME = "$(TARGET_NAME)"; | ||
| 2935 | }; | ||
| 2936 | name = WE; | ||
| 2937 | }; | ||
| 2938 | 2D604B9F16514B1A003AAF46 /* Debug */ = { | ||
| 2939 | isa = XCBuildConfiguration; | ||
| 2940 | buildSettings = { | ||
| 2941 | PRODUCT_NAME = "$(TARGET_NAME)"; | ||
| 2942 | }; | ||
| 2943 | name = Debug; | ||
| 2944 | }; | ||
| 2945 | 2D604BA016514B1A003AAF46 /* Release */ = { | ||
| 2946 | isa = XCBuildConfiguration; | ||
| 2947 | buildSettings = { | ||
| 2948 | PRODUCT_NAME = "$(TARGET_NAME)"; | ||
| 2949 | }; | ||
| 2950 | name = Release; | ||
| 2951 | }; | ||
| 2952 | 2D604BA116514B1A003AAF46 /* WE */ = { | ||
| 2953 | isa = XCBuildConfiguration; | ||
| 2954 | buildSettings = { | ||
| 2955 | PRODUCT_NAME = "$(TARGET_NAME)"; | ||
| 2956 | }; | ||
| 2957 | name = WE; | ||
| 2958 | }; | ||
| 2772 | 3104AFBA156D357B000A585A /* Debug */ = { | 2959 | 3104AFBA156D357B000A585A /* Debug */ = { |
| 2773 | isa = XCBuildConfiguration; | 2960 | isa = XCBuildConfiguration; |
| 2774 | buildSettings = { | 2961 | buildSettings = { |
| @@ -3616,6 +3803,26 @@ | |||
| 3616 | /* End XCBuildConfiguration section */ | 3803 | /* End XCBuildConfiguration section */ |
| 3617 | 3804 | ||
| 3618 | /* Begin XCConfigurationList section */ | 3805 | /* Begin XCConfigurationList section */ |
| 3806 | 2D07B9741636FC9900DB751B /* Build configuration list for PBXNativeTarget "mpseventsql" */ = { | ||
| 3807 | isa = XCConfigurationList; | ||
| 3808 | buildConfigurations = ( | ||
| 3809 | 2D07B9751636FC9900DB751B /* Debug */, | ||
| 3810 | 2D07B9761636FC9900DB751B /* Release */, | ||
| 3811 | 2D07B9771636FC9900DB751B /* WE */, | ||
| 3812 | ); | ||
| 3813 | defaultConfigurationIsVisible = 0; | ||
| 3814 | defaultConfigurationName = Release; | ||
| 3815 | }; | ||
| 3816 | 2D604BA216514B59003AAF46 /* Build configuration list for PBXNativeTarget "mpseventtxt" */ = { | ||
| 3817 | isa = XCConfigurationList; | ||
| 3818 | buildConfigurations = ( | ||
| 3819 | 2D604B9F16514B1A003AAF46 /* Debug */, | ||
| 3820 | 2D604BA016514B1A003AAF46 /* Release */, | ||
| 3821 | 2D604BA116514B1A003AAF46 /* WE */, | ||
| 3822 | ); | ||
| 3823 | defaultConfigurationIsVisible = 0; | ||
| 3824 | defaultConfigurationName = Release; | ||
| 3825 | }; | ||
| 3619 | 3104AFBC156D357B000A585A /* Build configuration list for PBXNativeTarget "apss" */ = { | 3826 | 3104AFBC156D357B000A585A /* Build configuration list for PBXNativeTarget "apss" */ = { |
| 3620 | isa = XCConfigurationList; | 3827 | isa = XCConfigurationList; |
| 3621 | buildConfigurations = ( | 3828 | buildConfigurations = ( |
| @@ -3816,7 +4023,7 @@ | |||
| 3816 | defaultConfigurationIsVisible = 0; | 4023 | defaultConfigurationIsVisible = 0; |
| 3817 | defaultConfigurationName = Release; | 4024 | defaultConfigurationName = Release; |
| 3818 | }; | 4025 | }; |
| 3819 | 3114A6CD156E9815001E0AA3 /* Build configuration list for PBXNativeTarget "eventcnv" */ = { | 4026 | 3114A6CD156E9815001E0AA3 /* Build configuration list for PBXNativeTarget "mpseventcnv" */ = { |
| 3820 | isa = XCConfigurationList; | 4027 | isa = XCConfigurationList; |
| 3821 | buildConfigurations = ( | 4028 | buildConfigurations = ( |
| 3822 | 3114A6CE156E9815001E0AA3 /* Debug */, | 4029 | 3114A6CE156E9815001E0AA3 /* Debug */, |
diff --git a/mps/code/mpscamc.h b/mps/code/mpscamc.h index 8d33ee4bb6a..710eea2f261 100644 --- a/mps/code/mpscamc.h +++ b/mps/code/mpscamc.h | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | extern mps_class_t mps_class_amc(void); | 12 | extern mps_class_t mps_class_amc(void); |
| 13 | extern mps_class_t mps_class_amcz(void); | 13 | extern mps_class_t mps_class_amcz(void); |
| 14 | 14 | ||
| 15 | extern void mps_amc_apply(mps_pool_t, | 15 | typedef void (*mps_amc_apply_stepper_t)(mps_addr_t, void *, size_t); |
| 16 | void (*)(mps_addr_t, void *, size_t), | 16 | extern void mps_amc_apply(mps_pool_t, mps_amc_apply_stepper_t, |
| 17 | void *, size_t); | 17 | void *, size_t); |
| 18 | 18 | ||
| 19 | #endif /* mpscamc_h */ | 19 | #endif /* mpscamc_h */ |
diff --git a/mps/code/mpscmfs.h b/mps/code/mpscmfs.h new file mode 100644 index 00000000000..4a46e10a84b --- /dev/null +++ b/mps/code/mpscmfs.h | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | /* mpscamfs.h: MEMORY POOL SYSTEM CLASS "MFS" | ||
| 2 | * | ||
| 3 | * $Id$ | ||
| 4 | * Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef mpscmfs_h | ||
| 8 | #define mpscmfs_h | ||
| 9 | |||
| 10 | #include "mps.h" | ||
| 11 | |||
| 12 | extern mps_class_t mps_class_mfs(void); | ||
| 13 | |||
| 14 | #endif /* mpscmfs_h */ | ||
| 15 | |||
| 16 | |||
| 17 | /* C. COPYRIGHT AND LICENSE | ||
| 18 | * | ||
| 19 | * Copyright (C) 2001-2012 Ravenbrook Limited <http://www.ravenbrook.com/>. | ||
| 20 | * All rights reserved. This is an open source license. Contact | ||
| 21 | * Ravenbrook for commercial licensing options. | ||
| 22 | * | ||
| 23 | * Redistribution and use in source and binary forms, with or without | ||
| 24 | * modification, are permitted provided that the following conditions are | ||
| 25 | * met: | ||
| 26 | * | ||
| 27 | * 1. Redistributions of source code must retain the above copyright | ||
| 28 | * notice, this list of conditions and the following disclaimer. | ||
| 29 | * | ||
| 30 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 31 | * notice, this list of conditions and the following disclaimer in the | ||
| 32 | * documentation and/or other materials provided with the distribution. | ||
| 33 | * | ||
| 34 | * 3. Redistributions in any form must be accompanied by information on how | ||
| 35 | * to obtain complete source code for this software and any accompanying | ||
| 36 | * software that uses this software. The source code must either be | ||
| 37 | * included in the distribution or be available for no more than the cost | ||
| 38 | * of distribution plus a nominal fee, and must be freely redistributable | ||
| 39 | * under reasonable conditions. For an executable file, complete source | ||
| 40 | * code means the source code for all modules it contains. It does not | ||
| 41 | * include source code for modules or files that typically accompany the | ||
| 42 | * major components of the operating system on which the executable file | ||
| 43 | * runs. | ||
| 44 | * | ||
| 45 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 46 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
| 47 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
| 48 | * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 49 | * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 50 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 51 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 52 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 53 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 54 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 55 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 56 | */ | ||
diff --git a/mps/code/mpscmvt.h b/mps/code/mpscmvt.h new file mode 100644 index 00000000000..be273177304 --- /dev/null +++ b/mps/code/mpscmvt.h | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | /* mpscmvt.h: MEMORY POOL SYSTEM CLASS "MVT" | ||
| 2 | * | ||
| 3 | * $Id$ | ||
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef mpscmvt_h | ||
| 8 | #define mpscmvt_h | ||
| 9 | |||
| 10 | #include "mps.h" | ||
| 11 | |||
| 12 | /* The mvt pool class has five extra parameters to mps_pool_create: | ||
| 13 | * mps_res_t mps_pool_create(mps_pool_t * pool, mps_arena_t arena, | ||
| 14 | * mps_class_t mvt_class, | ||
| 15 | * size_t minimum_size, | ||
| 16 | * size_t mean_size, | ||
| 17 | * size_t maximum_size, | ||
| 18 | * mps_count_t reserve_depth | ||
| 19 | * mps_count_t fragmentation_limit); | ||
| 20 | * minimum_, mean_, and maximum_size are the mimimum, mean, and | ||
| 21 | * maximum (typical) size of objects expected to be allocated in the | ||
| 22 | * pool. reserve_depth is a measure of the expected hysteresis of the | ||
| 23 | * object population. fragmentation_limit is a percentage (between 0 | ||
| 24 | * and 100): if the free space managed by the pool exceeds the | ||
| 25 | * specified percentage, the pool will resort to a "first fit" | ||
| 26 | * allocation policy. | ||
| 27 | */ | ||
| 28 | extern mps_class_t mps_class_mvt(void); | ||
| 29 | |||
| 30 | /* The mvt pool class supports two extensions to the pool protocol: | ||
| 31 | size and free_size. */ | ||
| 32 | extern size_t mps_mvt_free_size(mps_pool_t mps_pool); | ||
| 33 | extern size_t mps_mvt_size(mps_pool_t mps_pool); | ||
| 34 | |||
| 35 | #endif /* mpscmvt_h */ | ||
| 36 | |||
| 37 | |||
| 38 | /* C. COPYRIGHT AND LICENSE | ||
| 39 | * | ||
| 40 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. | ||
| 41 | * All rights reserved. This is an open source license. Contact | ||
| 42 | * Ravenbrook for commercial licensing options. | ||
| 43 | * | ||
| 44 | * Redistribution and use in source and binary forms, with or without | ||
| 45 | * modification, are permitted provided that the following conditions are | ||
| 46 | * met: | ||
| 47 | * | ||
| 48 | * 1. Redistributions of source code must retain the above copyright | ||
| 49 | * notice, this list of conditions and the following disclaimer. | ||
| 50 | * | ||
| 51 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 52 | * notice, this list of conditions and the following disclaimer in the | ||
| 53 | * documentation and/or other materials provided with the distribution. | ||
| 54 | * | ||
| 55 | * 3. Redistributions in any form must be accompanied by information on how | ||
| 56 | * to obtain complete source code for this software and any accompanying | ||
| 57 | * software that uses this software. The source code must either be | ||
| 58 | * included in the distribution or be available for no more than the cost | ||
| 59 | * of distribution plus a nominal fee, and must be freely redistributable | ||
| 60 | * under reasonable conditions. For an executable file, complete source | ||
| 61 | * code means the source code for all modules it contains. It does not | ||
| 62 | * include source code for modules or files that typically accompany the | ||
| 63 | * major components of the operating system on which the executable file | ||
| 64 | * runs. | ||
| 65 | * | ||
| 66 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 67 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
| 68 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
| 69 | * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 70 | * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 71 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 72 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 73 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 74 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 75 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 76 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 77 | */ | ||
diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 15bc692ee00..86855d5c606 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c | |||
| @@ -49,7 +49,6 @@ | |||
| 49 | 49 | ||
| 50 | #include "mpm.h" | 50 | #include "mpm.h" |
| 51 | #include "mps.h" | 51 | #include "mps.h" |
| 52 | #include "mpsavm.h" /* only for mps_space_create */ | ||
| 53 | #include "sac.h" | 52 | #include "sac.h" |
| 54 | #include "chain.h" | 53 | #include "chain.h" |
| 55 | 54 | ||
| @@ -941,8 +940,9 @@ mps_res_t (mps_ap_frame_pop)(mps_ap_t mps_ap, mps_frame_t frame) | |||
| 941 | 940 | ||
| 942 | /* mps_ap_fill -- called by mps_reserve when an AP hasn't enough arena | 941 | /* mps_ap_fill -- called by mps_reserve when an AP hasn't enough arena |
| 943 | * | 942 | * |
| 944 | * .ap.fill.internal: Note that mps_ap_fill should never be "called" | 943 | * .ap.fill.internal: mps_ap_fill is normally invoked by the |
| 945 | * directly by the client code. It is invoked by the mps_reserve macro. */ | 944 | * mps_reserve macro, but may be "called" directly by the client code |
| 945 | * if necessary. See <manual/topic/allocation> */ | ||
| 946 | 946 | ||
| 947 | mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size) | 947 | mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size) |
| 948 | { | 948 | { |
| @@ -1007,8 +1007,9 @@ mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *p_o, mps_ap_t mps_ap, | |||
| 1007 | 1007 | ||
| 1008 | /* mps_ap_trip -- called by mps_commit when an AP is tripped | 1008 | /* mps_ap_trip -- called by mps_commit when an AP is tripped |
| 1009 | * | 1009 | * |
| 1010 | * .ap.trip.internal: Note that mps_ap_trip should never be "called" | 1010 | * .ap.trip.internal: mps_ap_trip is normally invoked by the |
| 1011 | * directly by the client code. It is invoked by the mps_commit macro. */ | 1011 | * mps_commit macro, but may be "called" directly by the client code |
| 1012 | * if necessary. See <manual/topic/allocation> */ | ||
| 1012 | 1013 | ||
| 1013 | mps_bool_t mps_ap_trip(mps_ap_t mps_ap, mps_addr_t p, size_t size) | 1014 | mps_bool_t mps_ap_trip(mps_ap_t mps_ap, mps_addr_t p, size_t size) |
| 1014 | { | 1015 | { |
| @@ -1687,19 +1688,35 @@ mps_res_t mps_alert_collection_set(mps_arena_t arena, | |||
| 1687 | 1688 | ||
| 1688 | /* Telemetry */ | 1689 | /* Telemetry */ |
| 1689 | 1690 | ||
| 1691 | /* TODO: need to consider locking. See job003387, job003388. */ | ||
| 1692 | |||
| 1690 | mps_word_t mps_telemetry_control(mps_word_t resetMask, mps_word_t flipMask) | 1693 | mps_word_t mps_telemetry_control(mps_word_t resetMask, mps_word_t flipMask) |
| 1691 | { | 1694 | { |
| 1692 | /* Doesn't require locking and isn't arena-specific. */ | ||
| 1693 | return EventControl((Word)resetMask, (Word)flipMask); | 1695 | return EventControl((Word)resetMask, (Word)flipMask); |
| 1694 | } | 1696 | } |
| 1695 | 1697 | ||
| 1696 | mps_word_t mps_telemetry_intern(const char *label) | 1698 | void mps_telemetry_set(mps_word_t setMask) |
| 1699 | { | ||
| 1700 | EventControl((Word)setMask, (Word)setMask); | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | void mps_telemetry_reset(mps_word_t resetMask) | ||
| 1704 | { | ||
| 1705 | EventControl((Word)resetMask, 0); | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | mps_word_t mps_telemetry_get(void) | ||
| 1709 | { | ||
| 1710 | return EventControl(0, 0); | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | mps_label_t mps_telemetry_intern(const char *label) | ||
| 1697 | { | 1714 | { |
| 1698 | AVER(label != NULL); | 1715 | AVER(label != NULL); |
| 1699 | return (mps_word_t)EventInternString(label); | 1716 | return (mps_label_t)EventInternString(label); |
| 1700 | } | 1717 | } |
| 1701 | 1718 | ||
| 1702 | void mps_telemetry_label(mps_addr_t addr, mps_word_t intern_id) | 1719 | void mps_telemetry_label(mps_addr_t addr, mps_label_t intern_id) |
| 1703 | { | 1720 | { |
| 1704 | EventLabelAddr((Addr)addr, (Word)intern_id); | 1721 | EventLabelAddr((Addr)addr, (Word)intern_id); |
| 1705 | } | 1722 | } |
diff --git a/mps/code/mpsliban.c b/mps/code/mpsliban.c index 8abab586319..deca56d630f 100644 --- a/mps/code/mpsliban.c +++ b/mps/code/mpsliban.c | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | #include <stdlib.h> | 36 | #include <stdlib.h> |
| 37 | #include <stdio.h> | 37 | #include <stdio.h> |
| 38 | #include <string.h> | 38 | #include <string.h> |
| 39 | #include <ctype.h> | ||
| 40 | #include <assert.h> | ||
| 39 | 41 | ||
| 40 | 42 | ||
| 41 | int mps_lib_get_EOF(void) | 43 | int mps_lib_get_EOF(void) |
| @@ -92,15 +94,35 @@ int (mps_lib_memcmp)(const void *s1, const void *s2, size_t n) | |||
| 92 | 94 | ||
| 93 | /* @@@@ Platform specific conversion? */ | 95 | /* @@@@ Platform specific conversion? */ |
| 94 | /* See http://devworld.apple.com/dev/techsupport/insidemac/OSUtilities/OSUtilities-94.html#MARKER-9-32 */ | 96 | /* See http://devworld.apple.com/dev/techsupport/insidemac/OSUtilities/OSUtilities-94.html#MARKER-9-32 */ |
| 97 | |||
| 98 | /* If your platform has a low-resolution clock(), and there are | ||
| 99 | * higher-resolution clocks readily available, then using one of those | ||
| 100 | * will improve MPS scheduling decisions and the quality of telemetry | ||
| 101 | * output. For instance, with getrusage(): | ||
| 102 | * | ||
| 103 | * #include <sys/resource.h> | ||
| 104 | * struct rusage s; | ||
| 105 | * int res = getrusage(RUSAGE_SELF, &s); | ||
| 106 | * if (res != 0) { | ||
| 107 | * ... | ||
| 108 | * } | ||
| 109 | * return ((mps_clock_t)s.ru_utime.tv_sec) * 1000000 + s.ru_utime.tv_usec; | ||
| 110 | */ | ||
| 111 | |||
| 95 | mps_clock_t mps_clock(void) | 112 | mps_clock_t mps_clock(void) |
| 96 | { | 113 | { |
| 97 | return (unsigned long)clock(); | 114 | /* The clock values need to fit in mps_clock_t. If your platform |
| 115 | has a very wide clock type, trim or truncate it. */ | ||
| 116 | assert(sizeof(mps_clock_t) >= sizeof(clock_t)); | ||
| 117 | |||
| 118 | return (mps_clock_t)clock(); | ||
| 98 | } | 119 | } |
| 99 | 120 | ||
| 100 | 121 | ||
| 101 | mps_clock_t mps_clocks_per_sec(void) | 122 | mps_clock_t mps_clocks_per_sec(void) |
| 102 | { | 123 | { |
| 103 | return (unsigned long)CLOCKS_PER_SEC; | 124 | /* must correspond to whatever mps_clock() does */ |
| 125 | return (mps_clock_t)CLOCKS_PER_SEC; | ||
| 104 | } | 126 | } |
| 105 | 127 | ||
| 106 | 128 | ||
| @@ -112,6 +134,20 @@ mps_clock_t mps_clocks_per_sec(void) | |||
| 112 | #pragma warning( disable : 4996 ) | 134 | #pragma warning( disable : 4996 ) |
| 113 | #endif | 135 | #endif |
| 114 | 136 | ||
| 137 | /* Simple case-insensitive string comparison */ | ||
| 138 | static int striequal(const char *s0, const char *s1) | ||
| 139 | { | ||
| 140 | int c; | ||
| 141 | do { | ||
| 142 | c = *s0; | ||
| 143 | if (tolower(c) != tolower(*s1)) /* note: works for '\0' */ | ||
| 144 | return 0; | ||
| 145 | ++s0; | ||
| 146 | ++s1; | ||
| 147 | } while (c != '\0'); | ||
| 148 | return 1; | ||
| 149 | } | ||
| 150 | |||
| 115 | unsigned long mps_lib_telemetry_control(void) | 151 | unsigned long mps_lib_telemetry_control(void) |
| 116 | { | 152 | { |
| 117 | char *s; | 153 | char *s; |
| @@ -130,14 +166,20 @@ unsigned long mps_lib_telemetry_control(void) | |||
| 130 | if (mask != 0) | 166 | if (mask != 0) |
| 131 | return mask; | 167 | return mask; |
| 132 | 168 | ||
| 133 | /* Split the value at spaces and try to patch the words against the names | 169 | /* copy the envar to a buffer so we can mess with it. */ |
| 134 | of event kinds, enabling them if there's a match. */ | ||
| 135 | strncpy(buf, s, sizeof(buf) - 1); | 170 | strncpy(buf, s, sizeof(buf) - 1); |
| 136 | buf[sizeof(buf) - 1] = '\0'; | 171 | buf[sizeof(buf) - 1] = '\0'; |
| 172 | |||
| 173 | /* Split the value at spaces and try to match the words against the names | ||
| 174 | of event kinds, enabling them if there's a match. */ | ||
| 137 | for (word = strtok(buf, sep); word != NULL; word = strtok(NULL, sep)) { | 175 | for (word = strtok(buf, sep); word != NULL; word = strtok(NULL, sep)) { |
| 138 | #define TELEMATCH(X, rowName, rowDoc) \ | 176 | if (striequal(word, "all")) { |
| 139 | if (strcmp(word, #rowName) == 0) \ | 177 | mask = (unsigned long)-1; |
| 140 | mask |= (1ul << EventKind##rowName); | 178 | return mask; |
| 179 | } | ||
| 180 | #define TELEMATCH(X, name, rowDoc) \ | ||
| 181 | if (striequal(word, #name)) \ | ||
| 182 | mask |= (1ul << EventKind##name); | ||
| 141 | EventKindENUM(TELEMATCH, X) | 183 | EventKindENUM(TELEMATCH, X) |
| 142 | } | 184 | } |
| 143 | 185 | ||
diff --git a/mps/code/mpstd.h b/mps/code/mpstd.h index 0345810b723..ad695bc23a9 100644 --- a/mps/code/mpstd.h +++ b/mps/code/mpstd.h | |||
| @@ -97,7 +97,6 @@ | |||
| 97 | #define MPS_ARCH_I6 | 97 | #define MPS_ARCH_I6 |
| 98 | #define MPS_BUILD_MV | 98 | #define MPS_BUILD_MV |
| 99 | #define MPS_T_WORD unsigned __int64 | 99 | #define MPS_T_WORD unsigned __int64 |
| 100 | #define MPS_T_LONGEST __int64 | ||
| 101 | #define MPS_T_ULONGEST unsigned __int64 | 100 | #define MPS_T_ULONGEST unsigned __int64 |
| 102 | #define MPS_WORD_WIDTH 64 | 101 | #define MPS_WORD_WIDTH 64 |
| 103 | #define MPS_WORD_SHIFT 6 | 102 | #define MPS_WORD_SHIFT 6 |
diff --git a/mps/code/mv2test.c b/mps/code/mv2test.c index d8c80ba0d6a..5568f9dc713 100644 --- a/mps/code/mv2test.c +++ b/mps/code/mv2test.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "mpstd.h" | 10 | #include "mpstd.h" |
| 11 | #include <time.h> | 11 | #include <time.h> |
| 12 | 12 | ||
| 13 | #include "mpscmv2.h" | 13 | #include "mpscmvt.h" |
| 14 | #include "mps.h" | 14 | #include "mps.h" |
| 15 | 15 | ||
| 16 | typedef MPS_T_WORD mps_count_t; /* machine word (target dep.) */ | 16 | typedef MPS_T_WORD mps_count_t; /* machine word (target dep.) */ |
diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 1617c2e4f0a..71f7f8f6fe6 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* poolamc.c: AUTOMATIC MOSTLY-COPYING MEMORY POOL CLASS | 1 | /* poolamc.c: AUTOMATIC MOSTLY-COPYING MEMORY POOL CLASS |
| 2 | * | 2 | * |
| 3 | * $Id$ | 3 | * $Id$ |
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | 4 | * Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license. |
| 5 | * Portions copyright (C) 2002 Global Graphics Software. | 5 | * Portions copyright (C) 2002 Global Graphics Software. |
| 6 | * | 6 | * |
| 7 | * .sources: <design/poolamc/>. | 7 | * .sources: <design/poolamc/>. |
| @@ -1672,7 +1672,10 @@ static void amcFixInPlace(Pool pool, Seg seg, ScanState ss, Ref *refIO) | |||
| 1672 | return; | 1672 | return; |
| 1673 | } | 1673 | } |
| 1674 | SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); | 1674 | SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); |
| 1675 | SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); | 1675 | /* AMCZ segments don't contain references and so don't need to */ |
| 1676 | /* become grey */ | ||
| 1677 | if(SegRankSet(seg) != RankSetEMPTY) | ||
| 1678 | SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); | ||
| 1676 | } | 1679 | } |
| 1677 | 1680 | ||
| 1678 | 1681 | ||
| @@ -1792,7 +1795,8 @@ Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 1792 | /* Segment only needs greying if there are new traces for */ | 1795 | /* Segment only needs greying if there are new traces for */ |
| 1793 | /* which we are nailing. */ | 1796 | /* which we are nailing. */ |
| 1794 | if(!TraceSetSub(ss->traces, SegNailed(seg))) { | 1797 | if(!TraceSetSub(ss->traces, SegNailed(seg))) { |
| 1795 | SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); | 1798 | if(SegRankSet(seg) != RankSetEMPTY) /* not for AMCZ */ |
| 1799 | SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); | ||
| 1796 | SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); | 1800 | SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); |
| 1797 | } | 1801 | } |
| 1798 | res = ResOK; | 1802 | res = ResOK; |
| @@ -1826,7 +1830,9 @@ Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 1826 | 1830 | ||
| 1827 | /* Since we're moving an object from one segment to another, */ | 1831 | /* Since we're moving an object from one segment to another, */ |
| 1828 | /* union the greyness and the summaries together. */ | 1832 | /* union the greyness and the summaries together. */ |
| 1829 | grey = TraceSetUnion(ss->traces, SegGrey(seg)); | 1833 | grey = SegGrey(seg); |
| 1834 | if(SegRankSet(seg) != RankSetEMPTY) /* not for AMCZ */ | ||
| 1835 | grey = TraceSetUnion(grey, ss->traces); | ||
| 1830 | SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey)); | 1836 | SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey)); |
| 1831 | SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg))); | 1837 | SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg))); |
| 1832 | 1838 | ||
| @@ -1930,7 +1936,8 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 1930 | /* Segment only needs greying if there are new traces for */ | 1936 | /* Segment only needs greying if there are new traces for */ |
| 1931 | /* which we are nailing. */ | 1937 | /* which we are nailing. */ |
| 1932 | if(!TraceSetSub(ss->traces, SegNailed(seg))) { | 1938 | if(!TraceSetSub(ss->traces, SegNailed(seg))) { |
| 1933 | SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); | 1939 | if(SegRankSet(seg) != RankSetEMPTY) /* not for AMCZ */ |
| 1940 | SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); | ||
| 1934 | SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); | 1941 | SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); |
| 1935 | } | 1942 | } |
| 1936 | res = ResOK; | 1943 | res = ResOK; |
| @@ -1967,7 +1974,9 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 1967 | 1974 | ||
| 1968 | /* Since we're moving an object from one segment to another, */ | 1975 | /* Since we're moving an object from one segment to another, */ |
| 1969 | /* union the greyness and the summaries together. */ | 1976 | /* union the greyness and the summaries together. */ |
| 1970 | grey = TraceSetUnion(ss->traces, SegGrey(seg)); | 1977 | grey = SegGrey(seg); |
| 1978 | if(SegRankSet(seg) != RankSetEMPTY) /* not for AMCZ */ | ||
| 1979 | grey = TraceSetUnion(grey, ss->traces); | ||
| 1971 | SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey)); | 1980 | SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey)); |
| 1972 | SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg))); | 1981 | SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg))); |
| 1973 | 1982 | ||
| @@ -2429,7 +2438,7 @@ mps_class_t mps_class_amcz(void) | |||
| 2429 | */ | 2438 | */ |
| 2430 | 2439 | ||
| 2431 | typedef struct mps_amc_apply_closure_s { | 2440 | typedef struct mps_amc_apply_closure_s { |
| 2432 | void (*f)(mps_addr_t object, void *p, size_t s); | 2441 | mps_amc_apply_stepper_t f; |
| 2433 | void *p; | 2442 | void *p; |
| 2434 | size_t s; | 2443 | size_t s; |
| 2435 | } mps_amc_apply_closure_s; | 2444 | } mps_amc_apply_closure_s; |
| @@ -2449,7 +2458,7 @@ static void mps_amc_apply_iter(Addr addr, Format format, Pool pool, | |||
| 2449 | } | 2458 | } |
| 2450 | 2459 | ||
| 2451 | void mps_amc_apply(mps_pool_t mps_pool, | 2460 | void mps_amc_apply(mps_pool_t mps_pool, |
| 2452 | void (*f)(mps_addr_t object, void *p, size_t s), | 2461 | mps_amc_apply_stepper_t f, |
| 2453 | void *p, size_t s) | 2462 | void *p, size_t s) |
| 2454 | { | 2463 | { |
| 2455 | Pool pool = (Pool)mps_pool; | 2464 | Pool pool = (Pool)mps_pool; |
| @@ -2499,7 +2508,7 @@ static Bool AMCCheck(AMC amc) | |||
| 2499 | 2508 | ||
| 2500 | /* C. COPYRIGHT AND LICENSE | 2509 | /* C. COPYRIGHT AND LICENSE |
| 2501 | * | 2510 | * |
| 2502 | * Copyright (C) 2001-2002, 2008 Ravenbrook Limited <http://www.ravenbrook.com/>. | 2511 | * Copyright (C) 2001-2012 Ravenbrook Limited <http://www.ravenbrook.com/>. |
| 2503 | * All rights reserved. This is an open source license. Contact | 2512 | * All rights reserved. This is an open source license. Contact |
| 2504 | * Ravenbrook for commercial licensing options. | 2513 | * Ravenbrook for commercial licensing options. |
| 2505 | * | 2514 | * |
diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 82044e37589..ad4140a4479 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* poolmfs.c: MANUAL FIXED SMALL UNIT POOL | 1 | /* poolmfs.c: MANUAL FIXED SMALL UNIT POOL |
| 2 | * | 2 | * |
| 3 | * $Id$ | 3 | * $Id$ |
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | 4 | * Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license. |
| 5 | * | 5 | * |
| 6 | * This is the implementation of the MFS pool class. | 6 | * This is the implementation of the MFS pool class. |
| 7 | * | 7 | * |
| @@ -32,6 +32,7 @@ | |||
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | 34 | ||
| 35 | #include "mpscmfs.h" | ||
| 35 | #include "poolmfs.h" | 36 | #include "poolmfs.h" |
| 36 | #include "mpm.h" | 37 | #include "mpm.h" |
| 37 | 38 | ||
| @@ -282,6 +283,12 @@ PoolClass PoolClassMFS(void) | |||
| 282 | } | 283 | } |
| 283 | 284 | ||
| 284 | 285 | ||
| 286 | mps_class_t mps_class_mfs(void) | ||
| 287 | { | ||
| 288 | return (mps_class_t)PoolClassMFS(); | ||
| 289 | } | ||
| 290 | |||
| 291 | |||
| 285 | Bool MFSCheck(MFS mfs) | 292 | Bool MFSCheck(MFS mfs) |
| 286 | { | 293 | { |
| 287 | Arena arena; | 294 | Arena arena; |
| @@ -305,7 +312,7 @@ Bool MFSCheck(MFS mfs) | |||
| 305 | 312 | ||
| 306 | /* C. COPYRIGHT AND LICENSE | 313 | /* C. COPYRIGHT AND LICENSE |
| 307 | * | 314 | * |
| 308 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. | 315 | * Copyright (C) 2001-2012 Ravenbrook Limited <http://www.ravenbrook.com/>. |
| 309 | * All rights reserved. This is an open source license. Contact | 316 | * All rights reserved. This is an open source license. Contact |
| 310 | * Ravenbrook for commercial licensing options. | 317 | * Ravenbrook for commercial licensing options. |
| 311 | * | 318 | * |
diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index 9401f568b03..dc10ce990a8 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include "mpm.h" | 12 | #include "mpm.h" |
| 13 | #include "poolmv2.h" | 13 | #include "poolmv2.h" |
| 14 | #include "mpscmv2.h" | 14 | #include "mpscmvt.h" |
| 15 | #include "abq.h" | 15 | #include "abq.h" |
| 16 | #include "cbs.h" | 16 | #include "cbs.h" |
| 17 | #include "meter.h" | 17 | #include "meter.h" |
diff --git a/mps/code/seg.c b/mps/code/seg.c index f12b9fdcbc8..c544a8063e0 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c | |||
| @@ -267,7 +267,7 @@ void SegSetGrey(Seg seg, TraceSet grey) | |||
| 267 | { | 267 | { |
| 268 | AVERT(Seg, seg); | 268 | AVERT(Seg, seg); |
| 269 | AVER(TraceSetCheck(grey)); | 269 | AVER(TraceSetCheck(grey)); |
| 270 | AVER(SegRankSet(seg) != RankSetEMPTY); | 270 | AVER(grey == TraceSetEMPTY || SegRankSet(seg) != RankSetEMPTY); |
| 271 | 271 | ||
| 272 | /* Don't dispatch to the class method if there's no actual change in | 272 | /* Don't dispatch to the class method if there's no actual change in |
| 273 | greyness, or if the segment doesn't contain any references. */ | 273 | greyness, or if the segment doesn't contain any references. */ |
diff --git a/mps/code/testlib.h b/mps/code/testlib.h index 2bcd50e7c18..e3a11c34139 100644 --- a/mps/code/testlib.h +++ b/mps/code/testlib.h | |||
| @@ -74,31 +74,41 @@ | |||
| 74 | 74 | ||
| 75 | /* ulongest_t -- longest unsigned integer type | 75 | /* ulongest_t -- longest unsigned integer type |
| 76 | * | 76 | * |
| 77 | * Define a longest unsigned integer type for testing and printing. We'd | 77 | * Define a longest unsigned integer type for testing, scanning, and |
| 78 | * like to use C99's uintmax_t and PRIuMAX here, but the MPS is in C89 | 78 | * printing. We'd like to use C99's uintmax_t and PRIuMAX here, but |
| 79 | * and C99 isn't supported by Microsoft. | 79 | * the MPS is in C89 and C99 isn't supported by Microsoft. |
| 80 | * | 80 | * |
| 81 | * We avoid using the ones defined in mpstd.h because we want the tests to | 81 | * We avoid using the types defined in mpstd.h because we want the |
| 82 | * root out any incompatible assumptions by breaking. | 82 | * tests to root out any incompatible assumptions by breaking. |
| 83 | */ | 83 | */ |
| 84 | 84 | ||
| 85 | #if defined(MPS_ARCH_I6) | ||
| 86 | #define PRIwWORD "16" | ||
| 87 | #elif defined(MPS_ARCH_I3) | ||
| 88 | #define PRIwWORD "8" | ||
| 89 | #else | ||
| 90 | #error "How many beans make five?" | ||
| 91 | #endif | ||
| 92 | |||
| 85 | #ifdef MPS_PF_W3I6MV | 93 | #ifdef MPS_PF_W3I6MV |
| 86 | #define PRIuLONGEST "llu" | 94 | #define PRIuLONGEST "llu" |
| 87 | #define SCNuLONGEST "llu" | 95 | #define SCNuLONGEST "llu" |
| 96 | #define SCNXLONGEST "llX" | ||
| 88 | #define PRIXLONGEST "llX" | 97 | #define PRIXLONGEST "llX" |
| 89 | #define PRIwWORD "16" | ||
| 90 | typedef unsigned long long ulongest_t; | 98 | typedef unsigned long long ulongest_t; |
| 91 | typedef long long longest_t; | 99 | typedef long long longest_t; |
| 92 | #define MPS_WORD_CONST(n) (n##ull) | 100 | #define MPS_WORD_CONST(n) (n##ull) |
| 93 | #else | 101 | #else |
| 94 | #define PRIuLONGEST "lu" | 102 | #define PRIuLONGEST "lu" |
| 95 | #define SCNuLONGEST "lu" | 103 | #define SCNuLONGEST "lu" |
| 104 | #define SCNXLONGEST "lX" | ||
| 96 | #define PRIXLONGEST "lX" | 105 | #define PRIXLONGEST "lX" |
| 97 | #define PRIwWORD "8" | ||
| 98 | typedef unsigned long ulongest_t; | 106 | typedef unsigned long ulongest_t; |
| 99 | typedef long longest_t; | 107 | typedef long longest_t; |
| 100 | #define MPS_WORD_CONST(n) (n##ul) | 108 | #define MPS_WORD_CONST(n) (n##ul) |
| 101 | #endif | 109 | #endif |
| 110 | |||
| 111 | |||
| 102 | #define PRIXPTR "0"PRIwWORD PRIXLONGEST | 112 | #define PRIXPTR "0"PRIwWORD PRIXLONGEST |
| 103 | 113 | ||
| 104 | 114 | ||
diff --git a/mps/code/w3i3mv.nmk b/mps/code/w3i3mv.nmk index ebe971e1626..671b1b5847f 100644 --- a/mps/code/w3i3mv.nmk +++ b/mps/code/w3i3mv.nmk | |||
| @@ -50,6 +50,7 @@ TESTLIB = <testlib> | |||
| 50 | 50 | ||
| 51 | !IF "$(VARIETY)" == "hot" | 51 | !IF "$(VARIETY)" == "hot" |
| 52 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) | 52 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) |
| 53 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFHOT) $(CFLAGSSQLPOST) | ||
| 53 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) | 54 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) |
| 54 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) | 55 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) |
| 55 | MPMOBJ0 = $(MPM:<=w3i3mv\hot\) | 56 | MPMOBJ0 = $(MPM:<=w3i3mv\hot\) |
| @@ -67,6 +68,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\hot\) | |||
| 67 | 68 | ||
| 68 | !ELSEIF "$(VARIETY)" == "di" | 69 | !ELSEIF "$(VARIETY)" == "di" |
| 69 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFDI) $(CFLAGSCOMMONPOST) | 70 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFDI) $(CFLAGSCOMMONPOST) |
| 71 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFDI) $(CFLAGSSQLPOST) | ||
| 70 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFDI) | 72 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFDI) |
| 71 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSDI) | 73 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSDI) |
| 72 | MPMOBJ0 = $(MPM:<=w3i3mv\di\) | 74 | MPMOBJ0 = $(MPM:<=w3i3mv\di\) |
| @@ -84,6 +86,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\di\) | |||
| 84 | 86 | ||
| 85 | !ELSEIF "$(VARIETY)" == "cool" | 87 | !ELSEIF "$(VARIETY)" == "cool" |
| 86 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) | 88 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) |
| 89 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFCOOL) $(CFLAGSSQLPOST) | ||
| 87 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) | 90 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) |
| 88 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) | 91 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) |
| 89 | MPMOBJ0 = $(MPM:<=w3i3mv\cool\) | 92 | MPMOBJ0 = $(MPM:<=w3i3mv\cool\) |
| @@ -101,6 +104,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\cool\) | |||
| 101 | 104 | ||
| 102 | !ELSEIF "$(VARIETY)" == "ti" | 105 | !ELSEIF "$(VARIETY)" == "ti" |
| 103 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFTI) $(CFLAGSCOMMONPOST) | 106 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFTI) $(CFLAGSCOMMONPOST) |
| 107 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFTI) $(CFLAGSSQLPOST) | ||
| 104 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFTI) | 108 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFTI) |
| 105 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSTI) | 109 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSTI) |
| 106 | MPMOBJ0 = $(MPM:<=w3i3mv\ti\) | 110 | MPMOBJ0 = $(MPM:<=w3i3mv\ti\) |
| @@ -118,6 +122,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\ti\) | |||
| 118 | 122 | ||
| 119 | !ELSEIF "$(VARIETY)" == "rash" | 123 | !ELSEIF "$(VARIETY)" == "rash" |
| 120 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) | 124 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) |
| 125 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFRASH) $(CFLAGSSQLPOST) | ||
| 121 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) | 126 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) |
| 122 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) | 127 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) |
| 123 | MPMOBJ0 = $(MPM:<=w3i3mv\rash\) | 128 | MPMOBJ0 = $(MPM:<=w3i3mv\rash\) |
diff --git a/mps/code/w3i6mv.nmk b/mps/code/w3i6mv.nmk index 729509f05dc..75aae0aaa4d 100644 --- a/mps/code/w3i6mv.nmk +++ b/mps/code/w3i6mv.nmk | |||
| @@ -50,6 +50,7 @@ TESTLIB = <testlib> | |||
| 50 | 50 | ||
| 51 | !IF "$(VARIETY)" == "hot" | 51 | !IF "$(VARIETY)" == "hot" |
| 52 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) | 52 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) |
| 53 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFHOT) $(CFLAGSSQLPOST) | ||
| 53 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) | 54 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) |
| 54 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) | 55 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) |
| 55 | MPMOBJ0 = $(MPM:<=w3i6mv\hot\) | 56 | MPMOBJ0 = $(MPM:<=w3i6mv\hot\) |
| @@ -67,6 +68,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\hot\) | |||
| 67 | 68 | ||
| 68 | !ELSEIF "$(VARIETY)" == "di" | 69 | !ELSEIF "$(VARIETY)" == "di" |
| 69 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFDI) $(CFLAGSCOMMONPOST) | 70 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFDI) $(CFLAGSCOMMONPOST) |
| 71 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFDI) $(CFLAGSSQLPOST) | ||
| 70 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFDI) | 72 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFDI) |
| 71 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSDI) | 73 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSDI) |
| 72 | MPMOBJ0 = $(MPM:<=w3i6mv\di\) | 74 | MPMOBJ0 = $(MPM:<=w3i6mv\di\) |
| @@ -84,6 +86,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\di\) | |||
| 84 | 86 | ||
| 85 | !ELSEIF "$(VARIETY)" == "cool" | 87 | !ELSEIF "$(VARIETY)" == "cool" |
| 86 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) | 88 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) |
| 89 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFCOOL) $(CFLAGSSQLPOST) | ||
| 87 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) | 90 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) |
| 88 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) | 91 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) |
| 89 | MPMOBJ0 = $(MPM:<=w3i6mv\cool\) | 92 | MPMOBJ0 = $(MPM:<=w3i6mv\cool\) |
| @@ -101,6 +104,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\cool\) | |||
| 101 | 104 | ||
| 102 | !ELSEIF "$(VARIETY)" == "ti" | 105 | !ELSEIF "$(VARIETY)" == "ti" |
| 103 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFTI) $(CFLAGSCOMMONPOST) | 106 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFTI) $(CFLAGSCOMMONPOST) |
| 107 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFCOOL) $(CFLAGSSQLPOST) | ||
| 104 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFTI) | 108 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFTI) |
| 105 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSTI) | 109 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSTI) |
| 106 | MPMOBJ0 = $(MPM:<=w3i6mv\ti\) | 110 | MPMOBJ0 = $(MPM:<=w3i6mv\ti\) |
| @@ -118,6 +122,7 @@ TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\ti\) | |||
| 118 | 122 | ||
| 119 | !ELSEIF "$(VARIETY)" == "rash" | 123 | !ELSEIF "$(VARIETY)" == "rash" |
| 120 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) | 124 | CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) |
| 125 | CFLAGSSQL=$(CFLAGSSQLPRE) $(CFRASH) $(CFLAGSSQLPOST) | ||
| 121 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) | 126 | LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) |
| 122 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) | 127 | LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) |
| 123 | MPMOBJ0 = $(MPM:<=w3i6mv\rash\) | 128 | MPMOBJ0 = $(MPM:<=w3i6mv\rash\) |