@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,2710 @@
1
+ /*
2
+ * Copyright (c) 2016-2022 Moddable Tech, Inc.
3
+ *
4
+ * This file is part of the Moddable SDK Runtime.
5
+ *
6
+ * The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU Lesser General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>.
18
+ *
19
+ * This file incorporates work covered by the following copyright and
20
+ * permission notice:
21
+ *
22
+ * Copyright (C) 2010-2016 Marvell International Ltd.
23
+ * Copyright (C) 2002-2010 Kinoma, Inc.
24
+ *
25
+ * Licensed under the Apache License, Version 2.0 (the "License");
26
+ * you may not use this file except in compliance with the License.
27
+ * You may obtain a copy of the License at
28
+ *
29
+ * http://www.apache.org/licenses/LICENSE-2.0
30
+ *
31
+ * Unless required by applicable law or agreed to in writing, software
32
+ * distributed under the License is distributed on an "AS IS" BASIS,
33
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
+ * See the License for the specific language governing permissions and
35
+ * limitations under the License.
36
+ */
37
+
38
+ #include "xsAll.h"
39
+
40
+ #if MODDEF_XS_TEST
41
+ #undef MODDEF_XS_XSBUG_HOOKS
42
+ #define MODDEF_XS_XSBUG_HOOKS 1
43
+ #endif
44
+
45
+ #if defined(DEBUG_EFM)
46
+ char _lastDebugStrBuffer[256];
47
+ char _debugStrBuffer[256];
48
+ #endif
49
+ static void fxVReportException(void* console, txString thePath, txInteger theLine, txString theFormat, c_va_list theArguments);
50
+
51
+ #if defined(mxInstrument) || defined (mxDebug)
52
+ static const char gxHexaDigits[] ICACHE_FLASH_ATTR = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
53
+ #endif
54
+
55
+ #ifdef mxDebug
56
+ static void fxClearAllBreakpoints(txMachine* the);
57
+ static void fxClearBreakpoint(txMachine* the, txString thePath, txInteger theLine);
58
+ static void fxDebugParse(txMachine* the);
59
+ static void fxDebugParseTag(txMachine* the, txString name);
60
+ static void fxDebugPopTag(txMachine* the);
61
+ static void fxDebugPushTag(txMachine* the);
62
+ static void fxDebugScriptCDATA(txMachine* the, char c);
63
+ static void fxEcho(txMachine* the, txString theString);
64
+ static void fxEchoAddress(txMachine* the, txSlot* theSlot);
65
+ static void fxEchoBigInt(txMachine* the, txBigInt* bigint);
66
+ static void fxEchoCharacter(txMachine* the, char theCharacter);
67
+ static void fxEchoFlags(txMachine* the, txString state, txFlag flag);
68
+ static void fxEchoFormat(txMachine* the, txString theFormat, c_va_list theArguments);
69
+ static void fxEchoFrameName(txMachine* the, txSlot* theFrame);
70
+ static void fxEchoFramePathLine(txMachine* the, txSlot* theFrame);
71
+ static void fxEchoInteger(txMachine* the, txInteger theInteger);
72
+ static void fxEchoInstance(txMachine* the, txSlot* theInstance, txInspectorNameList* theList);
73
+ static void fxEchoModule(txMachine* the, txSlot* module, txInspectorNameList* list);
74
+ static void fxEchoNumber(txMachine* the, txNumber theNumber);
75
+ static void fxEchoPathLine(txMachine* the, txString thePath, txInteger theLine);
76
+ static void fxEchoProperty(txMachine* the, txSlot* theProperty, txInspectorNameList* theList, txString thePrefix, txIndex theIndex, txString theSuffix);
77
+ static void fxEchoPropertyHost(txMachine* the, txInspectorNameList* theList, txSlot* theInstance, txSlot* theHost);
78
+ static void fxEchoPropertyInstance(txMachine* the, txInspectorNameList* theList, txString thePrefix, txIndex theIndex, txString theSuffix, txID theID, txFlag theFlag, txSlot* theInstance);
79
+ static void fxEchoStart(txMachine* the);
80
+ static void fxEchoStop(txMachine* the);
81
+ static void fxEchoString(txMachine* the, txString theString);
82
+ static txSlot* fxFindFrame(txMachine* the);
83
+ static txSlot* fxFindRealm(txMachine* the);
84
+ static void fxGo(txMachine* the);
85
+ static void fxIndexToString(txMachine* the, txIndex theIndex, txString theBuffer, txSize theSize);
86
+ static void fxListFrames(txMachine* the);
87
+ static void fxListGlobal(txMachine* the);
88
+ static void fxListLocal(txMachine* the);
89
+ static void fxListModules(txMachine* the);
90
+ static void fxSetBreakpoint(txMachine* the, txString thePath, txInteger theLine);
91
+ static void fxSelect(txMachine* the, txSlot* slot);
92
+ static void fxStep(txMachine* the);
93
+ static void fxStepInside(txMachine* the);
94
+ static void fxStepOutside(txMachine* the);
95
+ static txSlot* fxToInstanceInspector(txMachine* the, txSlot* instance);
96
+ static void fxToggle(txMachine* the, txSlot* slot);
97
+ static void fxReportException(txMachine* the, txString thePath, txInteger theLine, txString theFormat, ...);
98
+
99
+ #define mxIsDigit(c) \
100
+ (('0' <= c) && (c <= '9'))
101
+ #define mxIsFirstLetter(c) \
102
+ ((('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z')) || (c == '_') || (c == ':'))
103
+ #define mxIsNextLetter(c) \
104
+ ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z')) || (c == '.') || (c == '-') || (c == '_') || (c == ':'))
105
+ #define mxIsSpace(c) \
106
+ ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))
107
+
108
+ enum {
109
+ XS_BODY_STATE = 0,
110
+ XS_CR_STATE,
111
+ XS_LF_STATE,
112
+ XS_TAG_STATE,
113
+ XS_START_TAG_NAME_STATE,
114
+ XS_START_TAG_SPACE_STATE,
115
+ XS_ATTRIBUTE_NAME_STATE,
116
+ XS_ATTRIBUTE_SPACE_STATE,
117
+ XS_ATTRIBUTE_EQUAL_STATE,
118
+ XS_ATTRIBUTE_VALUE_STATE,
119
+ XS_EMPTY_TAG_STATE,
120
+ XS_END_TAG_STATE,
121
+ XS_END_TAG_NAME_STATE,
122
+ XS_END_TAG_SPACE_STATE,
123
+ XS_PROCESSING_INSTRUCTION_STATE,
124
+ XS_PROCESSING_INSTRUCTION_SPACE_STATE,
125
+ XS_START_CDATA_STATE_1,
126
+ XS_START_CDATA_STATE_2,
127
+ XS_START_CDATA_STATE_3,
128
+ XS_START_CDATA_STATE_4,
129
+ XS_START_CDATA_STATE_5,
130
+ XS_START_CDATA_STATE_6,
131
+ XS_START_CDATA_STATE_7,
132
+ XS_CDATA_STATE,
133
+ XS_END_CDATA_STATE_1,
134
+ XS_END_CDATA_STATE_2,
135
+ XS_END_CDATA_STATE_3,
136
+ XS_ERROR_STATE
137
+ };
138
+
139
+ enum {
140
+ XS_ABORT_TAG = 0,
141
+ XS_BREAKPOINT_TAG,
142
+ XS_CLEAR_ALL_BREAKPOINTS_TAG,
143
+ XS_CLEAR_BREAKPOINTS_TAG,
144
+ XS_GO_TAG,
145
+ XS_IMPORT_TAG,
146
+ XS_LOGOUT_TAG,
147
+ XS_MODULE_TAG,
148
+ XS_SCRIPT_TAG,
149
+ XS_SET_BREAKPOINT_TAG,
150
+ XS_SET_ALL_BREAKPOINTS_TAG,
151
+ XS_SELECT_TAG,
152
+ XS_STEP_TAG,
153
+ XS_STEP_INSIDE_TAG,
154
+ XS_STEP_OUTSIDE_TAG,
155
+ XS_TOGGLE_TAG,
156
+ XS_START_PROFILING_TAG,
157
+ XS_STOP_PROFILING_TAG,
158
+ XS_UNKNOWN_TAG
159
+ };
160
+
161
+ enum {
162
+ XS_ID_ATTRIBUTE = 0,
163
+ XS_LINE_ATTRIBUTE,
164
+ XS_PATH_ATTRIBUTE,
165
+ XS_UNKNOWN_ATTRIBUTE
166
+ };
167
+
168
+ void fxCheck(txMachine* the, txString thePath, txInteger theLine)
169
+ {
170
+ #if mxWindows
171
+ printf("%s(%ld): fatal!\n", thePath, (int)theLine);
172
+ #else
173
+ c_printf("%s:%d: fatal!\n", thePath, (int)theLine);
174
+ #endif
175
+ fxAbort(the, XS_FATAL_CHECK_EXIT);
176
+ }
177
+
178
+ void fxClearAllBreakpoints(txMachine* the)
179
+ {
180
+ mxBreakpoints.value.list.first = C_NULL;
181
+ }
182
+
183
+ void fxClearBreakpoint(txMachine* the, txString thePath, txInteger theLine)
184
+ {
185
+ txID path;
186
+ txSlot** breakpointAddress;
187
+ txSlot* breakpoint;
188
+
189
+ if (!thePath)
190
+ return;
191
+ if (!c_strcmp(thePath, "exceptions")) {
192
+ the->breakOnExceptionsFlag = 0;
193
+ return;
194
+ }
195
+ if (!c_strcmp(thePath, "start")) {
196
+ the->breakOnStartFlag = 0;
197
+ return;
198
+ }
199
+ if ((theLine <= 0) || (0x00007FFF < theLine))
200
+ return;
201
+ path = fxFindName(the, thePath);
202
+ if (!path)
203
+ return;
204
+ breakpointAddress = &(mxBreakpoints.value.list.first);
205
+ while ((breakpoint = *breakpointAddress)) {
206
+ if ((breakpoint->ID == path) && (breakpoint->value.integer == theLine)) {
207
+ *breakpointAddress = breakpoint->next;
208
+ break;
209
+ }
210
+ breakpointAddress = &(breakpoint->next);
211
+ }
212
+ }
213
+
214
+ void fxDebugCommand(txMachine* the)
215
+ {
216
+ the->debugExit = 0;
217
+ the->debugModule = C_NULL;
218
+ while (fxIsConnected(the)) {
219
+ fxReceive(the);
220
+ fxDebugParse(the);
221
+ if ((the->debugState == XS_LF_STATE) && (the->debugExit > 0))
222
+ break;
223
+ }
224
+ mxHostInspectors.value.list.first = C_NULL;
225
+ mxHostInspectors.value.list.last = C_NULL;
226
+ #if MODDEF_XS_XSBUG_HOOKS
227
+ if (the->debugTag == XS_IMPORT_TAG)
228
+ fxQueueJob(the, 2, C_NULL);
229
+ else if (the->debugTag == XS_SCRIPT_TAG)
230
+ fxQueueJob(the, 6, C_NULL);
231
+ #endif
232
+ }
233
+
234
+ #if MODDEF_XS_XSBUG_HOOKS
235
+ void fxDebugImport(txMachine* the, txSlot* module, txString path)
236
+ {
237
+ if (!fxIsConnected(the))
238
+ return;
239
+ fxEchoStart(the);
240
+ fxEcho(the, "<import path=\"");
241
+ fxEcho(the, path + 8);
242
+ fxEcho(the, "\"/>");
243
+ fxEchoStop(the);
244
+ the->debugExit = 0;
245
+ the->debugModule = module;
246
+ while (fxIsConnected(the)) {
247
+ fxReceive(the);
248
+ fxDebugParse(the);
249
+ if ((the->debugState == XS_LF_STATE) && (the->debugExit > 1))
250
+ break;
251
+ }
252
+ if (the->debugTag == XS_MODULE_TAG){
253
+ mxRunCount(6);
254
+ mxPop();
255
+ }
256
+ }
257
+ #endif
258
+
259
+ void fxDebugLine(txMachine* the, txID id, txInteger line)
260
+ {
261
+ txSlot* breakpoint = C_NULL;
262
+ breakpoint = mxBreakpoints.value.list.first;
263
+ while (breakpoint) {
264
+ if ((breakpoint->ID == id) && (breakpoint->value.integer == line))
265
+ break;
266
+ breakpoint = breakpoint->next;
267
+ }
268
+ if (breakpoint)
269
+ fxDebugLoop(the, C_NULL, 0, "breakpoint");
270
+ else if ((the->frame->flag & XS_STEP_OVER_FLAG))
271
+ fxDebugLoop(the, C_NULL, 0, "step");
272
+ }
273
+
274
+ void fxDebugLoop(txMachine* the, txString path, txInteger line, txString message)
275
+ {
276
+ txSlot* frame;
277
+ if (!fxIsConnected(the))
278
+ return;
279
+
280
+ #ifdef mxInstrument
281
+ if (the->onBreak)
282
+ (the->onBreak)(the, 1);
283
+ #endif
284
+ #if defined(mxInstrument) || defined(mxProfile)
285
+ fxSuspendProfiler(the);
286
+ #endif
287
+
288
+ fxEchoStart(the);
289
+ frame = the->frame;
290
+ do {
291
+ frame->flag &= ~XS_DEBUG_FLAG;
292
+ frame = frame->next;
293
+ } while (frame);
294
+ the->frame->flag |= XS_DEBUG_FLAG;
295
+ fxListFrames(the);
296
+ fxListLocal(the);
297
+ fxListGlobal(the);
298
+ fxListModules(the);
299
+ fxEcho(the, "<break");
300
+ frame = the->frame;
301
+ while (frame && !path) {
302
+ txSlot* environment = mxFrameToEnvironment(frame);
303
+ if (environment->ID != XS_NO_ID) {
304
+ path = fxGetKeyName(the, environment->ID);
305
+ line = environment->value.environment.line;
306
+ }
307
+ frame = frame->next;
308
+ }
309
+ if (path)
310
+ fxEchoPathLine(the, path, line);
311
+ fxEcho(the, "># Break: ");
312
+ fxEchoString(the, message);
313
+ fxEcho(the, "!\n</break>");
314
+ fxEchoStop(the);
315
+
316
+ the->debugExit = 0;
317
+ the->debugModule = C_NULL;
318
+ while (fxIsConnected(the)) {
319
+ fxReceive(the);
320
+ fxDebugParse(the);
321
+ if ((the->debugState == XS_LF_STATE) && (the->debugExit > 1))
322
+ break;
323
+ }
324
+ mxHostInspectors.value.list.first = C_NULL;
325
+ mxHostInspectors.value.list.last = C_NULL;
326
+
327
+ #if defined(mxInstrument) || defined(mxProfile)
328
+ fxResumeProfiler(the);
329
+ #endif
330
+ #ifdef mxInstrument
331
+ if (the->onBreak)
332
+ (the->onBreak)(the, 0);
333
+ #endif
334
+ }
335
+
336
+ void fxDebugParse(txMachine* the)
337
+ {
338
+ txString string = the->debugBuffer;
339
+ txString limit = string + the->debugOffset;
340
+ char c;
341
+ while (string < limit) {
342
+ c = *string++;
343
+ switch (the->debugState) {
344
+ case XS_BODY_STATE:
345
+ if (c == '<')
346
+ the->debugState = XS_TAG_STATE;
347
+ else if (c == '\r')
348
+ the->debugState = XS_CR_STATE;
349
+ break;
350
+
351
+ case XS_CR_STATE:
352
+ if (c == '\n')
353
+ the->debugState = XS_LF_STATE;
354
+ else
355
+ the->debugState = XS_ERROR_STATE;
356
+ break;
357
+
358
+ case XS_LF_STATE:
359
+ if (c == '<')
360
+ the->debugState = XS_TAG_STATE;
361
+ else if (c == '\r')
362
+ the->debugState = XS_CR_STATE;
363
+ break;
364
+
365
+ case XS_TAG_STATE:
366
+ if (c == '/')
367
+ the->debugState = XS_END_TAG_STATE;
368
+ else if (c == '!')
369
+ the->debugState = XS_START_CDATA_STATE_1;
370
+ else if (c == '?')
371
+ the->debugState = XS_PROCESSING_INSTRUCTION_STATE;
372
+ else if (mxIsFirstLetter(c)) {
373
+ the->debugState = XS_START_TAG_NAME_STATE;
374
+ the->nameBuffer[0] = c;
375
+ the->nameIndex = 1;
376
+ }
377
+ else
378
+ the->debugState = XS_ERROR_STATE;
379
+ break;
380
+ case XS_START_TAG_NAME_STATE:
381
+ if (mxIsNextLetter(c)) {
382
+ if (the->nameIndex < 255) {
383
+ the->nameBuffer[the->nameIndex] = c;
384
+ the->nameIndex++;
385
+ }
386
+ else
387
+ the->debugState = XS_ERROR_STATE;
388
+ break;
389
+ }
390
+ the->debugState = XS_START_TAG_SPACE_STATE;
391
+ the->nameBuffer[the->nameIndex] = 0;
392
+ fxDebugParseTag(the, the->nameBuffer);
393
+ /* continue */
394
+ case XS_START_TAG_SPACE_STATE:
395
+ if (mxIsFirstLetter(c)) {
396
+ the->debugState = XS_ATTRIBUTE_NAME_STATE;
397
+ the->nameBuffer[0] = c;
398
+ the->nameIndex = 1;
399
+ }
400
+ else if (c == '/')
401
+ the->debugState = XS_EMPTY_TAG_STATE;
402
+ else if (c == '>') {
403
+ the->debugState = XS_BODY_STATE;
404
+ fxDebugPushTag(the);
405
+ }
406
+ else if (!mxIsSpace(c))
407
+ the->debugState = XS_ERROR_STATE;
408
+ break;
409
+
410
+ case XS_ATTRIBUTE_NAME_STATE:
411
+ if (mxIsNextLetter(c)) {
412
+ if (the->nameIndex < 255) {
413
+ the->nameBuffer[the->nameIndex] = c;
414
+ the->nameIndex++;
415
+ }
416
+ else
417
+ the->debugState = XS_ERROR_STATE;
418
+ break;
419
+ }
420
+ the->nameBuffer[the->nameIndex] = 0;
421
+ if (!c_strcmp(the->nameBuffer, "path")) {
422
+ the->debugAttribute = XS_PATH_ATTRIBUTE;
423
+ the->pathIndex = 0;
424
+ }
425
+ else if (!c_strcmp(the->nameBuffer, "line")) {
426
+ the->debugAttribute = XS_LINE_ATTRIBUTE;
427
+ the->lineValue = 0;
428
+ }
429
+ else if (!c_strcmp(the->nameBuffer, "id")) {
430
+ the->debugAttribute = XS_ID_ATTRIBUTE;
431
+ the->idValue = 0;
432
+ }
433
+ else
434
+ the->debugAttribute = XS_UNKNOWN_ATTRIBUTE;
435
+ /* continue */
436
+ case XS_ATTRIBUTE_SPACE_STATE:
437
+ if (c == '=')
438
+ the->debugState = XS_ATTRIBUTE_EQUAL_STATE;
439
+ else if (!mxIsSpace(c))
440
+ the->debugState = XS_ERROR_STATE;
441
+ break;
442
+ case XS_ATTRIBUTE_EQUAL_STATE:
443
+ if (c == '"')
444
+ the->debugState = XS_ATTRIBUTE_VALUE_STATE;
445
+ else if (!mxIsSpace(c))
446
+ the->debugState = XS_ERROR_STATE;
447
+ break;
448
+ case XS_ATTRIBUTE_VALUE_STATE:
449
+ if (the->debugAttribute == XS_PATH_ATTRIBUTE) {
450
+ if (c == '"') {
451
+ the->debugState = XS_START_TAG_SPACE_STATE;
452
+ the->pathValue[the->pathIndex] = 0;
453
+ }
454
+ else if (the->pathIndex < 255) {
455
+ the->pathValue[the->pathIndex] = c;
456
+ the->pathIndex++;
457
+ }
458
+ }
459
+ else if (the->debugAttribute == XS_LINE_ATTRIBUTE) {
460
+ if (c == '"')
461
+ the->debugState = XS_START_TAG_SPACE_STATE;
462
+ else if (('0' <= c) && (c <= '9'))
463
+ the->lineValue = (the->lineValue * 10) + (c - '0');
464
+ else
465
+ the->debugState = XS_ERROR_STATE;
466
+ }
467
+ else if (the->debugAttribute == XS_ID_ATTRIBUTE) {
468
+ if (c == '"')
469
+ the->debugState = XS_START_TAG_SPACE_STATE;
470
+ else if (('0' <= c) && (c <= '9'))
471
+ the->idValue = (the->idValue << 4) | (c - '0');
472
+ else if (('A' <= c) && (c <= 'F'))
473
+ the->idValue = (the->idValue << 4) | (c - 'A' + 10);
474
+ else if ((c != '@') || (the->idValue != 0))
475
+ the->debugState = XS_ERROR_STATE;
476
+ }
477
+ else {
478
+ if (c == '"')
479
+ the->debugState = XS_START_TAG_SPACE_STATE;
480
+ }
481
+ break;
482
+
483
+ case XS_EMPTY_TAG_STATE:
484
+ if (c == '>') {
485
+ the->debugState = XS_BODY_STATE;
486
+ fxDebugPushTag(the);
487
+ fxDebugPopTag(the);
488
+ }
489
+ else
490
+ the->debugState = XS_ERROR_STATE;
491
+ break;
492
+
493
+ case XS_END_TAG_STATE:
494
+ if (mxIsFirstLetter(c)) {
495
+ the->debugState = XS_END_TAG_NAME_STATE;
496
+ the->nameBuffer[0] = c;
497
+ the->nameIndex = 1;
498
+ }
499
+ else
500
+ the->debugState = XS_ERROR_STATE;
501
+ break;
502
+ case XS_END_TAG_NAME_STATE:
503
+ if (mxIsNextLetter(c)) {
504
+ if (the->nameIndex < 255) {
505
+ the->nameBuffer[the->nameIndex] = c;
506
+ the->nameIndex++;
507
+ }
508
+ else
509
+ the->debugState = XS_ERROR_STATE;
510
+ break;
511
+ }
512
+ the->nameBuffer[the->nameIndex] = 0;
513
+ the->debugState = XS_END_TAG_SPACE_STATE;
514
+ fxDebugParseTag(the, the->nameBuffer);
515
+ /* continue */
516
+ case XS_END_TAG_SPACE_STATE:
517
+ if (c == '>') {
518
+ the->debugState = XS_BODY_STATE;
519
+ fxDebugPopTag(the);
520
+ }
521
+ else if (!mxIsSpace(c))
522
+ the->debugState = XS_ERROR_STATE;
523
+ break;
524
+
525
+ case XS_PROCESSING_INSTRUCTION_STATE:
526
+ if (c == '?')
527
+ the->debugState = XS_PROCESSING_INSTRUCTION_SPACE_STATE;
528
+ break;
529
+ case XS_PROCESSING_INSTRUCTION_SPACE_STATE:
530
+ if (c == '>')
531
+ the->debugState = XS_BODY_STATE;
532
+ else
533
+ the->debugState = XS_ERROR_STATE;
534
+ break;
535
+
536
+ case XS_START_CDATA_STATE_1:
537
+ if (c == '[')
538
+ the->debugState = XS_START_CDATA_STATE_2;
539
+ else
540
+ the->debugState = XS_ERROR_STATE;
541
+ break;
542
+ case XS_START_CDATA_STATE_2:
543
+ if (c == 'C')
544
+ the->debugState = XS_START_CDATA_STATE_3;
545
+ else
546
+ the->debugState = XS_ERROR_STATE;
547
+ break;
548
+ case XS_START_CDATA_STATE_3:
549
+ if (c == 'D')
550
+ the->debugState = XS_START_CDATA_STATE_4;
551
+ else
552
+ the->debugState = XS_ERROR_STATE;
553
+ break;
554
+ case XS_START_CDATA_STATE_4:
555
+ if (c == 'A')
556
+ the->debugState = XS_START_CDATA_STATE_5;
557
+ else
558
+ the->debugState = XS_ERROR_STATE;
559
+ break;
560
+ case XS_START_CDATA_STATE_5:
561
+ if (c == 'T')
562
+ the->debugState = XS_START_CDATA_STATE_6;
563
+ else
564
+ the->debugState = XS_ERROR_STATE;
565
+ break;
566
+ case XS_START_CDATA_STATE_6:
567
+ if (c == 'A')
568
+ the->debugState = XS_START_CDATA_STATE_7;
569
+ else
570
+ the->debugState = XS_ERROR_STATE;
571
+ break;
572
+ case XS_START_CDATA_STATE_7:
573
+ if (c == '[')
574
+ the->debugState = XS_CDATA_STATE;
575
+ else
576
+ the->debugState = XS_ERROR_STATE;
577
+ break;
578
+ case XS_CDATA_STATE:
579
+ if (c == ']')
580
+ the->debugState = XS_END_CDATA_STATE_1;
581
+ else if (c == 0) {
582
+ fxDebugScriptCDATA(the, 0xF4);
583
+ fxDebugScriptCDATA(the, 0x90);
584
+ fxDebugScriptCDATA(the, 0x80);
585
+ fxDebugScriptCDATA(the, 0x80);
586
+ }
587
+ else
588
+ fxDebugScriptCDATA(the, c);
589
+ break;
590
+ case XS_END_CDATA_STATE_1:
591
+ if (c == ']')
592
+ the->debugState = XS_END_CDATA_STATE_2;
593
+ else {
594
+ fxDebugScriptCDATA(the, ']');
595
+ fxDebugScriptCDATA(the, c);
596
+ the->debugState = XS_CDATA_STATE;
597
+ }
598
+ break;
599
+ case XS_END_CDATA_STATE_2:
600
+ if (c == '>') {
601
+ fxDebugScriptCDATA(the, 0);
602
+ the->debugState = XS_BODY_STATE;
603
+ }
604
+ else {
605
+ fxDebugScriptCDATA(the, ']');
606
+ fxDebugScriptCDATA(the, ']');
607
+ fxDebugScriptCDATA(the, c);
608
+ the->debugState = XS_CDATA_STATE;
609
+ }
610
+ break;
611
+
612
+ case XS_ERROR_STATE:
613
+ // fprintf(stderr, "\nERROR: %c\n", c);
614
+ break;
615
+ }
616
+ }
617
+ the->debugOffset = 0;
618
+ }
619
+
620
+ void fxDebugParseTag(txMachine* the, txString name)
621
+ {
622
+ if (!c_strcmp(name, "abort"))
623
+ the->debugTag = XS_ABORT_TAG;
624
+ else if (!c_strcmp(name, "breakpoint"))
625
+ the->debugTag = XS_BREAKPOINT_TAG;
626
+ else if (!c_strcmp(name, "clear-all-breakpoints"))
627
+ the->debugTag = XS_CLEAR_ALL_BREAKPOINTS_TAG;
628
+ else if (!c_strcmp(name, "clear-breakpoint"))
629
+ the->debugTag = XS_CLEAR_BREAKPOINTS_TAG;
630
+ else if (!c_strcmp(name, "go"))
631
+ the->debugTag = XS_GO_TAG;
632
+ else if (!c_strcmp(name, "logout"))
633
+ the->debugTag = XS_LOGOUT_TAG;
634
+ else if (!c_strcmp(name, "select"))
635
+ the->debugTag = XS_SELECT_TAG;
636
+ else if (!c_strcmp(name, "set-all-breakpoints"))
637
+ the->debugTag = XS_SET_ALL_BREAKPOINTS_TAG;
638
+ else if (!c_strcmp(name, "set-breakpoint"))
639
+ the->debugTag = XS_SET_BREAKPOINT_TAG;
640
+ else if (!c_strcmp(name, "start-profiling"))
641
+ the->debugTag = XS_START_PROFILING_TAG;
642
+ else if (!c_strcmp(name, "step"))
643
+ the->debugTag = XS_STEP_TAG;
644
+ else if (!c_strcmp(name, "step-inside"))
645
+ the->debugTag = XS_STEP_INSIDE_TAG;
646
+ else if (!c_strcmp(name, "step-outside"))
647
+ the->debugTag = XS_STEP_OUTSIDE_TAG;
648
+ else if (!c_strcmp(name, "stop-profiling"))
649
+ the->debugTag = XS_STOP_PROFILING_TAG;
650
+ else if (!c_strcmp(name, "toggle"))
651
+ the->debugTag = XS_TOGGLE_TAG;
652
+ #if MODDEF_XS_XSBUG_HOOKS
653
+ else if (!c_strcmp(name, "import"))
654
+ the->debugTag = XS_IMPORT_TAG;
655
+ else if (!c_strcmp(name, "module"))
656
+ the->debugTag = XS_MODULE_TAG;
657
+ else if (!c_strcmp(name, "script"))
658
+ the->debugTag = XS_SCRIPT_TAG;
659
+ #endif
660
+ else
661
+ the->debugTag = XS_UNKNOWN_TAG;
662
+ }
663
+
664
+ void fxDebugPopTag(txMachine* the)
665
+ {
666
+ switch (the->debugTag) {
667
+ case XS_ABORT_TAG:
668
+ the->debugExit |= 2;
669
+ break;
670
+ case XS_BREAKPOINT_TAG:
671
+ break;
672
+ case XS_CLEAR_ALL_BREAKPOINTS_TAG:
673
+ the->debugExit |= 1;
674
+ break;
675
+ case XS_CLEAR_BREAKPOINTS_TAG:
676
+ the->debugExit |= 1;
677
+ break;
678
+ case XS_GO_TAG:
679
+ the->debugExit |= 2;
680
+ break;
681
+ case XS_LOGOUT_TAG:
682
+ the->debugExit |= 2;
683
+ break;
684
+ case XS_SELECT_TAG:
685
+ break;
686
+ case XS_SET_ALL_BREAKPOINTS_TAG:
687
+ the->debugExit |= 1;
688
+ break;
689
+ case XS_SET_BREAKPOINT_TAG:
690
+ the->debugExit |= 1;
691
+ break;
692
+ case XS_START_PROFILING_TAG:
693
+ the->debugExit |= 1;
694
+ break;
695
+ case XS_STEP_TAG:
696
+ the->debugExit |= 2;
697
+ break;
698
+ case XS_STEP_INSIDE_TAG:
699
+ the->debugExit |= 2;
700
+ break;
701
+ case XS_STEP_OUTSIDE_TAG:
702
+ the->debugExit |= 2;
703
+ break;
704
+ case XS_STOP_PROFILING_TAG:
705
+ the->debugExit |= 1;
706
+ break;
707
+ case XS_TOGGLE_TAG:
708
+ break;
709
+ #if MODDEF_XS_XSBUG_HOOKS
710
+ case XS_IMPORT_TAG:
711
+ the->debugExit |= 2;
712
+ break;
713
+ case XS_MODULE_TAG:
714
+ case XS_SCRIPT_TAG:
715
+ the->debugExit |= 2;
716
+ break;
717
+ #endif
718
+ }
719
+ }
720
+
721
+ void fxDebugPushTag(txMachine* the)
722
+ {
723
+ switch (the->debugTag) {
724
+ case XS_ABORT_TAG:
725
+ fxLogout(the);
726
+ fxGo(the);
727
+ fxAbort(the, XS_DEBUGGER_EXIT);
728
+ break;
729
+ case XS_BREAKPOINT_TAG:
730
+ fxSetBreakpoint(the, the->pathValue, the->lineValue);
731
+ break;
732
+ case XS_CLEAR_ALL_BREAKPOINTS_TAG:
733
+ fxClearAllBreakpoints(the);
734
+ break;
735
+ case XS_CLEAR_BREAKPOINTS_TAG:
736
+ fxClearBreakpoint(the, the->pathValue, the->lineValue);
737
+ break;
738
+ case XS_GO_TAG:
739
+ fxGo(the);
740
+ break;
741
+ case XS_LOGOUT_TAG:
742
+ fxLogout(the);
743
+ fxGo(the);
744
+ break;
745
+ case XS_SELECT_TAG:
746
+ fxSelect(the, (txSlot*)the->idValue);
747
+ fxEchoStart(the);
748
+ fxListLocal(the);
749
+ fxListGlobal(the);
750
+ fxListModules(the);
751
+ fxEchoStop(the);
752
+ break;
753
+ case XS_SET_ALL_BREAKPOINTS_TAG:
754
+ break;
755
+ case XS_SET_BREAKPOINT_TAG:
756
+ fxSetBreakpoint(the, the->pathValue, the->lineValue);
757
+ break;
758
+ case XS_START_PROFILING_TAG:
759
+ fxStartProfiling(the);
760
+ break;
761
+ case XS_STEP_TAG:
762
+ fxStep(the);
763
+ break;
764
+ case XS_STEP_INSIDE_TAG:
765
+ fxStepInside(the);
766
+ break;
767
+ case XS_STEP_OUTSIDE_TAG:
768
+ fxStepOutside(the);
769
+ break;
770
+ case XS_STOP_PROFILING_TAG:
771
+ fxStopProfiling(the, C_NULL);
772
+ break;
773
+ case XS_TOGGLE_TAG:
774
+ fxToggle(the, (txSlot*)the->idValue);
775
+ fxEchoStart(the);
776
+ fxListLocal(the);
777
+ fxListGlobal(the);
778
+ fxListModules(the);
779
+ fxEchoStop(the);
780
+ break;
781
+ #if MODDEF_XS_XSBUG_HOOKS
782
+ case XS_IMPORT_TAG:
783
+ /* THIS */
784
+ mxPushUndefined();
785
+ /* FUNCTION */
786
+ mxPush(mxGlobal);
787
+ mxGetID(fxID(the, "<xsbug:import>"));
788
+ mxCall();
789
+ mxPushStringC("xsbug://");
790
+ fxConcatStringC(the, the->stack, the->pathValue);
791
+ mxPushInteger(the->lineValue);
792
+ break;
793
+ case XS_MODULE_TAG:
794
+ case XS_SCRIPT_TAG:
795
+ fxCollectGarbage(the);
796
+ /* THIS */
797
+ mxPushUndefined();
798
+ /* FUNCTION */
799
+ mxPush(mxGlobal);
800
+ if (the->debugTag == XS_MODULE_TAG)
801
+ mxGetID(fxID(the, "<xsbug:module>"));
802
+ else
803
+ mxGetID(mxID(__xsbug_script_));
804
+ mxCall();
805
+ if (the->debugModule)
806
+ mxPushSlot(the->debugModule);
807
+ else
808
+ mxPushUndefined();
809
+ mxPushStringC(the->pathValue);
810
+ mxPushInteger(the->lineValue);
811
+ mxPushUndefined();
812
+ fxStringBuffer(the, the->stack, C_NULL, 256);
813
+ mxPushInteger(256);
814
+ mxPushInteger(0);
815
+ break;
816
+ #endif
817
+ }
818
+ }
819
+
820
+ void fxDebugScriptCDATA(txMachine* the, char c)
821
+ {
822
+ #if MODDEF_XS_XSBUG_HOOKS
823
+ if ((the->debugTag == XS_MODULE_TAG) || (the->debugTag == XS_SCRIPT_TAG)) {
824
+ txString string = the->stack[2].value.string;
825
+ txInteger size = the->stack[1].value.integer;
826
+ txInteger offset = the->stack[0].value.integer;
827
+ if (offset == size) {
828
+ txString result = (txString)fxRenewChunk(the, string, size + 256);
829
+ if (!result) {
830
+ result = (txString)fxNewChunk(the, size + 256);
831
+ string = the->stack[2].value.string;
832
+ c_memcpy(result, string, size);
833
+ }
834
+ the->stack[2].value.string = string = result;
835
+ the->stack[1].value.integer = size + 256;
836
+ }
837
+ string[offset++] = c;
838
+ the->stack[0].value.integer = offset;
839
+ }
840
+ #endif
841
+ }
842
+
843
+ void fxDebugThrow(txMachine* the, txString path, txInteger line, txString message)
844
+ {
845
+ if (fxIsConnected(the) && (the->breakOnExceptionsFlag))
846
+ fxDebugLoop(the, path, line, message);
847
+ else {
848
+ txSlot* frame = the->frame;
849
+ while (frame && !path) {
850
+ txSlot* environment = mxFrameToEnvironment(frame);
851
+ if (environment->ID != XS_NO_ID) {
852
+ path = fxGetKeyName(the, environment->ID);
853
+ line = environment->value.environment.line;
854
+ }
855
+ frame = frame->next;
856
+ }
857
+ fxReportException(the, path, line, "%s", message);
858
+ }
859
+ }
860
+
861
+ void fxEcho(txMachine* the, txString theString)
862
+ {
863
+ txInteger srcLength = mxStringLength(theString);
864
+ txInteger dstLength = sizeof(the->echoBuffer) - the->echoOffset;
865
+ while (srcLength > dstLength) {
866
+ c_memcpy(the->echoBuffer + the->echoOffset, theString, dstLength);
867
+ theString += dstLength;
868
+ srcLength -= dstLength;
869
+ the->echoOffset = sizeof(the->echoBuffer);
870
+ fxSend(the, 1);
871
+ the->echoOffset = 0;
872
+ dstLength = sizeof(the->echoBuffer);
873
+ }
874
+ c_memcpy(the->echoBuffer + the->echoOffset, theString, srcLength);
875
+ the->echoOffset += srcLength;
876
+ }
877
+
878
+ void fxEchoAddress(txMachine* the, txSlot* theSlot)
879
+ {
880
+ uintptr_t aValue = (uintptr_t)theSlot;
881
+ int aShift;
882
+
883
+ fxEcho(the, " value=\"@");
884
+ aShift = (8 * sizeof(aValue)) - 4;
885
+ while (aShift >= 0) {
886
+ fxEchoCharacter(the, c_read8(gxHexaDigits + ((aValue >> aShift) & 0x0F)));
887
+ aShift -= 4;
888
+ }
889
+ fxEcho(the, "\"");
890
+ }
891
+
892
+ void fxEchoBigInt(txMachine* the, txBigInt* bigint)
893
+ {
894
+ int i = bigint->size - 1;
895
+ if (i < 0) {
896
+ fxEchoCharacter(the, 'N');
897
+ fxEchoCharacter(the, 'a');
898
+ fxEchoCharacter(the, 'N');
899
+ }
900
+ else {
901
+ int echo = 0;
902
+ if (bigint->sign)
903
+ fxEchoCharacter(the, '-');
904
+ fxEchoCharacter(the, '0');
905
+ fxEchoCharacter(the, 'x');
906
+ while (i >= 0) {
907
+ txU4 value = bigint->data[i];
908
+ txU4 mask = 0xF;
909
+ int shift = 28;
910
+ while (shift >= 0) {
911
+ char digit = c_read8(gxHexaDigits + ((value & (mask << shift)) >> shift));
912
+ if (echo || (digit != '0')) {
913
+ echo = 1;
914
+ fxEchoCharacter(the, digit);
915
+ }
916
+ shift -= 4;
917
+ }
918
+ i--;
919
+ }
920
+ if (!echo)
921
+ fxEchoCharacter(the, '0');
922
+ fxEchoCharacter(the, 'n');
923
+ }
924
+ }
925
+
926
+ void fxEchoCharacter(txMachine* the, char theCharacter)
927
+ {
928
+ char c[2];
929
+ c[0] = theCharacter;
930
+ c[1] = 0;
931
+ fxEchoString(the, c);
932
+ }
933
+
934
+ void fxEchoFlags(txMachine* the, txString state, txFlag flag)
935
+ {
936
+ fxEcho(the, " flags=\"");
937
+ fxEcho(the, state);
938
+ if (flag & XS_DONT_DELETE_FLAG)
939
+ fxEcho(the, "C");
940
+ else
941
+ fxEcho(the, "c");
942
+ if (flag & XS_DONT_ENUM_FLAG)
943
+ fxEcho(the, "E");
944
+ else
945
+ fxEcho(the, "e");
946
+ if (flag & XS_DONT_SET_FLAG)
947
+ fxEcho(the, "W");
948
+ else
949
+ fxEcho(the, "w");
950
+ if (flag & XS_INSPECTOR_FLAG)
951
+ fxEcho(the, "I");
952
+ else if (flag & XS_MARK_FLAG)
953
+ fxEcho(the, "M");
954
+ else
955
+ fxEcho(the, "_");
956
+ fxEcho(the, "\"");
957
+ }
958
+
959
+ void fxEchoFormat(txMachine* the, txString theFormat, c_va_list theArguments)
960
+ {
961
+ char *p, c;
962
+
963
+ p = theFormat;
964
+ while ((c = c_read8(p++))) {
965
+ if (c != '%')
966
+ fxEchoCharacter(the, c);
967
+ else {
968
+ if (c_strncmp(p, "c", 1) == 0) {
969
+ fxEchoCharacter(the, c_va_arg(theArguments, int));
970
+ p++;
971
+ }
972
+ else if (c_strncmp(p, "hd", 2) == 0) {
973
+ fxEchoInteger(the, c_va_arg(theArguments, int));
974
+ p += 2;
975
+ }
976
+ else if (c_strncmp(p, "d", 1) == 0) {
977
+ fxEchoInteger(the, c_va_arg(theArguments, int));
978
+ p++;
979
+ }
980
+ else if (c_strncmp(p, "ld", 2) == 0) {
981
+ fxEchoInteger(the, c_va_arg(theArguments, long));
982
+ p += 2;
983
+ }
984
+ else if (c_strncmp(p, "g", 1) == 0) {
985
+ fxEchoNumber(the, c_va_arg(theArguments, double));
986
+ p++;
987
+ }
988
+ else if (c_strncmp(p, "s", 1) == 0) {
989
+ char *s = c_va_arg(theArguments, char *);
990
+ fxEchoString(the, s);
991
+ p++;
992
+ }
993
+ else {
994
+ fxEchoCharacter(the, c);
995
+ p++;
996
+ }
997
+ }
998
+ }
999
+ }
1000
+
1001
+ void fxEchoFrameName(txMachine* the, txSlot* theFrame)
1002
+ {
1003
+ char buffer[128] = "";
1004
+ fxBufferFrameName(the, buffer, sizeof(buffer), theFrame, "");
1005
+ fxEcho(the, buffer);
1006
+ }
1007
+
1008
+ void fxEchoFramePathLine(txMachine* the, txSlot* theFrame)
1009
+ {
1010
+ if (theFrame) {
1011
+ txSlot* environment = mxFrameToEnvironment(theFrame);
1012
+ if (environment->ID != XS_NO_ID)
1013
+ fxEchoPathLine(the, fxGetKeyName(the, environment->ID), environment->value.environment.line);
1014
+ }
1015
+ }
1016
+
1017
+ void fxEchoInteger(txMachine* the, txInteger theInteger)
1018
+ {
1019
+ char aBuffer[256];
1020
+
1021
+ fxIntegerToString(the->dtoa, theInteger, aBuffer, sizeof(aBuffer));
1022
+ fxEcho(the, aBuffer);
1023
+ }
1024
+
1025
+ void fxEchoInstance(txMachine* the, txSlot* theInstance, txInspectorNameList* theList)
1026
+ {
1027
+ txSlot* aParent;
1028
+ txSlot* aProperty;
1029
+ txSlot* aSlot;
1030
+ txInteger anIndex;
1031
+
1032
+ if (theInstance->ID) {
1033
+ txSlot* aliasInstance = the->aliasArray[theInstance->ID];
1034
+ if (aliasInstance)
1035
+ theInstance = aliasInstance;
1036
+ }
1037
+ aParent = fxGetPrototype(the, theInstance);
1038
+ if (aParent)
1039
+ fxEchoPropertyInstance(the, theList, "(..)", -1, C_NULL, XS_NO_ID, theInstance->flag & XS_MARK_FLAG, aParent);
1040
+ aProperty = theInstance->next;
1041
+ if (aProperty && (aProperty->flag & XS_INTERNAL_FLAG) && (aProperty->ID == XS_ARRAY_BEHAVIOR)) {
1042
+ fxEchoProperty(the, aProperty, theList, "(array)", -1, C_NULL);
1043
+ }
1044
+ else if (aProperty && (aProperty->flag & XS_INTERNAL_FLAG)) {
1045
+ switch (aProperty->kind) {
1046
+ case XS_CALLBACK_KIND:
1047
+ case XS_CALLBACK_X_KIND:
1048
+ case XS_CODE_KIND:
1049
+ case XS_CODE_X_KIND:
1050
+ if (aProperty->value.code.closures)
1051
+ fxEchoPropertyInstance(the, theList, "(closures)", -1, C_NULL, XS_NO_ID, aProperty->flag, aProperty->value.code.closures);
1052
+ fxEchoProperty(the, aProperty, theList, "(function)", -1, C_NULL);
1053
+ aProperty = aProperty->next;
1054
+ if ((aProperty->kind == XS_HOME_KIND) && (aProperty->value.home.object))
1055
+ fxEchoPropertyInstance(the, theList, "(home)", -1, C_NULL, XS_NO_ID, aProperty->flag, aProperty->value.home.object);
1056
+ aProperty = aProperty->next;
1057
+ break;
1058
+ case XS_ARRAY_BUFFER_KIND:
1059
+ aProperty = aProperty->next;
1060
+ fxEchoProperty(the, aProperty, theList, "(buffer)", -1, C_NULL);
1061
+ aProperty = aProperty->next;
1062
+ break;
1063
+ case XS_STRING_KIND:
1064
+ case XS_STRING_X_KIND:
1065
+ fxEchoProperty(the, aProperty, theList, "(string)", -1, C_NULL);
1066
+ aProperty = aProperty->next;
1067
+ break;
1068
+ case XS_BOOLEAN_KIND:
1069
+ fxEchoProperty(the, aProperty, theList, "(boolean)", -1, C_NULL);
1070
+ aProperty = aProperty->next;
1071
+ break;
1072
+ case XS_NUMBER_KIND:
1073
+ fxEchoProperty(the, aProperty, theList, "(number)", -1, C_NULL);
1074
+ aProperty = aProperty->next;
1075
+ break;
1076
+ case XS_BIGINT_KIND:
1077
+ case XS_BIGINT_X_KIND:
1078
+ fxEchoProperty(the, aProperty, theList, "(bigint)", -1, C_NULL);
1079
+ aProperty = aProperty->next;
1080
+ break;
1081
+ case XS_DATA_VIEW_KIND:
1082
+ fxEchoProperty(the, aProperty, theList, "(view)", -1, C_NULL);
1083
+ aProperty = aProperty->next;
1084
+ fxEchoProperty(the, aProperty, theList, "(data)", -1, C_NULL);
1085
+ aProperty = aProperty->next;
1086
+ break;
1087
+ case XS_DATE_KIND:
1088
+ fxEchoProperty(the, aProperty, theList, "(date)", -1, C_NULL);
1089
+ aProperty = aProperty->next;
1090
+ break;
1091
+ case XS_REGEXP_KIND:
1092
+ fxEchoProperty(the, aProperty, theList, "(regexp)", -1, C_NULL);
1093
+ aProperty = aProperty->next;
1094
+ break;
1095
+ case XS_HOST_KIND:
1096
+ fxEchoProperty(the, aProperty, theList, "(host)", -1, C_NULL);
1097
+ if (aProperty->value.host.data)
1098
+ fxEchoPropertyHost(the, theList, theInstance, aProperty);
1099
+ aProperty = aProperty->next;
1100
+ break;
1101
+ case XS_GLOBAL_KIND:
1102
+ aProperty = aProperty->next;
1103
+ break;
1104
+ case XS_PROMISE_KIND:
1105
+ fxEchoProperty(the, aProperty, theList, "(promise)", -1, C_NULL);
1106
+ aProperty = aProperty->next;
1107
+ break;
1108
+ case XS_MAP_KIND:
1109
+ aProperty = aProperty->next;
1110
+ anIndex = 0;
1111
+ aSlot = aProperty->value.list.first;
1112
+ while (aSlot) {
1113
+ if (!(aSlot->flag & XS_DONT_ENUM_FLAG)) {
1114
+ fxEchoProperty(the, aSlot, theList, "(", anIndex, ".0)");
1115
+ fxEchoProperty(the, aSlot->next, theList, "(", anIndex, ".1)");
1116
+ }
1117
+ anIndex++;
1118
+ aSlot = aSlot->next->next;
1119
+ }
1120
+ aProperty = aProperty->next;
1121
+ break;
1122
+ case XS_MODULE_KIND:
1123
+ aProperty = aProperty->next;
1124
+ fxEchoProperty(the, aProperty, theList, "(export)", -1, C_NULL);
1125
+ aProperty = aProperty->next;
1126
+ break;
1127
+ case XS_PROGRAM_KIND:
1128
+ aSlot = aProperty->value.module.realm;
1129
+ fxEchoProperty(the, mxRealmGlobal(aSlot), theList, "(globals)", -1, C_NULL);
1130
+ fxEchoProperty(the, mxOwnModules(aSlot), theList, "(modules)", -1, C_NULL);
1131
+ break;
1132
+ case XS_SET_KIND:
1133
+ aProperty = aProperty->next;
1134
+ anIndex = 0;
1135
+ aSlot = aProperty->value.list.first;
1136
+ while (aSlot) {
1137
+ if (!(aSlot->flag & XS_DONT_ENUM_FLAG))
1138
+ fxEchoProperty(the, aSlot, theList, "(", anIndex, ")");
1139
+ anIndex++;
1140
+ aSlot = aSlot->next;
1141
+ }
1142
+ aProperty = aProperty->next;
1143
+ break;
1144
+ case XS_TYPED_ARRAY_KIND:
1145
+ fxEchoProperty(the, aProperty, theList, "(per item)", -1, C_NULL);
1146
+ aProperty = aProperty->next;
1147
+ fxEchoProperty(the, aProperty, theList, "(view)", -1, C_NULL);
1148
+ aProperty = aProperty->next;
1149
+ fxEchoProperty(the, aProperty, theList, "(items)", -1, C_NULL);
1150
+ aProperty = aProperty->next;
1151
+ break;
1152
+ case XS_PROXY_KIND:
1153
+ if (aProperty->value.proxy.target)
1154
+ fxEchoPropertyInstance(the, theList, "(target)", -1, C_NULL, XS_NO_ID, aProperty->flag, aProperty->value.proxy.target);
1155
+ if (aProperty->value.proxy.handler)
1156
+ fxEchoPropertyInstance(the, theList, "(handler)", -1, C_NULL, XS_NO_ID, aProperty->flag, aProperty->value.proxy.handler);
1157
+ aProperty = aProperty->next;
1158
+ break;
1159
+ }
1160
+ }
1161
+ while (aProperty) {
1162
+ if (aProperty->flag & XS_INTERNAL_FLAG) {
1163
+ if (aProperty->kind == XS_ARRAY_KIND) {
1164
+ txSlot* item = aProperty->value.array.address;
1165
+ txIndex c = fxGetIndexSize(the, aProperty), i;
1166
+ for (i = 0; i < c; i++) {
1167
+ txIndex index = *((txIndex*)item);
1168
+ fxEchoProperty(the, item, theList, "[", index, "]");
1169
+ item++;
1170
+ }
1171
+ }
1172
+ else if (aProperty->kind == XS_PRIVATE_KIND) {
1173
+ txSlot* instanceInspector = fxToInstanceInspector(the, aProperty);
1174
+ char buffer[128] = "(";
1175
+ txSlot* check = aProperty->value.private.check;
1176
+ txSlot* item = aProperty->value.private.first;
1177
+ fxBufferFunctionName(the, &buffer[1], sizeof(buffer) - 1, check, ")");
1178
+ fxEcho(the, "<property");
1179
+ if (instanceInspector) {
1180
+ if (instanceInspector->value.instanceInspector.link)
1181
+ fxEchoFlags(the, " ", aProperty->flag);
1182
+ else
1183
+ fxEchoFlags(the, "-", aProperty->flag);
1184
+ }
1185
+ else
1186
+ fxEchoFlags(the, "+", aProperty->flag);
1187
+ fxEcho(the, " name=\"");
1188
+ fxEchoString(the, buffer);
1189
+ fxEcho(the, "\"");
1190
+ if (instanceInspector) {
1191
+ if (instanceInspector->value.instanceInspector.link) {
1192
+ txInspectorNameLink* link = theList->first;
1193
+ fxEcho(the, " value=\"");
1194
+ while (link) {
1195
+ fxEchoString(the, link->name);
1196
+ if (link == instanceInspector->value.instanceInspector.link)
1197
+ break;
1198
+ fxEcho(the, ".");
1199
+ link = link->next;
1200
+ }
1201
+ fxEcho(the, "\"/>");
1202
+ }
1203
+ else {
1204
+ txInspectorNameLink link;
1205
+ link.previous = theList->last;
1206
+ link.next = C_NULL;
1207
+ link.name = buffer;
1208
+ if (theList->first)
1209
+ theList->last->next = &link;
1210
+ else
1211
+ theList->first = &link;
1212
+ theList->last = &link;
1213
+ instanceInspector->value.instanceInspector.link = &link;
1214
+ fxEchoAddress(the, aProperty);
1215
+ fxEcho(the, ">");
1216
+ while (item) {
1217
+ fxEchoProperty(the, item, theList, C_NULL, -1, C_NULL);
1218
+ item = item->next;
1219
+ }
1220
+ fxEcho(the, "</property>");
1221
+ instanceInspector->value.instanceInspector.link = C_NULL;
1222
+ if (link.previous)
1223
+ link.previous->next = C_NULL;
1224
+ else
1225
+ theList->first = C_NULL;
1226
+ theList->last = link.previous;
1227
+ }
1228
+ }
1229
+ else {
1230
+ fxEchoAddress(the, aProperty);
1231
+ fxEcho(the, "/>");
1232
+ }
1233
+ }
1234
+ }
1235
+ else {
1236
+ fxEchoProperty(the, aProperty, theList, C_NULL, -1, C_NULL);
1237
+ }
1238
+ aProperty = aProperty->next;
1239
+ }
1240
+ }
1241
+
1242
+ void fxEchoModule(txMachine* the, txSlot* module, txInspectorNameList* list)
1243
+ {
1244
+ txSlot* exports = mxModuleExports(module);
1245
+ txSlot* instanceInspector = fxToInstanceInspector(the, module);
1246
+ txSlot* slot;
1247
+ fxEcho(the, "<node");
1248
+ if (instanceInspector)
1249
+ fxEchoFlags(the, "-", exports->flag);
1250
+ else
1251
+ fxEchoFlags(the, "+", exports->flag);
1252
+ fxEcho(the, " name=\"");
1253
+ slot = mxModuleInternal(module);
1254
+ fxEcho(the, fxGetKeyName(the, slot->value.module.id));
1255
+ fxEcho(the, "\"");
1256
+ fxEchoAddress(the, module);
1257
+ if (instanceInspector) {
1258
+ fxEcho(the, ">");
1259
+ fxEchoInstance(the, fxGetInstance(the, exports), list);
1260
+ fxEcho(the, "</node>");
1261
+ }
1262
+ else
1263
+ fxEcho(the, "/>");
1264
+ }
1265
+
1266
+ void fxEchoNumber(txMachine* the, txNumber theNumber)
1267
+ {
1268
+ char aBuffer[256];
1269
+
1270
+ fxNumberToString(the->dtoa, theNumber, aBuffer, sizeof(aBuffer), 0, 0);
1271
+ fxEcho(the, aBuffer);
1272
+ }
1273
+
1274
+ void fxEchoPathLine(txMachine* the, txString thePath, txInteger theLine)
1275
+ {
1276
+ if (thePath && theLine) {
1277
+ fxEcho(the, " path=\"");
1278
+ fxEchoString(the, thePath);
1279
+ fxEcho(the, "\"");
1280
+ fxEcho(the, " line=\"");
1281
+ fxEchoInteger(the, theLine);
1282
+ fxEcho(the, "\"");
1283
+ }
1284
+ }
1285
+
1286
+ void fxEchoProperty(txMachine* the, txSlot* theProperty, txInspectorNameList* theList, txString thePrefix, txIndex theIndex, txString theSuffix)
1287
+ {
1288
+ txID ID = theProperty->ID;
1289
+ txFlag flag = theProperty->flag;
1290
+ txSlot* instance;
1291
+ txString name;
1292
+ if ((theProperty->kind == XS_CLOSURE_KIND) || (theProperty->kind == XS_EXPORT_KIND)) {
1293
+ theProperty = theProperty->value.closure;
1294
+ if (!theProperty)
1295
+ return;
1296
+ if (theProperty->ID) {
1297
+ txSlot* slot = the->aliasArray[theProperty->ID];
1298
+ if (slot)
1299
+ theProperty = slot;
1300
+ }
1301
+ }
1302
+ if (theProperty->kind == XS_REFERENCE_KIND) {
1303
+ instance = fxGetInstance(the, theProperty);
1304
+ if (instance)
1305
+ fxEchoPropertyInstance(the, theList, thePrefix, theIndex, theSuffix, ID, flag, instance);
1306
+ }
1307
+ else if (theProperty->kind == XS_ACCESSOR_KIND) {
1308
+ instance = theProperty->value.accessor.getter;
1309
+ if (instance)
1310
+ fxEchoPropertyInstance(the, theList, thePrefix, theIndex, theSuffix, ID, flag | XS_GETTER_FLAG, instance);
1311
+ instance = theProperty->value.accessor.setter;
1312
+ if (instance)
1313
+ fxEchoPropertyInstance(the, theList, thePrefix, theIndex, theSuffix, ID, flag | XS_SETTER_FLAG, instance);
1314
+ }
1315
+ else {
1316
+ fxEcho(the, "<property");
1317
+ fxEchoFlags(the, " ", flag);
1318
+ fxEcho(the, " name=\"");
1319
+ if (thePrefix) {
1320
+ fxEchoString(the, thePrefix);
1321
+ if (theSuffix) {
1322
+ fxIndexToString(the, theIndex, the->nameBuffer, sizeof(the->nameBuffer));
1323
+ fxEchoString(the, the->nameBuffer);
1324
+ fxEchoString(the, theSuffix);
1325
+ }
1326
+ }
1327
+ else {
1328
+ fxIDToString(the, ID, the->nameBuffer, sizeof(the->nameBuffer));
1329
+ fxEchoString(the, the->nameBuffer);
1330
+ }
1331
+ fxEcho(the, "\"");
1332
+
1333
+ switch (theProperty->kind) {
1334
+ case XS_UNDEFINED_KIND:
1335
+ fxEcho(the, " value=\"undefined\"/>");
1336
+ break;
1337
+ case XS_NULL_KIND:
1338
+ fxEcho(the, " value=\"null\"/>");
1339
+ break;
1340
+ case XS_CALLBACK_KIND:
1341
+ case XS_CALLBACK_X_KIND:
1342
+ fxEcho(the, " value=\"(C code)\"/>");
1343
+ break;
1344
+ case XS_CODE_KIND:
1345
+ case XS_CODE_X_KIND:
1346
+ fxEcho(the, " value=\"(XS code)\"/>");
1347
+ break;
1348
+ #ifdef mxHostFunctionPrimitive
1349
+ case XS_HOST_FUNCTION_KIND:
1350
+ fxEcho(the, " value=\"(host function)\"/>");
1351
+ break;
1352
+ #endif
1353
+ case XS_ARRAY_KIND:
1354
+ fxEcho(the, " value=\"");
1355
+ fxEchoInteger(the, theProperty->value.array.length);
1356
+ fxEcho(the, " items\"/>");
1357
+ break;
1358
+ case XS_BUFFER_INFO_KIND:
1359
+ fxEcho(the, " value=\"");
1360
+ fxEchoInteger(the, theProperty->value.bufferInfo.length);
1361
+ if (theProperty->value.bufferInfo.maxLength >= 0) {
1362
+ fxEcho(the, " bytes <= ");
1363
+ fxEchoInteger(the, theProperty->value.bufferInfo.maxLength);
1364
+ }
1365
+ fxEcho(the, " bytes\"/>");
1366
+ break;
1367
+ case XS_STRING_KIND:
1368
+ case XS_STRING_X_KIND:
1369
+ fxEcho(the, " value=\"'");
1370
+ fxEchoString(the, theProperty->value.string);
1371
+ fxEcho(the, "'\"/>");
1372
+ break;
1373
+ case XS_BOOLEAN_KIND:
1374
+ fxEcho(the, " value=\"");
1375
+ if (theProperty->value.boolean)
1376
+ fxEcho(the, "true");
1377
+ else
1378
+ fxEcho(the, "false");
1379
+ fxEcho(the, "\"/>");
1380
+ break;
1381
+ case XS_INTEGER_KIND:
1382
+ fxEcho(the, " value=\"");
1383
+ fxEchoInteger(the, theProperty->value.integer);
1384
+ fxEcho(the, "\"/>");
1385
+ break;
1386
+ case XS_NUMBER_KIND:
1387
+ fxEcho(the, " value=\"");
1388
+ fxEchoNumber(the, theProperty->value.number);
1389
+ fxEcho(the, "\"/>");
1390
+ break;
1391
+ case XS_BIGINT_KIND:
1392
+ case XS_BIGINT_X_KIND:
1393
+ fxEcho(the, " value=\"");
1394
+ fxEchoBigInt(the, &theProperty->value.bigint);
1395
+ fxEcho(the, "\"/>");
1396
+ break;
1397
+ case XS_DATE_KIND:
1398
+ fxEcho(the, " value=\"");
1399
+ fxEchoNumber(the, theProperty->value.number);
1400
+ fxEcho(the, "\"/>");
1401
+ break;
1402
+ case XS_REGEXP_KIND:
1403
+ fxEcho(the, " value=\"\"/>");
1404
+ break;
1405
+ case XS_HOST_KIND:
1406
+ if (theProperty->value.host.data) {
1407
+ if (theProperty->flag & XS_HOST_CHUNK_FLAG)
1408
+ fxEcho(the, " value=\"XS data\"/>");
1409
+ else
1410
+ fxEcho(the, " value=\"C data\"/>");
1411
+ }
1412
+ else
1413
+ fxEcho(the, " value=\"NULL\"/>");
1414
+ break;
1415
+ case XS_PROMISE_KIND:
1416
+ switch (theProperty->value.integer) {
1417
+ case mxUndefinedStatus: fxEcho(the, " value=\"?\"/>"); break;
1418
+ case mxPendingStatus: fxEcho(the, " value=\"pending\"/>"); break;
1419
+ case mxFulfilledStatus: fxEcho(the, " value=\"fulfilled\"/>"); break;
1420
+ case mxRejectedStatus: fxEcho(the, " value=\"rejected\"/>"); break;
1421
+ }
1422
+ break;
1423
+ case XS_KEY_KIND:
1424
+ case XS_KEY_X_KIND:
1425
+ fxEcho(the, " value=\"'");
1426
+ fxEchoString(the, theProperty->value.key.string);
1427
+ fxEcho(the, "'\"/>");
1428
+ break;
1429
+ case XS_SYMBOL_KIND:
1430
+ name = fxGetKeyName(the, theProperty->value.symbol);
1431
+ fxEcho(the, " value=\"Symbol(");
1432
+ if (name)
1433
+ fxEchoString(the, name);
1434
+ fxEcho(the, ")\"/>");
1435
+ break;
1436
+ case XS_DATA_VIEW_KIND:
1437
+ fxEcho(the, " value=\"");
1438
+ fxEchoInteger(the, theProperty->value.dataView.offset);
1439
+ fxEcho(the, ", ");
1440
+ fxEchoInteger(the, fxGetDataViewSize(the, theProperty, theProperty->next));
1441
+ fxEcho(the, " bytes\"/>");
1442
+ break;
1443
+ case XS_TYPED_ARRAY_KIND:
1444
+ fxEcho(the, " value=\"");
1445
+ fxEchoInteger(the, theProperty->value.typedArray.dispatch->size);
1446
+ fxEcho(the, " bytes\"/>");
1447
+ break;
1448
+ default:
1449
+ fxEcho(the, "/>");
1450
+ break;
1451
+ }
1452
+ }
1453
+ }
1454
+
1455
+ void fxEchoPropertyHost(txMachine* the, txInspectorNameList* theList, txSlot* theInstance, txSlot* theHost)
1456
+ {
1457
+ txSlot* instanceInspector = fxToInstanceInspector(the, theInstance);
1458
+ if (instanceInspector) {
1459
+ txSlot* hostInspectors = &mxHostInspectors;
1460
+ txSlot* hostInspector;
1461
+ txSlot* cache;
1462
+ txSlot* cacheProperty;
1463
+ hostInspector = hostInspectors->value.list.first;
1464
+ while (hostInspector) {
1465
+ if (hostInspector->value.hostInspector.instance == theInstance) {
1466
+ break;
1467
+ }
1468
+ hostInspector = hostInspector->next;
1469
+ }
1470
+ if (!hostInspector) {
1471
+ txSlot* aParent;
1472
+ cache = fxNewInstance(the);
1473
+ hostInspector = fxNewSlot(the);
1474
+ hostInspector->kind = XS_HOST_INSPECTOR_KIND;
1475
+ hostInspector->value.hostInspector.cache = cache;
1476
+ hostInspector->value.hostInspector.instance = theInstance;
1477
+ if (hostInspectors->value.list.first)
1478
+ hostInspectors->value.list.last->next = hostInspector;
1479
+ else
1480
+ hostInspectors->value.list.first = hostInspector;
1481
+ hostInspectors->value.list.last = hostInspector;
1482
+ mxPop();
1483
+
1484
+ aParent = theInstance;
1485
+ while (aParent && (aParent->next->kind == XS_HOST_KIND)) {
1486
+ txSlot* aParentProperty = aParent->next;
1487
+ while (aParentProperty) {
1488
+ if ((aParentProperty->kind == XS_ACCESSOR_KIND) && (aParentProperty->value.accessor.getter)) {
1489
+ cacheProperty = mxBehaviorGetProperty(the, cache, aParentProperty->ID, 0, XS_ANY);
1490
+ if (!cacheProperty) {
1491
+ txSlot* aFunction = aParentProperty->value.accessor.getter;
1492
+ if (mxIsFunction(aFunction)) {
1493
+ fxBeginHost(the);
1494
+ /* THIS */
1495
+ mxPushReference(theInstance);
1496
+ /* FUNCTION */
1497
+ mxPushReference(aFunction);
1498
+ mxCall();
1499
+ mxRunCount(0);
1500
+ cacheProperty = mxBehaviorSetProperty(the, cache, aParentProperty->ID, 0, XS_ANY);
1501
+ cacheProperty->flag |= XS_INSPECTOR_FLAG;
1502
+ cacheProperty->kind = the->stack->kind;
1503
+ cacheProperty->value = the->stack->value;
1504
+ mxPop();
1505
+ fxEndHost(the);
1506
+ }
1507
+ }
1508
+ }
1509
+ aParentProperty = aParentProperty->next;
1510
+ }
1511
+ aParent = fxGetPrototype(the, aParent);
1512
+ }
1513
+ }
1514
+ cache = hostInspector->value.hostInspector.cache;
1515
+ cacheProperty = cache->next;
1516
+ while (cacheProperty) {
1517
+ if (cacheProperty->ID)
1518
+ fxEchoProperty(the, cacheProperty, theList, C_NULL, -1, C_NULL);
1519
+ cacheProperty = cacheProperty->next;
1520
+ }
1521
+ }
1522
+ }
1523
+
1524
+ void fxEchoPropertyInstance(txMachine* the, txInspectorNameList* theList, txString thePrefix, txIndex theIndex, txString theSuffix, txID theID, txFlag theFlag, txSlot* theInstance)
1525
+ {
1526
+ txSlot* instanceInspector = fxToInstanceInspector(the, theInstance);
1527
+ char buffer[128];
1528
+ txString p = buffer;
1529
+ txString q = p + sizeof(buffer);
1530
+
1531
+ if (theFlag & XS_GETTER_FLAG) {
1532
+ c_strcpy(p, "get ");
1533
+ p += 4;
1534
+ }
1535
+ else if (theFlag & XS_SETTER_FLAG) {
1536
+ c_strcpy(p, "set ");
1537
+ p += 4;
1538
+ }
1539
+ if (thePrefix) {
1540
+ c_strcpy(p, thePrefix);
1541
+ p += mxStringLength(thePrefix);
1542
+ if (theSuffix) {
1543
+ fxIndexToString(the, theIndex, p, mxPtrDiff(q - p - 1)); // assume mxStringLength(theSuffix) == 1;
1544
+ c_strcat(p, theSuffix);
1545
+ }
1546
+ }
1547
+ else
1548
+ fxIDToString(the, theID, p, mxPtrDiff(q - p));
1549
+
1550
+ fxEcho(the, "<property");
1551
+ if (instanceInspector) {
1552
+ if (instanceInspector->value.instanceInspector.link)
1553
+ fxEchoFlags(the, " ", theFlag);
1554
+ else
1555
+ fxEchoFlags(the, "-", theFlag);
1556
+ }
1557
+ else
1558
+ fxEchoFlags(the, "+", theFlag);
1559
+ fxEcho(the, " name=\"");
1560
+ fxEchoString(the, buffer);
1561
+ fxEcho(the, "\"");
1562
+
1563
+ if (instanceInspector) {
1564
+ if (instanceInspector->value.instanceInspector.link) {
1565
+ txInspectorNameLink* link = theList->first;
1566
+ fxEcho(the, " value=\"");
1567
+ while (link) {
1568
+ fxEchoString(the, link->name);
1569
+ if (link == instanceInspector->value.instanceInspector.link)
1570
+ break;
1571
+ fxEcho(the, ".");
1572
+ link = link->next;
1573
+ }
1574
+ fxEcho(the, "\"/>");
1575
+ }
1576
+ else {
1577
+ txInspectorNameLink link;
1578
+ link.previous = theList->last;
1579
+ link.next = C_NULL;
1580
+ link.name = buffer;
1581
+ if (theList->first)
1582
+ theList->last->next = &link;
1583
+ else
1584
+ theList->first = &link;
1585
+ theList->last = &link;
1586
+ instanceInspector->value.instanceInspector.link = &link;
1587
+
1588
+ fxEchoAddress(the, theInstance);
1589
+ fxEcho(the, ">");
1590
+ fxEchoInstance(the, theInstance, theList);
1591
+ fxEcho(the, "</property>");
1592
+
1593
+ instanceInspector->value.instanceInspector.link = C_NULL;
1594
+ if (link.previous)
1595
+ link.previous->next = C_NULL;
1596
+ else
1597
+ theList->first = C_NULL;
1598
+ theList->last = link.previous;
1599
+ }
1600
+ }
1601
+ else {
1602
+ fxEchoAddress(the, theInstance);
1603
+ fxEcho(the, "/>");
1604
+ }
1605
+ }
1606
+
1607
+ void fxEchoStart(txMachine* the)
1608
+ {
1609
+ the->echoOffset = 0;
1610
+ fxEcho(the, "\15\12<xsbug>");
1611
+ }
1612
+
1613
+ void fxEchoStop(txMachine* the)
1614
+ {
1615
+ fxEcho(the, "</xsbug>\15\12");
1616
+ fxSend(the, 0);
1617
+ the->echoOffset = 0;
1618
+ }
1619
+
1620
+ void fxEchoString(txMachine* the, txString theString)
1621
+ {
1622
+ static const txByte gxEscape[256] ICACHE_FLASH_ATTR = {
1623
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
1624
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */
1625
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */
1626
+ 1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1, /* 2x !"#$%&'()*+,-./ */
1627
+ 1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1, /* 3x 0123456789:;<=>? */
1628
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4x @ABCDEFGHIJKLMNO */
1629
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5X PQRSTUVWXYZ[\]^_ */
1630
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6x `abcdefghijklmno */
1631
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, /* 7X pqrstuvwxyz{|}~ */
1632
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 8X */
1633
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9X */
1634
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* AX */
1635
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* BX */
1636
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* CX */
1637
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* FX */
1638
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* EX */
1639
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 /* FX */
1640
+ };
1641
+ txU1 tmp;
1642
+ txU1* src;
1643
+ txU1* dst;
1644
+ txU1* start;
1645
+ txU1* stop;
1646
+
1647
+ src = (txU1*)theString;
1648
+ dst = (txU1*)the->echoBuffer + the->echoOffset;
1649
+ start = (txU1*)the->echoBuffer;
1650
+ stop = (txU1*)the->echoBuffer + sizeof(the->echoBuffer) - 1;
1651
+ while ((tmp = c_read8(src))) {
1652
+ src++;
1653
+ if (dst + 6 > stop) {
1654
+ the->echoOffset = mxPtrDiff(dst - start);
1655
+ fxSend(the, 1);
1656
+ dst = start;
1657
+ }
1658
+ #if mxCESU8
1659
+ if (tmp & 0x80) {
1660
+ txInteger character;
1661
+ src = (txU1*)fxCESU8Decode((txString)src - 1, &character);
1662
+ if (character > 128) {
1663
+ dst = (txU1*)fxUTF8Encode((txString)dst, character);
1664
+ continue;
1665
+ }
1666
+ tmp = (txU1)character;
1667
+ }
1668
+ #endif
1669
+ if (c_read8(gxEscape + tmp))
1670
+ *dst++ = tmp;
1671
+ else {
1672
+ *(dst++) = '&';
1673
+ *(dst++) = '#';
1674
+ if (tmp >= 100) {
1675
+ *(dst++) = '0' + (tmp / 100);
1676
+ tmp %= 100;
1677
+ *(dst++) = '0' + (tmp / 10);
1678
+ tmp %= 10;
1679
+ *(dst++) = '0' + tmp;
1680
+ }
1681
+ else if (tmp >= 10) {
1682
+ *(dst++) = '0' + (tmp / 10);
1683
+ tmp %= 10;
1684
+ *(dst++) = '0' + tmp;
1685
+ }
1686
+ else {
1687
+ *(dst++) = '0' + tmp;
1688
+ }
1689
+ *(dst++) = ';';
1690
+ }
1691
+ }
1692
+ the->echoOffset = mxPtrDiff(dst - start);
1693
+ }
1694
+
1695
+ txSlot* fxFindFrame(txMachine* the)
1696
+ {
1697
+ txSlot* frame = the->frame;
1698
+ while (frame) {
1699
+ if (frame->flag & XS_DEBUG_FLAG)
1700
+ break;
1701
+ frame = frame->next;
1702
+ }
1703
+ return frame;
1704
+ }
1705
+
1706
+ txSlot* fxFindRealm(txMachine* the)
1707
+ {
1708
+ txSlot* frame = fxFindFrame(the);
1709
+ txSlot* realm = C_NULL;
1710
+ if (frame && (!(frame->flag & XS_C_FLAG))) {
1711
+ txSlot* function = frame + 3;
1712
+ if (mxIsReference(function)) {
1713
+ txSlot* instance = function->value.reference;
1714
+ txSlot* home = mxFunctionInstanceHome(instance);
1715
+ txSlot* module = home->value.home.module;
1716
+ if (module)
1717
+ realm = mxModuleInstanceInternal(module)->value.module.realm;
1718
+ }
1719
+ }
1720
+ if (!realm)
1721
+ realm = mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm;
1722
+ return realm;
1723
+ }
1724
+
1725
+ void fxGo(txMachine* the)
1726
+ {
1727
+ txSlot* aSlot = the->frame;
1728
+ while (aSlot) {
1729
+ aSlot->flag &= ~(XS_STEP_INTO_FLAG | XS_STEP_OVER_FLAG);
1730
+ aSlot = aSlot->next;
1731
+ }
1732
+ }
1733
+
1734
+ void fxIndexToString(txMachine* the, txIndex theIndex, txString theBuffer, txSize theSize)
1735
+ {
1736
+ c_snprintf(theBuffer, theSize, "%u", theIndex);
1737
+ }
1738
+
1739
+ void fxListFrames(txMachine* the)
1740
+ {
1741
+ txSlot* aFrame;
1742
+
1743
+ fxEcho(the, "<frames>");
1744
+ aFrame = the->frame;
1745
+ while (aFrame) {
1746
+ fxEcho(the, "<frame");
1747
+ fxEcho(the, " name=\"");
1748
+ fxEchoFrameName(the, aFrame);
1749
+ fxEcho(the, "\"");
1750
+ fxEchoAddress(the, aFrame);
1751
+ fxEchoFramePathLine(the, aFrame);
1752
+ fxEcho(the, "/>");
1753
+ aFrame = aFrame->next;
1754
+ }
1755
+ fxEcho(the, "</frames>");
1756
+ }
1757
+
1758
+ void fxListGlobal(txMachine* the)
1759
+ {
1760
+ txInspectorNameList aList = { C_NULL, C_NULL };
1761
+ txSlot* realm = fxFindRealm(the);
1762
+ txSlot* global = mxRealmGlobal(realm)->value.reference;
1763
+ txSlot* slot = fxGetPrototype(the, global);
1764
+ fxEcho(the, "<global>");
1765
+ if (slot != mxObjectPrototype.value.reference) {
1766
+ fxEchoPropertyInstance(the, &aList, "(..)", -1, C_NULL, XS_NO_ID, global->flag & XS_MARK_FLAG, slot);
1767
+ }
1768
+ slot = global->next;
1769
+ while (slot) {
1770
+ fxEchoProperty(the, slot, &aList, C_NULL, -1, C_NULL);
1771
+ slot = slot->next;
1772
+ }
1773
+ global = mxRealmClosures(realm)->value.reference;
1774
+ slot = global->next;
1775
+ while (slot) {
1776
+ fxEchoProperty(the, slot, &aList, C_NULL, -1, C_NULL);
1777
+ slot = slot->next;
1778
+ }
1779
+ fxEcho(the, "</global>");
1780
+ }
1781
+
1782
+ void fxListLocal(txMachine* the)
1783
+ {
1784
+ txInspectorNameList aList = { C_NULL, C_NULL };
1785
+ txSlot* frame = fxFindFrame(the);
1786
+ txSlot* scope = C_NULL;
1787
+ if (!frame) // @@
1788
+ return;
1789
+ fxEcho(the, "<local");
1790
+ fxEcho(the, " name=\"");
1791
+ fxEchoFrameName(the, frame);
1792
+ fxEcho(the, "\"");
1793
+ fxEchoAddress(the, frame);
1794
+ fxEchoFramePathLine(the, frame);
1795
+ fxEcho(the, ">");
1796
+ fxEchoProperty(the, frame + 1, &aList, "(return)", -1, C_NULL);
1797
+ fxEchoProperty(the, frame + 2, &aList, "new.target", -1, C_NULL);
1798
+ fxEchoProperty(the, frame + 3, &aList, "(function)", -1, C_NULL);
1799
+ fxEchoProperty(the, frame + 4, &aList, "this", -1, C_NULL);
1800
+ if (frame == the->frame)
1801
+ scope = the->scope;
1802
+ else {
1803
+ txSlot* current = the->frame;
1804
+ while (current->next != frame)
1805
+ current = current->next;
1806
+ if (current)
1807
+ scope = current->value.frame.scope;
1808
+ }
1809
+ if (frame->flag & XS_C_FLAG) {
1810
+ txInteger aCount, anIndex;
1811
+ aCount = (frame - 1)->value.integer;
1812
+ for (anIndex = 0; anIndex < aCount; anIndex++) {
1813
+ fxEchoProperty(the, (frame - 2 - anIndex), &aList, "arg(", anIndex, ")");
1814
+ }
1815
+ if (scope) {
1816
+ aCount = scope->value.environment.variable.count;
1817
+ for (anIndex = 0; anIndex < aCount; anIndex++) {
1818
+ fxEchoProperty(the, (scope - 1 - anIndex), &aList, "var(", anIndex, ")");
1819
+ }
1820
+ }
1821
+ }
1822
+ else {
1823
+ if (scope) {
1824
+ txSlot* aSlot = mxFrameToEnvironment(frame);
1825
+ txID id;
1826
+ while (aSlot > scope) {
1827
+ aSlot--;
1828
+ id = aSlot->ID;
1829
+ if ((0 < id) && (id < the->keyCount)) {
1830
+ txSlot* key;
1831
+ if (id < the->keyOffset)
1832
+ key = the->keyArrayHost[id];
1833
+ else
1834
+ key = the->keyArray[id - the->keyOffset];
1835
+ if (key) {
1836
+ txKind kind = mxGetKeySlotKind(key);
1837
+ if ((kind == XS_KEY_KIND) || (kind == XS_KEY_X_KIND)) {
1838
+ if (key->value.key.string[0] != '#')
1839
+ fxEchoProperty(the, aSlot, &aList, C_NULL, -1, C_NULL);
1840
+ }
1841
+ else
1842
+ fxEchoProperty(the, aSlot, &aList, C_NULL, -1, C_NULL);
1843
+ }
1844
+ }
1845
+ }
1846
+ }
1847
+ }
1848
+ fxEcho(the, "</local>");
1849
+ }
1850
+
1851
+ void fxListModules(txMachine* the)
1852
+ {
1853
+ txInspectorNameList aList = { C_NULL, C_NULL };
1854
+ txSlot* realm = fxFindRealm(the);
1855
+ txSlot* moduleMap = mxModuleMap(realm);
1856
+ txSlot* instance = fxGetInstance(the, moduleMap);
1857
+ txSlot* instanceInspector = fxToInstanceInspector(the, instance);
1858
+ txSlot* modules = mxOwnModules(realm)->value.reference;
1859
+ txSlot* module;
1860
+ fxEcho(the, "<grammar>");
1861
+ if (instance->next) {
1862
+ fxEcho(the, "<node");
1863
+ if (instanceInspector)
1864
+ fxEchoFlags(the, "-", moduleMap->flag);
1865
+ else
1866
+ fxEchoFlags(the, "+", moduleMap->flag);
1867
+ fxEcho(the, " name=\"(map)\"");
1868
+ fxEchoAddress(the, instance);
1869
+ if (instanceInspector) {
1870
+ fxEcho(the, ">");
1871
+ fxEchoInstance(the, instance, &aList);
1872
+ fxEcho(the, "</node>");
1873
+ }
1874
+ else
1875
+ fxEcho(the, "/>");
1876
+ }
1877
+ module = modules->next;
1878
+ while (module) {
1879
+ if (mxIsReference(module))
1880
+ fxEchoModule(the, module, &aList);
1881
+ module = module->next;
1882
+ }
1883
+ modules = modules->value.instance.prototype;
1884
+ if (modules) {
1885
+ module = modules->next;
1886
+ while (module) {
1887
+ if (mxIsReference(module))
1888
+ fxEchoModule(the, module, &aList);
1889
+ module = module->next;
1890
+ }
1891
+ }
1892
+ fxEcho(the, "</grammar>");
1893
+ }
1894
+
1895
+ void fxLogin(txMachine* the)
1896
+ {
1897
+ if (!fxIsConnected(the)) {
1898
+ fxConnect(the);
1899
+ if (!fxIsConnected(the))
1900
+ return;
1901
+ }
1902
+ fxEchoStart(the);
1903
+ fxEcho(the, "<login name=\"");
1904
+ if (the->name)
1905
+ fxEchoString(the, the->name);
1906
+ else
1907
+ fxEchoString(the, "xslib");
1908
+ fxEcho(the, "\" value=\"");
1909
+ fxEcho(the, "XS");
1910
+ fxEcho(the, "\"/>");
1911
+ fxEchoStop(the);
1912
+ if (the->sharedMachine) {
1913
+ fxToggle(the, the->sharedMachine->stackTop[-1 - mxGlobalStackIndex].value.reference);
1914
+ fxToggle(the, the->sharedMachine->stackTop[-1 - mxCompartmentGlobalStackIndex].value.reference);
1915
+ }
1916
+ fxDebugCommand(the);
1917
+ }
1918
+
1919
+ void fxLogout(txMachine* the)
1920
+ {
1921
+ if (!fxIsConnected(the))
1922
+ return;
1923
+ fxStopProfiling(the, C_NULL);
1924
+ fxDisconnect(the);
1925
+ }
1926
+
1927
+ void fxSelect(txMachine* the, txSlot* slot)
1928
+ {
1929
+ txSlot* frame = the->frame;
1930
+ while (frame) {
1931
+ if (frame == slot)
1932
+ frame->flag |= XS_DEBUG_FLAG;
1933
+ else
1934
+ frame->flag &= ~XS_DEBUG_FLAG;
1935
+ frame = frame->next;
1936
+ }
1937
+ }
1938
+
1939
+ void fxSetBreakpoint(txMachine* the, txString thePath, txInteger theLine)
1940
+ {
1941
+ txID path;
1942
+ txSlot* breakpoint;
1943
+
1944
+ if (!thePath)
1945
+ return;
1946
+ if (!c_strcmp(thePath, "exceptions")) {
1947
+ the->breakOnExceptionsFlag = 1;
1948
+ return;
1949
+ }
1950
+ if (!c_strcmp(thePath, "start")) {
1951
+ the->breakOnStartFlag = 1;
1952
+ return;
1953
+ }
1954
+ if ((theLine <= 0) || (0x00007FFF < theLine))
1955
+ return;
1956
+ path = fxNewNameC(the, thePath);
1957
+ if (!path)
1958
+ return;
1959
+ breakpoint = mxBreakpoints.value.list.first;
1960
+ while (breakpoint) {
1961
+ if ((breakpoint->ID == path) && (breakpoint->value.integer == theLine))
1962
+ return;
1963
+ breakpoint = breakpoint->next;
1964
+ }
1965
+ breakpoint = fxNewSlot(the);
1966
+ breakpoint->next = mxBreakpoints.value.list.first;
1967
+ breakpoint->ID = path;
1968
+ breakpoint->kind = XS_INTEGER_KIND;
1969
+ breakpoint->value.integer = theLine;
1970
+ mxBreakpoints.value.list.first = breakpoint;
1971
+ }
1972
+
1973
+ void fxStep(txMachine* the)
1974
+ {
1975
+ txSlot* aSlot = the->frame;
1976
+ if (aSlot) {
1977
+ while (aSlot) {
1978
+ aSlot->flag &= ~XS_STEP_INTO_FLAG;
1979
+ aSlot->flag |= XS_STEP_OVER_FLAG;
1980
+ aSlot = aSlot->next;
1981
+ }
1982
+ }
1983
+ else {
1984
+ the->breakOnStartFlag = 1;
1985
+ }
1986
+ }
1987
+
1988
+ void fxStepInside(txMachine* the)
1989
+ {
1990
+ txSlot* aSlot = the->frame;
1991
+ while (aSlot) {
1992
+ aSlot->flag |= XS_STEP_INTO_FLAG | XS_STEP_OVER_FLAG;
1993
+ aSlot = aSlot->next;
1994
+ }
1995
+ }
1996
+
1997
+ void fxStepOutside(txMachine* the)
1998
+ {
1999
+ txSlot* aSlot = the->frame;
2000
+ if (aSlot) {
2001
+ aSlot->flag &= ~(XS_STEP_INTO_FLAG | XS_STEP_OVER_FLAG);
2002
+ aSlot = aSlot->next;
2003
+ while (aSlot) {
2004
+ aSlot->flag &= ~XS_STEP_INTO_FLAG;
2005
+ aSlot->flag |= XS_STEP_OVER_FLAG;
2006
+ aSlot = aSlot->next;
2007
+ }
2008
+ }
2009
+ }
2010
+
2011
+ txSlot* fxToInstanceInspector(txMachine* the, txSlot* slot)
2012
+ {
2013
+ txSlot* instanceInspector = mxInstanceInspectors.value.list.first;
2014
+ while (instanceInspector) {
2015
+ if (instanceInspector->value.instanceInspector.slot == slot)
2016
+ return instanceInspector;
2017
+ if (instanceInspector->value.instanceInspector.slot > slot)
2018
+ break;
2019
+ instanceInspector = instanceInspector->next;
2020
+ }
2021
+ return C_NULL;
2022
+ }
2023
+
2024
+ void fxToggle(txMachine* the, txSlot* slot)
2025
+ {
2026
+ txSlot** instanceInspectorAddress = &(mxInstanceInspectors.value.list.first);
2027
+ txSlot* instanceInspector;
2028
+ while ((instanceInspector = *instanceInspectorAddress)) {
2029
+ if (instanceInspector->value.instanceInspector.slot == slot) {
2030
+ *instanceInspectorAddress = instanceInspector->next;
2031
+ return;
2032
+ }
2033
+ if (instanceInspector->value.instanceInspector.slot > slot)
2034
+ break;
2035
+ instanceInspectorAddress = &(instanceInspector->next);
2036
+ }
2037
+ instanceInspector = fxNewSlot(the);
2038
+ instanceInspector->next = *instanceInspectorAddress;
2039
+ instanceInspector->kind = XS_INSTANCE_INSPECTOR_KIND;
2040
+ instanceInspector->value.instanceInspector.slot = slot;
2041
+ instanceInspector->value.instanceInspector.link = C_NULL;
2042
+ *instanceInspectorAddress = instanceInspector;
2043
+ }
2044
+
2045
+ #endif
2046
+
2047
+ void fxBubble(txMachine* the, txInteger flags, void* message, txInteger length, txString conversation)
2048
+ {
2049
+ #ifdef mxDebug
2050
+ if (fxIsConnected(the)) {
2051
+ txString path = C_NULL;
2052
+ txInteger line = 0;
2053
+ txSlot* frame = the->frame;
2054
+ while (frame && !path) {
2055
+ txSlot* environment = mxFrameToEnvironment(frame);
2056
+ if (environment->ID != XS_NO_ID) {
2057
+ path = fxGetKeyName(the, environment->ID);
2058
+ line = environment->value.environment.line;
2059
+ }
2060
+ frame = frame->next;
2061
+ }
2062
+ fxEchoStart(the);
2063
+ fxEcho(the, "<bubble name=\"");
2064
+ if (conversation)
2065
+ fxEchoString(the, conversation);
2066
+ fxEcho(the, "\" value=\"");
2067
+ fxEchoInteger(the, flags);
2068
+ fxEcho(the, "\"");
2069
+ fxEchoPathLine(the, path, line);
2070
+ fxEcho(the, ">");
2071
+ if (flags & XS_BUBBLE_BINARY) {
2072
+ txU1* bytes = message;
2073
+ txInteger byteLength = length;
2074
+ while (byteLength) {
2075
+ txU1 byte = c_read8(bytes);
2076
+ fxEchoCharacter(the, gxHexaDigits[(byte & 0xF0) >> 4]);
2077
+ fxEchoCharacter(the, gxHexaDigits[(byte & 0x0F)]);
2078
+ bytes++;
2079
+ byteLength--;
2080
+ }
2081
+ }
2082
+ else
2083
+ fxEchoString(the, message);
2084
+ fxEcho(the, "</bubble>");
2085
+ fxEchoStop(the);
2086
+ }
2087
+ #elif defined(mxInstrument)
2088
+ if (!(flags & XS_BUBBLE_BINARY)) {
2089
+ if (conversation)
2090
+ fxReport(the, "%s: %s\n", conversation, message);
2091
+ else
2092
+ fxReport(the, "%s\n", message);
2093
+ }
2094
+ #endif
2095
+ }
2096
+
2097
+ void fxFileEvalString(txMachine* the, txString string, txString tag)
2098
+ {
2099
+ #ifdef mxDebug
2100
+ if (fxIsConnected(the)) {
2101
+ fxEchoStart(the);
2102
+ fxEcho(the, "<eval path=\"");
2103
+ fxEchoString(the, tag);
2104
+ fxEcho(the, "\"");
2105
+ fxEcho(the, ">");
2106
+ fxEchoString(the, string);
2107
+ fxEcho(the, "</eval>");
2108
+ fxEchoStop(the);
2109
+ }
2110
+ #endif
2111
+ }
2112
+
2113
+ void fxReport(txMachine* the, txString theFormat, ...)
2114
+ {
2115
+ c_va_list arguments;
2116
+
2117
+ c_va_start(arguments, theFormat);
2118
+ fxVReport(the, theFormat, arguments);
2119
+ c_va_end(arguments);
2120
+ #ifndef mxNoConsole
2121
+ c_va_start(arguments, theFormat);
2122
+ c_vprintf(theFormat, arguments);
2123
+ c_va_end(arguments);
2124
+ #endif
2125
+ }
2126
+
2127
+ void fxReportException(txMachine* the, txString thePath, txInteger theLine, txString theFormat, ...)
2128
+ {
2129
+ c_va_list arguments;
2130
+
2131
+ c_va_start(arguments, theFormat);
2132
+ fxVReportException(the, thePath, theLine, theFormat, arguments);
2133
+ c_va_end(arguments);
2134
+ #ifndef mxNoConsole
2135
+ if (thePath && theLine)
2136
+ #if mxWindows
2137
+ printf("%s(%d): exception: ", thePath, (int)theLine);
2138
+ #else
2139
+ c_printf("%s:%d: exception: ", thePath, (int)theLine);
2140
+ #endif
2141
+ else
2142
+ c_printf("# exception: ");
2143
+ c_va_start(arguments, theFormat);
2144
+ c_vprintf(theFormat, arguments);
2145
+ c_va_end(arguments);
2146
+ c_printf("!\n");
2147
+ #endif
2148
+ }
2149
+
2150
+ void fxReportError(txMachine* the, txString thePath, txInteger theLine, txString theFormat, ...)
2151
+ {
2152
+ c_va_list arguments;
2153
+
2154
+ c_va_start(arguments, theFormat);
2155
+ fxVReportError(the, thePath, theLine, theFormat, arguments);
2156
+ c_va_end(arguments);
2157
+ #ifndef mxNoConsole
2158
+ if (thePath && theLine)
2159
+ #if mxWindows
2160
+ printf("%s(%d): error: ", thePath, (int)theLine);
2161
+ #else
2162
+ c_printf("%s:%d: error: ", thePath, (int)theLine);
2163
+ #endif
2164
+ else
2165
+ c_printf("# error: ");
2166
+ c_va_start(arguments, theFormat);
2167
+ c_vprintf(theFormat, arguments);
2168
+ c_va_end(arguments);
2169
+ c_printf("!\n");
2170
+ #endif
2171
+ }
2172
+
2173
+ void fxReportWarning(txMachine* the, txString thePath, txInteger theLine, txString theFormat, ...)
2174
+ {
2175
+ c_va_list arguments;
2176
+
2177
+ c_va_start(arguments, theFormat);
2178
+ fxVReportWarning(the, thePath, theLine, theFormat, arguments);
2179
+ c_va_end(arguments);
2180
+ #ifndef mxNoConsole
2181
+ if (thePath && theLine)
2182
+ #if mxWindows
2183
+ printf("%s(%d): warning: ", thePath, (int)theLine);
2184
+ #else
2185
+ c_printf("%s:%d: warning: ", thePath, (int)theLine);
2186
+ #endif
2187
+ else
2188
+ c_printf("# warning: ");
2189
+ c_va_start(arguments, theFormat);
2190
+ c_vprintf(theFormat, arguments);
2191
+ c_va_end(arguments);
2192
+ c_printf("!\n");
2193
+ #endif
2194
+ }
2195
+
2196
+ txID fxGenerateProfileID(void* console)
2197
+ {
2198
+ txMachine* the = console;
2199
+ txID id = the->profileID;
2200
+ the->profileID++;
2201
+ return id;
2202
+ }
2203
+
2204
+ void fxGenerateTag(void* console, txString buffer, txInteger bufferSize, txString path)
2205
+ {
2206
+ txMachine* the = console;
2207
+ if (path)
2208
+ c_snprintf(buffer, bufferSize, "#%d@%s", the->tag, path);
2209
+ else
2210
+ c_snprintf(buffer, bufferSize, "#%d", the->tag);
2211
+ the->tag++;
2212
+ }
2213
+
2214
+ void fxVReport(void* console, txString theFormat, c_va_list theArguments)
2215
+ {
2216
+ #ifdef mxDebug
2217
+ txMachine* the = console;
2218
+ if (fxIsConnected(the)) {
2219
+ fxEchoStart(the);
2220
+ fxEcho(the, "<log>");
2221
+ fxEchoFormat(the, theFormat, theArguments);
2222
+ fxEcho(the, "</log>");
2223
+ fxEchoStop(the);
2224
+ }
2225
+ #endif
2226
+ #if defined(DEBUG_EFM)
2227
+ memmove(_lastDebugStrBuffer, _debugStrBuffer, 256);
2228
+ vsprintf(_debugStrBuffer, theFormat, theArguments);
2229
+ _debugStrBuffer[255] = '\0';
2230
+ #endif
2231
+ }
2232
+
2233
+ void fxVReportException(void* console, txString thePath, txInteger theLine, txString theFormat, c_va_list theArguments)
2234
+ {
2235
+ #ifdef mxDebug
2236
+ txMachine* the = console;
2237
+ if (fxIsConnected(the)) {
2238
+ fxEchoStart(the);
2239
+ fxEcho(the, "<log");
2240
+ fxEchoPathLine(the, thePath, theLine);
2241
+ fxEcho(the, "># Exception: ");
2242
+ fxEchoFormat(the, theFormat, theArguments);
2243
+ fxEcho(the, "!\n</log>");
2244
+ fxEchoStop(the);
2245
+ }
2246
+ #endif
2247
+ #if defined(DEBUG_EFM)
2248
+ if (thePath && theLine)
2249
+ sprintf(_debugStrBuffer, "%s:%d: exception: ", thePath, (int)theLine);
2250
+ else
2251
+ sprintf(_debugStrBuffer, "# exception: ");
2252
+ memmove(_lastDebugStrBuffer, _debugStrBuffer, 256);
2253
+ vsprintf(_debugStrBuffer, theFormat, theArguments);
2254
+ _debugStrBuffer[255] = '\0';
2255
+ #endif
2256
+ }
2257
+
2258
+ void fxVReportError(void* console, txString thePath, txInteger theLine, txString theFormat, c_va_list theArguments)
2259
+ {
2260
+ #ifdef mxDebug
2261
+ txMachine* the = console;
2262
+ if (fxIsConnected(the)) {
2263
+ fxEchoStart(the);
2264
+ fxEcho(the, "<log");
2265
+ fxEchoPathLine(the, thePath, theLine);
2266
+ fxEcho(the, "># Error: ");
2267
+ fxEchoFormat(the, theFormat, theArguments);
2268
+ fxEcho(the, "!\n</log>");
2269
+ fxEchoStop(the);
2270
+ }
2271
+ #endif
2272
+ #if defined(DEBUG_EFM)
2273
+ if (thePath && theLine)
2274
+ sprintf(_debugStrBuffer, "%s:%d: error: ", thePath, (int)theLine);
2275
+ else
2276
+ sprintf(_debugStrBuffer, "# error: ");
2277
+ vsprintf(_debugStrBuffer, theFormat, theArguments);
2278
+ _debugStrBuffer[255] = '\0';
2279
+ #endif
2280
+ }
2281
+
2282
+ void fxVReportWarning(void* console, txString thePath, txInteger theLine, txString theFormat, c_va_list theArguments)
2283
+ {
2284
+ #ifdef mxDebug
2285
+ txMachine* the = console;
2286
+ if (fxIsConnected(the)) {
2287
+ fxEchoStart(the);
2288
+ fxEcho(the, "<log");
2289
+ fxEchoPathLine(the, thePath, theLine);
2290
+ fxEcho(the, "># Warning: ");
2291
+ fxEchoFormat(the, theFormat, theArguments);
2292
+ fxEcho(the, "!\n</log>");
2293
+ fxEchoStop(the);
2294
+ }
2295
+ #endif
2296
+ #if defined(DEBUG_EFM)
2297
+ if (thePath && theLine)
2298
+ sprintf(_debugStrBuffer, "%s:%d: warning: ", thePath, (int)theLine);
2299
+ else
2300
+ sprintf(_debugStrBuffer, "# warning: ");
2301
+ vsprintf(_debugStrBuffer, theFormat, theArguments);
2302
+ _debugStrBuffer[255] = '\0';
2303
+ #endif
2304
+ }
2305
+
2306
+ #ifdef mxInstrument
2307
+ #define xsInstrumentCount 11
2308
+ static char* const xsInstrumentNames[xsInstrumentCount] ICACHE_XS6STRING_ATTR = {
2309
+ "Chunk used",
2310
+ "Chunk available",
2311
+ "Slot used",
2312
+ "Slot available",
2313
+ "Stack used",
2314
+ "Stack available",
2315
+ "Garbage collections",
2316
+ "Keys used",
2317
+ "Modules loaded",
2318
+ "Parser used",
2319
+ "Floating Point",
2320
+ };
2321
+ static char* const xsInstrumentUnits[xsInstrumentCount] ICACHE_XS6STRING_ATTR = {
2322
+ " / ",
2323
+ " bytes",
2324
+ " / ",
2325
+ " bytes",
2326
+ " / ",
2327
+ " bytes",
2328
+ " times",
2329
+ " keys",
2330
+ " modules",
2331
+ " bytes",
2332
+ " operations",
2333
+ };
2334
+
2335
+ void fxDescribeInstrumentation(txMachine* the, txInteger count, txString* names, txString* units)
2336
+ {
2337
+ txInteger i, j = 0;
2338
+ #ifdef mxDebug
2339
+ if (fxIsConnected(the)) {
2340
+ fxEchoStart(the);
2341
+ fxEcho(the, "<instruments>");
2342
+ for (i = 0; i < count; i++, j++) {
2343
+ fxEcho(the, "<instrument name=\"");
2344
+ fxEchoString(the, names[i]);
2345
+ fxEcho(the, "\" value=\"");
2346
+ fxEchoString(the, units[i]);
2347
+ fxEcho(the, "\"/>");
2348
+ }
2349
+ for (i = 0; i < xsInstrumentCount; i++, j++) {
2350
+ fxEcho(the, "<instrument name=\"");
2351
+ fxEchoString(the, (txString) xsInstrumentNames[i]);
2352
+ fxEcho(the, "\" value=\"");
2353
+ fxEchoString(the, (txString) xsInstrumentUnits[i]);
2354
+ fxEcho(the, "\"/>");
2355
+ }
2356
+ fxEcho(the, "</instruments>");
2357
+ fxEchoStop(the);
2358
+ //fxReceive(the);
2359
+ return;
2360
+ }
2361
+ #endif
2362
+ #ifndef mxNoConsole
2363
+ j = 0;
2364
+ c_printf("instruments key: ");
2365
+ for (i = 0; i < count; i++, j++) {
2366
+ if (j)
2367
+ c_printf(",");
2368
+ c_printf("%s", names[i]);
2369
+ }
2370
+ for (i = 0; i < xsInstrumentCount; i++, j++) {
2371
+ if (j)
2372
+ c_printf(",");
2373
+ c_printf("%s", xsInstrumentNames[i]);
2374
+ }
2375
+ c_printf("\n");
2376
+ #endif
2377
+ }
2378
+
2379
+ void fxSampleInstrumentation(txMachine* the, txInteger count, txInteger* values)
2380
+ {
2381
+ txInteger xsInstrumentValues[xsInstrumentCount];
2382
+ xsInstrumentValues[0] = the->currentChunksSize;
2383
+ xsInstrumentValues[1] = the->maximumChunksSize;
2384
+ xsInstrumentValues[2] = the->currentHeapCount * sizeof(txSlot);
2385
+ xsInstrumentValues[3] = the->maximumHeapCount * sizeof(txSlot);
2386
+ xsInstrumentValues[4] = (mxPtrDiff(the->stackTop - the->stackPeak)) * sizeof(txSlot);
2387
+ xsInstrumentValues[5] = (mxPtrDiff(the->stackTop - the->stackBottom)) * sizeof(txSlot);
2388
+ xsInstrumentValues[6] = the->garbageCollectionCount;
2389
+ xsInstrumentValues[7] = the->keyIndex - the->keyOffset;
2390
+ xsInstrumentValues[8] = the->loadedModulesCount;
2391
+ xsInstrumentValues[9] = the->peakParserSize;
2392
+ xsInstrumentValues[10] = the->floatingPointOps;
2393
+
2394
+ txInteger i, j = 0;
2395
+ #ifdef mxDebug
2396
+ if (fxIsConnected(the)) {
2397
+ fxEchoStart(the);
2398
+ fxEcho(the, "<samples>");
2399
+ for (i = 0; i < count; i++, j++) {
2400
+ if (j)
2401
+ fxEcho(the, ",");
2402
+ fxEchoInteger(the, values[i]);
2403
+ }
2404
+ for (i = 0; i < xsInstrumentCount; i++, j++) {
2405
+ if (j)
2406
+ fxEcho(the, ",");
2407
+ fxEchoInteger(the, xsInstrumentValues[i]);
2408
+ }
2409
+ fxEcho(the, "</samples>");
2410
+ fxEchoStop(the);
2411
+ return;
2412
+ }
2413
+ #endif
2414
+ #ifndef mxNoConsole
2415
+ j = 0;
2416
+ c_printf("instruments: ");
2417
+ for (i = 0; i < count; i++, j++) {
2418
+ if (j)
2419
+ c_printf(",");
2420
+ c_printf("%d", values[i]);
2421
+ }
2422
+ for (i = 0; i < xsInstrumentCount; i++, j++) {
2423
+ if (j)
2424
+ c_printf(",");
2425
+ c_printf("%d", xsInstrumentValues[i]);
2426
+ }
2427
+ c_printf("\n");
2428
+ #endif
2429
+ }
2430
+
2431
+ #if defined(modMicrosecondsInstrumentation) || defined(modMicroseconds)
2432
+ typedef txU4 txMicroseconds;
2433
+ #else
2434
+ typedef txU8 txMicroseconds;
2435
+ #endif
2436
+
2437
+ #define mxProfilerSampleCount 8
2438
+
2439
+ typedef struct sxProfiler txProfiler;
2440
+ struct sxProfiler {
2441
+ txMicroseconds when;
2442
+ txMicroseconds former;
2443
+ // txMicroseconds start;
2444
+ txMicroseconds stop;
2445
+ txU4 interval;
2446
+ txSize recordCount;
2447
+ txByte* records;
2448
+ txSize sampleIndex;
2449
+ txSize sampleSize;
2450
+ txID* samples;
2451
+ txU4 deltas[mxProfilerSampleCount];
2452
+ };
2453
+
2454
+ static void fxEchoUnsigned(txMachine* the, txUnsigned value, txInteger radix);
2455
+ static txID fxFrameToProfilerID(txMachine* the, txSlot* frame);
2456
+ static txMicroseconds fxGetMicroSeconds();
2457
+ static void fxSendProfilerRecord(txMachine* the, txSlot* frame, txID id, txSlot* code);
2458
+ static void fxSendProfilerSamples(txMachine* the, txProfiler* profiler);
2459
+ static void fxSendProfilerTime(txMachine* the, txString name, txMicroseconds when);
2460
+
2461
+ void fxCheckProfiler(txMachine* the, txSlot* frame)
2462
+ {
2463
+ txProfiler* profiler = the->profiler;
2464
+ if (!profiler)
2465
+ return;
2466
+ txMicroseconds when = profiler->when;
2467
+ txMicroseconds time = fxGetMicroSeconds();
2468
+ if (when <= time) {
2469
+ txSize sampleIndex = profiler->sampleIndex;
2470
+ txSize sampleSize = profiler->sampleSize;
2471
+ txID* samples = profiler->samples + (sampleIndex * sampleSize);
2472
+ txU4 interval = profiler->interval;
2473
+ profiler->deltas[sampleIndex] = (txU4)(time - profiler->former);
2474
+ profiler->former = time;
2475
+ profiler->when = time + interval - (time % interval);
2476
+ if (!frame) {
2477
+ frame = the->frame;
2478
+ if (frame)
2479
+ *samples++ = 1;
2480
+ }
2481
+ while (frame) {
2482
+ txID id = fxFrameToProfilerID(the, frame);
2483
+ if (id)
2484
+ *samples++ = id;
2485
+ frame = frame->next;
2486
+ }
2487
+ *samples++ = 0;
2488
+ sampleIndex++;
2489
+ if (sampleIndex == mxProfilerSampleCount) {
2490
+ fxSendProfilerSamples(the, profiler);
2491
+ sampleIndex = 0;
2492
+ }
2493
+ profiler->sampleIndex = sampleIndex;
2494
+ }
2495
+ }
2496
+
2497
+ void fxCreateProfiler(txMachine* the)
2498
+ {
2499
+ txProfiler* profiler = the->profiler = c_malloc(sizeof(txProfiler));
2500
+ if (profiler == C_NULL)
2501
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
2502
+ profiler->interval = 1250;
2503
+ profiler->former = fxGetMicroSeconds();
2504
+ profiler->when = profiler->former + profiler->interval;
2505
+
2506
+ profiler->recordCount = 128;
2507
+ profiler->records = c_calloc(1, profiler->recordCount);
2508
+ if (profiler->records == C_NULL)
2509
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
2510
+
2511
+ profiler->sampleIndex = 0;
2512
+ profiler->sampleSize = (the->stackTop - the->stackBottom) >> 3;
2513
+ profiler->samples = (txID*)c_malloc((size_t)(mxProfilerSampleCount * profiler->sampleSize * sizeof(txID)));
2514
+ if (profiler->samples == C_NULL)
2515
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
2516
+
2517
+ fxSendProfilerTime(the, "start", profiler->former);
2518
+ fxSendProfilerRecord(the, C_NULL, 0, C_NULL);
2519
+ fxSendProfilerRecord(the, C_NULL, 1, C_NULL);
2520
+ profiler->records[0] = 0x03;
2521
+ }
2522
+
2523
+ void fxDeleteProfiler(txMachine* the, void* stream)
2524
+ {
2525
+ txProfiler* profiler = the->profiler;
2526
+ fxSendProfilerTime(the, "stop", fxGetMicroSeconds());
2527
+ c_free(profiler->samples);
2528
+ c_free(profiler->records);
2529
+ c_free(profiler);
2530
+ the->profiler = C_NULL;
2531
+ }
2532
+
2533
+ #ifdef mxDebug
2534
+ void fxEchoUnsigned(txMachine* the, txUnsigned value, txInteger radix)
2535
+ {
2536
+ char buffer[256];
2537
+ char *p = &buffer[sizeof(buffer) - 1];
2538
+ *p-- = 0;
2539
+ do {
2540
+ *p-- = c_read8(gxHexaDigits + (value % radix));
2541
+ value /= radix;
2542
+ } while (value);
2543
+ fxEcho(the, p + 1);
2544
+ }
2545
+ #endif
2546
+
2547
+ txID fxFrameToProfilerID(txMachine* the, txSlot* frame)
2548
+ {
2549
+ txProfiler* profiler = the->profiler;
2550
+ txSlot* function = frame + 3;
2551
+ txSlot* code = C_NULL;
2552
+ txID id = XS_NO_ID;
2553
+ if (function->kind == XS_REFERENCE_KIND) {
2554
+ function = function->value.reference;
2555
+ if (mxIsFunction(function)) {
2556
+ code = mxFunctionInstanceCode(function);
2557
+ id = mxFunctionInstanceHome(function)->ID;
2558
+ }
2559
+ }
2560
+ #ifdef mxHostFunctionPrimitive
2561
+ else if (function->kind == XS_HOST_FUNCTION_KIND)
2562
+ id = function->value.hostFunction.profileID;
2563
+ #endif
2564
+ if (id != XS_NO_ID) {
2565
+ txInteger recordIndex = id >> 3;
2566
+ txInteger recordMask = 1 << (id & 0x07);
2567
+ txInteger recordCount = profiler->recordCount;
2568
+ if (recordIndex >= recordCount) {
2569
+ while (recordIndex >= recordCount)
2570
+ recordCount += 128;
2571
+ profiler->records = c_realloc(profiler->records, recordCount);
2572
+ if (profiler->records == C_NULL)
2573
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
2574
+ c_memset(profiler->records + profiler->recordCount, 0, (recordCount - profiler->recordCount));
2575
+ profiler->recordCount = recordCount;
2576
+ }
2577
+ else if (profiler->records[recordIndex] & recordMask)
2578
+ return id;
2579
+ profiler->records[recordIndex] |= recordMask;
2580
+ fxSendProfilerRecord(the, frame, id, code);
2581
+ return id;
2582
+ }
2583
+ return 0;
2584
+ }
2585
+
2586
+ txMicroseconds fxGetMicroSeconds()
2587
+ {
2588
+ #if defined(modMicrosecondsInstrumentation)
2589
+ return modMicrosecondsInstrumentation();
2590
+ #elif defined(modMicroseconds)
2591
+ return modMicroseconds();
2592
+ #else
2593
+ c_timeval tv;
2594
+ c_gettimeofday(&tv, NULL);
2595
+ return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
2596
+ #endif
2597
+ }
2598
+
2599
+ void fxResumeProfiler(txMachine* the)
2600
+ {
2601
+ txProfiler* profiler = the->profiler;
2602
+ if (!profiler)
2603
+ return;
2604
+ txMicroseconds delta = fxGetMicroSeconds();
2605
+ fxSendProfilerTime(the, "resume", delta);
2606
+ delta -= profiler->stop;
2607
+ profiler->when += delta;
2608
+ profiler->former += delta;
2609
+ }
2610
+
2611
+ void fxSendProfilerRecord(txMachine* the, txSlot* frame, txID id, txSlot* code)
2612
+ {
2613
+ #ifdef mxDebug
2614
+ if (fxIsConnected(the)) {
2615
+ fxEchoStart(the);
2616
+ if (id == 0) {
2617
+ fxEcho(the, "<pr name=\"(host)\" value=\"0\"");
2618
+ }
2619
+ else if (id == 1) {
2620
+ fxEcho(the, "<pr name=\"(gc)\" value=\"1\"");
2621
+ }
2622
+ else {
2623
+ fxEcho(the, "<pr name=\"");
2624
+ fxEchoFrameName(the, frame);
2625
+ fxEcho(the, "\" value=\"");
2626
+ fxEchoInteger(the, id);
2627
+ fxEcho(the, "\"");
2628
+ }
2629
+ if (code) {
2630
+ if ((code->kind == XS_CODE_KIND) || (code->kind == XS_CODE_X_KIND)) {
2631
+ txByte* p = code->value.code.address + 2;
2632
+ if (*p == XS_CODE_FILE) {
2633
+ txID file;
2634
+ txS2 line;
2635
+ p++;
2636
+ mxDecodeID(p, file);
2637
+ p++;
2638
+ mxDecode2(p, line);
2639
+ fxEchoPathLine(the, fxGetKeyName(the, file), line);
2640
+ }
2641
+ }
2642
+ }
2643
+ fxEcho(the, "/>");
2644
+ fxEchoStop(the);
2645
+ }
2646
+ #endif
2647
+ }
2648
+
2649
+ void fxSendProfilerSamples(txMachine* the, txProfiler* profiler)
2650
+ {
2651
+ #ifdef mxDebug
2652
+ if (fxIsConnected(the)) {
2653
+ txID* samples = profiler->samples;
2654
+ txSize sampleSize = profiler->sampleSize;
2655
+ txSize sampleIndex = 0;
2656
+ txID* ids;
2657
+ txID id;
2658
+ fxEchoStart(the);
2659
+ fxEcho(the, "<ps>");
2660
+ for (;;) {
2661
+ fxEchoUnsigned(the, profiler->deltas[sampleIndex], 36);
2662
+ ids = samples;
2663
+ while ((id = *ids++)) {
2664
+ fxEcho(the, ",");
2665
+ fxEchoUnsigned(the, id, 36);
2666
+ }
2667
+ sampleIndex++;
2668
+ if (sampleIndex < mxProfilerSampleCount)
2669
+ fxEcho(the, ",0.");
2670
+ else {
2671
+ fxEcho(the, ",0</ps>");
2672
+ break;
2673
+ }
2674
+ samples += sampleSize;
2675
+ }
2676
+ fxEchoStop(the);
2677
+ }
2678
+ #endif
2679
+ }
2680
+
2681
+ void fxSendProfilerTime(txMachine* the, txString name, txMicroseconds when)
2682
+ {
2683
+ #ifdef mxDebug
2684
+ if (fxIsConnected(the)) {
2685
+ int shift;
2686
+ fxEchoStart(the);
2687
+ fxEcho(the, "<pt name=\"");
2688
+ fxEchoString(the, name);
2689
+ fxEcho(the, "\" value=\"@");
2690
+ shift = (8 * sizeof(when)) - 4;
2691
+ while (shift >= 0) {
2692
+ fxEchoCharacter(the, c_read8(gxHexaDigits + ((when >> shift) & 0x0F)));
2693
+ shift -= 4;
2694
+ }
2695
+ fxEcho(the, "\"/>");
2696
+ fxEchoStop(the);
2697
+ }
2698
+ #endif
2699
+ }
2700
+
2701
+ void fxSuspendProfiler(txMachine* the)
2702
+ {
2703
+ txProfiler* profiler = the->profiler;
2704
+ if (!profiler)
2705
+ return;
2706
+ profiler->stop = fxGetMicroSeconds();
2707
+ fxSendProfilerTime(the, "suspend", profiler->stop);
2708
+ }
2709
+
2710
+ #endif /* mxInstrument */