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