@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.
- package/README.md +3 -3
- package/api.js +4 -2
- package/build.env +1 -1
- package/moddable/modules/data/base64/base64.js +28 -0
- package/moddable/modules/data/base64/manifest.json +11 -0
- package/moddable/modules/data/base64/modBase64.c +188 -0
- package/moddable/modules/data/binaryMessage/BinaryMessage.js +106 -0
- package/moddable/modules/data/crc/crc.c +205 -0
- package/moddable/modules/data/crc/crc.js +36 -0
- package/moddable/modules/data/crc/manifest.json +8 -0
- package/moddable/modules/data/hex/hex.js +28 -0
- package/moddable/modules/data/hex/manifest.json +11 -0
- package/moddable/modules/data/hex/modHex.c +139 -0
- package/moddable/modules/data/logical/logical.js +32 -0
- package/moddable/modules/data/logical/modLogical.c +98 -0
- package/moddable/modules/data/qrcode/manifest.json +9 -0
- package/moddable/modules/data/qrcode/qrcode.c +93 -0
- package/moddable/modules/data/qrcode/qrcode.js +23 -0
- package/moddable/modules/data/qrcode/qrcodegen.c +1025 -0
- package/moddable/modules/data/qrcode/qrcodegen.h +267 -0
- package/moddable/modules/data/text/decoder/manifest.json +8 -0
- package/moddable/modules/data/text/decoder/textdecoder.c +480 -0
- package/moddable/modules/data/text/decoder/textdecoder.js +27 -0
- package/moddable/modules/data/text/encoder/manifest.json +8 -0
- package/moddable/modules/data/text/encoder/textencoder.c +232 -0
- package/moddable/modules/data/text/encoder/textencoder.js +24 -0
- package/moddable/modules/data/tinyint/tinyint.c +150 -0
- package/moddable/modules/data/tinyint/tinyint.js +53 -0
- package/moddable/modules/data/url/manifest.json +17 -0
- package/moddable/modules/data/url/url.c +1959 -0
- package/moddable/modules/data/url/url.js +210 -0
- package/moddable/modules/data/wavreader/manifest.json +8 -0
- package/moddable/modules/data/wavreader/wavreader.js +128 -0
- package/moddable/modules/data/zlib/deflate.c +161 -0
- package/moddable/modules/data/zlib/deflate.js +63 -0
- package/moddable/modules/data/zlib/inflate.c +145 -0
- package/moddable/modules/data/zlib/inflate.js +66 -0
- package/moddable/modules/data/zlib/manifest_deflate.json +9 -0
- package/moddable/modules/data/zlib/manifest_inflate.json +9 -0
- package/moddable/modules/data/zlib/miniz.c +4924 -0
- package/moddable/xs/includes/xs.d.ts +73 -0
- package/moddable/xs/includes/xs.h +1533 -0
- package/moddable/xs/includes/xsmc.h +206 -0
- package/moddable/xs/makefiles/lin/makefile +33 -0
- package/moddable/xs/makefiles/lin/xsc.mk +118 -0
- package/moddable/xs/makefiles/lin/xsid.mk +90 -0
- package/moddable/xs/makefiles/lin/xsl.mk +168 -0
- package/moddable/xs/makefiles/lin/xst.mk +201 -0
- package/moddable/xs/makefiles/mac/makefile +33 -0
- package/moddable/xs/makefiles/mac/xsc.mk +130 -0
- package/moddable/xs/makefiles/mac/xsid.mk +102 -0
- package/moddable/xs/makefiles/mac/xsl.mk +177 -0
- package/moddable/xs/makefiles/mac/xst.mk +203 -0
- package/moddable/xs/makefiles/mac/xst_no_asan.txt +52 -0
- package/moddable/xs/makefiles/win/build.bat +26 -0
- package/moddable/xs/makefiles/win/xsc.mak +142 -0
- package/moddable/xs/makefiles/win/xsid.mak +113 -0
- package/moddable/xs/makefiles/win/xsl.mak +186 -0
- package/moddable/xs/makefiles/win/xst.mak +195 -0
- package/moddable/xs/platforms/lin_xs.h +99 -0
- package/moddable/xs/platforms/mac_xs.h +97 -0
- package/moddable/xs/platforms/wasm_xs.h +79 -0
- package/moddable/xs/platforms/win_xs.h +104 -0
- package/moddable/xs/platforms/xsHost.h +63 -0
- package/moddable/xs/platforms/xsPlatform.h +618 -0
- package/moddable/xs/sources/xsAPI.c +2555 -0
- package/moddable/xs/sources/xsAll.c +294 -0
- package/moddable/xs/sources/xsAll.h +2741 -0
- package/moddable/xs/sources/xsArguments.c +222 -0
- package/moddable/xs/sources/xsArray.c +2657 -0
- package/moddable/xs/sources/xsAtomics.c +844 -0
- package/moddable/xs/sources/xsBigInt.c +1859 -0
- package/moddable/xs/sources/xsBoolean.c +109 -0
- package/moddable/xs/sources/xsCode.c +4493 -0
- package/moddable/xs/sources/xsCommon.c +1710 -0
- package/moddable/xs/sources/xsCommon.h +1142 -0
- package/moddable/xs/sources/xsDataView.c +2890 -0
- package/moddable/xs/sources/xsDate.c +1541 -0
- package/moddable/xs/sources/xsDebug.c +2710 -0
- package/moddable/xs/sources/xsDefaults.c +134 -0
- package/moddable/xs/sources/xsError.c +353 -0
- package/moddable/xs/sources/xsFunction.c +776 -0
- package/moddable/xs/sources/xsGenerator.c +865 -0
- package/moddable/xs/sources/xsGlobal.c +839 -0
- package/moddable/xs/sources/xsJSON.c +1091 -0
- package/moddable/xs/sources/xsLexical.c +1969 -0
- package/moddable/xs/sources/xsLockdown.c +933 -0
- package/moddable/xs/sources/xsMapSet.c +1649 -0
- package/moddable/xs/sources/xsMarshall.c +1020 -0
- package/moddable/xs/sources/xsMath.c +624 -0
- package/moddable/xs/sources/xsMemory.c +1941 -0
- package/moddable/xs/sources/xsModule.c +3101 -0
- package/moddable/xs/sources/xsNumber.c +560 -0
- package/moddable/xs/sources/xsObject.c +1102 -0
- package/moddable/xs/sources/xsPlatforms.c +480 -0
- package/moddable/xs/sources/xsProfile.c +577 -0
- package/moddable/xs/sources/xsPromise.c +1199 -0
- package/moddable/xs/sources/xsProperty.c +636 -0
- package/moddable/xs/sources/xsProxy.c +1014 -0
- package/moddable/xs/sources/xsRegExp.c +1168 -0
- package/moddable/xs/sources/xsRun.c +4889 -0
- package/moddable/xs/sources/xsScope.c +1293 -0
- package/moddable/xs/sources/xsScript.c +288 -0
- package/moddable/xs/sources/xsScript.h +1186 -0
- package/moddable/xs/sources/xsSnapshot.c +2161 -0
- package/moddable/xs/sources/xsSnapshot.h +51 -0
- package/moddable/xs/sources/xsSourceMap.c +218 -0
- package/moddable/xs/sources/xsString.c +3332 -0
- package/moddable/xs/sources/xsSymbol.c +503 -0
- package/moddable/xs/sources/xsSyntaxical.c +4193 -0
- package/moddable/xs/sources/xsTree.c +1893 -0
- package/moddable/xs/sources/xsType.c +1488 -0
- package/moddable/xs/sources/xsdtoa.c +6672 -0
- package/moddable/xs/sources/xsmc.c +340 -0
- package/moddable/xs/sources/xsre.c +7578 -0
- package/package.json +37 -20
- package/scripts/get_xsnap_version.sh +14 -0
- package/scripts/test-package.sh +21 -0
- package/src/avaAssertXS.js +6 -2
- package/src/avaHandler.cjs +2 -5
- package/src/avaXS.js +7 -8
- package/src/build.js +161 -28
- package/src/replay.js +0 -3
- package/src/xsnap.js +105 -91
- package/src/xsrepl.js +2 -3
- package/xsnap-native/xsnap/makefiles/lin/makefile +10 -0
- package/xsnap-native/xsnap/makefiles/lin/xsnap-worker.mk +156 -0
- package/xsnap-native/xsnap/makefiles/lin/xsnap.mk +144 -0
- package/xsnap-native/xsnap/makefiles/mac/makefile +10 -0
- package/xsnap-native/xsnap/makefiles/mac/xsnap-worker.mk +165 -0
- package/xsnap-native/xsnap/makefiles/mac/xsnap.mk +153 -0
- package/xsnap-native/xsnap/sources/xsnap-worker.c +1008 -0
- package/xsnap-native/xsnap/sources/xsnap.c +717 -0
- package/xsnap-native/xsnap/sources/xsnap.h +142 -0
- package/xsnap-native/xsnap/sources/xsnapPlatform.c +1501 -0
- package/xsnap-native/xsnap/sources/xsnapPlatform.h +105 -0
- 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 */
|