1 /* 2 * ejsVar.h -- EJS Universal Variable Type 3 */ 4 5 /* 6 * @copy default 7 * 8 * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. 9 * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. 10 * 11 * This software is distributed under commercial and open source licenses. 12 * You may use the GPL open source license described below or you may acquire 13 * a commercial license from Mbedthis Software. You agree to be fully bound 14 * by the terms of either license. Consult the LICENSE.TXT distributed with 15 * this software for full details. 16 * 17 * This software is open source; you can redistribute it and/or modify it 18 * under the terms of the GNU General Public License as published by the 19 * Free Software Foundation; either version 2 of the License, or (at your 20 * option) any later version. See the GNU General Public License for more 21 * details at: http://www.mbedthis.com/downloads/gplLicense.html 22 * 23 * This program is distributed WITHOUT ANY WARRANTY; without even the 24 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 25 * 26 * This GPL license does NOT permit incorporating this software into 27 * proprietary programs. If you are unable to comply with the GPL, you must 28 * acquire a commercial license to use this software. Commercial licenses 29 * for this software and support services are available from Mbedthis 30 * Software at http://www.mbedthis.com 31 * 32 * @end 33 */ 34 35 /* 36 * Variables can efficiently store primitive types and can hold references to 37 * objects. Objects can store properties which are themselves variables. 38 * Properties can be primitive data types, other objects or methods. 39 * Properties are indexed by a character name. A variable may store one of 40 * the following types: 41 * 42 * string, integer, integer-64bit, C method, C method with string args, 43 * Javascript method, Floating point number, boolean value, Undefined 44 * value and the Null value. 45 * 46 * Variables have names while objects may be referenced by multiple variables. 47 * Objects use reference counting for garbage collection. 48 * 49 * This module is not thread safe for performance and compactness. It relies 50 * on upper modules to provide thread synchronization as required. The API 51 * provides primitives to get variable/object references or to get copies of 52 * variables which will help minimize required lock times. 53 */ 54 55 #ifndef _h_EJS_VAR 56 #define _h_EJS_VAR 1 57 58 /********************************* Includes ***********************************/ 59 60 #include "mpr.h" 61 62 /********************************** Defines ***********************************/ 63 #ifdef __cplusplus 64 extern "C" { 65 #endif 66 67 /* 68 * Defined in ejs.h 69 */ 70 typedef struct Ejs Ejs; 71 72 /* 73 * Constants 74 */ 75 #if BLD_FEATURE_SQUEEZE 76 /** 77 * Maximum property or variable name size 78 */ 79 #define EJS_MAX_ID 64 80 81 /* 82 * EJS_VAR_HASH_SIZE must be less than the size of the bit field 83 * propertyIndex in EjsProperty. 84 */ 85 #define EJS_OBJ_HASH_SIZE 13 86 87 /** 88 * Maximum number of arguments per function call 89 */ 90 #define EJS_MAX_ARGS 32 91 #define EJS_INC_ARGS 8 /* Frame stack increment */ 92 93 #else 94 #define EJS_MAX_ID 256 95 #define EJS_OBJ_HASH_SIZE 29 96 #define EJS_MAX_ARGS 64 97 #define EJS_INC_ARGS 8 98 #endif 99 100 #define EJS_VAR_MAX_RECURSE 5 /* Max object loops */ 101 102 #if !DOXYGEN 103 /* 104 * Forward declare types 105 */ 106 struct Ejs; 107 struct EjsObj; 108 struct EjsProperty; 109 struct EjsVar; 110 #endif 111 112 /** 113 * @overview EJ primitive variable type 114 * @description EJ primitive variable values are stored in EjsVar structures. 115 * The type of the primitive data is described by an EjsType field. 116 * EjsVar variable types. 117 * @stability Prototype. 118 * @library libejs. 119 * @see EJS_TYPE_UNDEFINED, EJS_TYPE_NULL, EJS_TYPE_BOOL, EJS_TYPE_CMETHOD, 120 * EJS_TYPE_FLOAT, EJS_TYPE_INT, EJS_TYPE_INT64, EJS_TYPE_OBJECT, 121 * EJS_TYPE_METHOD, EJS_TYPE_STRING, EJS_TYPE_STRING_CMETHOD, EJS_TYPE_PTR, 122 */ 123 typedef uint EjsType; 124 #define EJS_TYPE_UNDEFINED 0 /**< Undefined. No value has been set */ 125 #define EJS_TYPE_NULL 1 /**< Value defined to be null. */ 126 #define EJS_TYPE_BOOL 2 /**< Boolean type. */ 127 #define EJS_TYPE_CMETHOD 3 /**< C method */ 128 #define EJS_TYPE_FLOAT 4 /**< Floating point number */ 129 #define EJS_TYPE_INT 5 /**< Integer number */ 130 #define EJS_TYPE_INT64 6 /**< 64-bit Integer number */ 131 #define EJS_TYPE_OBJECT 7 /**< Object reference */ 132 #define EJS_TYPE_METHOD 8 /**< JavaScript method */ 133 #define EJS_TYPE_STRING 9 /**< String (immutable) */ 134 #define EJS_TYPE_STRING_CMETHOD 10 /**< C method with string args */ 135 #define EJS_TYPE_PTR 11 /**< Opaque pointer */ 136 137 /* 138 * Create a type for the default number type 139 * Config.h will define the default number type. For example: 140 * 141 * BLD_FEATURE_NUM_TYPE=int 142 * BLD_FEATURE_NUM_TYPE_ID=EJS_TYPE_INT 143 */ 144 145 /** 146 * Set to the type used for EJS numeric variables. Will equate to int, int64 147 * or double. 148 */ 149 typedef BLD_FEATURE_NUM_TYPE EjsNum; 150 151 /** 152 * Set to the EJS_TYPE used for EJS numeric variables. Will equate to 153 * EJS_TYPE_INT, EJS_TYPE_INT64 or EJS_TYPE_FLOAT. 154 */ 155 #define EJS_NUM_VAR BLD_FEATURE_NUM_TYPE_ID 156 #define EJS_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID 157 158 /* 159 * Return TRUE if a variable is a method type 160 */ 161 #define ejsVarIsMethod(vp) \ 162 ((vp)->type == EJS_TYPE_METHOD || (vp)->type == EJS_TYPE_STRING_CMETHOD || \ 163 (vp)->type == EJS_TYPE_CMETHOD) 164 165 /* 166 * Return TRUE if a variable is a numeric type 167 */ 168 #define ejsVarIsNumber(vp) \ 169 ((vp)->type == EJS_TYPE_INT || (vp)->type == EJS_TYPE_INT64 || \ 170 (vp)->type == EJS_TYPE_FLOAT) 171 172 /* 173 * Return TRUE if a variable is a boolean 174 */ 175 #define ejsVarIsBoolean(vp) \ 176 ((vp)->type == EJS_TYPE_BOOL) 177 178 /* 179 * Return TRUE if a variable is an integer type 180 */ 181 #define ejsVarIsInteger(vp) ((vp)->type == EJS_TYPE_INT) 182 183 /* 184 * Return TRUE if a variable is a string 185 */ 186 #define ejsVarIsString(vp) \ 187 ((vp)->type == EJS_TYPE_STRING) 188 189 /* 190 * Return TRUE if a variable is an object 191 */ 192 #define ejsVarIsObject(vp) \ 193 ((vp)->type == EJS_TYPE_OBJECT) 194 195 /* 196 * Return TRUE if a variable is a floating number 197 */ 198 #define ejsVarIsFloating(vp) \ 199 ((vp)->type == EJS_TYPE_FLOAT) 200 201 /* 202 * Return TRUE if a variable is undefined 203 */ 204 #define ejsVarIsUndefined(var) \ 205 ((var)->type == EJS_TYPE_UNDEFINED) 206 207 /* 208 * Return TRUE if a variable is null 209 */ 210 #define ejsVarIsNull(var) \ 211 ((var)->type == EJS_TYPE_NULL) 212 213 /* 214 * Return TRUE if a variable is a valid type (not null or undefined) 215 */ 216 #define ejsVarIsValid(var) \ 217 (((var)->type != EJS_TYPE_NULL) && ((var)->type != EJS_TYPE_UNDEFINED)) 218 219 /* 220 * Return TRUE if a variable is a ptr type 221 */ 222 #define ejsVarIsPtr(vp) \ 223 ((vp)->type == EJS_TYPE_PTR) 224 225 /* MOB -- convert all ep to ejs */ 226 /** 227 * @overview C Method signature 228 * @description This is the calling signature for C Methods. 229 * @param ejs Ejs reference returned from ejsCreateInterp 230 * @param thisObj Reference to the "this" object. (The object containing the 231 * method). 232 * @param argc Number of arguments. 233 * @param argv Array of arguments. Each argument is held in an EjsVar type. 234 * @stability Prototype. 235 * @library libejs. 236 * @see ejsCreateCMethodVar 237 */ 238 typedef int (*EjsCMethod)(struct Ejs *ejs, struct EjsVar *thisObj, 239 int argc, struct EjsVar **argv); 240 241 /** 242 * C Method with string arguments signature 243 * @overview C Method with string arguments signature 244 * @description This is the calling signature for C Methods. 245 * @param ejs Ejs reference returned from ejsCreateInterp 246 * @param thisObj Reference to the "this" object (object containing the 247 * method. 248 * @param argc Number of arguments. 249 * @param argv Array of arguments. Each argument is held in an C string 250 * pointer. 251 * @stability Prototype. 252 * @library libejs. 253 * @see ejsCreateStringCMethodVar 254 */ 255 typedef int (*EjsStringCMethod)(struct Ejs *ep, struct EjsVar *thisObj, 256 int argc, char **argv); 257 258 /** 259 * Flags for types: EJS_TYPE_CMETHOD, EJS_TYPE_STRING_CMETHOD 260 * NOTE: flags == 0 means to use the EJS handle on method callbacks 261 */ 262 /* Use the primary handle on method callbacks */ 263 #define EJS_PRIMARY_HANDLE 0x1 264 265 /* Use the alternate handle on method callbacks */ 266 #define EJS_ALT_HANDLE 0x2 267 268 /** Method should not create a new local variable block */ 269 #define EJS_NO_LOCAL 0x4 270 271 /* Method is a get accessor */ 272 #define EJS_GET_ACCESSOR 0x8 273 274 /* Method is a set accessor */ 275 #define EJS_SET_ACCESSOR 0x10 276 277 /* 278 * Flags for E4X (Xml type) 279 */ 280 /* Node is a text node */ 281 #define EJS_XML_FLAGS_TEXT 0x1 282 283 /* Node is a processing instruction */ 284 #define EJS_XML_FLAGS_PI 0x2 285 286 /* Node is a comment */ 287 #define EJS_XML_FLAGS_COMMENT 0x4 288 289 /* Node is an attribute */ 290 #define EJS_XML_FLAGS_ATTRIBUTE 0x8 291 292 /* Node is an element */ 293 #define EJS_XML_FLAGS_ELEMENT 0x10 294 295 /** 296 * Copy depth 297 * @overview Specifies how an object should be copied 298 * @description The EjsCopyDepth type specifies how an object's properties 299 * should be copied. Several routines take EjsCopyDepth parameters to 300 * control how the properties of an object should be copied. It provides 301 * three copy options: 302 * @see ejsWriteVar 303 */ 304 typedef enum EjsCopyDepth { 305 /** 306 * During an object copy, object property references will be copied so 307 * that the original object and the copy will share the same reference to 308 * a property object. Properties containing primitive types including 309 * strings will have their values copied and will not share references. 310 */ 311 EJS_SHALLOW_COPY, /** Copy strings. Copy object references. */ 312 /* 313 * During an object copy, object properties will be replicated so that 314 * the original object and the copy will not share references to the same 315 * object properties. If the original object's properties are themselves 316 * objects, their properties will not be copied. Only their references 317 * will be copied. i.e. the deep copy is one level deep. 318 */ 319 EJS_DEEP_COPY, /** Copy strings and copy object contents. */ 320 /* 321 * During an object copy, all object properties will be replicated so that 322 * the original object and the copy will not share references to the same 323 * object properties. If the original object's properties are themselves 324 * objects, their properties will be copied. i.e. the copy is of infinite 325 * depth. 326 */ 327 EJS_RECURSIVE_DEEP_COPY /** Copy strings and copy object contents 328 recursively (complete copy). */ 329 } EjsCopyDepth; 330 331 332 /* 333 * Enumeration flags 334 */ 335 /** Enumerate data properties */ 336 #define EJS_ENUM_DATA 0x0 337 338 /** Enumerate sub classes */ 339 #define EJS_ENUM_CLASSES 0x1 340 341 /** Enumerate non-enumerable properties */ 342 #define EJS_ENUM_HIDDEN 0x2 343 344 /** Enumerate all properties */ 345 #define EJS_ENUM_ALL (0x3) 346 347 /** Magic number when allocated */ 348 #define EJS_MAGIC 0xe801e2ec 349 #define EJS_MAGIC_FREE 0xe701e3ea 350 351 352 /* 353 * Garbage Collection Linkage. Free list only uses the next pointers. 354 */ 355 typedef struct EjsGCLink { 356 #if BLD_DEBUG 357 uint magic; /* Magic number */ 358 #endif 359 #if BLD_FEATURE_ALLOC_LEAK_TRACK 360 const char *allocatedBy; /* Who allocated this */ 361 #endif 362 struct EjsGCLink *next; /* Next property */ 363 } EjsGCLink; 364 365 366 /** 367 * @overview EJS Variable Type 368 * @description The EJ language supports an extensive set of primitive types. 369 * These variable types can efficiently store primitive data types such as 370 * integers, strings, binary string, booleans, floating point numbers, 371 * pointer references, and objects. EjsVars are the universal type used by 372 * EJ to hold objects, classes and properties. 373 * \n\n 374 * An EjsVar may store one of the following types: 375 * @li Boolean 376 * @li Floating point (if supported in this build) 377 * @li Integer 378 * @li 64 bit integer (if supported in this build) 379 * @li String 380 * @li Binary string 381 * @li C function or C++ method 382 * @li C function with string args 383 * @li Javascript method 384 * @li Object 385 * @li Null value. 386 * @li Undefined value 387 * \n\n 388 * Objects can hold object properties which are themselves EJS variables. 389 * Properties are hash indexed by the property name and are stored in 390 * an ordered sequence. i.e. Order of properties is maintained. Objects may 391 * be referenced by multiple variables and they use garbage collection to 392 * reclaim memory no longer in use by objects and properties. 393 * 394 * @warning This module is @e not thread safe for performance and 395 * compactness. It relies on upper modules to provide thread 396 * synchronization as required. The API provides primitives to get 397 * variable/object references or to get copies of variables which should 398 * help minimize required lock times. 399 * @stability Prototype. 400 * @library libejs 401 * @see Ejs, EjsProperty, ejsCreateStringVar, ejsFreeVar 402 */ 403 404 typedef struct EjsVar { /* Size 12 bytes */ 405 /* 406 * GC must be first 407 */ 408 #if BLD_DEBUG || BLD_FEATURE_ALLOC_LEAK_TRACK 409 EjsGCLink gc; /* Garbage collection links */ 410 #endif 411 412 #if BLD_DEBUG 413 const char *propertyName; /* Ptr to property name */ 414 #endif 415 416 /* 417 * Union of primitive types. When debugging on Linux, don't use unions 418 * as the gdb debugger can't display them. 419 */ 420 #if (!BLD_DEBUG && !VXWORKS) || WIN || BREW_SIMULATOR 421 union { 422 #endif 423 /* 424 * For debugging, we order the common types first 425 */ 426 struct EjsObj *objectState; /* Object state information */ 427 int integer; 428 bool boolean; 429 430 #if BLD_FEATURE_FLOATING_POINT 431 double floating; 432 #endif 433 #if BLD_FEATURE_INT64 434 int64 integer64; 435 #endif 436 437 struct { 438 int length; /* String length (sans null) */ 439 /* 440 * All strings always have a trailing null allocated 441 */ 442 union { 443 char *string; /* String */ 444 uchar *ustring; /* Binary string */ 445 }; 446 }; 447 448 struct { /* Javascript methods */ 449 MprArray *args; /* Null terminated */ 450 char *body; 451 } method; 452 453 struct { /* Method with EjsVar args */ 454 EjsCMethod fn; /* Method pointer */ 455 void *userData; /* User data for method */ 456 } cMethod; 457 458 struct { /* Method with string args */ 459 EjsStringCMethod fn; /* Method pointer */ 460 void *userData; /* User data for method */ 461 } cMethodWithStrings; 462 463 struct { 464 void *userPtr; /* Opaque pointer */ 465 int (*destructor)(Ejs *ejs, struct EjsVar *vp); 466 } ptr; 467 468 #if (!BLD_DEBUG && !VXWORKS) || WIN || BREW_SIMULATOR 469 }; 470 #endif 471 472 /* 473 * Packed bit field (32 bits) 474 */ 475 uint flags : 8; /* Type specific flags */ 476 EjsType type : 4; /* Selector into union */ 477 uint stringLen : 4; /* Length of string if inline */ 478 uint allocatedData : 1; /* Node needs freeing */ 479 uint isArray : 1; /* Var is an array */ 480 uint isArrayLength : 1; /* Var is array.length */ 481 uint callsSuper : 1; /* Method calls super() */ 482 uint isProperty : 1; /* Part of a property */ 483 uint reserved : 11; /* Unused */ 484 485 } EjsVar; 486 487 488 /* 489 * Linkage for the ordered list of properties 490 */ 491 typedef struct EjsPropLink { 492 struct EjsPropLink *next; /* Next property */ 493 struct EjsPropLink *prev; /* Previous property */ 494 495 /* 496 * To make debugging easier 497 */ 498 #if BLD_DEBUG 499 const char *propertyName; /* Pointer to name */ 500 struct EjsProperty *property; /* Pointer to property */ 501 struct EjsPropLink *head; /* Dummy head of list */ 502 #endif 503 } EjsPropLink; 504 505 506 /** 507 * @overview Object Property Type 508 * @description The EjsProperty type is used to store all object properties. 509 * It contains the property name, property linkage, propery attributes 510 * such as public/private, enumerable and readonly settings. It also 511 * contains an EjsVar to store the property data value. 512 * @stability Prototype. 513 * @library libejs 514 * @see Ejs, EjsVar 515 */ 516 typedef struct EjsProperty { /* Size 96 bytes in squeeze */ 517 /* 518 * EjsVar must be first. We often take the address of "var" and take 519 * advantage of if an EjsProperty is null, then &prop->var will be null 520 * also. Be WARNED. External users should use ejsGetVarPtr and 521 * ejsGetPropertyPtr to convert between the two. 522 */ 523 EjsVar var; /* Property value */ 524 525 /* OPT change this to a pointer to the base class property */ 526 char name[EJS_MAX_ID]; /* Name */ 527 528 uint visited : 1; /* Has been traversed */ 529 uint isPrivate : 1; /* Property is private */ 530 uint isProtected : 1; /* Property is protected */ 531 uint dontEnumerate : 1; /* Not enumerable */ 532 uint dontDelete : 1; /* Prevent delete */ 533 uint readonly : 1; /* Unmodifiable */ 534 uint allowNonUnique : 1; /* Multiple of same name ok */ 535 uint delayedDelete : 1; 536 uint reserved : 24; 537 538 EjsPropLink link; /* Ordered linked list */ 539 struct EjsProperty *hashNext; /* Hash table linkage */ 540 541 /* MOB -- is this really required */ 542 struct EjsObj *parentObj; /* Pointer to parent object */ 543 544 } EjsProperty; 545 546 547 #define EJS_OP_DOT 0x1 548 #define EJS_OP_INDEX 0x2 549 #define EJS_OP_PLUS 0x3 550 #define EJS_OP_MINUS 0x4 551 #define EJS_OP_MULTIPLY 0x5 552 #define EJS_OP_DIVIDE 0x6 553 #define EJS_OP_CALL 0x7 554 555 typedef struct EjsOp { 556 int opType; 557 558 } EjsOp; 559 560 /* 561 * Propety Access Methods. Used per class. 562 * MOB -- rename EjsHelpers 563 */ 564 typedef struct EjsMethods { 565 #if FUTURE 566 int (*create)(Ejs *ep, EjsVar *thisObj); 567 int (*deleteProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); 568 EjsVar *(*getProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); 569 EjsVar *(*setProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); 570 int (*hasProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); 571 int (*hasInstance)(Ejs *ep, EjsVar *thisObj, const char *prop); 572 int (*operate)(Ejs *ep, EjsVar *thisObj, EjsOp op, EjsVar *result, 573 EjsVar *lhs, EjsVar *rhs, int *code); 574 #else 575 576 EjsVar *(*createProperty)(Ejs *ep, EjsVar *obj, const char *property); 577 int (*deleteProperty)(Ejs *ep, EjsVar *obj, const char *property); 578 EjsVar *(*getProperty)(Ejs *ep, EjsVar *obj, const char *property); 579 EjsVar *(*setProperty)(Ejs *ep, EjsVar *obj, const char *property, 580 const EjsVar *value); 581 /* 582 * Other implemented internal properties in ECMA-262 are: 583 * 584 * [[Construct]] implemented via EjsVar methods 585 * [[Prototype]] implemented via EjsObj->baseClass 586 * [[Class]] implemented via EjsObj->baseClass->name 587 * [[Value]] Implemented via EjsProperty + EjsVar + EjsObj 588 */ 589 590 /* 591 * FUTURE -- not implemented 592 */ 593 int (*canPut)(Ejs *ep, EjsVar *obj, const char *property); 594 int (*defaultValue)(Ejs *ep, EjsVar *obj, const char *property, 595 const char *hint); 596 int (*hasProperty)(Ejs *ep, EjsVar *obj, const char *property); 597 EjsVar *(*call)(Ejs *ep, EjsVar *obj, const char *property, 598 EjsVar *args); 599 int (*hasInstance)(Ejs *ep, EjsVar *obj, const char *property); 600 int (*scope)(Ejs *ep, EjsVar *obj, const char *property); 601 int (*match)(Ejs *ep, EjsVar *obj, const char *property, 602 const char *string, int index); 603 #endif 604 } EjsMethods; 605 606 607 /* 608 * Ejs Object Type 609 */ 610 typedef struct EjsObj { 611 /* 612 * GC must be first 613 */ 614 EjsGCLink gc; /* Garbage collection links */ 615 616 union { 617 char *objName; /* Object name */ 618 char *className; /* Class name */ 619 }; 620 621 struct EjsVar *baseClass; /* Pointer to base class object */ 622 623 EjsPropLink link; /* Ordered list of properties */ 624 625 /* OPT -- dynamically allocate this only if required */ 626 EjsProperty *propertyHash[EJS_OBJ_HASH_SIZE]; /* Hash chains */ 627 628 /* OPT -- could save this and store off baseClass only */ 629 EjsMethods *methods; /* Property access methods */ 630 void *nativeData; /* Native object data */ 631 632 int (*destructor)(Ejs *ejs, struct EjsVar *vp); 633 634 uint numProperties : 16; /* Total count of items */ 635 uint visited : 1; /* Has been traversed */ 636 uint gcMarked : 1; /* Node marked in-use by GC */ 637 uint permanent : 1; /* Permanent object, dont GC */ 638 uint alive : 1; /* Only GC if alive */ 639 uint noConstructor : 1; /* Object has no constructor */ 640 uint dirty : 1; /* Object has been modified */ 641 uint hasErrors : 1; /* Update error */ 642 uint preventDeleteProp : 1; /* Don't allow prop deletion */ 643 uint delayedDeleteProp : 1; /* Delayed delete of props */ 644 uint reserved : 7; /* Unused */ 645 646 Ejs *ejs; /* Owning interp */ 647 648 #if BLD_FEATURE_MULTITHREAD 649 MprLock *mutex; /* Advisory mutex lock */ 650 #endif 651 } EjsObj; 652 653 654 /* 655 * Define a field macro so code an use numbers in a "generic" fashion. 656 */ 657 #if EJS_NUM_VAR == EJS_TYPE_INT || DOXYGEN 658 /* 659 * Default numeric type 660 */ 661 #define ejsNumber integer 662 #endif 663 #if EJS_NUM_VAR == EJS_TYPE_INT64 664 /* Default numeric type */ 665 #define ejsNumber integer64 666 #endif 667 #if EJS_NUM_VAR == EJS_TYPE_FLOAT 668 /* Default numeric type */ 669 #define ejsNumber floating 670 #endif 671 672 typedef BLD_FEATURE_NUM_TYPE EjsNumber; 673 674 /* 675 * Memory allocation slabs 676 */ 677 #define EJS_SLAB_OBJ 0 678 #define EJS_SLAB_PROPERTY 1 679 #define EJS_SLAB_VAR 2 680 #define EJS_SLAB_MAX 3 681 682 /** 683 * Object and pointer property destructory type 684 */ 685 typedef int (*EjsDestructor)(Ejs *ejs, EjsVar *vp); 686 687 #if BLD_FEATURE_ALLOC_LEAK_TRACK || DOXYGEN 688 /* 689 * Line number information args and declarations for ejsAlloc. 690 * Use EJS_LOC_ARGS in normal user code. 691 * Use EJS_LOC_DEC in declarations. 692 * Use EJS_LOC_PASS in layered APIs to pass original line info down. 693 */ 694 #define EJS_LOC_ARGS(ejs) ejs, MPR_LOC 695 #define EJS_LOC_DEC(ejs, loc) Ejs *ejs, const char *loc 696 #define EJS_LOC_PASS(ejs, loc) ejs, loc 697 #else 698 #define EJS_LOC_ARGS(ejs) ejs 699 #define EJS_LOC_DEC(ejs, loc) Ejs *ejs 700 #define EJS_LOC_PASS(ejs, loc) ejs 701 #endif 702 703 /******************************* Internal Prototypes **************************/ 704 705 #define ejsInitVar(vp, varType) \ 706 if (1) { \ 707 (vp)->type = varType; \ 708 (vp)->isArray = 0; \ 709 (vp)->flags = 0; \ 710 } else 711 extern void ejsClearVar(Ejs *ep, EjsVar *vp); 712 713 extern int ejsDestroyObj(Ejs *ep, EjsObj *obj); 714 extern EjsVar *ejsCreatePropertyMethod(Ejs *ep, EjsVar *obj, 715 const char *name); 716 extern EjsVar *ejsSetPropertyMethod(Ejs *ep, EjsVar *obj, const char *name, 717 const EjsVar *value); 718 extern EjsVar *ejsGetPropertyMethod(Ejs *ep, EjsVar *obj, const char *name); 719 extern int ejsDeletePropertyMethod(Ejs *ep, EjsVar *obj, 720 const char *name); 721 extern void ejsSetArrayLength(Ejs *ep, EjsVar *obj, const char *creating, 722 const char *deleting, const EjsVar *setLength); 723 724 /* 725 * At the moment, these are the same routine 726 */ 727 extern void ejsSetClassName(Ejs *ep, EjsVar *obj, const char *name); 728 #define ejsSetObjName ejsSetObjName 729 730 extern bool ejsIsObjDirty(EjsVar *vp); 731 extern void ejsResetObjDirtyBit(EjsVar *vp); 732 733 extern int ejsObjHasErrors(EjsVar *vp); 734 extern void ejsClearObjErrors(EjsVar *vp); 735 736 extern EjsVar *ejsClearProperty(Ejs *ep, EjsVar *obj, const char *prop); 737 738 typedef int (*EjsSortFn)(Ejs *ep, EjsProperty *p1, EjsProperty *p2, 739 const char *propertyName, int order); 740 extern void ejsSortProperties(Ejs *ep, EjsVar *obj, EjsSortFn fn, 741 const char *propertyName, int order); 742 743 #if BLD_DEBUG 744 #define ejsSetVarName(ep, vp, varName) \ 745 if (1) { \ 746 (vp)->propertyName = varName; \ 747 if ((vp)->type == EJS_TYPE_OBJECT && \ 748 (vp)->objectState && \ 749 ((vp)->objectState->objName == 0)) { \ 750 (vp)->objectState->objName = \ 751 mprStrdup(ep, varName); \ 752 } \ 753 } else 754 #else 755 #define ejsSetVarName(ep, vp, varName) 756 #endif 757 758 EjsVar *ejsFindProperty(Ejs *ep, EjsVar **obj, char **property, 759 EjsVar *global, EjsVar *local, const char *fullName, 760 int create); 761 762 extern EjsVar *ejsCopyProperties(Ejs *ep, EjsVar *dest, 763 const EjsVar *src, EjsCopyDepth copyDepth); 764 765 #define EJS_LINK_OFFSET ((uint) (&((EjsProperty*) 0)->link)) 766 #define ejsGetPropertyFromLink(lp) \ 767 ((EjsProperty*) ((char*) lp - EJS_LINK_OFFSET)) 768 769 #define ejsGetObjPtr(vp) ((EjsObj*) vp->objectState) 770 771 extern void ejsMakePropertyPrivate(EjsProperty *pp, int isPrivate); 772 extern void ejsMakePropertyReadOnly(EjsProperty *pp, int readonly); 773 extern void ejsMakePropertyUndeleteable(EjsProperty *pp, int deletable); 774 extern int ejsMakeObjLive(EjsVar *vp, bool alive); 775 extern void ejsMakeClassNoConstructor(EjsVar *vp); 776 777 extern bool ejsBlockInUseInt(EjsVar *vp); 778 #if BLD_DEBUG 779 #define ejsBlockInUse(vp) ejsBlockInUseInt(vp) 780 #else 781 #define ejsBlockInUse(vp) 782 #endif 783 784 /********************************* Prototypes *********************************/ 785 786 /* 787 * Variable constructors and destructors 788 */ 789 extern EjsVar *ejsCreateBinaryStringVar(Ejs *ep, const uchar *value, 790 int len); 791 extern EjsVar *ejsCreateBoolVar(Ejs *ep, int value); 792 extern EjsVar *ejsCreateCMethodVar(Ejs *ep, EjsCMethod fn, 793 void *userData, int flags); 794 #if BLD_FEATURE_FLOATING_POINT 795 extern EjsVar *ejsCreateFloatVar(Ejs *ep, double value); 796 #endif 797 extern EjsVar *ejsCreateIntegerVar(Ejs *ep, int value); 798 #if BLD_FEATURE_INT64 799 extern EjsVar *ejsCreateInteger64Var(Ejs *ep, int64 value); 800 #endif 801 802 extern EjsVar *ejsCreateMethodVar(Ejs *ep, const char *body, 803 MprArray *args, int flags); 804 extern EjsVar *ejsCreateNullVar(Ejs *ep); 805 extern EjsVar *ejsCreateNumberVar(Ejs *ep, EjsNumber value); 806 807 #define ejsCreateObjVar(ep) \ 808 ejsCreateObjVarInternal(EJS_LOC_ARGS(ep)) 809 extern EjsVar *ejsCreateObjVarInternal(EJS_LOC_DEC(ep, loc)); 810 811 extern EjsVar *ejsCreatePtrVar(Ejs *ep, void *ptr, EjsDestructor dest); 812 813 extern EjsVar *ejsCreateStringCMethodVar(Ejs *ep, EjsStringCMethod fn, 814 void *userData, int flags); 815 816 #define ejsCreateStringVar(ep, value) \ 817 ejsCreateStringVarInternal(EJS_LOC_ARGS(ep), value) 818 extern EjsVar *ejsCreateStringVarInternal(EJS_LOC_DEC(ep, loc), 819 const char *value); 820 821 extern EjsVar *ejsCreateUndefinedVar(Ejs *ep); 822 823 /* MOB -- naming. Should be Create/Destroy */ 824 extern void ejsFreeVar(Ejs *ep, EjsVar *vp); 825 826 /* 827 * Var support routines 828 */ 829 extern int ejsGetVarFlags(EjsVar *vp); 830 extern void ejsSetVarFlags(EjsVar *obj, int flags); 831 832 extern EjsType ejsGetVarType(EjsVar *vp); 833 extern const char *ejsGetVarTypeAsString(EjsVar *vp); 834 835 extern void *ejsGetCMethodUserData(EjsVar *obj); 836 extern void ejsSetCMethodUserData(EjsVar *obj, void *userData); 837 838 extern void *ejsGetVarUserPtr(EjsVar *vp); 839 extern void ejsSetVarUserPtr(EjsVar *vp, void *data); 840 841 842 /* 843 * Variable access and manipulation. These work on standalone objects. 844 */ 845 #define ejsDupVar(ep, src, copyDepth) \ 846 ejsDupVarInternal(EJS_LOC_ARGS(ep), src, copyDepth) 847 extern EjsVar *ejsDupVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *src, 848 EjsCopyDepth copyDepth); 849 #define ejsWriteVar(ep, dest, src, copyDepth) \ 850 ejsWriteVarInternal(EJS_LOC_ARGS(ep), dest, src, copyDepth) 851 extern EjsVar *ejsWriteVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *dest, 852 const EjsVar *src, EjsCopyDepth copyDepth); 853 extern EjsVar *ejsWriteVarAsBinaryString(Ejs *ep, EjsVar *dest, 854 const uchar *value, int len); 855 extern EjsVar *ejsWriteVarAsBoolean(Ejs *ep, EjsVar *dest, bool value); 856 extern EjsVar *ejsWriteVarAsCMethod(Ejs *ep, EjsVar *dest, EjsCMethod fn, 857 void *userData, int flags); 858 #if BLD_FEATURE_FLOATING_POINT 859 extern EjsVar *ejsWriteVarAsFloat(Ejs *ep, EjsVar *dest, double value); 860 #endif 861 extern EjsVar *ejsWriteVarAsInteger(Ejs *ep, EjsVar *dest, int value); 862 #if BLD_FEATURE_INT64 863 extern EjsVar *ejsWriteVarAsInteger64(Ejs *ep, EjsVar *dest, int64 value); 864 #endif 865 extern EjsVar *ejsWriteVarAsMethod(Ejs *ep, EjsVar *dest, 866 const char *body, MprArray *args); 867 extern EjsVar *ejsWriteVarAsNull(Ejs *ep, EjsVar *dest); 868 extern EjsVar *ejsWriteVarAsNumber(Ejs *ep, EjsVar *dest, EjsNum value); 869 #define ejsWriteVarAsString(ep, dest, value) \ 870 ejsWriteVarAsStringInternal(EJS_LOC_ARGS(ep), dest, value) 871 extern EjsVar *ejsWriteVarAsStringInternal(EJS_LOC_DEC(ep, loc), 872 EjsVar *dest, const char *value); 873 extern EjsVar *ejsWriteVarAsStringCMethod(Ejs *ep, EjsVar *dest, 874 EjsStringCMethod fn, void *userData, int flags); 875 extern EjsVar *ejsWriteVarAsUndefined(Ejs *ep, EjsVar *dest); 876 877 /* 878 * These routines do not convert types 879 */ 880 /* MOB -- make this a fn and pass back the length as an arg */ 881 #define ejsReadVarAsBinaryString(vp) ((const uchar*) (vp->ustring)); 882 #define ejsReadVarAsBoolean(vp) (vp->boolean); 883 #define ejsReadVarAsCMethod(vp) (vp->cMethod); 884 #if BLD_FEATURE_FLOATING_POINT 885 #define ejsReadVarAsFloat(vp) (vp->floating); 886 #endif 887 #define ejsReadVarAsInteger(vp) (vp->integer); 888 #if BLD_FEATURE_INT64 889 #define ejsReadVarAsInteger64(vp) (vp->int64); 890 #endif 891 #define ejsReadVarAsString(vp) ((const char*) (vp->string)); 892 #define ejsReadVarAsStringCMethod(vp) (vp->cMethodWithStrings); 893 /* MOB -- remove this fn */ 894 #define ejsReadVarStringLength(vp) (vp->length); 895 896 /* 897 * Object property creation routines 898 */ 899 extern EjsProperty *ejsCreateProperty(Ejs *ep, EjsVar *obj, const char *prop); 900 extern EjsProperty *ejsCreateSimpleProperty(Ejs *ep, EjsVar *obj, 901 const char *prop); 902 extern EjsProperty *ejsCreateSimpleNonUniqueProperty(Ejs *ep, EjsVar *obj, 903 const char *prop); 904 /* MOB -- should be destroy */ 905 extern int ejsDeleteProperty(Ejs *ep, EjsVar *obj, const char *prop); 906 907 908 /* 909 * Get property routines 910 */ 911 extern EjsProperty *ejsGetProperty(Ejs *ep, EjsVar *obj, const char *prop); 912 extern EjsProperty *ejsGetSimpleProperty(Ejs *ep, EjsVar *obj, 913 const char *prop); 914 915 extern EjsVar *ejsGetPropertyAsVar(Ejs *ep, EjsVar *obj, 916 const char *prop); 917 extern int ejsGetPropertyCount(EjsVar *obj); 918 919 extern const uchar *ejsGetPropertyAsBinaryString(Ejs *ep, EjsVar *obj, 920 const char *prop, int *length); 921 extern bool ejsGetPropertyAsBoolean(Ejs *ep, EjsVar *obj, 922 const char *prop); 923 extern int ejsGetPropertyAsInteger(Ejs *ep, EjsVar *obj, 924 const char *prop); 925 extern int64 ejsGetPropertyAsInteger64(Ejs *ep, EjsVar *obj, 926 const char *prop); 927 extern EjsNum ejsGetPropertyAsNumber(Ejs *ep, EjsVar *obj, 928 const char *prop); 929 extern void *ejsGetPropertyAsPtr(Ejs *ep, EjsVar *obj, 930 const char *prop); 931 extern const char *ejsGetPropertyAsString(Ejs *ep, EjsVar *obj, 932 const char *prop); 933 934 /* 935 * Object property update routines 936 */ 937 extern EjsProperty *ejsSetBaseProperty(Ejs *ep, EjsVar *obj, const char *prop, 938 const EjsVar *value); 939 extern EjsProperty *ejsSetProperty(Ejs *ep, EjsVar *obj, const char *prop, 940 const EjsVar *value); 941 extern EjsProperty *ejsSetPropertyAndFree(Ejs *ep, EjsVar *obj, 942 const char *prop, EjsVar *value); 943 extern EjsProperty *ejsSetPropertyToBinaryString(Ejs *ep, EjsVar *obj, 944 const char *prop, const uchar *value, int len); 945 extern EjsProperty *ejsSetPropertyToBoolean(Ejs *ep, EjsVar *obj, 946 const char *prop, bool value); 947 extern EjsProperty *ejsSetPropertyToCMethod(Ejs *ep, EjsVar *obj, 948 const char *prop, EjsCMethod fn, void *userData, 949 int flags); 950 #if BLD_FEATURE_FLOATING_POINT 951 extern EjsProperty *ejsSetPropertyToFloat(Ejs *ep, EjsVar *obj, 952 const char *prop, double value); 953 #endif 954 extern EjsProperty *ejsSetPropertyToInteger(Ejs *ep, EjsVar *obj, 955 const char *prop, int value); 956 #if BLD_FEATURE_INT64 957 extern EjsProperty *ejsSetPropertyToInteger64(Ejs *ep, EjsVar *obj, 958 const char *prop, int64 value); 959 #endif 960 extern EjsProperty *ejsSetPropertyToMethod(Ejs *ep, EjsVar *obj, 961 const char *prop, const char *body, MprArray *args, 962 int flags); 963 extern EjsProperty *ejsSetPropertyToNewObj(Ejs *ep, EjsVar *obj, 964 const char *prop, const char *className, 965 MprArray *args); 966 extern EjsProperty *ejsSetPropertyToNull(Ejs *ep, EjsVar *obj, 967 const char *prop); 968 extern EjsProperty *ejsSetPropertyToNumber(Ejs *ep, EjsVar *obj, 969 const char *prop, EjsNum value); 970 extern EjsProperty *ejsSetPropertyToObj(Ejs *ep, EjsVar *obj, 971 const char *prop); 972 extern EjsProperty *ejsSetPropertyToPtr(Ejs *ep, EjsVar *obj, 973 const char *prop, void *ptr, EjsDestructor destructor); 974 975 extern EjsProperty *ejsSetPropertyToStringCMethod(Ejs *ep, EjsVar *obj, 976 const char *prop, EjsStringCMethod fn, 977 void *userData, int flags); 978 extern EjsProperty *ejsSetPropertyToString(Ejs *ep, EjsVar *obj, 979 const char *prop, const char *value); 980 extern EjsProperty *ejsSetPropertyToUndefined(Ejs *ep, EjsVar *obj, 981 const char *prop); 982 983 984 /* Convenience function */ 985 extern EjsVar *ejsSetPropertyToObjAsVar(Ejs *ep, EjsVar *obj, 986 const char *prop); 987 extern void ejsSetObjDestructor(Ejs *ep, EjsVar *obj, 988 EjsDestructor destructor); 989 extern void ejsClearObjDestructor(Ejs *ep, EjsVar *obj); 990 991 /* 992 * Enumeration of properties 993 * MOB -- should these take an ejs parameter to be consistent 994 */ 995 extern EjsProperty *ejsGetFirstProperty(const EjsVar *obj, int flags); 996 extern EjsProperty *ejsGetNextProperty(EjsProperty *last, int flags); 997 998 /* 999 * Method definition and control. 1000 */ 1001 extern EjsProperty *ejsDefineMethod(Ejs *ep, EjsVar *obj, const char *prop, 1002 const char *body, MprArray *args); 1003 extern EjsProperty *ejsDefineCMethod(Ejs *ep, EjsVar *obj, const char *prop, 1004 EjsCMethod fn, int flags); 1005 1006 extern EjsProperty *ejsDefineStringCMethod(Ejs *ep, EjsVar *obj, 1007 const char *prop, EjsStringCMethod fn, int flags); 1008 1009 extern EjsProperty *ejsDefineAccessors(Ejs *ep, EjsVar *obj, 1010 const char *prop, const char *getBody, 1011 const char *setBody); 1012 extern EjsProperty *ejsDefineCAccessors(Ejs *ep, EjsVar *obj, 1013 const char *prop, EjsCMethod getFn, EjsCMethod setFn, 1014 int flags); 1015 1016 /* 1017 * Macro to get the variable value portion of a property 1018 */ 1019 #define ejsGetVarPtr(pp) (&((pp)->var)) 1020 #define ejsGetPropertyPtr(vp) ((EjsProperty*) vp) 1021 1022 /* MOB -- take ejs to be consistent */ 1023 extern int ejsMakePropertyEnumerable(EjsProperty *pp, bool enumerable); 1024 extern int ejsMakeObjPermanent(EjsVar *vp, bool permanent); 1025 1026 1027 /* 1028 * Var conversion routines 1029 * MOB -- should these take an Ejs as first arg for consistency 1030 */ 1031 extern bool ejsVarToBoolean(EjsVar *vp); 1032 #if BLD_FEATURE_FLOATING_POINT 1033 extern double ejsVarToFloat(EjsVar *vp); 1034 #endif 1035 extern int ejsVarToInteger(EjsVar *vp); 1036 #if BLD_FEATURE_INT64 1037 extern int64 ejsVarToInteger64(EjsVar *vp); 1038 #endif 1039 extern EjsNum ejsVarToNumber(EjsVar *vp); 1040 extern char *ejsVarToString(Ejs *ep, EjsVar *vp); 1041 extern char *ejsVarToStringEx(Ejs *ep, EjsVar *vp, bool *alloc); 1042 extern char *ejsFormatVar(Ejs *ep, const char *fmt, EjsVar *vp); 1043 1044 #if BLD_FEATURE_FLOATING_POINT 1045 extern double ejsParseFloat(const char *str); 1046 #endif 1047 /* 1048 * Parsing and type range checking routines 1049 */ 1050 extern bool ejsParseBoolean(const char *str); 1051 extern int ejsParseInteger(const char *str); 1052 #if BLD_FEATURE_INT64 1053 extern int64 ejsParseInteger64(const char *str); 1054 #endif 1055 extern EjsNum ejsParseNumber(const char *str); 1056 extern EjsVar *ejsParseVar(Ejs *ep, const char *str, EjsType prefType); 1057 1058 #if BLD_FEATURE_FLOATING_POINT 1059 extern bool ejsIsInfinite(double f); 1060 extern bool ejsIsNan(double f); 1061 #endif 1062 1063 /* 1064 * Advisory locking support 1065 */ 1066 #if BLD_FEATURE_MULTITHREAD 1067 extern void ejsLockObj(EjsVar *vp); 1068 extern void ejsUnlockObj(EjsVar *vp); 1069 #endif 1070 1071 /* 1072 * Just for debugging 1073 */ 1074 extern bool ejsObjIsCollectable(EjsVar *vp); 1075 1076 #ifdef __cplusplus 1077 } 1078 #endif 1079 1080 /*****************************************************************************/ 1081 #endif /* _h_EJS_VAR */ 1082 1083 /* 1084 * Local variables: 1085 * tab-width: 4 1086 * c-basic-offset: 4 1087 * End: 1088 * vim:tw=78 1089 * vim600: sw=4 ts=4 fdm=marker 1090 * vim<600: sw=4 ts=4 1091 */ 1092