1 /* data.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2009 */
2 
3 /*
4 
5 Copyright (c) 2005-2009 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 #define	NEED_FP_NAN
35 #define	NEED_ISINF
36 #include	"parser.h"
37 
38 
39 namespace sswf
40 {
41 namespace as
42 {
43 
44 
45 struct type_name_t {
46 	node_t		f_type;
47 	const char *	f_name;
48 };
49 
50 #define	NODE_TYPE_NAME(node)	{ NODE_##node, TO_STR_sub(node) }
51 
52 static const type_name_t node_type_name[] =
53 {
54 	NODE_TYPE_NAME(EOF),
55 	NODE_TYPE_NAME(UNKNOWN),
56 	NODE_TYPE_NAME(ADD),
57 	NODE_TYPE_NAME(BITWISE_AND),
58 	NODE_TYPE_NAME(BITWISE_NOT),
59 	NODE_TYPE_NAME(ASSIGNMENT),
60 	NODE_TYPE_NAME(BITWISE_OR),
61 	NODE_TYPE_NAME(BITWISE_XOR),
62 	NODE_TYPE_NAME(CLOSE_CURVLY_BRACKET),
63 	NODE_TYPE_NAME(CLOSE_PARENTHESIS),
64 	NODE_TYPE_NAME(CLOSE_SQUARE_BRACKET),
65 	NODE_TYPE_NAME(COLON),
66 	NODE_TYPE_NAME(COMMA),
67 	NODE_TYPE_NAME(CONDITIONAL),
68 	NODE_TYPE_NAME(DIVIDE),
69 	NODE_TYPE_NAME(GREATER),
70 	NODE_TYPE_NAME(LESS),
71 	NODE_TYPE_NAME(LOGICAL_NOT),
72 	NODE_TYPE_NAME(MODULO),
73 	NODE_TYPE_NAME(MULTIPLY),
74 	NODE_TYPE_NAME(OPEN_CURVLY_BRACKET),
75 	NODE_TYPE_NAME(OPEN_PARENTHESIS),
76 	NODE_TYPE_NAME(OPEN_SQUARE_BRACKET),
77 	NODE_TYPE_NAME(MEMBER),
78 	NODE_TYPE_NAME(SEMICOLON),
79 	NODE_TYPE_NAME(SUBTRACT),
80 	NODE_TYPE_NAME(ARRAY),
81 	NODE_TYPE_NAME(ARRAY_LITERAL),
82 	NODE_TYPE_NAME(AS),
83 	NODE_TYPE_NAME(ASSIGNMENT_ADD),
84 	NODE_TYPE_NAME(ASSIGNMENT_BITWISE_AND),
85 	NODE_TYPE_NAME(ASSIGNMENT_BITWISE_OR),
86 	NODE_TYPE_NAME(ASSIGNMENT_BITWISE_XOR),
87 	NODE_TYPE_NAME(ASSIGNMENT_DIVIDE),
88 	NODE_TYPE_NAME(ASSIGNMENT_LOGICAL_AND),
89 	NODE_TYPE_NAME(ASSIGNMENT_LOGICAL_OR),
90 	NODE_TYPE_NAME(ASSIGNMENT_LOGICAL_XOR),
91 	NODE_TYPE_NAME(ASSIGNMENT_MAXIMUM),
92 	NODE_TYPE_NAME(ASSIGNMENT_MINIMUM),
93 	NODE_TYPE_NAME(ASSIGNMENT_MODULO),
94 	NODE_TYPE_NAME(ASSIGNMENT_MULTIPLY),
95 	NODE_TYPE_NAME(ASSIGNMENT_POWER),
96 	NODE_TYPE_NAME(ASSIGNMENT_ROTATE_LEFT),
97 	NODE_TYPE_NAME(ASSIGNMENT_ROTATE_RIGHT),
98 	NODE_TYPE_NAME(ASSIGNMENT_SHIFT_LEFT),
99 	NODE_TYPE_NAME(ASSIGNMENT_SHIFT_RIGHT),
100 	NODE_TYPE_NAME(ASSIGNMENT_SHIFT_RIGHT_UNSIGNED),
101 	NODE_TYPE_NAME(ASSIGNMENT_SUBTRACT),
102 	NODE_TYPE_NAME(ATTRIBUTES),
103 	NODE_TYPE_NAME(AUTO),
104 	NODE_TYPE_NAME(BREAK),
105 	NODE_TYPE_NAME(CALL),
106 	NODE_TYPE_NAME(CASE),
107 	NODE_TYPE_NAME(CATCH),
108 	NODE_TYPE_NAME(CLASS),
109 	NODE_TYPE_NAME(CONST),
110 	NODE_TYPE_NAME(CONTINUE),
111 	NODE_TYPE_NAME(DECREMENT),
112 	NODE_TYPE_NAME(DEFAULT),
113 	NODE_TYPE_NAME(DELETE),
114 	NODE_TYPE_NAME(DIRECTIVE_LIST),
115 	NODE_TYPE_NAME(DO),
116 	NODE_TYPE_NAME(ELSE),
117 	NODE_TYPE_NAME(EMPTY),
118 	NODE_TYPE_NAME(ENTRY),
119 	NODE_TYPE_NAME(ENUM),
120 	NODE_TYPE_NAME(EQUAL),
121 	NODE_TYPE_NAME(EXCLUDE),
122 	NODE_TYPE_NAME(EXTENDS),
123 	NODE_TYPE_NAME(FALSE),
124 	NODE_TYPE_NAME(FINALLY),
125 	NODE_TYPE_NAME(FLOAT64),
126 	NODE_TYPE_NAME(FOR),
127 	NODE_TYPE_NAME(FOR_IN),
128 	NODE_TYPE_NAME(FUNCTION),
129 	NODE_TYPE_NAME(GOTO),
130 	NODE_TYPE_NAME(GREATER_EQUAL),
131 	NODE_TYPE_NAME(IDENTIFIER),
132 	NODE_TYPE_NAME(IF),
133 	NODE_TYPE_NAME(IMPLEMENTS),
134 	NODE_TYPE_NAME(IMPORT),
135 	NODE_TYPE_NAME(IN),
136 	NODE_TYPE_NAME(INCLUDE),
137 	NODE_TYPE_NAME(INCREMENT),
138 	NODE_TYPE_NAME(INSTANCEOF),
139 	NODE_TYPE_NAME(INT64),
140 	NODE_TYPE_NAME(INTERFACE),
141 	NODE_TYPE_NAME(IS),
142 	NODE_TYPE_NAME(LABEL),
143 	NODE_TYPE_NAME(LESS_EQUAL),
144 	NODE_TYPE_NAME(LIST),
145 	NODE_TYPE_NAME(LOGICAL_AND),
146 	NODE_TYPE_NAME(LOGICAL_OR),
147 	NODE_TYPE_NAME(LOGICAL_XOR),
148 	NODE_TYPE_NAME(MATCH),
149 	NODE_TYPE_NAME(MAXIMUM),
150 	NODE_TYPE_NAME(MINIMUM),
151 	NODE_TYPE_NAME(NAME),
152 	NODE_TYPE_NAME(NAMESPACE),
153 	NODE_TYPE_NAME(NEW),
154 	NODE_TYPE_NAME(NOT_EQUAL),
155 	/*NODE_TYPE_NAME(NULL),*/
156 	{ NODE_NULL, "NULL" },
157 	NODE_TYPE_NAME(OBJECT_LITERAL),
158 	NODE_TYPE_NAME(PACKAGE),
159 	NODE_TYPE_NAME(PARAM),
160 	NODE_TYPE_NAME(PARAMETERS),
161 	NODE_TYPE_NAME(PARAM_MATCH),
162 	NODE_TYPE_NAME(POST_DECREMENT),
163 	NODE_TYPE_NAME(POST_INCREMENT),
164 	NODE_TYPE_NAME(POWER),
165 	NODE_TYPE_NAME(PRIVATE),
166 	NODE_TYPE_NAME(PROGRAM),
167 	NODE_TYPE_NAME(PUBLIC),
168 	NODE_TYPE_NAME(RANGE),
169 	NODE_TYPE_NAME(REGULAR_EXPRESSION),
170 	NODE_TYPE_NAME(REST),
171 	NODE_TYPE_NAME(RETURN),
172 	NODE_TYPE_NAME(ROOT),
173 	NODE_TYPE_NAME(ROTATE_LEFT),
174 	NODE_TYPE_NAME(ROTATE_RIGHT),
175 	NODE_TYPE_NAME(SCOPE),
176 	NODE_TYPE_NAME(SET),
177 	NODE_TYPE_NAME(SHIFT_LEFT),
178 	NODE_TYPE_NAME(SHIFT_RIGHT),
179 	NODE_TYPE_NAME(SHIFT_RIGHT_UNSIGNED),
180 	NODE_TYPE_NAME(STRICTLY_EQUAL),
181 	NODE_TYPE_NAME(STRICTLY_NOT_EQUAL),
182 	NODE_TYPE_NAME(STRING),
183 	NODE_TYPE_NAME(SUPER),
184 	NODE_TYPE_NAME(SWITCH),
185 	NODE_TYPE_NAME(THIS),
186 	NODE_TYPE_NAME(THROW),
187 	NODE_TYPE_NAME(TRUE),
188 	NODE_TYPE_NAME(TRY),
189 	NODE_TYPE_NAME(TYPE),
190 	NODE_TYPE_NAME(TYPEOF),
191 	NODE_TYPE_NAME(UNDEFINED),
192 	NODE_TYPE_NAME(USE),
193 	NODE_TYPE_NAME(VAR),
194 	NODE_TYPE_NAME(VARIABLE),
195 	NODE_TYPE_NAME(VAR_ATTRIBUTES),
196 	NODE_TYPE_NAME(VIDENTIFIER),
197 	NODE_TYPE_NAME(VOID),
198 	NODE_TYPE_NAME(WHILE),
199 	NODE_TYPE_NAME(WITH),
200 
201 	// end list
202 	{ (node_t)0, 0 }
203 };
204 
205 
206 /**********************************************************************/
207 /**********************************************************************/
208 /***  DATA DISPLAY  ***************************************************/
209 /**********************************************************************/
210 /**********************************************************************/
211 
DisplayStr(FILE * out,String str)212 static void DisplayStr(FILE *out, String str)
213 {
214 	fprintf(out, ": '");
215 	long len = str.GetLength();
216 	const long *s = str.Get();
217 	while(len > 0) {
218 		len--;
219 		if((unsigned long) *s < 0x7f) {
220 			fprintf(out, "%c", (char) *s);
221 		}
222 		else {
223 			fprintf(out, "\\U%lX", *s);
224 		}
225 		s++;
226 	}
227 	fprintf(out, "'");
228 }
229 
230 
231 
GetTypeName(void) const232 const char *Data::GetTypeName(void) const
233 {
234 	const type_name_t *tn;
235 	tn = node_type_name;
236 	while(tn->f_name != 0) {
237 		if(tn->f_type == f_type) {
238 			return tn->f_name;
239 		}
240 		tn++;
241 	}
242 	return "<undefined type name>";
243 }
244 
245 
Display(FILE * out) const246 void Data::Display(FILE *out) const
247 {
248 	const char *name;
249 
250 	name = GetTypeName();
251 	fprintf(out, "%04d: %s", f_type, name);
252 	if(f_type > ' ' && f_type < 0x7F) {
253 		fprintf(out, " = '%c'", f_type);
254 	}
255 
256 	switch(f_type) {
257 	case NODE_IDENTIFIER:
258 	case NODE_VIDENTIFIER:
259 	case NODE_STRING:
260 	case NODE_GOTO:
261 	case NODE_LABEL:
262 	case NODE_IMPORT:
263 	case NODE_CLASS:
264 	case NODE_INTERFACE:
265 	case NODE_ENUM:
266 		DisplayStr(out, f_str);
267 		break;
268 
269 	case NODE_PACKAGE:
270 	{
271 		DisplayStr(out, f_str);
272 		int flags = f_int.Get();
273 		if((flags & NODE_PACKAGE_FLAG_FOUND_LABELS) != 0) {
274 			fprintf(out, " FOUND-LABELS");
275 		}
276 	}
277 		break;
278 
279 	case NODE_INT64:
280 		fprintf(out, ": %lld, 0x%016llX", f_int.Get(), f_int.Get());
281 		break;
282 
283 	case NODE_FLOAT64:
284 		fprintf(out, ": %f", f_float.Get());
285 		break;
286 
287 	case NODE_FUNCTION:
288 	{
289 		DisplayStr(out, f_str);
290 		int flags = f_int.Get();
291 		if((flags & NODE_FUNCTION_FLAG_GETTER) != 0) {
292 			fprintf(out, " GETTER");
293 		}
294 		if((flags & NODE_FUNCTION_FLAG_SETTER) != 0) {
295 			fprintf(out, " SETTER");
296 		}
297 	}
298 		break;
299 
300 	case NODE_PARAM:
301 	{
302 		DisplayStr(out, f_str);
303 		int flags = f_int.Get();
304 		if((flags & NODE_PARAMETERS_FLAG_CONST) != 0) {
305 			fprintf(out, " CONST");
306 		}
307 		if((flags & NODE_PARAMETERS_FLAG_IN) != 0) {
308 			fprintf(out, " IN");
309 		}
310 		if((flags & NODE_PARAMETERS_FLAG_OUT) != 0) {
311 			fprintf(out, " OUT");
312 		}
313 		if((flags & NODE_PARAMETERS_FLAG_NAMED) != 0) {
314 			fprintf(out, " NAMED");
315 		}
316 		if((flags & NODE_PARAMETERS_FLAG_REST) != 0) {
317 			fprintf(out, " REST");
318 		}
319 		if((flags & NODE_PARAMETERS_FLAG_UNCHECKED) != 0) {
320 			fprintf(out, " UNCHECKED");
321 		}
322 		if((flags & NODE_PARAMETERS_FLAG_UNPROTOTYPED) != 0) {
323 			fprintf(out, " UNPROTOTYPED");
324 		}
325 		if((flags & NODE_PARAMETERS_FLAG_REFERENCED) != 0) {
326 			fprintf(out, " REFERENCED");
327 		}
328 		if((flags & NODE_PARAMETERS_FLAG_PARAMREF) != 0) {
329 			fprintf(out, " PARAMREF");
330 		}
331 	}
332 		break;
333 
334 	case NODE_PARAM_MATCH:
335 	{
336 		fprintf(out, ":");
337 		int flags = f_int.Get();
338 		if((flags & NODE_PARAM_MATCH_FLAG_UNPROTOTYPED) != 0) {
339 			fprintf(out, " UNPROTOTYPED");
340 		}
341 	}
342 		break;
343 
344 	case NODE_VARIABLE:
345 	case NODE_VAR_ATTRIBUTES:
346 	{
347 		DisplayStr(out, f_str);
348 		int flags = f_int.Get();
349 		if((flags & NODE_VAR_FLAG_CONST) != 0) {
350 			fprintf(out, " CONST");
351 		}
352 		if((flags & NODE_VAR_FLAG_LOCAL) != 0) {
353 			fprintf(out, " LOCAL");
354 		}
355 		if((flags & NODE_VAR_FLAG_MEMBER) != 0) {
356 			fprintf(out, " MEMBER");
357 		}
358 		if((flags & NODE_VAR_FLAG_ATTRIBUTES) != 0) {
359 			fprintf(out, " ATTRIBUTES");
360 		}
361 		if((flags & NODE_VAR_FLAG_ENUM) != 0) {
362 			fprintf(out, " ENUM");
363 		}
364 		if((flags & NODE_VAR_FLAG_COMPILED) != 0) {
365 			fprintf(out, " COMPILED");
366 		}
367 		if((flags & NODE_VAR_FLAG_INUSE) != 0) {
368 			fprintf(out, " INUSE");
369 		}
370 		if((flags & NODE_VAR_FLAG_ATTRS) != 0) {
371 			fprintf(out, " ATTRS");
372 		}
373 		if((flags & NODE_VAR_FLAG_DEFINED) != 0) {
374 			fprintf(out, " DEFINED");
375 		}
376 		if((flags & NODE_VAR_FLAG_DEFINING) != 0) {
377 			fprintf(out, " DEFINING");
378 		}
379 		if((flags & NODE_VAR_FLAG_TOADD) != 0) {
380 			fprintf(out, " TOADD");
381 		}
382 	}
383 		break;
384 
385 	default:
386 		break;
387 
388 	}
389 
390 	const int size = f_user_data.Size();
391 	if(size > 0) {
392 		const int *p = f_user_data.Buffer();
393 		fprintf(out, " Raw Data (%p):", p);
394 		for(int idx = 0; idx < size; ++idx) {
395 			fprintf(out, " %08X", p[idx]);
396 		}
397 	}
398 }
399 
400 
401 /**********************************************************************/
402 /**********************************************************************/
403 /***  DATA CONVERSION  ************************************************/
404 /**********************************************************************/
405 /**********************************************************************/
406 
ToBoolean(void)407 bool Data::ToBoolean(void)
408 {
409 	switch(f_type) {
410 	case NODE_TRUE:
411 	case NODE_FALSE:
412 		// already a boolean
413 		break;
414 
415 	case NODE_NULL:
416 	case NODE_UNDEFINED:
417 		f_type = NODE_FALSE;
418 		break;
419 
420 	case NODE_INT64:
421 		f_type = f_int.Get() != 0 ? NODE_TRUE : NODE_FALSE;
422 		break;
423 
424 	case NODE_FLOAT64:
425 	{
426 		double value = f_float.Get();
427 		f_type = value != 0 && !isnan(value) ? NODE_TRUE : NODE_FALSE;
428 	}
429 		break;
430 
431 	case NODE_STRING:
432 		f_type = f_str.IsEmpty() ? NODE_FALSE : NODE_TRUE;
433 		break;
434 
435 	// At this time Data doesn't support any of these:
436 	//case CHARACTER:
437 	//case NAMESPACE:
438 	//case COMPOUNDATTRIBUTE:
439 	//case CLASS:
440 	//case SIMPLEINSTANCE:
441 	//case METHODCLOSURE:
442 	//case DATE:
443 	//case REGEXP:
444 	//case PACKAGE:
445 	//	f_type = NODE_TRUE;
446 	//	break;
447 
448 	default:
449 		// failure (can't convert)
450 		return false;
451 
452 	}
453 
454 	return true;
455 }
456 
457 
ToNumber(void)458 bool Data::ToNumber(void)
459 {
460 	switch(f_type) {
461 	case NODE_INT64:
462 	case NODE_FLOAT64:
463 		break;
464 
465 	case NODE_TRUE:
466 		f_type = NODE_INT64;
467 		f_int.Set(1);
468 		break;
469 
470 	case NODE_NULL:
471 	case NODE_FALSE:
472 		f_type = NODE_INT64;
473 		f_int.Set(0);
474 		break;
475 
476 	case NODE_UNDEFINED:
477 		f_type = NODE_FLOAT64;
478 		f_float.Set(FP_NAN);
479 		break;
480 
481 	default:
482 		// failure (can't convert)
483 		return false;
484 
485 	}
486 
487 	return true;
488 }
489 
490 
ToString(void)491 bool Data::ToString(void)
492 {
493 	char	buf[256];
494 
495 	buf[sizeof(buf) - 1] = '\0';
496 
497 	switch(f_type) {
498 	case NODE_STRING:
499 		break;
500 
501 	case NODE_UNDEFINED:
502 		f_type = NODE_STRING;
503 		f_str = "undefined";
504 		break;
505 
506 	case NODE_NULL:
507 		f_type = NODE_STRING;
508 		f_str = "null";
509 		break;
510 
511 	case NODE_TRUE:
512 		f_type = NODE_STRING;
513 		f_str = "true";
514 		break;
515 
516 	case NODE_FALSE:
517 		f_type = NODE_STRING;
518 		f_str = "false";
519 		break;
520 
521 	case NODE_INT64:
522 		f_type = NODE_STRING;
523 		snprintf(buf, sizeof(buf) - 1, "%lld", f_int.Get());
524 		f_str = buf;
525 		break;
526 
527 	case NODE_FLOAT64:
528 	{
529 		double value = f_float.Get();
530 		f_type = NODE_STRING;
531 		if(isnan(value)) {
532 			f_str = "NaN";
533 		}
534 		else if(value == 0.0) {
535 			f_str = "0";
536 		}
537 		else if(isinf(value) < 0) {
538 			f_str = "-Infinity";
539 		}
540 		else if(isinf(value) > 0) {
541 			f_str = "Infinity";
542 		}
543 		else {
544 			snprintf(buf, sizeof(buf) - 1, "%g", value);
545 			f_str = buf;
546 		}
547 	}
548 		break;
549 
550 	default:
551 		// failure (can't convert)
552 		return false;
553 
554 	}
555 
556 	return true;
557 }
558 
559 
560 
561 };	// namespace as
562 };	// namespace sswf
563