keep obsolete file in samba4 source directory.
[kai/samba-autobuild/.git] / source4 / lib / appweb / ejs-2.0 / ejs / ejsVar.h
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  */