@agoric/xsnap 0.14.3-u14.0 → 0.14.3-u16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +3 -3
  2. package/api.js +4 -2
  3. package/build.env +1 -1
  4. package/moddable/modules/data/base64/base64.js +28 -0
  5. package/moddable/modules/data/base64/manifest.json +11 -0
  6. package/moddable/modules/data/base64/modBase64.c +188 -0
  7. package/moddable/modules/data/binaryMessage/BinaryMessage.js +106 -0
  8. package/moddable/modules/data/crc/crc.c +205 -0
  9. package/moddable/modules/data/crc/crc.js +36 -0
  10. package/moddable/modules/data/crc/manifest.json +8 -0
  11. package/moddable/modules/data/hex/hex.js +28 -0
  12. package/moddable/modules/data/hex/manifest.json +11 -0
  13. package/moddable/modules/data/hex/modHex.c +139 -0
  14. package/moddable/modules/data/logical/logical.js +32 -0
  15. package/moddable/modules/data/logical/modLogical.c +98 -0
  16. package/moddable/modules/data/qrcode/manifest.json +9 -0
  17. package/moddable/modules/data/qrcode/qrcode.c +93 -0
  18. package/moddable/modules/data/qrcode/qrcode.js +23 -0
  19. package/moddable/modules/data/qrcode/qrcodegen.c +1025 -0
  20. package/moddable/modules/data/qrcode/qrcodegen.h +267 -0
  21. package/moddable/modules/data/text/decoder/manifest.json +8 -0
  22. package/moddable/modules/data/text/decoder/textdecoder.c +480 -0
  23. package/moddable/modules/data/text/decoder/textdecoder.js +27 -0
  24. package/moddable/modules/data/text/encoder/manifest.json +8 -0
  25. package/moddable/modules/data/text/encoder/textencoder.c +232 -0
  26. package/moddable/modules/data/text/encoder/textencoder.js +24 -0
  27. package/moddable/modules/data/tinyint/tinyint.c +150 -0
  28. package/moddable/modules/data/tinyint/tinyint.js +53 -0
  29. package/moddable/modules/data/url/manifest.json +17 -0
  30. package/moddable/modules/data/url/url.c +1959 -0
  31. package/moddable/modules/data/url/url.js +210 -0
  32. package/moddable/modules/data/wavreader/manifest.json +8 -0
  33. package/moddable/modules/data/wavreader/wavreader.js +128 -0
  34. package/moddable/modules/data/zlib/deflate.c +161 -0
  35. package/moddable/modules/data/zlib/deflate.js +63 -0
  36. package/moddable/modules/data/zlib/inflate.c +145 -0
  37. package/moddable/modules/data/zlib/inflate.js +66 -0
  38. package/moddable/modules/data/zlib/manifest_deflate.json +9 -0
  39. package/moddable/modules/data/zlib/manifest_inflate.json +9 -0
  40. package/moddable/modules/data/zlib/miniz.c +4924 -0
  41. package/moddable/xs/includes/xs.d.ts +73 -0
  42. package/moddable/xs/includes/xs.h +1533 -0
  43. package/moddable/xs/includes/xsmc.h +206 -0
  44. package/moddable/xs/makefiles/lin/makefile +33 -0
  45. package/moddable/xs/makefiles/lin/xsc.mk +118 -0
  46. package/moddable/xs/makefiles/lin/xsid.mk +90 -0
  47. package/moddable/xs/makefiles/lin/xsl.mk +168 -0
  48. package/moddable/xs/makefiles/lin/xst.mk +201 -0
  49. package/moddable/xs/makefiles/mac/makefile +33 -0
  50. package/moddable/xs/makefiles/mac/xsc.mk +130 -0
  51. package/moddable/xs/makefiles/mac/xsid.mk +102 -0
  52. package/moddable/xs/makefiles/mac/xsl.mk +177 -0
  53. package/moddable/xs/makefiles/mac/xst.mk +203 -0
  54. package/moddable/xs/makefiles/mac/xst_no_asan.txt +52 -0
  55. package/moddable/xs/makefiles/win/build.bat +26 -0
  56. package/moddable/xs/makefiles/win/xsc.mak +142 -0
  57. package/moddable/xs/makefiles/win/xsid.mak +113 -0
  58. package/moddable/xs/makefiles/win/xsl.mak +186 -0
  59. package/moddable/xs/makefiles/win/xst.mak +195 -0
  60. package/moddable/xs/platforms/lin_xs.h +99 -0
  61. package/moddable/xs/platforms/mac_xs.h +97 -0
  62. package/moddable/xs/platforms/wasm_xs.h +79 -0
  63. package/moddable/xs/platforms/win_xs.h +104 -0
  64. package/moddable/xs/platforms/xsHost.h +63 -0
  65. package/moddable/xs/platforms/xsPlatform.h +618 -0
  66. package/moddable/xs/sources/xsAPI.c +2555 -0
  67. package/moddable/xs/sources/xsAll.c +294 -0
  68. package/moddable/xs/sources/xsAll.h +2741 -0
  69. package/moddable/xs/sources/xsArguments.c +222 -0
  70. package/moddable/xs/sources/xsArray.c +2657 -0
  71. package/moddable/xs/sources/xsAtomics.c +844 -0
  72. package/moddable/xs/sources/xsBigInt.c +1859 -0
  73. package/moddable/xs/sources/xsBoolean.c +109 -0
  74. package/moddable/xs/sources/xsCode.c +4493 -0
  75. package/moddable/xs/sources/xsCommon.c +1710 -0
  76. package/moddable/xs/sources/xsCommon.h +1142 -0
  77. package/moddable/xs/sources/xsDataView.c +2890 -0
  78. package/moddable/xs/sources/xsDate.c +1541 -0
  79. package/moddable/xs/sources/xsDebug.c +2710 -0
  80. package/moddable/xs/sources/xsDefaults.c +134 -0
  81. package/moddable/xs/sources/xsError.c +353 -0
  82. package/moddable/xs/sources/xsFunction.c +776 -0
  83. package/moddable/xs/sources/xsGenerator.c +865 -0
  84. package/moddable/xs/sources/xsGlobal.c +839 -0
  85. package/moddable/xs/sources/xsJSON.c +1091 -0
  86. package/moddable/xs/sources/xsLexical.c +1969 -0
  87. package/moddable/xs/sources/xsLockdown.c +933 -0
  88. package/moddable/xs/sources/xsMapSet.c +1649 -0
  89. package/moddable/xs/sources/xsMarshall.c +1020 -0
  90. package/moddable/xs/sources/xsMath.c +624 -0
  91. package/moddable/xs/sources/xsMemory.c +1941 -0
  92. package/moddable/xs/sources/xsModule.c +3101 -0
  93. package/moddable/xs/sources/xsNumber.c +560 -0
  94. package/moddable/xs/sources/xsObject.c +1102 -0
  95. package/moddable/xs/sources/xsPlatforms.c +480 -0
  96. package/moddable/xs/sources/xsProfile.c +577 -0
  97. package/moddable/xs/sources/xsPromise.c +1199 -0
  98. package/moddable/xs/sources/xsProperty.c +636 -0
  99. package/moddable/xs/sources/xsProxy.c +1014 -0
  100. package/moddable/xs/sources/xsRegExp.c +1168 -0
  101. package/moddable/xs/sources/xsRun.c +4889 -0
  102. package/moddable/xs/sources/xsScope.c +1293 -0
  103. package/moddable/xs/sources/xsScript.c +288 -0
  104. package/moddable/xs/sources/xsScript.h +1186 -0
  105. package/moddable/xs/sources/xsSnapshot.c +2161 -0
  106. package/moddable/xs/sources/xsSnapshot.h +51 -0
  107. package/moddable/xs/sources/xsSourceMap.c +218 -0
  108. package/moddable/xs/sources/xsString.c +3332 -0
  109. package/moddable/xs/sources/xsSymbol.c +503 -0
  110. package/moddable/xs/sources/xsSyntaxical.c +4193 -0
  111. package/moddable/xs/sources/xsTree.c +1893 -0
  112. package/moddable/xs/sources/xsType.c +1488 -0
  113. package/moddable/xs/sources/xsdtoa.c +6672 -0
  114. package/moddable/xs/sources/xsmc.c +340 -0
  115. package/moddable/xs/sources/xsre.c +7578 -0
  116. package/package.json +37 -20
  117. package/scripts/get_xsnap_version.sh +14 -0
  118. package/scripts/test-package.sh +21 -0
  119. package/src/avaAssertXS.js +6 -2
  120. package/src/avaHandler.cjs +2 -5
  121. package/src/avaXS.js +7 -8
  122. package/src/build.js +161 -28
  123. package/src/replay.js +0 -3
  124. package/src/xsnap.js +105 -91
  125. package/src/xsrepl.js +2 -3
  126. package/xsnap-native/xsnap/makefiles/lin/makefile +10 -0
  127. package/xsnap-native/xsnap/makefiles/lin/xsnap-worker.mk +156 -0
  128. package/xsnap-native/xsnap/makefiles/lin/xsnap.mk +144 -0
  129. package/xsnap-native/xsnap/makefiles/mac/makefile +10 -0
  130. package/xsnap-native/xsnap/makefiles/mac/xsnap-worker.mk +165 -0
  131. package/xsnap-native/xsnap/makefiles/mac/xsnap.mk +153 -0
  132. package/xsnap-native/xsnap/sources/xsnap-worker.c +1008 -0
  133. package/xsnap-native/xsnap/sources/xsnap.c +717 -0
  134. package/xsnap-native/xsnap/sources/xsnap.h +142 -0
  135. package/xsnap-native/xsnap/sources/xsnapPlatform.c +1501 -0
  136. package/xsnap-native/xsnap/sources/xsnapPlatform.h +105 -0
  137. package/CHANGELOG.md +0 -654
@@ -0,0 +1,1501 @@
1
+ #include "xsAll.h"
2
+ #include "xsScript.h"
3
+ #include "xsSnapshot.h"
4
+
5
+ #ifndef mxReserveChunkSize
6
+ #define mxReserveChunkSize 1024 * 1024 * 1024
7
+ #endif
8
+
9
+
10
+ mxExport void fxRunModuleFile(txMachine* the, txString path);
11
+ mxExport void fxRunProgramFile(txMachine* the, txString path);
12
+ mxExport void fxRunLoop(txMachine* the);
13
+
14
+ mxExport void fxClearTimer(txMachine* the);
15
+ mxExport void fxSetTimer(txMachine* the, txNumber interval, txBoolean repeat);
16
+
17
+ mxExport void fxVersion(txString theBuffer, txSize theSize);
18
+ #ifdef mxMetering
19
+ mxExport txUnsigned fxGetCurrentMeter(txMachine* the);
20
+ mxExport void fxSetCurrentMeter(txMachine* the, txUnsigned value);
21
+ #endif
22
+
23
+ typedef struct sxJob txJob;
24
+
25
+ struct sxJob {
26
+ txJob* next;
27
+ txMachine* the;
28
+ txNumber when;
29
+ txSlot self;
30
+ txSlot function;
31
+ txSlot argument;
32
+ txNumber interval;
33
+ };
34
+
35
+ static void fxDestroyTimer(void* data);
36
+ static void fxMarkTimer(txMachine* the, void* it, txMarkRoot markRoot);
37
+
38
+ static txHostHooks gxTimerHooks = {
39
+ fxDestroyTimer,
40
+ fxMarkTimer
41
+ };
42
+
43
+ void fxClearTimer(txMachine* the)
44
+ {
45
+ txHostHooks* hooks = fxGetHostHooks(the, mxArgv(0));
46
+ if (hooks == &gxTimerHooks) {
47
+ txJob* job = fxGetHostData(the, mxArgv(0));
48
+ if (job) {
49
+ fxForget(the, &job->self);
50
+ fxSetHostData(the, mxArgv(0), NULL);
51
+ job->the = NULL;
52
+ }
53
+ }
54
+ else
55
+ mxTypeError("no timer");
56
+ }
57
+
58
+ void fxDestroyTimer(void* data)
59
+ {
60
+ }
61
+
62
+ void fxMarkTimer(txMachine* the, void* it, txMarkRoot markRoot)
63
+ {
64
+ txJob* job = it;
65
+ if (job) {
66
+ (*markRoot)(the, &job->function);
67
+ (*markRoot)(the, &job->argument);
68
+ }
69
+ }
70
+
71
+ void fxSetTimer(txMachine* the, txNumber interval, txBoolean repeat)
72
+ {
73
+ c_timeval tv;
74
+ txJob* job;
75
+ txJob** address = (txJob**)&(the->timerJobs);
76
+ while ((job = *address))
77
+ address = &(job->next);
78
+ job = *address = malloc(sizeof(txJob));
79
+ c_memset(job, 0, sizeof(txJob));
80
+ job->the = the;
81
+ c_gettimeofday(&tv, NULL);
82
+ if (repeat)
83
+ job->interval = interval;
84
+ job->when = ((txNumber)(tv.tv_sec) * 1000.0) + ((txNumber)(tv.tv_usec) / 1000.0) + interval;
85
+ fxNewHostObject(the, NULL);
86
+ mxPull(job->self);
87
+ job->function = *mxArgv(0);
88
+ if (mxArgc > 2)
89
+ job->argument = *mxArgv(2);
90
+ else
91
+ job->argument = mxUndefined;
92
+ fxSetHostData(the, &job->self, job);
93
+ fxSetHostHooks(the, &job->self, &gxTimerHooks);
94
+ fxRemember(the, &job->self);
95
+ fxAccess(the, &job->self);
96
+ *mxResult = the->scratch;
97
+ }
98
+
99
+ /* PLATFORM */
100
+
101
+ static void fxFulfillModuleFile(txMachine* the);
102
+ static void fxRejectModuleFile(txMachine* the);
103
+ static txScript* fxLoadScript(txMachine* the, txString path, txUnsigned flags);
104
+
105
+ void fxAbort(txMachine* the, int status)
106
+ {
107
+ switch (status) {
108
+ case XS_STACK_OVERFLOW_EXIT:
109
+ fxReport(the, "stack overflow\n");
110
+ #ifdef mxDebug
111
+ fxDebugger(the, (char *)__FILE__, __LINE__);
112
+ #endif
113
+ the->abortStatus = status;
114
+ fxExitToHost(the);
115
+ break;
116
+ case XS_NOT_ENOUGH_MEMORY_EXIT:
117
+ fxReport(the, "memory full\n");
118
+ #ifdef mxDebug
119
+ fxDebugger(the, (char *)__FILE__, __LINE__);
120
+ #endif
121
+ the->abortStatus = status;
122
+ fxExitToHost(the);
123
+ break;
124
+ case XS_NO_MORE_KEYS_EXIT:
125
+ fxReport(the, "not enough keys\n");
126
+ #ifdef mxDebug
127
+ fxDebugger(the, (char *)__FILE__, __LINE__);
128
+ #endif
129
+ the->abortStatus = status;
130
+ fxExitToHost(the);
131
+ break;
132
+ case XS_TOO_MUCH_COMPUTATION_EXIT:
133
+ fxReport(the, "too much computation\n");
134
+ #ifdef mxDebug
135
+ fxDebugger(the, (char *)__FILE__, __LINE__);
136
+ #endif
137
+ the->abortStatus = status;
138
+ fxExitToHost(the);
139
+ break;
140
+ case XS_UNHANDLED_EXCEPTION_EXIT: {
141
+ mxPush(mxException);
142
+ txSlot *exc = the->stack;
143
+ fxReport(the, "unhandled exception: %s\n", fxToString(the, &mxException));
144
+ mxException = mxUndefined;
145
+ mxTry(the) {
146
+ mxOverflow(-8);
147
+ mxPush(mxGlobal);
148
+ fxGetID(the, fxFindName(the, "console"));
149
+ fxCallID(the, fxFindName(the, "error"));
150
+ mxPushStringC("Unhandled exception:");
151
+ mxPushSlot(exc);
152
+ fxRunCount(the, 2);
153
+ mxPop();
154
+ }
155
+ mxCatch(the) {
156
+ fprintf(stderr, "Unhandled exception %s\n", fxToString(the, exc));
157
+ }
158
+ the->abortStatus = status;
159
+ fxExitToHost(the);
160
+ mxPop();
161
+ break;
162
+ }
163
+ case XS_UNHANDLED_REJECTION_EXIT: {
164
+ mxPush(mxException);
165
+ txSlot *exc = the->stack;
166
+ fxReport(the, "unhandled rejection: %s\n", fxToString(the, &mxException));
167
+ mxException = mxUndefined;
168
+ mxTry(the) {
169
+ mxOverflow(-8);
170
+ mxPush(mxGlobal);
171
+ fxGetID(the, fxFindName(the, "console"));
172
+ fxCallID(the, fxFindName(the, "error"));
173
+ mxPushStringC("UnhandledPromiseRejectionWarning:");
174
+ mxPushSlot(exc);
175
+ fxRunCount(the, 2);
176
+ mxPop();
177
+ }
178
+ mxCatch(the) {
179
+ fprintf(stderr, "Unhandled exception %s\n", fxToString(the, exc));
180
+ }
181
+ break;
182
+ }
183
+ default:
184
+ fxReport(the, "fxAbort(%d) - %s\n", status, fxToString(the, &mxException));
185
+ #ifdef mxDebug
186
+ fxDebugger(the, (char *)__FILE__, __LINE__);
187
+ #endif
188
+ the->abortStatus = status;
189
+ fxExitToHost(the);
190
+ break;
191
+ }
192
+ }
193
+
194
+ static txSize gxPageSize = 0;
195
+
196
+ static txSize fxRoundToPageSize(txMachine* the, txSize size)
197
+ {
198
+ txSize modulo;
199
+ if (!gxPageSize) {
200
+ #if mxWindows
201
+ SYSTEM_INFO info;
202
+ GetSystemInfo(&info);
203
+ gxPageSize = (txSize)info.dwAllocationGranularity;
204
+ #else
205
+ gxPageSize = getpagesize();
206
+ #endif
207
+ }
208
+ modulo = size & (gxPageSize - 1);
209
+ if (modulo)
210
+ size = fxAddChunkSizes(the, size, gxPageSize - modulo);
211
+ return size;
212
+ }
213
+
214
+ static void adjustSpaceMeter(txMachine* the, txSize theSize)
215
+ {
216
+ size_t previous = the->allocatedSpace;
217
+ the->allocatedSpace += theSize;
218
+ if (the->allocatedSpace > the->allocationLimit ||
219
+ // overflow?
220
+ the->allocatedSpace < previous) {
221
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
222
+ }
223
+ }
224
+
225
+ void* fxAllocateChunks(txMachine* the, txSize size)
226
+ {
227
+ txByte* base;
228
+ txByte* result;
229
+ adjustSpaceMeter(the, size);
230
+ if (the->firstBlock) {
231
+ base = (txByte*)(the->firstBlock);
232
+ result = (txByte*)(the->firstBlock->limit);
233
+ }
234
+ else
235
+ #if mxWindows
236
+ base = result = VirtualAlloc(NULL, mxReserveChunkSize, MEM_RESERVE, PAGE_READWRITE);
237
+ #else
238
+ base = result = mmap(NULL, mxReserveChunkSize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
239
+ #endif
240
+ if (result) {
241
+ txSize current = (txSize)(result - base);
242
+ size = fxAddChunkSizes(the, current, size);
243
+ current = fxRoundToPageSize(the, current);
244
+ size = fxRoundToPageSize(the, size);
245
+ #if mxWindows
246
+ if (!VirtualAlloc(base + current, size - current, MEM_COMMIT, PAGE_READWRITE))
247
+ #else
248
+ if (size > mxReserveChunkSize)
249
+ result = NULL;
250
+ else if (mprotect(base + current, size - current, PROT_READ | PROT_WRITE))
251
+ #endif
252
+ result = NULL;
253
+ }
254
+ return result;
255
+ }
256
+
257
+ void fxFreeChunks(txMachine* the, void* theChunks)
258
+ {
259
+ #if mxWindows
260
+ VirtualFree(theChunks, 0, MEM_RELEASE);
261
+ #else
262
+ munmap(theChunks, mxReserveChunkSize);
263
+ #endif
264
+ }
265
+
266
+ txSlot* fxAllocateSlots(txMachine* the, txSize theCount)
267
+ {
268
+ // fprintf(stderr, "fxAllocateSlots(%u) * %d = %ld\n", theCount, sizeof(txSlot), theCount * sizeof(txSlot));
269
+ adjustSpaceMeter(the, theCount * sizeof(txSlot));
270
+ return (txSlot*)c_malloc(theCount * sizeof(txSlot));
271
+ }
272
+
273
+ void fxFreeSlots(txMachine* the, void* theSlots)
274
+ {
275
+ c_free(theSlots);
276
+ }
277
+
278
+ void fxCreateMachinePlatform(txMachine* the)
279
+ {
280
+ #ifdef mxDebug
281
+ #ifdef mxInstrument
282
+ #else
283
+ the->connection = mxNoSocket;
284
+ #endif
285
+ #endif
286
+ // Original 10x strategy:
287
+ // SLOGFILE=out.slog agoric start local-chain
288
+ // jq -s '.|.[]|.dr[2].allocate' < out.slog|grep -v null|sort -u | sort -nr
289
+ // int MB = 1024 * 1024;
290
+ // int measured_max = 30 * MB;
291
+ // the->allocationLimit = 10 * measured_max;
292
+
293
+ size_t GB = 1024 * 1024 * 1024;
294
+ the->allocationLimit = 2 * GB;
295
+ }
296
+
297
+ void fxDeleteMachinePlatform(txMachine* the)
298
+ {
299
+ }
300
+
301
+ void fxQueuePromiseJobs(txMachine* the)
302
+ {
303
+ the->promiseJobs = 1;
304
+ }
305
+
306
+ void fxRunDebugger(txMachine* the)
307
+ {
308
+ #ifdef mxDebug
309
+ fxDebugCommand(the);
310
+ #endif
311
+ }
312
+
313
+ void fxRunLoop(txMachine* the)
314
+ {
315
+ c_timeval tv;
316
+ txNumber when;
317
+ txJob* job;
318
+ txJob** address;
319
+ for (;;) {
320
+ while (the->promiseJobs) {
321
+ the->promiseJobs = 0;
322
+ fxRunPromiseJobs(the);
323
+ }
324
+ fxEndJob(the);
325
+ if (the->promiseJobs) {
326
+ continue;
327
+ }
328
+ c_gettimeofday(&tv, NULL);
329
+ when = ((txNumber)(tv.tv_sec) * 1000.0) + ((txNumber)(tv.tv_usec) / 1000.0);
330
+ address = (txJob**)&(the->timerJobs);
331
+ if (!*address)
332
+ break;
333
+ while ((job = *address)) {
334
+ txMachine* the = job->the;
335
+ if (the) {
336
+ if (job->when <= when) {
337
+ fxBeginHost(the);
338
+ mxTry(the) {
339
+ mxPushUndefined();
340
+ mxPush(job->function);
341
+ mxCall();
342
+ mxPush(job->argument);
343
+ mxRunCount(1);
344
+ mxPop();
345
+ if (job->the) {
346
+ if (job->interval) {
347
+ job->when += job->interval;
348
+ }
349
+ else {
350
+ fxAccess(the, &job->self);
351
+ *mxResult = the->scratch;
352
+ fxForget(the, &job->self);
353
+ fxSetHostData(the, mxResult, NULL);
354
+ job->the = NULL;
355
+ }
356
+ }
357
+ }
358
+ mxCatch(the) {
359
+ fxAccess(the, &job->self);
360
+ *mxResult = the->scratch;
361
+ fxForget(the, &job->self);
362
+ fxSetHostData(the, mxResult, NULL);
363
+ job->the = NULL;
364
+ fxAbort(the, XS_UNHANDLED_EXCEPTION_EXIT);
365
+ }
366
+ fxEndHost(the);
367
+ break; // to run promise jobs queued by the timer in the same "tick"
368
+ }
369
+ address = &(job->next);
370
+ }
371
+ else {
372
+ *address = job->next;
373
+ c_free(job);
374
+ }
375
+ }
376
+ }
377
+ fxCheckUnhandledRejections(the, 1);
378
+ }
379
+
380
+ void fxFulfillModuleFile(txMachine* the)
381
+ {
382
+ mxException = mxUndefined;
383
+ }
384
+
385
+ void fxRejectModuleFile(txMachine* the)
386
+ {
387
+ mxException = *mxArgv(0);
388
+ }
389
+
390
+ void fxRunModuleFile(txMachine* the, txString path)
391
+ {
392
+ txSlot* realm = mxProgram.value.reference->next->value.module.realm;
393
+ mxPushStringC(path);
394
+ fxRunImport(the, realm, XS_NO_ID);
395
+ mxDub();
396
+ fxGetID(the, mxID(_then));
397
+ mxCall();
398
+ fxNewHostFunction(the, fxFulfillModuleFile, 1, XS_NO_ID, XS_NO_ID);
399
+ fxNewHostFunction(the, fxRejectModuleFile, 1, XS_NO_ID, XS_NO_ID);
400
+ mxRunCount(2);
401
+ mxPop();
402
+ }
403
+
404
+ void fxRunProgramFile(txMachine* the, txString path)
405
+ {
406
+ txSlot* realm = mxProgram.value.reference->next->value.module.realm;
407
+ txScript* script = fxLoadScript(the, path, mxProgramFlag | mxDebugFlag);
408
+ mxModuleInstanceInternal(mxProgram.value.reference)->value.module.id = fxID(the, path);
409
+ fxRunScript(the, script, mxRealmGlobal(realm), C_NULL, mxRealmClosures(realm)->value.reference, C_NULL, mxProgram.value.reference);
410
+ mxPullSlot(mxResult);
411
+ }
412
+
413
+ txID fxFindModule(txMachine* the, txSlot* realm, txID moduleID, txSlot* slot)
414
+ {
415
+ char name[C_PATH_MAX];
416
+ char path[C_PATH_MAX];
417
+ txInteger dot = 0;
418
+ txString slash;
419
+ fxToStringBuffer(the, slot, name, sizeof(name));
420
+ if (name[0] == '.') {
421
+ if (name[1] == '/') {
422
+ dot = 1;
423
+ }
424
+ else if ((name[1] == '.') && (name[2] == '/')) {
425
+ dot = 2;
426
+ }
427
+ }
428
+ if (dot) {
429
+ if (moduleID == XS_NO_ID)
430
+ return XS_NO_ID;
431
+ c_strncpy(path, fxGetKeyName(the, moduleID), C_PATH_MAX - 1);
432
+ path[C_PATH_MAX - 1] = 0;
433
+ slash = c_strrchr(path, mxSeparator);
434
+ if (!slash)
435
+ return XS_NO_ID;
436
+ if (dot == 2) {
437
+ *slash = 0;
438
+ slash = c_strrchr(path, mxSeparator);
439
+ if (!slash)
440
+ return XS_NO_ID;
441
+ }
442
+ #if mxWindows
443
+ {
444
+ char c;
445
+ char* s = name;
446
+ while ((c = *s)) {
447
+ if (c == '/')
448
+ *s = '\\';
449
+ s++;
450
+ }
451
+ }
452
+ #endif
453
+ }
454
+ else
455
+ slash = path;
456
+ *slash = 0;
457
+ if ((c_strlen(path) + c_strlen(name + dot)) >= sizeof(path))
458
+ mxRangeError("path too long");
459
+ c_strcat(path, name + dot);
460
+ return fxNewNameC(the, path);
461
+ }
462
+
463
+ void fxLoadModule(txMachine* the, txSlot* module, txID moduleID)
464
+ {
465
+ char path[C_PATH_MAX];
466
+ char real[C_PATH_MAX];
467
+ txScript* script;
468
+ #ifdef mxDebug
469
+ txUnsigned flags = mxDebugFlag;
470
+ #else
471
+ txUnsigned flags = 0;
472
+ #endif
473
+ c_strncpy(path, fxGetKeyName(the, moduleID), C_PATH_MAX - 1);
474
+ path[C_PATH_MAX - 1] = 0;
475
+ if (c_realpath(path, real)) {
476
+ script = fxLoadScript(the, real, flags);
477
+ if (script)
478
+ fxResolveModule(the, module, moduleID, script, C_NULL, C_NULL);
479
+ }
480
+ }
481
+
482
+ txScript* fxLoadScript(txMachine* the, txString path, txUnsigned flags)
483
+ {
484
+ txParser _parser;
485
+ txParser* parser = &_parser;
486
+ txParserJump jump;
487
+ FILE* file = NULL;
488
+ txString name = NULL;
489
+ char map[C_PATH_MAX];
490
+ txScript* script = NULL;
491
+ fxInitializeParser(parser, the, the->parserBufferSize, the->parserTableModulo);
492
+ parser->firstJump = &jump;
493
+ file = fopen(path, "r");
494
+ if (c_setjmp(jump.jmp_buf) == 0) {
495
+ mxParserThrowElse(file);
496
+ parser->path = fxNewParserSymbol(parser, path);
497
+ fxParserTree(parser, file, (txGetter)fgetc, flags, &name);
498
+ fclose(file);
499
+ file = NULL;
500
+ if (name) {
501
+ mxParserThrowElse(c_realpath(fxCombinePath(parser, path, name), map));
502
+ parser->path = fxNewParserSymbol(parser, map);
503
+ file = fopen(map, "r");
504
+ mxParserThrowElse(file);
505
+ fxParserSourceMap(parser, file, (txGetter)fgetc, flags, &name);
506
+ fclose(file);
507
+ file = NULL;
508
+ if ((parser->errorCount == 0) && name) {
509
+ mxParserThrowElse(c_realpath(fxCombinePath(parser, map, name), map));
510
+ parser->path = fxNewParserSymbol(parser, map);
511
+ }
512
+ }
513
+ fxParserHoist(parser);
514
+ fxParserBind(parser);
515
+ script = fxParserCode(parser);
516
+ }
517
+ if (file)
518
+ fclose(file);
519
+ #ifdef mxInstrument
520
+ if (the->peakParserSize < parser->total)
521
+ the->peakParserSize = parser->total;
522
+ #endif
523
+ fxTerminateParser(parser);
524
+ return script;
525
+ }
526
+
527
+ /* DEBUG */
528
+
529
+ #ifdef mxDebug
530
+
531
+ #ifdef mxInstrument
532
+
533
+ void fxConnect(txMachine* the)
534
+ {
535
+ }
536
+
537
+ void fxDisconnect(txMachine* the)
538
+ {
539
+ }
540
+
541
+ txBoolean fxIsConnected(txMachine* the)
542
+ {
543
+ return 1;
544
+ }
545
+
546
+ txBoolean fxIsReadable(txMachine* the)
547
+ {
548
+ return 0;
549
+ }
550
+
551
+ void fxReceive(txMachine* the)
552
+ {
553
+ ssize_t count;
554
+ again:
555
+ count = read(5, the->debugBuffer, sizeof(the->debugBuffer) - 1);
556
+ if (count < 0) {
557
+ if (errno == EINTR)
558
+ goto again;
559
+ the->debugOffset = 0;
560
+ }
561
+ else
562
+ the->debugOffset = count;
563
+ the->debugBuffer[the->debugOffset] = 0;
564
+ }
565
+
566
+ void fxSend(txMachine* the, txBoolean more)
567
+ {
568
+ ssize_t count;
569
+ again:
570
+ count = write(6, the->echoBuffer, the->echoOffset);
571
+ if (count < 0) {
572
+ if (errno == EINTR)
573
+ goto again;
574
+ }
575
+ }
576
+
577
+ #else
578
+
579
+ void fxConnect(txMachine* the)
580
+ {
581
+ char name[256];
582
+ char* colon;
583
+ int port;
584
+ struct sockaddr_in address;
585
+ #if mxWindows
586
+ if (GetEnvironmentVariable("XSBUG_HOST", name, sizeof(name))) {
587
+ #else
588
+ colon = getenv("XSBUG_HOST");
589
+ if ((colon) && (c_strlen(colon) + 1 < sizeof(name))) {
590
+ c_strcpy(name, colon);
591
+ #endif
592
+ colon = strchr(name, ':');
593
+ if (colon == NULL)
594
+ port = 5002;
595
+ else {
596
+ *colon = 0;
597
+ colon++;
598
+ port = strtol(colon, NULL, 10);
599
+ }
600
+ }
601
+ else {
602
+ // Require XSBUG_HOST to be set for debugging.
603
+ return;
604
+ // strcpy(name, "localhost");
605
+ // port = 5002;
606
+ }
607
+ memset(&address, 0, sizeof(address));
608
+ address.sin_family = AF_INET;
609
+ address.sin_addr.s_addr = inet_addr(name);
610
+ if (address.sin_addr.s_addr == INADDR_NONE) {
611
+ struct hostent *host = gethostbyname(name);
612
+ if (!host)
613
+ return;
614
+ memcpy(&(address.sin_addr), host->h_addr, host->h_length);
615
+ }
616
+ address.sin_port = htons(port);
617
+ #if mxWindows
618
+ {
619
+ WSADATA wsaData;
620
+ unsigned long flag;
621
+ if (WSAStartup(0x202, &wsaData) == SOCKET_ERROR)
622
+ return;
623
+ the->connection = socket(AF_INET, SOCK_STREAM, 0);
624
+ if (the->connection == INVALID_SOCKET)
625
+ return;
626
+ flag = 1;
627
+ ioctlsocket(the->connection, FIONBIO, &flag);
628
+ if (connect(the->connection, (struct sockaddr*)&address, sizeof(address)) == SOCKET_ERROR) {
629
+ if (WSAEWOULDBLOCK == WSAGetLastError()) {
630
+ fd_set fds;
631
+ struct timeval timeout = { 2, 0 }; // 2 seconds, 0 micro-seconds
632
+ FD_ZERO(&fds);
633
+ FD_SET(the->connection, &fds);
634
+ if (select(0, NULL, &fds, NULL, &timeout) == 0)
635
+ goto bail;
636
+ if (!FD_ISSET(the->connection, &fds))
637
+ goto bail;
638
+ }
639
+ else
640
+ goto bail;
641
+ }
642
+ flag = 0;
643
+ ioctlsocket(the->connection, FIONBIO, &flag);
644
+ }
645
+ #else
646
+ {
647
+ int flag;
648
+ the->connection = socket(AF_INET, SOCK_STREAM, 0);
649
+ if (the->connection <= 0)
650
+ goto bail;
651
+ c_signal(SIGPIPE, SIG_IGN);
652
+ #if mxMacOSX
653
+ {
654
+ int set = 1;
655
+ setsockopt(the->connection, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
656
+ }
657
+ #endif
658
+ flag = fcntl(the->connection, F_GETFL, 0);
659
+ fcntl(the->connection, F_SETFL, flag | O_NONBLOCK);
660
+ if (connect(the->connection, (struct sockaddr*)&address, sizeof(address)) < 0) {
661
+ if (errno == EINPROGRESS) {
662
+ fd_set fds;
663
+ struct timeval timeout = { 2, 0 }; // 2 seconds, 0 micro-seconds
664
+ int error = 0;
665
+ unsigned int length = sizeof(error);
666
+ FD_ZERO(&fds);
667
+ FD_SET(the->connection, &fds);
668
+ if (select(the->connection + 1, NULL, &fds, NULL, &timeout) == 0)
669
+ goto bail;
670
+ if (!FD_ISSET(the->connection, &fds))
671
+ goto bail;
672
+ if (getsockopt(the->connection, SOL_SOCKET, SO_ERROR, &error, &length) < 0)
673
+ goto bail;
674
+ if (error)
675
+ goto bail;
676
+ }
677
+ else
678
+ goto bail;
679
+ }
680
+ fcntl(the->connection, F_SETFL, flag);
681
+ c_signal(SIGPIPE, SIG_DFL);
682
+ }
683
+ #endif
684
+ return;
685
+ bail:
686
+ fxDisconnect(the);
687
+ }
688
+
689
+ void fxDisconnect(txMachine* the)
690
+ {
691
+ #if mxWindows
692
+ if (the->connection != INVALID_SOCKET) {
693
+ closesocket(the->connection);
694
+ the->connection = INVALID_SOCKET;
695
+ }
696
+ WSACleanup();
697
+ #else
698
+ if (the->connection >= 0) {
699
+ close(the->connection);
700
+ the->connection = mxNoSocket;
701
+ }
702
+ #endif
703
+ }
704
+
705
+ txBoolean fxIsConnected(txMachine* the)
706
+ {
707
+ return (the->connection != mxNoSocket) ? 1 : 0;
708
+ }
709
+
710
+ txBoolean fxIsReadable(txMachine* the)
711
+ {
712
+ return 0;
713
+ }
714
+
715
+ void fxReceive(txMachine* the)
716
+ {
717
+ int count;
718
+ if (the->connection != mxNoSocket) {
719
+ #if mxWindows
720
+ count = recv(the->connection, the->debugBuffer, sizeof(the->debugBuffer) - 1, 0);
721
+ if (count < 0)
722
+ fxDisconnect(the);
723
+ else
724
+ the->debugOffset = count;
725
+ #else
726
+ again:
727
+ count = read(the->connection, the->debugBuffer, sizeof(the->debugBuffer) - 1);
728
+ if (count < 0) {
729
+ if (errno == EINTR)
730
+ goto again;
731
+ else
732
+ fxDisconnect(the);
733
+ }
734
+ else
735
+ the->debugOffset = count;
736
+ #endif
737
+ }
738
+ the->debugBuffer[the->debugOffset] = 0;
739
+ }
740
+
741
+ void fxSend(txMachine* the, txBoolean more)
742
+ {
743
+ if (the->connection != mxNoSocket) {
744
+ #if mxWindows
745
+ if (send(the->connection, the->echoBuffer, the->echoOffset, 0) <= 0)
746
+ fxDisconnect(the);
747
+ #else
748
+ again:
749
+ if (write(the->connection, the->echoBuffer, the->echoOffset) <= 0) {
750
+ if (errno == EINTR)
751
+ goto again;
752
+ else
753
+ fxDisconnect(the);
754
+ }
755
+ #endif
756
+ }
757
+ }
758
+
759
+ #endif /* mxInstrument */
760
+
761
+ #endif /* mxDebug */
762
+
763
+ void fxVersion(txString theBuffer, txSize theSize)
764
+ {
765
+ c_snprintf(theBuffer, theSize, "%d.%d.%d", XS_MAJOR_VERSION, XS_MINOR_VERSION, XS_PATCH_VERSION);
766
+ }
767
+
768
+ #ifdef mxMetering
769
+ txUnsigned fxGetCurrentMeter(txMachine* the)
770
+ {
771
+ return the->meterIndex;
772
+ }
773
+
774
+ void fxSetCurrentMeter(txMachine* the, txUnsigned value)
775
+ {
776
+ the->meterIndex = value;
777
+ }
778
+ #endif
779
+
780
+ txSize fxGetCurrentHeapCount(txMachine* the)
781
+ {
782
+ return the->currentHeapCount;
783
+ }
784
+
785
+ extern void fxDumpSnapshot(txMachine* the, txSnapshot* snapshot);
786
+
787
+ typedef void (*txDumpChunk)(FILE* file, txByte* data, txSize size);
788
+
789
+ #define mxThrowIf(_ERROR) { if (_ERROR) { snapshot->error = _ERROR; fxJump(the); } }
790
+
791
+ static void fxDumpChunk(txSlot* slot, txByte* block);
792
+ static void fxDumpChunkAddress(FILE* file, void* address);
793
+ static void fxDumpChunkArray(FILE* file, txByte* data, txSize size);
794
+ static void fxDumpChunkData(FILE* file, txByte* data, txSize size);
795
+ static void fxDumpChunkString(FILE* file, txByte* data, txSize size);
796
+ static void fxDumpChunkTable(FILE* file, txByte* data, txSize size);
797
+ static void fxDumpID(FILE* file, txID id);
798
+ static void fxDumpNumber(FILE* file, txNumber value);
799
+ static void fxDumpSlot(FILE* file, txSlot* slot);
800
+ static void fxDumpSlotAddress(FILE* file, void* address);
801
+ static void fxDumpSlotTable(FILE* file, txByte* buffer, txSize size);
802
+
803
+ void fxDumpSnapshot(txMachine* the, txSnapshot* snapshot)
804
+ {
805
+ Atom atom;
806
+ txByte byte;
807
+ txCreation creation;
808
+ txID profileID;
809
+ txInteger tag;
810
+ Atom blockAtom;
811
+ txByte* block = C_NULL;
812
+ // txByte* blockLimit;
813
+ Atom heapAtom;
814
+ txSlot* heap = C_NULL;
815
+ txSlot* heapLimit;
816
+ Atom stackAtom;
817
+ txSlot* stack = C_NULL;
818
+ txSlot* stackLimit;
819
+
820
+ txSlot* current;
821
+
822
+ txByte* buffer = C_NULL;
823
+ txByte* address;
824
+ txSize offset, size;
825
+ txString string;
826
+
827
+ mxTry(the) {
828
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
829
+ atom.atomSize = ntohl(atom.atomSize) - 8;
830
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
831
+
832
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
833
+ atom.atomSize = ntohl(atom.atomSize) - 8;
834
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
835
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
836
+ fprintf(stderr, "\t%d.", byte);
837
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
838
+ fprintf(stderr, "%d.", byte);
839
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
840
+ fprintf(stderr, "%d ", byte);
841
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
842
+ fprintf(stderr, "(%d)\n", byte);
843
+
844
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
845
+ atom.atomSize = ntohl(atom.atomSize) - 8;
846
+ buffer = c_malloc(atom.atomSize);
847
+ mxThrowIf(buffer == C_NULL);
848
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
849
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
850
+ fprintf(stderr, "\t%s\n", (txString)buffer);
851
+ c_free(buffer);
852
+
853
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
854
+ atom.atomSize = ntohl(atom.atomSize) - 8;
855
+ mxThrowIf((*snapshot->read)(snapshot->stream, &creation, sizeof(txCreation)));
856
+ mxThrowIf((*snapshot->read)(snapshot->stream, &profileID, sizeof(txID)));
857
+ mxThrowIf((*snapshot->read)(snapshot->stream, &tag, sizeof(txInteger)));
858
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
859
+ fprintf(stderr, "\tinitialChunkSize: %d\n", creation.initialChunkSize);
860
+ fprintf(stderr, "\tincrementalChunkSize: %d\n", creation.incrementalChunkSize);
861
+ fprintf(stderr, "\tinitialHeapCount: %d\n", creation.initialHeapCount);
862
+ fprintf(stderr, "\tincrementalHeapCount: %d\n", creation.incrementalHeapCount);
863
+ fprintf(stderr, "\tstackCount: %d\n", creation.stackCount);
864
+ fprintf(stderr, "\tinitialKeyCount: %d\n", creation.initialKeyCount);
865
+ fprintf(stderr, "\tincrementalKeyCount: %d\n", creation.incrementalKeyCount);
866
+ fprintf(stderr, "\tnameModulo: %d\n", creation.nameModulo);
867
+ fprintf(stderr, "\tsymbolModulo: %d\n", creation.symbolModulo);
868
+ fprintf(stderr, "\tparserBufferSize: %d\n", creation.parserBufferSize);
869
+ fprintf(stderr, "\tparserTableModulo: %d\n", creation.parserTableModulo);
870
+ fprintf(stderr, "\tstaticSize: %d\n", creation.staticSize);
871
+ fprintf(stderr, "\tprofileID: %d\n", profileID);
872
+ fprintf(stderr, "\ttag: %d\n", tag);
873
+
874
+ mxThrowIf((*snapshot->read)(snapshot->stream, &blockAtom, sizeof(Atom)));
875
+ blockAtom.atomSize = ntohl(blockAtom.atomSize) - 8;
876
+ block = c_malloc(blockAtom.atomSize);
877
+ mxThrowIf(block == C_NULL);
878
+ mxThrowIf((*snapshot->read)(snapshot->stream, block, blockAtom.atomSize));
879
+ // blockLimit = block + blockAtom.atomSize;
880
+
881
+ mxThrowIf((*snapshot->read)(snapshot->stream, &heapAtom, sizeof(Atom)));
882
+ heapAtom.atomSize = ntohl(heapAtom.atomSize) - 8;
883
+ heap = c_malloc(sizeof(txSlot) + heapAtom.atomSize);
884
+ mxThrowIf(heap == C_NULL);
885
+ c_memset(heap, 0, sizeof(txSlot));
886
+ mxThrowIf((*snapshot->read)(snapshot->stream, heap + 1, heapAtom.atomSize));
887
+ heapLimit = heap + 1 + (heapAtom.atomSize / sizeof(txSlot));
888
+
889
+ mxThrowIf((*snapshot->read)(snapshot->stream, &stackAtom, sizeof(Atom)));
890
+ stackAtom.atomSize = ntohl(stackAtom.atomSize) - 8;
891
+ stack = c_malloc(stackAtom.atomSize);
892
+ mxThrowIf(stack == C_NULL);
893
+ mxThrowIf((*snapshot->read)(snapshot->stream, stack, stackAtom.atomSize));
894
+ stackLimit = stack + (stackAtom.atomSize / sizeof(txSlot));
895
+
896
+ current = heap;
897
+ while (current < heapLimit) {
898
+ fxDumpChunk(current, block);
899
+ current++;
900
+ }
901
+ current = stack;
902
+ while (current < stackLimit) {
903
+ fxDumpChunk(current, block);
904
+ current++;
905
+ }
906
+
907
+ fprintf(stderr, "%4.4s %d\n", (txString)&(blockAtom.atomType), blockAtom.atomSize + 8);
908
+ address = block;
909
+ offset = 0;
910
+ while (offset < blockAtom.atomSize) {
911
+ txChunk* chunk = (txChunk*)address;
912
+ fprintf(stderr, "\t<%8.8lu> %8d ", offset + sizeof(txChunk), chunk->size);
913
+ if (chunk->temporary)
914
+ (*(txDumpChunk)(chunk->temporary))(stderr, address + sizeof(txChunk), chunk->size - sizeof(txChunk));
915
+ else
916
+ fxDumpChunkData(stderr, address + sizeof(txChunk), chunk->size - sizeof(txChunk));
917
+ // fxDumpChunkData(stderr, address + sizeof(txChunk), chunk->size - sizeof(txChunk));
918
+ fprintf(stderr, "\n");
919
+ address += chunk->size;
920
+ offset += chunk->size;
921
+ }
922
+
923
+ fprintf(stderr, "%4.4s %d\n", (txString)&(heapAtom.atomType), heapAtom.atomSize + 8);
924
+ current = heap;
925
+ offset = 0;
926
+ while (current < heapLimit) {
927
+ fprintf(stderr, "\t[%8.8d] ", offset);
928
+ fxDumpSlotAddress(stderr, current->next);
929
+ fprintf(stderr, " ");
930
+ fxDumpSlot(stderr, current);
931
+ fprintf(stderr, "\n");
932
+ current++;
933
+ offset++;
934
+ }
935
+
936
+ fprintf(stderr, "%4.4s %d\n", (txString)&(stackAtom.atomType), stackAtom.atomSize + 8);
937
+ current = stack;
938
+ while (current < stackLimit) {
939
+ fprintf(stderr, "\t ");
940
+ fxDumpSlotAddress(stderr, current->next);
941
+ fprintf(stderr, " ");
942
+ fxDumpSlot(stderr, current);
943
+ fprintf(stderr, "\n");
944
+ current++;
945
+ }
946
+
947
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
948
+ atom.atomSize = ntohl(atom.atomSize) - 8;
949
+ buffer = c_malloc(atom.atomSize);
950
+ mxThrowIf(buffer == C_NULL);
951
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
952
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
953
+ address = buffer;
954
+ offset = 0;
955
+ size = atom.atomSize / sizeof(txSlot*);
956
+ while (offset < size) {
957
+ txSlot* slot = *((txSlot**)address);
958
+ fprintf(stderr, "\tID_%6.6d", offset);
959
+ if (slot) {
960
+ fprintf(stderr, " [%8.8zu]", (size_t)slot);
961
+ slot = ((txSlot*)heap) + (size_t)slot;
962
+ string = ((txString)block) + (size_t)(slot->value.key.string);
963
+ fprintf(stderr, " %s\n", string);
964
+ }
965
+ else
966
+ fprintf(stderr, " [ ]\n");
967
+ address += sizeof(txSlot*);
968
+ offset++;
969
+ }
970
+ c_free(buffer);
971
+ buffer = C_NULL;
972
+
973
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
974
+ atom.atomSize = ntohl(atom.atomSize) - 8;
975
+ buffer = c_malloc(atom.atomSize);
976
+ mxThrowIf(buffer == C_NULL);
977
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
978
+ fprintf(stderr, "%4.4s %d", (txString)&(atom.atomType), atom.atomSize + 8);
979
+ fxDumpSlotTable(stderr, buffer, atom.atomSize);
980
+ fprintf(stderr, "\n");
981
+
982
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
983
+ atom.atomSize = ntohl(atom.atomSize) - 8;
984
+ buffer = c_malloc(atom.atomSize);
985
+ mxThrowIf(buffer == C_NULL);
986
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
987
+ fprintf(stderr, "%4.4s %d", (txString)&(atom.atomType), atom.atomSize + 8);
988
+ fxDumpSlotTable(stderr, buffer, atom.atomSize);
989
+ fprintf(stderr, "\n");
990
+
991
+ c_free(stack);
992
+ c_free(heap);
993
+ c_free(block);
994
+ }
995
+ mxCatch(the) {
996
+ if (buffer)
997
+ c_free(buffer);
998
+ if (stack)
999
+ c_free(stack);
1000
+ if (heap)
1001
+ c_free(heap);
1002
+ if (block)
1003
+ c_free(block);
1004
+ }
1005
+ }
1006
+
1007
+ void fxDumpChunk(txSlot* slot, txByte* block)
1008
+ {
1009
+ txChunk* chunk;
1010
+ switch (slot->kind) {
1011
+ case XS_STRING_KIND: {
1012
+ chunk = (txChunk*)(block + (size_t)(slot->value.string) - sizeof(txChunk));
1013
+ chunk->temporary = (txByte*)fxDumpChunkString;
1014
+ } break;
1015
+ case XS_BIGINT_KIND: {
1016
+ chunk = (txChunk*)(block + (size_t)(slot->value.bigint.data) - sizeof(txChunk));
1017
+ chunk->temporary = (txByte*)fxDumpChunkData;
1018
+ } break;
1019
+ case XS_ARGUMENTS_SLOPPY_KIND:
1020
+ case XS_ARGUMENTS_STRICT_KIND:
1021
+ case XS_ARRAY_KIND:
1022
+ case XS_STACK_KIND: {
1023
+ if (slot->value.array.address) {
1024
+ chunk = (txChunk*)(block + (size_t)(slot->value.array.address) - sizeof(txChunk));
1025
+ chunk->temporary = (txByte*)fxDumpChunkArray;
1026
+
1027
+ {
1028
+ txIndex size = chunk->size / sizeof(txSlot);
1029
+ txSlot* item = (txSlot*)(block + (size_t)(slot->value.array.address));
1030
+ while (size) {
1031
+ fxDumpChunk(item, block);
1032
+ size--;
1033
+ item++;
1034
+ }
1035
+ }
1036
+
1037
+ }
1038
+ } break;
1039
+ case XS_ARRAY_BUFFER_KIND: {
1040
+ if (slot->value.arrayBuffer.address) {
1041
+ chunk = (txChunk*)(block + (size_t)(slot->value.arrayBuffer.address) - sizeof(txChunk));
1042
+ chunk->temporary = (txByte*)fxDumpChunkData;
1043
+ }
1044
+ } break;
1045
+ case XS_CODE_KIND: {
1046
+ chunk = (txChunk*)(block + (size_t)(slot->value.code.address) - sizeof(txChunk));
1047
+ chunk->temporary = (txByte*)fxDumpChunkData;
1048
+ } break;
1049
+ case XS_REGEXP_KIND: {
1050
+ if (slot->value.regexp.code) {
1051
+ chunk = (txChunk*)(block + (size_t)(slot->value.regexp.code) - sizeof(txChunk));
1052
+ chunk->temporary = (txByte*)fxDumpChunkData;
1053
+ }
1054
+ if (slot->value.regexp.data) {
1055
+ chunk = (txChunk*)(block + (size_t)(slot->value.regexp.data) - sizeof(txChunk));
1056
+ chunk->temporary = (txByte*)fxDumpChunkData;
1057
+ }
1058
+ } break;
1059
+ case XS_KEY_KIND: {
1060
+ if (slot->value.key.string) {
1061
+ chunk = (txChunk*)(block + (size_t)(slot->value.key.string) - sizeof(txChunk));
1062
+ chunk->temporary = (txByte*)fxDumpChunkString;
1063
+ }
1064
+ } break;
1065
+ case XS_GLOBAL_KIND:
1066
+ case XS_MAP_KIND:
1067
+ case XS_SET_KIND: {
1068
+ chunk = (txChunk*)(block + (size_t)(slot->value.table.address) - sizeof(txChunk));
1069
+ chunk->temporary = (txByte*)fxDumpChunkTable;
1070
+ } break;
1071
+ case XS_HOST_KIND: {
1072
+ if (slot->value.host.data) {
1073
+ chunk = (txChunk*)(block + (size_t)(slot->value.host.data) - sizeof(txChunk));
1074
+ chunk->temporary = (txByte*)fxDumpChunkData;
1075
+ }
1076
+ } break;
1077
+ default:
1078
+ break;
1079
+ }
1080
+ }
1081
+
1082
+ void fxDumpChunkAddress(FILE* file, void* address)
1083
+ {
1084
+ if (address)
1085
+ fprintf(file, "<%8.8zu>", (size_t)address);
1086
+ else
1087
+ fprintf(file, "< >");
1088
+ }
1089
+
1090
+ void fxDumpChunkArray(FILE* file, txByte* data, txSize size)
1091
+ {
1092
+ txSize offset = 0;
1093
+ txSlot* slot = (txSlot*)data;
1094
+ size /= sizeof(txSlot);
1095
+ while (offset < size) {
1096
+ fprintf(file, "\n\t\t%8zu ", (size_t)slot->next);
1097
+ fxDumpSlot(file, slot);
1098
+ offset++;
1099
+ slot++;
1100
+ }
1101
+ }
1102
+
1103
+ void fxDumpChunkData(FILE* file, txByte* data, txSize size)
1104
+ {
1105
+ txSize offset = 0;
1106
+ txU1* address = (txU1*)data;
1107
+ while (offset < size) {
1108
+ if (offset % 32)
1109
+ fprintf(file, " ");
1110
+ else
1111
+ fprintf(file, "\n\t\t");
1112
+ fprintf(file, "%2.2x", address[offset]);
1113
+ offset++;
1114
+ }
1115
+ }
1116
+
1117
+ void fxDumpChunkString(FILE* file, txByte* data, txSize size)
1118
+ {
1119
+ fprintf(file, " %s", data);
1120
+ }
1121
+
1122
+ void fxDumpChunkTable(FILE* file, txByte* data, txSize size)
1123
+ {
1124
+ txSize offset = 0;
1125
+ txSlot** address = (txSlot**)data;
1126
+ size /= sizeof(txSlot*);
1127
+ while (offset < size) {
1128
+ txSlot* slot = *((txSlot**)address);
1129
+ if (offset % 8)
1130
+ fprintf(file, " ");
1131
+ else
1132
+ fprintf(file, "\n\t\t");
1133
+ fxDumpSlotAddress(file, slot);
1134
+ offset++;
1135
+ address++;
1136
+ }
1137
+ }
1138
+
1139
+ void fxDumpID(FILE* file, txID id)
1140
+ {
1141
+ if (id == 0)
1142
+ fprintf(file, " ");
1143
+ else
1144
+ fprintf(file, "ID_%6.6d", id);
1145
+ }
1146
+
1147
+ void fxDumpNumber(FILE* file, txNumber value)
1148
+ {
1149
+ switch (c_fpclassify(value)) {
1150
+ case C_FP_INFINITE:
1151
+ if (value < 0)
1152
+ fprintf(file, "-C_INFINITY");
1153
+ else
1154
+ fprintf(file, "C_INFINITY");
1155
+ break;
1156
+ case C_FP_NAN:
1157
+ fprintf(file, "C_NAN");
1158
+ break;
1159
+ default:
1160
+ fprintf(file, "%.20e", value);
1161
+ break;
1162
+ }
1163
+ }
1164
+
1165
+ void fxDumpSlot(FILE* file, txSlot* slot)
1166
+ {
1167
+ if (slot->flag & XS_MARK_FLAG)
1168
+ fprintf(file, "M");
1169
+ else
1170
+ fprintf(file, "_");
1171
+ if (slot->kind == XS_INSTANCE_KIND) {
1172
+ if (slot->flag & XS_DONT_MARSHALL_FLAG)
1173
+ fprintf(file, "H");
1174
+ else
1175
+ fprintf(file, "_");
1176
+ if (slot->flag & XS_LEVEL_FLAG)
1177
+ fprintf(file, "L");
1178
+ else
1179
+ fprintf(file, "_");
1180
+ if (slot->flag & XS_DONT_PATCH_FLAG)
1181
+ fprintf(file, "P");
1182
+ else
1183
+ fprintf(file, "_");
1184
+ if (slot->flag & XS_FIELD_FLAG)
1185
+ fprintf(file, "F");
1186
+ else
1187
+ fprintf(file, "_");
1188
+ if (slot->flag & XS_CAN_CONSTRUCT_FLAG)
1189
+ fprintf(file, "N");
1190
+ else
1191
+ fprintf(file, "_");
1192
+ if (slot->flag & XS_CAN_CALL_FLAG)
1193
+ fprintf(file, "C");
1194
+ else
1195
+ fprintf(file, "_");
1196
+ if (slot->flag & XS_EXOTIC_FLAG)
1197
+ fprintf(file, "X");
1198
+ else
1199
+ fprintf(file, "_");
1200
+ }
1201
+ else {
1202
+ if (slot->flag & XS_DERIVED_FLAG)
1203
+ fprintf(file, "H");
1204
+ else
1205
+ fprintf(file, "_");
1206
+ if (slot->flag & XS_BASE_FLAG)
1207
+ fprintf(file, "B");
1208
+ else
1209
+ fprintf(file, "_");
1210
+ if (slot->flag & XS_INSPECTOR_FLAG)
1211
+ fprintf(file, "L");
1212
+ else
1213
+ fprintf(file, "_");
1214
+ if (slot->flag & XS_DONT_SET_FLAG)
1215
+ fprintf(file, "S");
1216
+ else
1217
+ fprintf(file, "_");
1218
+ if (slot->flag & XS_DONT_ENUM_FLAG)
1219
+ fprintf(file, "E");
1220
+ else
1221
+ fprintf(file, "_");
1222
+ if (slot->flag & XS_DONT_DELETE_FLAG)
1223
+ fprintf(file, "D");
1224
+ else
1225
+ fprintf(file, "_");
1226
+ if (slot->flag & XS_INTERNAL_FLAG)
1227
+ fprintf(file, "I");
1228
+ else
1229
+ fprintf(file, "_");
1230
+
1231
+ }
1232
+ fprintf(file, " ");
1233
+ fxDumpID(file, slot->ID);
1234
+ fprintf(file, " ");
1235
+ switch (slot->kind) {
1236
+ case XS_UNINITIALIZED_KIND: {
1237
+ fprintf(file, "unititialized");
1238
+ } break;
1239
+ case XS_UNDEFINED_KIND: {
1240
+ fprintf(file, "undefined");
1241
+ } break;
1242
+ case XS_NULL_KIND: {
1243
+ fprintf(file, "null");
1244
+ } break;
1245
+ case XS_BOOLEAN_KIND: {
1246
+ fprintf(file, "boolean = %d", slot->value.boolean);
1247
+ } break;
1248
+ case XS_INTEGER_KIND: {
1249
+ fprintf(file, "integer = %d", slot->value.integer);
1250
+ } break;
1251
+ case XS_NUMBER_KIND: {
1252
+ fprintf(file, "number = ");
1253
+ fxDumpNumber(file, slot->value.number);
1254
+ } break;
1255
+ case XS_STRING_KIND: {
1256
+ fprintf(file, "string = ");
1257
+ fxDumpChunkAddress(file, slot->value.string);
1258
+ } break;
1259
+ case XS_SYMBOL_KIND: {
1260
+ fprintf(file, "symbol = ");
1261
+ fxDumpID(file, slot->value.symbol);
1262
+ } break;
1263
+ case XS_BIGINT_KIND: {
1264
+ fprintf(file, "bigint = { .data = ");
1265
+ fxDumpChunkAddress(file, slot->value.bigint.data);
1266
+ fprintf(file, ", .size = %d, ", slot->value.bigint.size);
1267
+ fprintf(file, ".sign = %d, ", slot->value.bigint.sign);
1268
+ fprintf(file, " }");
1269
+ } break;
1270
+ case XS_REFERENCE_KIND: {
1271
+ fprintf(file, "reference = ");
1272
+ fxDumpSlotAddress(file, slot->value.reference);
1273
+ } break;
1274
+ case XS_CLOSURE_KIND: {
1275
+ fprintf(file, "closure = ");
1276
+ fxDumpSlotAddress(file, slot->value.closure);
1277
+ } break;
1278
+ case XS_INSTANCE_KIND: {
1279
+ fprintf(file, "instance = { .garbage = ");
1280
+ fxDumpSlotAddress(file, slot->value.instance.garbage);
1281
+ fprintf(file, ", .prototype = ");
1282
+ fxDumpSlotAddress(file, slot->value.instance.prototype);
1283
+ fprintf(file, " }");
1284
+ } break;
1285
+ case XS_ARGUMENTS_SLOPPY_KIND:
1286
+ case XS_ARGUMENTS_STRICT_KIND:
1287
+ case XS_ARRAY_KIND: {
1288
+ fprintf(file, "array = { .address = ");
1289
+ fxDumpChunkAddress(file, slot->value.array.address);
1290
+ fprintf(file, ", .length = %d }", (int)slot->value.array.length);
1291
+ } break;
1292
+ case XS_ARRAY_BUFFER_KIND: {
1293
+ fprintf(file, "arrayBuffer = { .address = ");
1294
+ fxDumpChunkAddress(file, slot->value.arrayBuffer.address);
1295
+ fprintf(file, " }");
1296
+ } break;
1297
+ case XS_BUFFER_INFO_KIND: {
1298
+ fprintf(file, "bufferInfo = { .length = %d, maxLength = %d }", slot->value.bufferInfo.length, slot->value.bufferInfo.maxLength);
1299
+ } break;
1300
+ case XS_CALLBACK_KIND: {
1301
+ fprintf(file, "callback");
1302
+ } break;
1303
+ case XS_CODE_KIND: {
1304
+ fprintf(file, "code = { .address = ");
1305
+ fxDumpChunkAddress(file, slot->value.code.address);
1306
+ fprintf(file, ", .closures = ");
1307
+ fxDumpSlotAddress(file, slot->value.code.closures);
1308
+ fprintf(file, " }");
1309
+ } break;
1310
+ case XS_DATE_KIND: {
1311
+ fprintf(file, "date = ");
1312
+ fxDumpNumber(file, slot->value.number);
1313
+ } break;
1314
+ case XS_DATA_VIEW_KIND: {
1315
+ fprintf(file, "dataView = { .offset = %d, .size = %d }", slot->value.dataView.offset, slot->value.dataView.size);
1316
+ } break;
1317
+ case XS_FINALIZATION_CELL_KIND: {
1318
+ fprintf(file, "finalizationCell = { .target = ");
1319
+ fxDumpSlotAddress(file, slot->value.finalizationCell.target);
1320
+ fprintf(file, ", .token = ");
1321
+ fxDumpSlotAddress(file, slot->value.finalizationCell.token);
1322
+ fprintf(file, " }");
1323
+ } break;
1324
+ case XS_FINALIZATION_REGISTRY_KIND: {
1325
+ fprintf(file, "finalizationRegistry = { .target = ");
1326
+ fxDumpSlotAddress(file, slot->value.finalizationRegistry.callback);
1327
+ fprintf(file, ", .flags = %d }", slot->value.finalizationRegistry.flags);
1328
+ } break;
1329
+ case XS_GLOBAL_KIND: {
1330
+ fprintf(file, "global = { .address = ");
1331
+ fxDumpChunkAddress(file, slot->value.table.address);
1332
+ fprintf(file, ", .length = %d }", (int)slot->value.table.length);
1333
+ } break;
1334
+ case XS_MAP_KIND: {
1335
+ fprintf(file, "map = { .address = ");
1336
+ fxDumpChunkAddress(file, slot->value.table.address);
1337
+ fprintf(file, ", .length = %d }", (int)slot->value.table.length);
1338
+ } break;
1339
+ case XS_MODULE_KIND: {
1340
+ fprintf(file, "module = { .realm = ");
1341
+ fxDumpSlotAddress(file, slot->value.module.realm);
1342
+ fprintf(file, ", .id = ");
1343
+ fxDumpID(file, slot->value.module.id);
1344
+ fprintf(file, " }");
1345
+ } break;
1346
+ case XS_PROGRAM_KIND: {
1347
+ fprintf(file, "program = { .realm = ");
1348
+ fxDumpSlotAddress(file, slot->value.module.realm);
1349
+ fprintf(file, ", .id = ");
1350
+ fxDumpID(file, slot->value.module.id);
1351
+ fprintf(file, " }");
1352
+ } break;
1353
+ case XS_PROMISE_KIND: {
1354
+ fprintf(file, "promise = %d }", slot->value.integer);
1355
+ } break;
1356
+ case XS_PROXY_KIND: {
1357
+ fprintf(file, "proxy = { .handler = ");
1358
+ fxDumpSlotAddress(file, slot->value.proxy.handler);
1359
+ fprintf(file, ", .target = ");
1360
+ fxDumpSlotAddress(file, slot->value.proxy.target);
1361
+ fprintf(file, " }");
1362
+ } break;
1363
+ case XS_REGEXP_KIND: {
1364
+ fprintf(file, "regexp = { .code = ");
1365
+ fxDumpChunkAddress(file, slot->value.regexp.code);
1366
+ fprintf(file, ", .data = ");
1367
+ fxDumpChunkAddress(file, slot->value.regexp.data);
1368
+ fprintf(file, " }");
1369
+ } break;
1370
+ case XS_SET_KIND: {
1371
+ fprintf(file, "set = { .address = ");
1372
+ fxDumpChunkAddress(file, slot->value.table.address);
1373
+ fprintf(file, ", .length = %d }", (int)slot->value.table.length);
1374
+ } break;
1375
+ case XS_TYPED_ARRAY_KIND: {
1376
+ fprintf(file, ".kind = XS_TYPED_ARRAY_KIND}, ");
1377
+ fprintf(file, ".value = { .typedArray = { .dispatch = gxTypeDispatches[%zu], .atomics = gxTypeAtomics[%zu] }", (size_t)slot->value.typedArray.dispatch, (size_t)slot->value.typedArray.atomics);
1378
+ } break;
1379
+ case XS_WEAK_MAP_KIND: {
1380
+ fprintf(file, "weakMap = { .first = ");
1381
+ fxDumpSlotAddress(file, slot->value.weakList.first);
1382
+ fprintf(file, ", .link = ");
1383
+ fxDumpSlotAddress(file, slot->value.weakList.link);
1384
+ fprintf(file, " }");
1385
+ } break;
1386
+ case XS_WEAK_SET_KIND: {
1387
+ fprintf(file, "weakSet = { .first = ");
1388
+ fxDumpSlotAddress(file, slot->value.weakList.first);
1389
+ fprintf(file, ", .link = ");
1390
+ fxDumpSlotAddress(file, slot->value.weakList.link);
1391
+ fprintf(file, " }");
1392
+ } break;
1393
+ case XS_WEAK_REF_KIND: {
1394
+ fprintf(file, "weakRef = { .target = ");
1395
+ fxDumpSlotAddress(file, slot->value.weakRef.target);
1396
+ fprintf(file, ", .link = ");
1397
+ fxDumpSlotAddress(file, slot->value.weakRef.link);
1398
+ fprintf(file, " }");
1399
+ } break;
1400
+ case XS_ACCESSOR_KIND: {
1401
+ fprintf(file, "accessor = { .getter = ");
1402
+ fxDumpSlotAddress(file, slot->value.accessor.getter);
1403
+ fprintf(file, ", .setter = ");
1404
+ fxDumpSlotAddress(file, slot->value.accessor.setter);
1405
+ fprintf(file, " }");
1406
+ } break;
1407
+ case XS_AT_KIND: {
1408
+ fprintf(file, "at = { 0x%x, %d }", slot->value.at.index, slot->value.at.id);
1409
+ } break;
1410
+ case XS_ENTRY_KIND: {
1411
+ fprintf(file, "entry = { ");
1412
+ fxDumpSlotAddress(file, slot->value.entry.slot);
1413
+ fprintf(file, ", 0x%x }", slot->value.entry.sum);
1414
+ } break;
1415
+ case XS_ERROR_KIND: {
1416
+ fprintf(file, "error = { ");
1417
+ fxDumpSlotAddress(file, slot->value.error.info);
1418
+ fprintf(file, ", %d }", slot->value.error.which);
1419
+ } break;
1420
+ case XS_EXPORT_KIND: {
1421
+ fprintf(file, "export = { .closure = ");
1422
+ fxDumpSlotAddress(file, slot->value.export.closure);
1423
+ fprintf(file, ", .module = ");
1424
+ fxDumpSlotAddress(file, slot->value.export.module);
1425
+ fprintf(file, " }");
1426
+ } break;
1427
+ case XS_HOME_KIND: {
1428
+ fprintf(file, "home = { .object = ");
1429
+ fxDumpSlotAddress(file, slot->value.home.object);
1430
+ fprintf(file, ", .module = ");
1431
+ fxDumpSlotAddress(file, slot->value.home.module);
1432
+ fprintf(file, " }");
1433
+ } break;
1434
+ case XS_KEY_KIND: {
1435
+ fprintf(file, "key = { .string = ");
1436
+ fxDumpChunkAddress(file, slot->value.key.string);
1437
+ fprintf(file, ", .sum = 0x%x }", slot->value.key.sum);
1438
+ } break;
1439
+ case XS_LIST_KIND: {
1440
+ fprintf(file, "list = { .first = ");
1441
+ fxDumpSlotAddress(file, slot->value.list.first);
1442
+ fprintf(file, ", .last = ");
1443
+ fxDumpSlotAddress(file, slot->value.list.last);
1444
+ fprintf(file, " }");
1445
+ } break;
1446
+ case XS_PRIVATE_KIND: {
1447
+ fprintf(file, "private = { .check = ");
1448
+ fxDumpSlotAddress(file, slot->value.private.check);
1449
+ fprintf(file, ", .first = ");
1450
+ fxDumpSlotAddress(file, slot->value.private.first);
1451
+ fprintf(file, " }");
1452
+ } break;
1453
+ case XS_STACK_KIND: {
1454
+ fprintf(file, "stack = { .address = ");
1455
+ fxDumpChunkAddress(file, slot->value.array.address);
1456
+ fprintf(file, ", .length = %d }", (int)slot->value.array.length);
1457
+ } break;
1458
+ case XS_WEAK_ENTRY_KIND: {
1459
+ fprintf(file, "weakEntry = { .check = ");
1460
+ fxDumpSlotAddress(file, slot->value.weakEntry.check);
1461
+ fprintf(file, ", .value = ");
1462
+ fxDumpSlotAddress(file, slot->value.weakEntry.value);
1463
+ fprintf(file, " }");
1464
+ } break;
1465
+ case XS_HOST_KIND: {
1466
+ fprintf(file, "host = { .data = ");
1467
+ fxDumpChunkAddress(file, slot->value.host.data);
1468
+ fprintf(file, " }");
1469
+ } break;
1470
+ default:
1471
+ break;
1472
+ }
1473
+ }
1474
+
1475
+ void fxDumpSlotAddress(FILE* file, void* address)
1476
+ {
1477
+ if (address)
1478
+ fprintf(file, "[%8.8zu]", (size_t)address);
1479
+ else
1480
+ fprintf(file, "[ ]");
1481
+ }
1482
+
1483
+ void fxDumpSlotTable(FILE* file, txByte* buffer, txSize size)
1484
+ {
1485
+ txSize offset = 0;
1486
+ txSlot** address = (txSlot**)buffer;
1487
+ size /= sizeof(txSlot*);
1488
+ while (offset < size) {
1489
+ txSlot* slot = *((txSlot**)address);
1490
+ if (offset % 8)
1491
+ fprintf(file, " ");
1492
+ else
1493
+ fprintf(file, "\n\t");
1494
+ fxDumpSlotAddress(file, slot);
1495
+ offset++;
1496
+ address++;
1497
+ }
1498
+ }
1499
+
1500
+
1501
+