@agoric/xsnap 0.14.3-upgrade-14-dev-c8f9e7b.0 → 0.14.3-upgrade-16-dev-8879538.0

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 (134) hide show
  1. package/README.md +3 -3
  2. package/api.js +4 -2
  3. package/moddable/modules/data/base64/base64.js +28 -0
  4. package/moddable/modules/data/base64/manifest.json +11 -0
  5. package/moddable/modules/data/base64/modBase64.c +188 -0
  6. package/moddable/modules/data/binaryMessage/BinaryMessage.js +106 -0
  7. package/moddable/modules/data/crc/crc.c +205 -0
  8. package/moddable/modules/data/crc/crc.js +36 -0
  9. package/moddable/modules/data/crc/manifest.json +8 -0
  10. package/moddable/modules/data/hex/hex.js +28 -0
  11. package/moddable/modules/data/hex/manifest.json +11 -0
  12. package/moddable/modules/data/hex/modHex.c +139 -0
  13. package/moddable/modules/data/logical/logical.js +32 -0
  14. package/moddable/modules/data/logical/modLogical.c +98 -0
  15. package/moddable/modules/data/qrcode/manifest.json +9 -0
  16. package/moddable/modules/data/qrcode/qrcode.c +93 -0
  17. package/moddable/modules/data/qrcode/qrcode.js +23 -0
  18. package/moddable/modules/data/qrcode/qrcodegen.c +1025 -0
  19. package/moddable/modules/data/qrcode/qrcodegen.h +267 -0
  20. package/moddable/modules/data/text/decoder/manifest.json +8 -0
  21. package/moddable/modules/data/text/decoder/textdecoder.c +480 -0
  22. package/moddable/modules/data/text/decoder/textdecoder.js +27 -0
  23. package/moddable/modules/data/text/encoder/manifest.json +8 -0
  24. package/moddable/modules/data/text/encoder/textencoder.c +232 -0
  25. package/moddable/modules/data/text/encoder/textencoder.js +24 -0
  26. package/moddable/modules/data/tinyint/tinyint.c +150 -0
  27. package/moddable/modules/data/tinyint/tinyint.js +53 -0
  28. package/moddable/modules/data/url/manifest.json +17 -0
  29. package/moddable/modules/data/url/url.c +1959 -0
  30. package/moddable/modules/data/url/url.js +210 -0
  31. package/moddable/modules/data/wavreader/manifest.json +8 -0
  32. package/moddable/modules/data/wavreader/wavreader.js +128 -0
  33. package/moddable/modules/data/zlib/deflate.c +161 -0
  34. package/moddable/modules/data/zlib/deflate.js +63 -0
  35. package/moddable/modules/data/zlib/inflate.c +145 -0
  36. package/moddable/modules/data/zlib/inflate.js +66 -0
  37. package/moddable/modules/data/zlib/manifest_deflate.json +9 -0
  38. package/moddable/modules/data/zlib/manifest_inflate.json +9 -0
  39. package/moddable/modules/data/zlib/miniz.c +4924 -0
  40. package/moddable/xs/includes/xs.d.ts +73 -0
  41. package/moddable/xs/includes/xs.h +1533 -0
  42. package/moddable/xs/includes/xsmc.h +206 -0
  43. package/moddable/xs/makefiles/lin/makefile +33 -0
  44. package/moddable/xs/makefiles/lin/xsc.mk +118 -0
  45. package/moddable/xs/makefiles/lin/xsid.mk +90 -0
  46. package/moddable/xs/makefiles/lin/xsl.mk +168 -0
  47. package/moddable/xs/makefiles/lin/xst.mk +201 -0
  48. package/moddable/xs/makefiles/mac/makefile +33 -0
  49. package/moddable/xs/makefiles/mac/xsc.mk +130 -0
  50. package/moddable/xs/makefiles/mac/xsid.mk +102 -0
  51. package/moddable/xs/makefiles/mac/xsl.mk +177 -0
  52. package/moddable/xs/makefiles/mac/xst.mk +203 -0
  53. package/moddable/xs/makefiles/mac/xst_no_asan.txt +52 -0
  54. package/moddable/xs/makefiles/win/build.bat +26 -0
  55. package/moddable/xs/makefiles/win/xsc.mak +142 -0
  56. package/moddable/xs/makefiles/win/xsid.mak +113 -0
  57. package/moddable/xs/makefiles/win/xsl.mak +186 -0
  58. package/moddable/xs/makefiles/win/xst.mak +195 -0
  59. package/moddable/xs/platforms/lin_xs.h +99 -0
  60. package/moddable/xs/platforms/mac_xs.h +97 -0
  61. package/moddable/xs/platforms/wasm_xs.h +79 -0
  62. package/moddable/xs/platforms/win_xs.h +104 -0
  63. package/moddable/xs/platforms/xsHost.h +63 -0
  64. package/moddable/xs/platforms/xsPlatform.h +618 -0
  65. package/moddable/xs/sources/xsAPI.c +2555 -0
  66. package/moddable/xs/sources/xsAll.c +294 -0
  67. package/moddable/xs/sources/xsAll.h +2741 -0
  68. package/moddable/xs/sources/xsArguments.c +222 -0
  69. package/moddable/xs/sources/xsArray.c +2657 -0
  70. package/moddable/xs/sources/xsAtomics.c +844 -0
  71. package/moddable/xs/sources/xsBigInt.c +1859 -0
  72. package/moddable/xs/sources/xsBoolean.c +109 -0
  73. package/moddable/xs/sources/xsCode.c +4493 -0
  74. package/moddable/xs/sources/xsCommon.c +1710 -0
  75. package/moddable/xs/sources/xsCommon.h +1142 -0
  76. package/moddable/xs/sources/xsDataView.c +2890 -0
  77. package/moddable/xs/sources/xsDate.c +1541 -0
  78. package/moddable/xs/sources/xsDebug.c +2710 -0
  79. package/moddable/xs/sources/xsDefaults.c +134 -0
  80. package/moddable/xs/sources/xsError.c +353 -0
  81. package/moddable/xs/sources/xsFunction.c +776 -0
  82. package/moddable/xs/sources/xsGenerator.c +865 -0
  83. package/moddable/xs/sources/xsGlobal.c +839 -0
  84. package/moddable/xs/sources/xsJSON.c +1091 -0
  85. package/moddable/xs/sources/xsLexical.c +1969 -0
  86. package/moddable/xs/sources/xsLockdown.c +933 -0
  87. package/moddable/xs/sources/xsMapSet.c +1649 -0
  88. package/moddable/xs/sources/xsMarshall.c +1020 -0
  89. package/moddable/xs/sources/xsMath.c +624 -0
  90. package/moddable/xs/sources/xsMemory.c +1941 -0
  91. package/moddable/xs/sources/xsModule.c +3101 -0
  92. package/moddable/xs/sources/xsNumber.c +560 -0
  93. package/moddable/xs/sources/xsObject.c +1102 -0
  94. package/moddable/xs/sources/xsPlatforms.c +480 -0
  95. package/moddable/xs/sources/xsProfile.c +577 -0
  96. package/moddable/xs/sources/xsPromise.c +1199 -0
  97. package/moddable/xs/sources/xsProperty.c +636 -0
  98. package/moddable/xs/sources/xsProxy.c +1014 -0
  99. package/moddable/xs/sources/xsRegExp.c +1168 -0
  100. package/moddable/xs/sources/xsRun.c +4889 -0
  101. package/moddable/xs/sources/xsScope.c +1293 -0
  102. package/moddable/xs/sources/xsScript.c +288 -0
  103. package/moddable/xs/sources/xsScript.h +1186 -0
  104. package/moddable/xs/sources/xsSnapshot.c +2161 -0
  105. package/moddable/xs/sources/xsSnapshot.h +51 -0
  106. package/moddable/xs/sources/xsSourceMap.c +218 -0
  107. package/moddable/xs/sources/xsString.c +3332 -0
  108. package/moddable/xs/sources/xsSymbol.c +503 -0
  109. package/moddable/xs/sources/xsSyntaxical.c +4193 -0
  110. package/moddable/xs/sources/xsTree.c +1893 -0
  111. package/moddable/xs/sources/xsType.c +1488 -0
  112. package/moddable/xs/sources/xsdtoa.c +6672 -0
  113. package/moddable/xs/sources/xsmc.c +340 -0
  114. package/moddable/xs/sources/xsre.c +7578 -0
  115. package/package.json +35 -20
  116. package/src/avaAssertXS.js +4 -2
  117. package/src/avaHandler.cjs +2 -5
  118. package/src/avaXS.js +7 -8
  119. package/src/build.js +126 -26
  120. package/src/replay.js +0 -3
  121. package/src/xsnap.js +105 -91
  122. package/src/xsrepl.js +2 -3
  123. package/xsnap-native/xsnap/makefiles/lin/makefile +10 -0
  124. package/xsnap-native/xsnap/makefiles/lin/xsnap-worker.mk +153 -0
  125. package/xsnap-native/xsnap/makefiles/lin/xsnap.mk +144 -0
  126. package/xsnap-native/xsnap/makefiles/mac/makefile +10 -0
  127. package/xsnap-native/xsnap/makefiles/mac/xsnap-worker.mk +162 -0
  128. package/xsnap-native/xsnap/makefiles/mac/xsnap.mk +153 -0
  129. package/xsnap-native/xsnap/sources/xsnap-worker.c +996 -0
  130. package/xsnap-native/xsnap/sources/xsnap.c +716 -0
  131. package/xsnap-native/xsnap/sources/xsnap.h +142 -0
  132. package/xsnap-native/xsnap/sources/xsnapPlatform.c +1496 -0
  133. package/xsnap-native/xsnap/sources/xsnapPlatform.h +105 -0
  134. package/CHANGELOG.md +0 -646
@@ -0,0 +1,1496 @@
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
+ c_strcat(path, name + dot);
458
+ return fxNewNameC(the, path);
459
+ }
460
+
461
+ void fxLoadModule(txMachine* the, txSlot* module, txID moduleID)
462
+ {
463
+ char path[C_PATH_MAX];
464
+ char real[C_PATH_MAX];
465
+ txScript* script;
466
+ #ifdef mxDebug
467
+ txUnsigned flags = mxDebugFlag;
468
+ #else
469
+ txUnsigned flags = 0;
470
+ #endif
471
+ c_strncpy(path, fxGetKeyName(the, moduleID), C_PATH_MAX - 1);
472
+ path[C_PATH_MAX - 1] = 0;
473
+ if (c_realpath(path, real)) {
474
+ script = fxLoadScript(the, real, flags);
475
+ if (script)
476
+ fxResolveModule(the, module, moduleID, script, C_NULL, C_NULL);
477
+ }
478
+ }
479
+
480
+ txScript* fxLoadScript(txMachine* the, txString path, txUnsigned flags)
481
+ {
482
+ txParser _parser;
483
+ txParser* parser = &_parser;
484
+ txParserJump jump;
485
+ FILE* file = NULL;
486
+ txString name = NULL;
487
+ char map[C_PATH_MAX];
488
+ txScript* script = NULL;
489
+ fxInitializeParser(parser, the, the->parserBufferSize, the->parserTableModulo);
490
+ parser->firstJump = &jump;
491
+ file = fopen(path, "r");
492
+ if (c_setjmp(jump.jmp_buf) == 0) {
493
+ mxParserThrowElse(file);
494
+ parser->path = fxNewParserSymbol(parser, path);
495
+ fxParserTree(parser, file, (txGetter)fgetc, flags, &name);
496
+ fclose(file);
497
+ file = NULL;
498
+ if (name) {
499
+ mxParserThrowElse(c_realpath(fxCombinePath(parser, path, name), map));
500
+ parser->path = fxNewParserSymbol(parser, map);
501
+ file = fopen(map, "r");
502
+ mxParserThrowElse(file);
503
+ fxParserSourceMap(parser, file, (txGetter)fgetc, flags, &name);
504
+ fclose(file);
505
+ file = NULL;
506
+ if ((parser->errorCount == 0) && name) {
507
+ mxParserThrowElse(c_realpath(fxCombinePath(parser, map, name), map));
508
+ parser->path = fxNewParserSymbol(parser, map);
509
+ }
510
+ }
511
+ fxParserHoist(parser);
512
+ fxParserBind(parser);
513
+ script = fxParserCode(parser);
514
+ }
515
+ if (file)
516
+ fclose(file);
517
+ #ifdef mxInstrument
518
+ if (the->peakParserSize < parser->total)
519
+ the->peakParserSize = parser->total;
520
+ #endif
521
+ fxTerminateParser(parser);
522
+ return script;
523
+ }
524
+
525
+ /* DEBUG */
526
+
527
+ #ifdef mxDebug
528
+
529
+ #ifdef mxInstrument
530
+
531
+ void fxConnect(txMachine* the)
532
+ {
533
+ }
534
+
535
+ void fxDisconnect(txMachine* the)
536
+ {
537
+ }
538
+
539
+ txBoolean fxIsConnected(txMachine* the)
540
+ {
541
+ return 1;
542
+ }
543
+
544
+ txBoolean fxIsReadable(txMachine* the)
545
+ {
546
+ return 0;
547
+ }
548
+
549
+ void fxReceive(txMachine* the)
550
+ {
551
+ ssize_t count;
552
+ again:
553
+ count = read(5, the->debugBuffer, sizeof(the->debugBuffer) - 1);
554
+ if (count < 0) {
555
+ if (errno == EINTR)
556
+ goto again;
557
+ the->debugOffset = 0;
558
+ }
559
+ else
560
+ the->debugOffset = count;
561
+ the->debugBuffer[the->debugOffset] = 0;
562
+ }
563
+
564
+ void fxSend(txMachine* the, txBoolean more)
565
+ {
566
+ ssize_t count;
567
+ again:
568
+ count = write(6, the->echoBuffer, the->echoOffset);
569
+ if (count < 0) {
570
+ if (errno == EINTR)
571
+ goto again;
572
+ }
573
+ }
574
+
575
+ #else
576
+
577
+ void fxConnect(txMachine* the)
578
+ {
579
+ char name[256];
580
+ char* colon;
581
+ int port;
582
+ struct sockaddr_in address;
583
+ #if mxWindows
584
+ if (GetEnvironmentVariable("XSBUG_HOST", name, sizeof(name))) {
585
+ #else
586
+ colon = getenv("XSBUG_HOST");
587
+ if ((colon) && (c_strlen(colon) + 1 < sizeof(name))) {
588
+ c_strcpy(name, colon);
589
+ #endif
590
+ colon = strchr(name, ':');
591
+ if (colon == NULL)
592
+ port = 5002;
593
+ else {
594
+ *colon = 0;
595
+ colon++;
596
+ port = strtol(colon, NULL, 10);
597
+ }
598
+ }
599
+ else {
600
+ // Require XSBUG_HOST to be set for debugging.
601
+ return;
602
+ // strcpy(name, "localhost");
603
+ // port = 5002;
604
+ }
605
+ memset(&address, 0, sizeof(address));
606
+ address.sin_family = AF_INET;
607
+ address.sin_addr.s_addr = inet_addr(name);
608
+ if (address.sin_addr.s_addr == INADDR_NONE) {
609
+ struct hostent *host = gethostbyname(name);
610
+ if (!host)
611
+ return;
612
+ memcpy(&(address.sin_addr), host->h_addr, host->h_length);
613
+ }
614
+ address.sin_port = htons(port);
615
+ #if mxWindows
616
+ {
617
+ WSADATA wsaData;
618
+ unsigned long flag;
619
+ if (WSAStartup(0x202, &wsaData) == SOCKET_ERROR)
620
+ return;
621
+ the->connection = socket(AF_INET, SOCK_STREAM, 0);
622
+ if (the->connection == INVALID_SOCKET)
623
+ return;
624
+ flag = 1;
625
+ ioctlsocket(the->connection, FIONBIO, &flag);
626
+ if (connect(the->connection, (struct sockaddr*)&address, sizeof(address)) == SOCKET_ERROR) {
627
+ if (WSAEWOULDBLOCK == WSAGetLastError()) {
628
+ fd_set fds;
629
+ struct timeval timeout = { 2, 0 }; // 2 seconds, 0 micro-seconds
630
+ FD_ZERO(&fds);
631
+ FD_SET(the->connection, &fds);
632
+ if (select(0, NULL, &fds, NULL, &timeout) == 0)
633
+ goto bail;
634
+ if (!FD_ISSET(the->connection, &fds))
635
+ goto bail;
636
+ }
637
+ else
638
+ goto bail;
639
+ }
640
+ flag = 0;
641
+ ioctlsocket(the->connection, FIONBIO, &flag);
642
+ }
643
+ #else
644
+ {
645
+ int flag;
646
+ the->connection = socket(AF_INET, SOCK_STREAM, 0);
647
+ if (the->connection <= 0)
648
+ goto bail;
649
+ c_signal(SIGPIPE, SIG_IGN);
650
+ #if mxMacOSX
651
+ {
652
+ int set = 1;
653
+ setsockopt(the->connection, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
654
+ }
655
+ #endif
656
+ flag = fcntl(the->connection, F_GETFL, 0);
657
+ fcntl(the->connection, F_SETFL, flag | O_NONBLOCK);
658
+ if (connect(the->connection, (struct sockaddr*)&address, sizeof(address)) < 0) {
659
+ if (errno == EINPROGRESS) {
660
+ fd_set fds;
661
+ struct timeval timeout = { 2, 0 }; // 2 seconds, 0 micro-seconds
662
+ int error = 0;
663
+ unsigned int length = sizeof(error);
664
+ FD_ZERO(&fds);
665
+ FD_SET(the->connection, &fds);
666
+ if (select(the->connection + 1, NULL, &fds, NULL, &timeout) == 0)
667
+ goto bail;
668
+ if (!FD_ISSET(the->connection, &fds))
669
+ goto bail;
670
+ if (getsockopt(the->connection, SOL_SOCKET, SO_ERROR, &error, &length) < 0)
671
+ goto bail;
672
+ if (error)
673
+ goto bail;
674
+ }
675
+ else
676
+ goto bail;
677
+ }
678
+ fcntl(the->connection, F_SETFL, flag);
679
+ c_signal(SIGPIPE, SIG_DFL);
680
+ }
681
+ #endif
682
+ return;
683
+ bail:
684
+ fxDisconnect(the);
685
+ }
686
+
687
+ void fxDisconnect(txMachine* the)
688
+ {
689
+ #if mxWindows
690
+ if (the->connection != INVALID_SOCKET) {
691
+ closesocket(the->connection);
692
+ the->connection = INVALID_SOCKET;
693
+ }
694
+ WSACleanup();
695
+ #else
696
+ if (the->connection >= 0) {
697
+ close(the->connection);
698
+ the->connection = mxNoSocket;
699
+ }
700
+ #endif
701
+ }
702
+
703
+ txBoolean fxIsConnected(txMachine* the)
704
+ {
705
+ return (the->connection != mxNoSocket) ? 1 : 0;
706
+ }
707
+
708
+ txBoolean fxIsReadable(txMachine* the)
709
+ {
710
+ return 0;
711
+ }
712
+
713
+ void fxReceive(txMachine* the)
714
+ {
715
+ int count;
716
+ if (the->connection != mxNoSocket) {
717
+ #if mxWindows
718
+ count = recv(the->connection, the->debugBuffer, sizeof(the->debugBuffer) - 1, 0);
719
+ if (count < 0)
720
+ fxDisconnect(the);
721
+ else
722
+ the->debugOffset = count;
723
+ #else
724
+ again:
725
+ count = read(the->connection, the->debugBuffer, sizeof(the->debugBuffer) - 1);
726
+ if (count < 0) {
727
+ if (errno == EINTR)
728
+ goto again;
729
+ else
730
+ fxDisconnect(the);
731
+ }
732
+ else
733
+ the->debugOffset = count;
734
+ #endif
735
+ }
736
+ the->debugBuffer[the->debugOffset] = 0;
737
+ }
738
+
739
+ void fxSend(txMachine* the, txBoolean more)
740
+ {
741
+ if (the->connection != mxNoSocket) {
742
+ #if mxWindows
743
+ if (send(the->connection, the->echoBuffer, the->echoOffset, 0) <= 0)
744
+ fxDisconnect(the);
745
+ #else
746
+ again:
747
+ if (write(the->connection, the->echoBuffer, the->echoOffset) <= 0) {
748
+ if (errno == EINTR)
749
+ goto again;
750
+ else
751
+ fxDisconnect(the);
752
+ }
753
+ #endif
754
+ }
755
+ }
756
+
757
+ #endif /* mxInstrument */
758
+
759
+ #endif /* mxDebug */
760
+
761
+ void fxVersion(txString theBuffer, txSize theSize)
762
+ {
763
+ c_snprintf(theBuffer, theSize, "%d.%d.%d", XS_MAJOR_VERSION, XS_MINOR_VERSION, XS_PATCH_VERSION);
764
+ }
765
+
766
+ #ifdef mxMetering
767
+ txUnsigned fxGetCurrentMeter(txMachine* the)
768
+ {
769
+ return the->meterIndex;
770
+ }
771
+
772
+ void fxSetCurrentMeter(txMachine* the, txUnsigned value)
773
+ {
774
+ the->meterIndex = value;
775
+ }
776
+ #endif
777
+
778
+ txSize fxGetCurrentHeapCount(txMachine* the)
779
+ {
780
+ return the->currentHeapCount;
781
+ }
782
+
783
+ extern void fxDumpSnapshot(txMachine* the, txSnapshot* snapshot);
784
+
785
+ typedef void (*txDumpChunk)(FILE* file, txByte* data, txSize size);
786
+
787
+ #define mxThrowIf(_ERROR) { if (_ERROR) { snapshot->error = _ERROR; fxJump(the); } }
788
+
789
+ static void fxDumpChunk(txSlot* slot, txByte* block);
790
+ static void fxDumpChunkAddress(FILE* file, void* address);
791
+ static void fxDumpChunkArray(FILE* file, txByte* data, txSize size);
792
+ static void fxDumpChunkData(FILE* file, txByte* data, txSize size);
793
+ static void fxDumpChunkString(FILE* file, txByte* data, txSize size);
794
+ static void fxDumpChunkTable(FILE* file, txByte* data, txSize size);
795
+ static void fxDumpID(FILE* file, txID id);
796
+ static void fxDumpNumber(FILE* file, txNumber value);
797
+ static void fxDumpSlot(FILE* file, txSlot* slot);
798
+ static void fxDumpSlotAddress(FILE* file, void* address);
799
+ static void fxDumpSlotTable(FILE* file, txByte* buffer, txSize size);
800
+
801
+ void fxDumpSnapshot(txMachine* the, txSnapshot* snapshot)
802
+ {
803
+ Atom atom;
804
+ txByte byte;
805
+ txID profileID;
806
+ txCreation creation;
807
+ Atom blockAtom;
808
+ txByte* block = C_NULL;
809
+ // txByte* blockLimit;
810
+ Atom heapAtom;
811
+ txSlot* heap = C_NULL;
812
+ txSlot* heapLimit;
813
+ Atom stackAtom;
814
+ txSlot* stack = C_NULL;
815
+ txSlot* stackLimit;
816
+
817
+ txSlot* current;
818
+
819
+ txByte* buffer = C_NULL;
820
+ txByte* address;
821
+ txSize offset, size;
822
+ txString string;
823
+
824
+ mxTry(the) {
825
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
826
+ atom.atomSize = ntohl(atom.atomSize) - 8;
827
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
828
+
829
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
830
+ atom.atomSize = ntohl(atom.atomSize) - 8;
831
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
832
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
833
+ fprintf(stderr, "\t%d.", byte);
834
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
835
+ fprintf(stderr, "%d.", byte);
836
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
837
+ fprintf(stderr, "%d ", byte);
838
+ mxThrowIf((*snapshot->read)(snapshot->stream, &byte, 1));
839
+ fprintf(stderr, "(%d)\n", byte);
840
+
841
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
842
+ atom.atomSize = ntohl(atom.atomSize) - 8;
843
+ buffer = c_malloc(atom.atomSize);
844
+ mxThrowIf(buffer == C_NULL);
845
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
846
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
847
+ fprintf(stderr, "\t%s\n", (txString)buffer);
848
+ c_free(buffer);
849
+
850
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
851
+ atom.atomSize = ntohl(atom.atomSize) - 8;
852
+ mxThrowIf((*snapshot->read)(snapshot->stream, &creation, sizeof(txCreation)));
853
+ mxThrowIf((*snapshot->read)(snapshot->stream, &profileID, sizeof(txID)));
854
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
855
+ fprintf(stderr, "\tinitialChunkSize: %d\n", creation.initialChunkSize);
856
+ fprintf(stderr, "\tincrementalChunkSize: %d\n", creation.incrementalChunkSize);
857
+ fprintf(stderr, "\tinitialHeapCount: %d\n", creation.initialHeapCount);
858
+ fprintf(stderr, "\tincrementalHeapCount: %d\n", creation.incrementalHeapCount);
859
+ fprintf(stderr, "\tstackCount: %d\n", creation.stackCount);
860
+ fprintf(stderr, "\tinitialKeyCount: %d\n", creation.initialKeyCount);
861
+ fprintf(stderr, "\tincrementalKeyCount: %d\n", creation.incrementalKeyCount);
862
+ fprintf(stderr, "\tnameModulo: %d\n", creation.nameModulo);
863
+ fprintf(stderr, "\tsymbolModulo: %d\n", creation.symbolModulo);
864
+ fprintf(stderr, "\tparserBufferSize: %d\n", creation.parserBufferSize);
865
+ fprintf(stderr, "\tparserTableModulo: %d\n", creation.parserTableModulo);
866
+ fprintf(stderr, "\tstaticSize: %d\n", creation.staticSize);
867
+ fprintf(stderr, "\tprofileID: %d\n", profileID);
868
+
869
+ mxThrowIf((*snapshot->read)(snapshot->stream, &blockAtom, sizeof(Atom)));
870
+ blockAtom.atomSize = ntohl(blockAtom.atomSize) - 8;
871
+ block = c_malloc(blockAtom.atomSize);
872
+ mxThrowIf(block == C_NULL);
873
+ mxThrowIf((*snapshot->read)(snapshot->stream, block, blockAtom.atomSize));
874
+ // blockLimit = block + blockAtom.atomSize;
875
+
876
+ mxThrowIf((*snapshot->read)(snapshot->stream, &heapAtom, sizeof(Atom)));
877
+ heapAtom.atomSize = ntohl(heapAtom.atomSize) - 8;
878
+ heap = c_malloc(sizeof(txSlot) + heapAtom.atomSize);
879
+ mxThrowIf(heap == C_NULL);
880
+ c_memset(heap, 0, sizeof(txSlot));
881
+ mxThrowIf((*snapshot->read)(snapshot->stream, heap + 1, heapAtom.atomSize));
882
+ heapLimit = heap + 1 + (heapAtom.atomSize / sizeof(txSlot));
883
+
884
+ mxThrowIf((*snapshot->read)(snapshot->stream, &stackAtom, sizeof(Atom)));
885
+ stackAtom.atomSize = ntohl(stackAtom.atomSize) - 8;
886
+ stack = c_malloc(stackAtom.atomSize);
887
+ mxThrowIf(stack == C_NULL);
888
+ mxThrowIf((*snapshot->read)(snapshot->stream, stack, stackAtom.atomSize));
889
+ stackLimit = stack + (stackAtom.atomSize / sizeof(txSlot));
890
+
891
+ current = heap;
892
+ while (current < heapLimit) {
893
+ fxDumpChunk(current, block);
894
+ current++;
895
+ }
896
+ current = stack;
897
+ while (current < stackLimit) {
898
+ fxDumpChunk(current, block);
899
+ current++;
900
+ }
901
+
902
+ fprintf(stderr, "%4.4s %d\n", (txString)&(blockAtom.atomType), blockAtom.atomSize + 8);
903
+ address = block;
904
+ offset = 0;
905
+ while (offset < blockAtom.atomSize) {
906
+ txChunk* chunk = (txChunk*)address;
907
+ fprintf(stderr, "\t<%8.8lu> %8d ", offset + sizeof(txChunk), chunk->size);
908
+ if (chunk->temporary)
909
+ (*(txDumpChunk)(chunk->temporary))(stderr, address + sizeof(txChunk), chunk->size - sizeof(txChunk));
910
+ else
911
+ fxDumpChunkData(stderr, address + sizeof(txChunk), chunk->size - sizeof(txChunk));
912
+ // fxDumpChunkData(stderr, address + sizeof(txChunk), chunk->size - sizeof(txChunk));
913
+ fprintf(stderr, "\n");
914
+ address += chunk->size;
915
+ offset += chunk->size;
916
+ }
917
+
918
+ fprintf(stderr, "%4.4s %d\n", (txString)&(heapAtom.atomType), heapAtom.atomSize + 8);
919
+ current = heap;
920
+ offset = 0;
921
+ while (current < heapLimit) {
922
+ fprintf(stderr, "\t[%8.8d] ", offset);
923
+ fxDumpSlotAddress(stderr, current->next);
924
+ fprintf(stderr, " ");
925
+ fxDumpSlot(stderr, current);
926
+ fprintf(stderr, "\n");
927
+ current++;
928
+ offset++;
929
+ }
930
+
931
+ fprintf(stderr, "%4.4s %d\n", (txString)&(stackAtom.atomType), stackAtom.atomSize + 8);
932
+ current = stack;
933
+ while (current < stackLimit) {
934
+ fprintf(stderr, "\t ");
935
+ fxDumpSlotAddress(stderr, current->next);
936
+ fprintf(stderr, " ");
937
+ fxDumpSlot(stderr, current);
938
+ fprintf(stderr, "\n");
939
+ current++;
940
+ }
941
+
942
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
943
+ atom.atomSize = ntohl(atom.atomSize) - 8;
944
+ buffer = c_malloc(atom.atomSize);
945
+ mxThrowIf(buffer == C_NULL);
946
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
947
+ fprintf(stderr, "%4.4s %d\n", (txString)&(atom.atomType), atom.atomSize + 8);
948
+ address = buffer;
949
+ offset = 0;
950
+ size = atom.atomSize / sizeof(txSlot*);
951
+ while (offset < size) {
952
+ txSlot* slot = *((txSlot**)address);
953
+ fprintf(stderr, "\tID_%6.6d", offset);
954
+ if (slot) {
955
+ fprintf(stderr, " [%8.8zu]", (size_t)slot);
956
+ slot = ((txSlot*)heap) + (size_t)slot;
957
+ string = ((txString)block) + (size_t)(slot->value.key.string);
958
+ fprintf(stderr, " %s\n", string);
959
+ }
960
+ else
961
+ fprintf(stderr, " [ ]\n");
962
+ address += sizeof(txSlot*);
963
+ offset++;
964
+ }
965
+ c_free(buffer);
966
+ buffer = C_NULL;
967
+
968
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
969
+ atom.atomSize = ntohl(atom.atomSize) - 8;
970
+ buffer = c_malloc(atom.atomSize);
971
+ mxThrowIf(buffer == C_NULL);
972
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
973
+ fprintf(stderr, "%4.4s %d", (txString)&(atom.atomType), atom.atomSize + 8);
974
+ fxDumpSlotTable(stderr, buffer, atom.atomSize);
975
+ fprintf(stderr, "\n");
976
+
977
+ mxThrowIf((*snapshot->read)(snapshot->stream, &atom, sizeof(Atom)));
978
+ atom.atomSize = ntohl(atom.atomSize) - 8;
979
+ buffer = c_malloc(atom.atomSize);
980
+ mxThrowIf(buffer == C_NULL);
981
+ mxThrowIf((*snapshot->read)(snapshot->stream, buffer, atom.atomSize));
982
+ fprintf(stderr, "%4.4s %d", (txString)&(atom.atomType), atom.atomSize + 8);
983
+ fxDumpSlotTable(stderr, buffer, atom.atomSize);
984
+ fprintf(stderr, "\n");
985
+
986
+ c_free(stack);
987
+ c_free(heap);
988
+ c_free(block);
989
+ }
990
+ mxCatch(the) {
991
+ if (buffer)
992
+ c_free(buffer);
993
+ if (stack)
994
+ c_free(stack);
995
+ if (heap)
996
+ c_free(heap);
997
+ if (block)
998
+ c_free(block);
999
+ }
1000
+ }
1001
+
1002
+ void fxDumpChunk(txSlot* slot, txByte* block)
1003
+ {
1004
+ txChunk* chunk;
1005
+ switch (slot->kind) {
1006
+ case XS_STRING_KIND: {
1007
+ chunk = (txChunk*)(block + (size_t)(slot->value.string) - sizeof(txChunk));
1008
+ chunk->temporary = (txByte*)fxDumpChunkString;
1009
+ } break;
1010
+ case XS_BIGINT_KIND: {
1011
+ chunk = (txChunk*)(block + (size_t)(slot->value.bigint.data) - sizeof(txChunk));
1012
+ chunk->temporary = (txByte*)fxDumpChunkData;
1013
+ } break;
1014
+ case XS_ARGUMENTS_SLOPPY_KIND:
1015
+ case XS_ARGUMENTS_STRICT_KIND:
1016
+ case XS_ARRAY_KIND:
1017
+ case XS_STACK_KIND: {
1018
+ if (slot->value.array.address) {
1019
+ chunk = (txChunk*)(block + (size_t)(slot->value.array.address) - sizeof(txChunk));
1020
+ chunk->temporary = (txByte*)fxDumpChunkArray;
1021
+
1022
+ {
1023
+ txIndex size = chunk->size / sizeof(txSlot);
1024
+ txSlot* item = (txSlot*)(block + (size_t)(slot->value.array.address));
1025
+ while (size) {
1026
+ fxDumpChunk(item, block);
1027
+ size--;
1028
+ item++;
1029
+ }
1030
+ }
1031
+
1032
+ }
1033
+ } break;
1034
+ case XS_ARRAY_BUFFER_KIND: {
1035
+ if (slot->value.arrayBuffer.address) {
1036
+ chunk = (txChunk*)(block + (size_t)(slot->value.arrayBuffer.address) - sizeof(txChunk));
1037
+ chunk->temporary = (txByte*)fxDumpChunkData;
1038
+ }
1039
+ } break;
1040
+ case XS_CODE_KIND: {
1041
+ chunk = (txChunk*)(block + (size_t)(slot->value.code.address) - sizeof(txChunk));
1042
+ chunk->temporary = (txByte*)fxDumpChunkData;
1043
+ } break;
1044
+ case XS_REGEXP_KIND: {
1045
+ if (slot->value.regexp.code) {
1046
+ chunk = (txChunk*)(block + (size_t)(slot->value.regexp.code) - sizeof(txChunk));
1047
+ chunk->temporary = (txByte*)fxDumpChunkData;
1048
+ }
1049
+ if (slot->value.regexp.data) {
1050
+ chunk = (txChunk*)(block + (size_t)(slot->value.regexp.data) - sizeof(txChunk));
1051
+ chunk->temporary = (txByte*)fxDumpChunkData;
1052
+ }
1053
+ } break;
1054
+ case XS_KEY_KIND: {
1055
+ if (slot->value.key.string) {
1056
+ chunk = (txChunk*)(block + (size_t)(slot->value.key.string) - sizeof(txChunk));
1057
+ chunk->temporary = (txByte*)fxDumpChunkString;
1058
+ }
1059
+ } break;
1060
+ case XS_GLOBAL_KIND:
1061
+ case XS_MAP_KIND:
1062
+ case XS_SET_KIND: {
1063
+ chunk = (txChunk*)(block + (size_t)(slot->value.table.address) - sizeof(txChunk));
1064
+ chunk->temporary = (txByte*)fxDumpChunkTable;
1065
+ } break;
1066
+ case XS_HOST_KIND: {
1067
+ if (slot->value.host.data) {
1068
+ chunk = (txChunk*)(block + (size_t)(slot->value.host.data) - sizeof(txChunk));
1069
+ chunk->temporary = (txByte*)fxDumpChunkData;
1070
+ }
1071
+ } break;
1072
+ default:
1073
+ break;
1074
+ }
1075
+ }
1076
+
1077
+ void fxDumpChunkAddress(FILE* file, void* address)
1078
+ {
1079
+ if (address)
1080
+ fprintf(file, "<%8.8zu>", (size_t)address);
1081
+ else
1082
+ fprintf(file, "< >");
1083
+ }
1084
+
1085
+ void fxDumpChunkArray(FILE* file, txByte* data, txSize size)
1086
+ {
1087
+ txSize offset = 0;
1088
+ txSlot* slot = (txSlot*)data;
1089
+ size /= sizeof(txSlot);
1090
+ while (offset < size) {
1091
+ fprintf(file, "\n\t\t%8zu ", (size_t)slot->next);
1092
+ fxDumpSlot(file, slot);
1093
+ offset++;
1094
+ slot++;
1095
+ }
1096
+ }
1097
+
1098
+ void fxDumpChunkData(FILE* file, txByte* data, txSize size)
1099
+ {
1100
+ txSize offset = 0;
1101
+ txU1* address = (txU1*)data;
1102
+ while (offset < size) {
1103
+ if (offset % 32)
1104
+ fprintf(file, " ");
1105
+ else
1106
+ fprintf(file, "\n\t\t");
1107
+ fprintf(file, "%2.2x", address[offset]);
1108
+ offset++;
1109
+ }
1110
+ }
1111
+
1112
+ void fxDumpChunkString(FILE* file, txByte* data, txSize size)
1113
+ {
1114
+ fprintf(file, " %s", data);
1115
+ }
1116
+
1117
+ void fxDumpChunkTable(FILE* file, txByte* data, txSize size)
1118
+ {
1119
+ txSize offset = 0;
1120
+ txSlot** address = (txSlot**)data;
1121
+ size /= sizeof(txSlot*);
1122
+ while (offset < size) {
1123
+ txSlot* slot = *((txSlot**)address);
1124
+ if (offset % 8)
1125
+ fprintf(file, " ");
1126
+ else
1127
+ fprintf(file, "\n\t\t");
1128
+ fxDumpSlotAddress(file, slot);
1129
+ offset++;
1130
+ address++;
1131
+ }
1132
+ }
1133
+
1134
+ void fxDumpID(FILE* file, txID id)
1135
+ {
1136
+ if (id == 0)
1137
+ fprintf(file, " ");
1138
+ else
1139
+ fprintf(file, "ID_%6.6d", id);
1140
+ }
1141
+
1142
+ void fxDumpNumber(FILE* file, txNumber value)
1143
+ {
1144
+ switch (c_fpclassify(value)) {
1145
+ case C_FP_INFINITE:
1146
+ if (value < 0)
1147
+ fprintf(file, "-C_INFINITY");
1148
+ else
1149
+ fprintf(file, "C_INFINITY");
1150
+ break;
1151
+ case C_FP_NAN:
1152
+ fprintf(file, "C_NAN");
1153
+ break;
1154
+ default:
1155
+ fprintf(file, "%.20e", value);
1156
+ break;
1157
+ }
1158
+ }
1159
+
1160
+ void fxDumpSlot(FILE* file, txSlot* slot)
1161
+ {
1162
+ if (slot->flag & XS_MARK_FLAG)
1163
+ fprintf(file, "M");
1164
+ else
1165
+ fprintf(file, "_");
1166
+ if (slot->kind == XS_INSTANCE_KIND) {
1167
+ if (slot->flag & XS_DONT_MARSHALL_FLAG)
1168
+ fprintf(file, "H");
1169
+ else
1170
+ fprintf(file, "_");
1171
+ if (slot->flag & XS_LEVEL_FLAG)
1172
+ fprintf(file, "L");
1173
+ else
1174
+ fprintf(file, "_");
1175
+ if (slot->flag & XS_DONT_PATCH_FLAG)
1176
+ fprintf(file, "P");
1177
+ else
1178
+ fprintf(file, "_");
1179
+ if (slot->flag & XS_FIELD_FLAG)
1180
+ fprintf(file, "F");
1181
+ else
1182
+ fprintf(file, "_");
1183
+ if (slot->flag & XS_CAN_CONSTRUCT_FLAG)
1184
+ fprintf(file, "N");
1185
+ else
1186
+ fprintf(file, "_");
1187
+ if (slot->flag & XS_CAN_CALL_FLAG)
1188
+ fprintf(file, "C");
1189
+ else
1190
+ fprintf(file, "_");
1191
+ if (slot->flag & XS_EXOTIC_FLAG)
1192
+ fprintf(file, "X");
1193
+ else
1194
+ fprintf(file, "_");
1195
+ }
1196
+ else {
1197
+ if (slot->flag & XS_DERIVED_FLAG)
1198
+ fprintf(file, "H");
1199
+ else
1200
+ fprintf(file, "_");
1201
+ if (slot->flag & XS_BASE_FLAG)
1202
+ fprintf(file, "B");
1203
+ else
1204
+ fprintf(file, "_");
1205
+ if (slot->flag & XS_INSPECTOR_FLAG)
1206
+ fprintf(file, "L");
1207
+ else
1208
+ fprintf(file, "_");
1209
+ if (slot->flag & XS_DONT_SET_FLAG)
1210
+ fprintf(file, "S");
1211
+ else
1212
+ fprintf(file, "_");
1213
+ if (slot->flag & XS_DONT_ENUM_FLAG)
1214
+ fprintf(file, "E");
1215
+ else
1216
+ fprintf(file, "_");
1217
+ if (slot->flag & XS_DONT_DELETE_FLAG)
1218
+ fprintf(file, "D");
1219
+ else
1220
+ fprintf(file, "_");
1221
+ if (slot->flag & XS_INTERNAL_FLAG)
1222
+ fprintf(file, "I");
1223
+ else
1224
+ fprintf(file, "_");
1225
+
1226
+ }
1227
+ fprintf(file, " ");
1228
+ fxDumpID(file, slot->ID);
1229
+ fprintf(file, " ");
1230
+ switch (slot->kind) {
1231
+ case XS_UNINITIALIZED_KIND: {
1232
+ fprintf(file, "unititialized");
1233
+ } break;
1234
+ case XS_UNDEFINED_KIND: {
1235
+ fprintf(file, "undefined");
1236
+ } break;
1237
+ case XS_NULL_KIND: {
1238
+ fprintf(file, "null");
1239
+ } break;
1240
+ case XS_BOOLEAN_KIND: {
1241
+ fprintf(file, "boolean = %d", slot->value.boolean);
1242
+ } break;
1243
+ case XS_INTEGER_KIND: {
1244
+ fprintf(file, "integer = %d", slot->value.integer);
1245
+ } break;
1246
+ case XS_NUMBER_KIND: {
1247
+ fprintf(file, "number = ");
1248
+ fxDumpNumber(file, slot->value.number);
1249
+ } break;
1250
+ case XS_STRING_KIND: {
1251
+ fprintf(file, "string = ");
1252
+ fxDumpChunkAddress(file, slot->value.string);
1253
+ } break;
1254
+ case XS_SYMBOL_KIND: {
1255
+ fprintf(file, "symbol = ");
1256
+ fxDumpID(file, slot->value.symbol);
1257
+ } break;
1258
+ case XS_BIGINT_KIND: {
1259
+ fprintf(file, "bigint = { .data = ");
1260
+ fxDumpChunkAddress(file, slot->value.bigint.data);
1261
+ fprintf(file, ", .size = %d, ", slot->value.bigint.size);
1262
+ fprintf(file, ".sign = %d, ", slot->value.bigint.sign);
1263
+ fprintf(file, " }");
1264
+ } break;
1265
+ case XS_REFERENCE_KIND: {
1266
+ fprintf(file, "reference = ");
1267
+ fxDumpSlotAddress(file, slot->value.reference);
1268
+ } break;
1269
+ case XS_CLOSURE_KIND: {
1270
+ fprintf(file, "closure = ");
1271
+ fxDumpSlotAddress(file, slot->value.closure);
1272
+ } break;
1273
+ case XS_INSTANCE_KIND: {
1274
+ fprintf(file, "instance = { .garbage = ");
1275
+ fxDumpSlotAddress(file, slot->value.instance.garbage);
1276
+ fprintf(file, ", .prototype = ");
1277
+ fxDumpSlotAddress(file, slot->value.instance.prototype);
1278
+ fprintf(file, " }");
1279
+ } break;
1280
+ case XS_ARGUMENTS_SLOPPY_KIND:
1281
+ case XS_ARGUMENTS_STRICT_KIND:
1282
+ case XS_ARRAY_KIND: {
1283
+ fprintf(file, "array = { .address = ");
1284
+ fxDumpChunkAddress(file, slot->value.array.address);
1285
+ fprintf(file, ", .length = %d }", (int)slot->value.array.length);
1286
+ } break;
1287
+ case XS_ARRAY_BUFFER_KIND: {
1288
+ fprintf(file, "arrayBuffer = { .address = ");
1289
+ fxDumpChunkAddress(file, slot->value.arrayBuffer.address);
1290
+ fprintf(file, " }");
1291
+ } break;
1292
+ case XS_BUFFER_INFO_KIND: {
1293
+ fprintf(file, "bufferInfo = { .length = %d, maxLength = %d }", slot->value.bufferInfo.length, slot->value.bufferInfo.maxLength);
1294
+ } break;
1295
+ case XS_CALLBACK_KIND: {
1296
+ fprintf(file, "callback");
1297
+ } break;
1298
+ case XS_CODE_KIND: {
1299
+ fprintf(file, "code = { .address = ");
1300
+ fxDumpChunkAddress(file, slot->value.code.address);
1301
+ fprintf(file, ", .closures = ");
1302
+ fxDumpSlotAddress(file, slot->value.code.closures);
1303
+ fprintf(file, " }");
1304
+ } break;
1305
+ case XS_DATE_KIND: {
1306
+ fprintf(file, "date = ");
1307
+ fxDumpNumber(file, slot->value.number);
1308
+ } break;
1309
+ case XS_DATA_VIEW_KIND: {
1310
+ fprintf(file, "dataView = { .offset = %d, .size = %d }", slot->value.dataView.offset, slot->value.dataView.size);
1311
+ } break;
1312
+ case XS_FINALIZATION_CELL_KIND: {
1313
+ fprintf(file, "finalizationCell = { .target = ");
1314
+ fxDumpSlotAddress(file, slot->value.finalizationCell.target);
1315
+ fprintf(file, ", .token = ");
1316
+ fxDumpSlotAddress(file, slot->value.finalizationCell.token);
1317
+ fprintf(file, " }");
1318
+ } break;
1319
+ case XS_FINALIZATION_REGISTRY_KIND: {
1320
+ fprintf(file, "finalizationRegistry = { .target = ");
1321
+ fxDumpSlotAddress(file, slot->value.finalizationRegistry.callback);
1322
+ fprintf(file, ", .flags = %d }", slot->value.finalizationRegistry.flags);
1323
+ } break;
1324
+ case XS_GLOBAL_KIND: {
1325
+ fprintf(file, "global = { .address = ");
1326
+ fxDumpChunkAddress(file, slot->value.table.address);
1327
+ fprintf(file, ", .length = %d }", (int)slot->value.table.length);
1328
+ } break;
1329
+ case XS_MAP_KIND: {
1330
+ fprintf(file, "map = { .address = ");
1331
+ fxDumpChunkAddress(file, slot->value.table.address);
1332
+ fprintf(file, ", .length = %d }", (int)slot->value.table.length);
1333
+ } break;
1334
+ case XS_MODULE_KIND: {
1335
+ fprintf(file, "module = { .realm = ");
1336
+ fxDumpSlotAddress(file, slot->value.module.realm);
1337
+ fprintf(file, ", .id = ");
1338
+ fxDumpID(file, slot->value.module.id);
1339
+ fprintf(file, " }");
1340
+ } break;
1341
+ case XS_PROGRAM_KIND: {
1342
+ fprintf(file, "program = { .realm = ");
1343
+ fxDumpSlotAddress(file, slot->value.module.realm);
1344
+ fprintf(file, ", .id = ");
1345
+ fxDumpID(file, slot->value.module.id);
1346
+ fprintf(file, " }");
1347
+ } break;
1348
+ case XS_PROMISE_KIND: {
1349
+ fprintf(file, "promise = %d }", slot->value.integer);
1350
+ } break;
1351
+ case XS_PROXY_KIND: {
1352
+ fprintf(file, "proxy = { .handler = ");
1353
+ fxDumpSlotAddress(file, slot->value.proxy.handler);
1354
+ fprintf(file, ", .target = ");
1355
+ fxDumpSlotAddress(file, slot->value.proxy.target);
1356
+ fprintf(file, " }");
1357
+ } break;
1358
+ case XS_REGEXP_KIND: {
1359
+ fprintf(file, "regexp = { .code = ");
1360
+ fxDumpChunkAddress(file, slot->value.regexp.code);
1361
+ fprintf(file, ", .data = ");
1362
+ fxDumpChunkAddress(file, slot->value.regexp.data);
1363
+ fprintf(file, " }");
1364
+ } break;
1365
+ case XS_SET_KIND: {
1366
+ fprintf(file, "set = { .address = ");
1367
+ fxDumpChunkAddress(file, slot->value.table.address);
1368
+ fprintf(file, ", .length = %d }", (int)slot->value.table.length);
1369
+ } break;
1370
+ case XS_TYPED_ARRAY_KIND: {
1371
+ fprintf(file, ".kind = XS_TYPED_ARRAY_KIND}, ");
1372
+ fprintf(file, ".value = { .typedArray = { .dispatch = gxTypeDispatches[%zu], .atomics = gxTypeAtomics[%zu] }", (size_t)slot->value.typedArray.dispatch, (size_t)slot->value.typedArray.atomics);
1373
+ } break;
1374
+ case XS_WEAK_MAP_KIND: {
1375
+ fprintf(file, "weakMap = { .first = ");
1376
+ fxDumpSlotAddress(file, slot->value.weakList.first);
1377
+ fprintf(file, ", .link = ");
1378
+ fxDumpSlotAddress(file, slot->value.weakList.link);
1379
+ fprintf(file, " }");
1380
+ } break;
1381
+ case XS_WEAK_SET_KIND: {
1382
+ fprintf(file, "weakSet = { .first = ");
1383
+ fxDumpSlotAddress(file, slot->value.weakList.first);
1384
+ fprintf(file, ", .link = ");
1385
+ fxDumpSlotAddress(file, slot->value.weakList.link);
1386
+ fprintf(file, " }");
1387
+ } break;
1388
+ case XS_WEAK_REF_KIND: {
1389
+ fprintf(file, "weakRef = { .target = ");
1390
+ fxDumpSlotAddress(file, slot->value.weakRef.target);
1391
+ fprintf(file, ", .link = ");
1392
+ fxDumpSlotAddress(file, slot->value.weakRef.link);
1393
+ fprintf(file, " }");
1394
+ } break;
1395
+ case XS_ACCESSOR_KIND: {
1396
+ fprintf(file, "accessor = { .getter = ");
1397
+ fxDumpSlotAddress(file, slot->value.accessor.getter);
1398
+ fprintf(file, ", .setter = ");
1399
+ fxDumpSlotAddress(file, slot->value.accessor.setter);
1400
+ fprintf(file, " }");
1401
+ } break;
1402
+ case XS_AT_KIND: {
1403
+ fprintf(file, "at = { 0x%x, %d }", slot->value.at.index, slot->value.at.id);
1404
+ } break;
1405
+ case XS_ENTRY_KIND: {
1406
+ fprintf(file, "entry = { ");
1407
+ fxDumpSlotAddress(file, slot->value.entry.slot);
1408
+ fprintf(file, ", 0x%x }", slot->value.entry.sum);
1409
+ } break;
1410
+ case XS_ERROR_KIND: {
1411
+ fprintf(file, "error = { ");
1412
+ fxDumpSlotAddress(file, slot->value.error.info);
1413
+ fprintf(file, ", %d }", slot->value.error.which);
1414
+ } break;
1415
+ case XS_EXPORT_KIND: {
1416
+ fprintf(file, "export = { .closure = ");
1417
+ fxDumpSlotAddress(file, slot->value.export.closure);
1418
+ fprintf(file, ", .module = ");
1419
+ fxDumpSlotAddress(file, slot->value.export.module);
1420
+ fprintf(file, " }");
1421
+ } break;
1422
+ case XS_HOME_KIND: {
1423
+ fprintf(file, "home = { .object = ");
1424
+ fxDumpSlotAddress(file, slot->value.home.object);
1425
+ fprintf(file, ", .module = ");
1426
+ fxDumpSlotAddress(file, slot->value.home.module);
1427
+ fprintf(file, " }");
1428
+ } break;
1429
+ case XS_KEY_KIND: {
1430
+ fprintf(file, "key = { .string = ");
1431
+ fxDumpChunkAddress(file, slot->value.key.string);
1432
+ fprintf(file, ", .sum = 0x%x }", slot->value.key.sum);
1433
+ } break;
1434
+ case XS_LIST_KIND: {
1435
+ fprintf(file, "list = { .first = ");
1436
+ fxDumpSlotAddress(file, slot->value.list.first);
1437
+ fprintf(file, ", .last = ");
1438
+ fxDumpSlotAddress(file, slot->value.list.last);
1439
+ fprintf(file, " }");
1440
+ } break;
1441
+ case XS_PRIVATE_KIND: {
1442
+ fprintf(file, "private = { .check = ");
1443
+ fxDumpSlotAddress(file, slot->value.private.check);
1444
+ fprintf(file, ", .first = ");
1445
+ fxDumpSlotAddress(file, slot->value.private.first);
1446
+ fprintf(file, " }");
1447
+ } break;
1448
+ case XS_STACK_KIND: {
1449
+ fprintf(file, "stack = { .address = ");
1450
+ fxDumpChunkAddress(file, slot->value.array.address);
1451
+ fprintf(file, ", .length = %d }", (int)slot->value.array.length);
1452
+ } break;
1453
+ case XS_WEAK_ENTRY_KIND: {
1454
+ fprintf(file, "weakEntry = { .check = ");
1455
+ fxDumpSlotAddress(file, slot->value.weakEntry.check);
1456
+ fprintf(file, ", .value = ");
1457
+ fxDumpSlotAddress(file, slot->value.weakEntry.value);
1458
+ fprintf(file, " }");
1459
+ } break;
1460
+ case XS_HOST_KIND: {
1461
+ fprintf(file, "host = { .data = ");
1462
+ fxDumpChunkAddress(file, slot->value.host.data);
1463
+ fprintf(file, " }");
1464
+ } break;
1465
+ default:
1466
+ break;
1467
+ }
1468
+ }
1469
+
1470
+ void fxDumpSlotAddress(FILE* file, void* address)
1471
+ {
1472
+ if (address)
1473
+ fprintf(file, "[%8.8zu]", (size_t)address);
1474
+ else
1475
+ fprintf(file, "[ ]");
1476
+ }
1477
+
1478
+ void fxDumpSlotTable(FILE* file, txByte* buffer, txSize size)
1479
+ {
1480
+ txSize offset = 0;
1481
+ txSlot** address = (txSlot**)buffer;
1482
+ size /= sizeof(txSlot*);
1483
+ while (offset < size) {
1484
+ txSlot* slot = *((txSlot**)address);
1485
+ if (offset % 8)
1486
+ fprintf(file, " ");
1487
+ else
1488
+ fprintf(file, "\n\t");
1489
+ fxDumpSlotAddress(file, slot);
1490
+ offset++;
1491
+ address++;
1492
+ }
1493
+ }
1494
+
1495
+
1496
+