0
|
1
|
|
2 /* Digital Mars DMDScript source code.
|
|
3 * Copyright (c) 2000-2002 by Chromium Communications
|
|
4 * D version Copyright (c) 2004-2006 by Digital Mars
|
|
5 * All Rights Reserved
|
|
6 * written by Walter Bright
|
|
7 * www.digitalmars.com
|
|
8 * Use at your own risk. There is no warranty, express or implied.
|
|
9 * License for redistribution is by the GNU General Public License in gpl.txt.
|
|
10 *
|
|
11 * A binary, non-exclusive license for commercial use can be
|
|
12 * purchased from www.digitalmars.com/dscript/buy.html.
|
|
13 *
|
|
14 * DMDScript is implemented in the D Programming Language,
|
|
15 * www.digitalmars.com/d/
|
|
16 *
|
|
17 * For a C++ implementation of DMDScript, including COM support,
|
|
18 * see www.digitalmars.com/dscript/cppscript.html.
|
|
19 */
|
|
20
|
|
21
|
3
|
22 module dmdscript_tango.script;
|
0
|
23
|
|
24 import std.ctype;
|
|
25 import std.string;
|
|
26 import std.c.stdlib;
|
|
27 import std.c.stdarg;
|
|
28
|
|
29 /* =================== Configuration ======================= */
|
|
30
|
|
31 const uint MAJOR_VERSION = 5; // ScriptEngineMajorVersion
|
|
32 const uint MINOR_VERSION = 5; // ScriptEngineMinorVersion
|
|
33
|
|
34 const uint BUILD_VERSION = 1; // ScriptEngineBuildVersion
|
|
35
|
|
36 const uint JSCRIPT_CATCH_BUG = 1; // emulate Jscript's bug in scoping of
|
|
37 // catch objects in violation of ECMA
|
|
38 const uint JSCRIPT_ESCAPEV_BUG = 0; // emulate Jscript's bug where \v is
|
|
39 // not recognized as vertical tab
|
|
40
|
|
41 //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
42
|
|
43 alias char tchar;
|
|
44
|
|
45 alias ulong number_t;
|
|
46 alias double real_t;
|
|
47
|
|
48 alias uint Loc; // file location (line number)
|
|
49
|
|
50 struct ErrInfo
|
|
51 {
|
|
52 tchar[] message; // error message (null if no error)
|
|
53 tchar[] srcline; // string of source line (null if not known)
|
|
54 uint linnum; // source line number (1 based, 0 if not available)
|
|
55 int charpos; // character position (1 based, 0 if not available)
|
|
56 int code; // error code (0 if not known)
|
|
57 }
|
|
58
|
|
59 class ScriptException : Exception
|
|
60 {
|
|
61 ErrInfo ei;
|
|
62
|
|
63 this(tchar[] msg)
|
|
64 { ei.message = msg;
|
|
65 super(msg);
|
|
66 }
|
|
67
|
|
68 this(ErrInfo* pei)
|
|
69 {
|
|
70 ei = *pei;
|
|
71 super(ei.message);
|
|
72 }
|
|
73 }
|
|
74
|
|
75 int logflag; // used for debugging
|
|
76
|
|
77
|
|
78 // Aliases for script primitive types
|
|
79 alias uint d_boolean;
|
|
80 alias double d_number;
|
|
81 alias int d_int32;
|
|
82 alias uint d_uint32;
|
|
83 alias ushort d_uint16;
|
|
84 alias tchar[] d_string;
|
|
85
|
4
|
86 import dmdscript_tango.value;
|
|
87 import dmdscript_tango.dobject;
|
|
88 import dmdscript_tango.program;
|
|
89 import dmdscript_tango.text;
|
|
90 import dmdscript_tango.functiondefinition;
|
0
|
91
|
|
92 struct CallContext
|
|
93 {
|
|
94 Dobject[] scopex; // current scope chain
|
|
95 Dobject variable; // object for variable instantiation
|
|
96 Dobject global; // global object
|
|
97 uint scoperoot; // number of entries in scope[] starting from 0
|
|
98 // to copy onto new scopes
|
|
99 uint globalroot; // number of entries in scope[] starting from 0
|
|
100 // that are in the "global" context. Always <= scoperoot
|
|
101 void* lastnamedfunc; // points to the last named function added as an event
|
|
102 Program prog;
|
|
103 Dobject callerothis; // caller's othis
|
|
104 Dobject caller; // caller function object
|
|
105 FunctionDefinition callerf;
|
|
106
|
|
107 char[16] value; // place to store exception; must be same size as Value
|
|
108 uint linnum; // source line number of exception (1 based, 0 if not available)
|
|
109
|
|
110 int finallyret; // !=0 if IRfinallyret was executed
|
|
111 int Interrupt; // !=0 if cancelled due to interrupt
|
|
112 }
|
|
113
|
|
114 struct Global
|
|
115 {
|
|
116 tchar[] copyright = "Copyright (c) 1999-2009 by Digital Mars";
|
|
117 tchar[] written = "written by Walter Bright";
|
|
118 }
|
|
119
|
|
120 Global global;
|
|
121
|
|
122 tchar[] banner()
|
|
123 {
|
|
124 return std.string.format(
|
|
125 "Digital Mars DMDScript 1.15\n",
|
|
126 "http://www.digitalmars.com\n",
|
|
127 "Compiled by Digital Mars DMD D compiler\n",
|
|
128 global.copyright, "\n",
|
|
129 global.written);
|
|
130 }
|
|
131
|
|
132 int isStrWhiteSpaceChar(dchar c)
|
|
133 {
|
|
134 switch (c)
|
|
135 {
|
|
136 case ' ':
|
|
137 case '\t':
|
|
138 case 0xA0: // <NBSP>
|
|
139 case '\f':
|
|
140 case '\v':
|
|
141 case '\r':
|
|
142 case '\n':
|
|
143 case 0x2028: // <LS>
|
|
144 case 0x2029: // <PS>
|
|
145 case 0x2001: // <USP>
|
|
146 case 0x2000: // should we do this one?
|
|
147 return 1;
|
|
148
|
|
149 default:
|
|
150 break;
|
|
151 }
|
|
152 return 0;
|
|
153 }
|
|
154
|
|
155
|
|
156 /************************
|
|
157 * Convert d_string to an index, if it is one.
|
|
158 * Returns:
|
|
159 * true it's an index, and *index is set
|
|
160 * false it's not an index
|
|
161 */
|
|
162
|
|
163 int StringToIndex(d_string name, out d_uint32 index)
|
|
164 {
|
|
165 if (name.length)
|
|
166 {
|
|
167 d_uint32 i = 0;
|
|
168
|
|
169 for (uint j = 0; j < name.length; j++)
|
|
170 { tchar c = name[j];
|
|
171
|
|
172 switch (c)
|
|
173 {
|
|
174 case '0':
|
|
175 case '1':
|
|
176 case '2':
|
|
177 case '3':
|
|
178 case '4':
|
|
179 case '5':
|
|
180 case '6':
|
|
181 case '7':
|
|
182 case '8':
|
|
183 case '9':
|
|
184 if ((i == 0 && j) || // if leading zeros
|
|
185 i >= 0xFFFFFFFF / 10) // or overflow
|
|
186 goto Lnotindex;
|
|
187 i = i * 10 + c - '0';
|
|
188 break;
|
|
189
|
|
190 default:
|
|
191 goto Lnotindex;
|
|
192 }
|
|
193 }
|
|
194 index = i;
|
|
195 return true;
|
|
196 }
|
|
197
|
|
198 Lnotindex:
|
|
199 return false;
|
|
200 }
|
|
201
|
|
202
|
|
203 /********************************
|
|
204 * Parse string numeric literal into a number.
|
|
205 * Input:
|
|
206 * parsefloat 0: convert per ECMA 9.3.1
|
|
207 * 1: convert per ECMA 15.1.2.3 (global.parseFloat())
|
|
208 */
|
|
209
|
|
210 d_number StringNumericLiteral(d_string string, out size_t endidx, int parsefloat)
|
|
211 {
|
|
212 // Convert StringNumericLiteral using ECMA 9.3.1
|
|
213 d_number number;
|
|
214 int sign = 0;
|
|
215 size_t i;
|
|
216 size_t len;
|
|
217 size_t eoff;
|
|
218
|
|
219 // Skip leading whitespace
|
|
220 eoff = string.length;
|
|
221 foreach (size_t j, dchar c; string)
|
|
222 {
|
|
223 if (!isStrWhiteSpaceChar(c))
|
|
224 {
|
|
225 eoff = j;
|
|
226 break;
|
|
227 }
|
|
228 }
|
|
229 string = string[eoff .. length];
|
|
230 len = string.length;
|
|
231
|
|
232 // Check for [+|-]
|
|
233 i = 0;
|
|
234 if (len)
|
|
235 {
|
|
236 switch (string[0])
|
|
237 { case '+':
|
|
238 sign = 0;
|
|
239 i++;
|
|
240 break;
|
|
241
|
|
242 case '-':
|
|
243 sign = 1;
|
|
244 i++;
|
|
245 break;
|
|
246
|
|
247 default:
|
|
248 sign = 0;
|
|
249 break;
|
|
250 }
|
|
251 }
|
|
252
|
|
253 size_t inflen = TEXT_Infinity.length;
|
|
254 if (len - i >= inflen &&
|
|
255 string[i .. i + inflen] == TEXT_Infinity)
|
|
256 {
|
|
257 number = sign ? -d_number.infinity : d_number.infinity;
|
|
258 endidx = eoff + i + inflen;
|
|
259 }
|
|
260 else if (len - i >= 2 &&
|
|
261 string[i] == '0' && (string[i + 1] == 'x' || string[i + 1] == 'X'))
|
|
262 {
|
|
263 // Check for 0[x|X]HexDigit...
|
|
264 number = 0;
|
|
265 if (parsefloat)
|
|
266 { // Do not recognize the 0x, treat it as if it's just a '0'
|
|
267 i += 1;
|
|
268 }
|
|
269 else
|
|
270 {
|
|
271 i += 2;
|
|
272 for (; i < len; i++)
|
|
273 { tchar c;
|
|
274
|
|
275 c = string[i]; // don't need to decode UTF here
|
|
276 if ('0' <= c && c <= '9')
|
|
277 number = number * 16 + (c - '0');
|
|
278 else if ('a' <= c && c <= 'f')
|
|
279 number = number * 16 + (c - 'a' + 10);
|
|
280 else if ('A' <= c && c <= 'F')
|
|
281 number = number * 16 + (c - 'A' + 10);
|
|
282 else
|
|
283 break;
|
|
284 }
|
|
285 }
|
|
286 if (sign)
|
|
287 number = -number;
|
|
288 endidx = eoff + i;
|
|
289 }
|
|
290 else
|
|
291 { char* endptr;
|
|
292 char* s = std.string.toStringz(string[i .. len]);
|
|
293
|
|
294 endptr = s;
|
|
295 number = std.c.stdlib.strtod(s, &endptr);
|
|
296 endidx = (endptr - s) + i;
|
|
297
|
|
298 //printf("s = '%s', endidx = %d, eoff = %d, number = %g\n", s, endidx, eoff, number);
|
|
299
|
|
300 // Correctly produce a -0 for the
|
|
301 // string "-1e-2000"
|
|
302 if (sign)
|
|
303 number = -number;
|
|
304 if (endidx == i && (parsefloat || i != 0))
|
|
305 number = d_number.nan;
|
|
306 endidx += eoff;
|
|
307 }
|
|
308
|
|
309 return number;
|
|
310 }
|
|
311
|
|
312
|
|
313
|
|
314
|
|
315 int localeCompare(CallContext *cc, d_string s1, d_string s2)
|
|
316 { // no locale support here
|
|
317 return std.string.cmp(s1, s2);
|
|
318 }
|
|
319
|