diff options
Diffstat (limited to 'source4/lib/appweb/ejs')
-rw-r--r-- | source4/lib/appweb/ejs/config.h | 141 | ||||
-rw-r--r-- | source4/lib/appweb/ejs/ejs.h | 136 | ||||
-rw-r--r-- | source4/lib/appweb/ejs/ejsInternal.h | 295 | ||||
-rw-r--r-- | source4/lib/appweb/ejs/ejsLex.c | 923 | ||||
-rw-r--r-- | source4/lib/appweb/ejs/ejsLib.c | 1090 | ||||
-rw-r--r-- | source4/lib/appweb/ejs/ejsParser.c | 2436 | ||||
-rw-r--r-- | source4/lib/appweb/ejs/ejsProcs.c | 704 |
7 files changed, 0 insertions, 5725 deletions
diff --git a/source4/lib/appweb/ejs/config.h b/source4/lib/appweb/ejs/config.h deleted file mode 100644 index 8c06d28147..0000000000 --- a/source4/lib/appweb/ejs/config.h +++ /dev/null @@ -1,141 +0,0 @@ -#define BLD_PRODUCT "Samba4" -#define BLD_NAME "Samba4 WEB Applications" -#define BLD_VERSION "4" -#define BLD_NUMBER "1" -#define BLD_TYPE "DEBUG" -#define BLD_DEFAULTS "normal" -#define BLD_PACKAGES "" -#define BLD_APPWEB_CONFIG "normal.conf" -#define BLD_APPWEB 0 -#define BLD_COMPANY "Mbedthis" -#define BLD_DEBUG 0 -#define BLD_DIRS "bootstrap include obj bin mpr ejs esp http doc appWeb appWebSamples images" -#define BLD_HTTP_PORT 7777 -#define BLD_LIB_VERSION "1.0.0" -#define BLD_SSL_PORT 4443 -#define BLD_CLEAN_INSTALL "0" -#define BLD_LICENSE "gpl" -#define BLD_HOST_SYSTEM "i686-pc-linux-gnu" -#define BLD_BUILD_SYSTEM "i686-pc-linux-gnu" -#define BLD_HOST_OS "LINUX" -#define BLD_HOST_CPU_ARCH MPR_CPU_IX86 -#define BLD_HOST_CPU "i686" -#define BLD_HOST_UNIX 1 -#define BLD_BUILD_OS "LINUX" -#define BLD_BUILD_CPU_ARCH MPR_CPU_IX86 -#define BLD_BUILD_CPU i686 -#define BLD_BUILD_UNIX 1 -#define BLD_ROOT_PREFIX "/" -#define BLD_FEATURE_ACCESS_LOG 0 -#define BLD_FEATURE_ADMIN_MODULE 0 -#define BLD_FEATURE_ASPNET_MODULE 0 -#define BLD_FEATURE_ASSERT 1 -#define BLD_FEATURE_AUTH_MODULE 0 -#define BLD_FEATURE_C_API_MODULE 1 -#define BLD_FEATURE_C_API_CLIENT 0 -#define BLD_FEATURE_CGI_MODULE 0 -#define BLD_FEATURE_COMPAT_MODULE 0 -#define BLD_FEATURE_CONFIG_PARSE 0 -#define BLD_FEATURE_CONFIG_SAVE 0 -#define BLD_FEATURE_COOKIE 0 -#define BLD_FEATURE_COPY_MODULE 0 -#define BLD_FEATURE_DIGEST 0 -#define BLD_FEATURE_DLL 0 -#define BLD_FEATURE_EGI_MODULE 0 -#define BLD_FEATURE_EJS 1 -#define BLD_FEATURE_ESP_MODULE 1 -#define BLD_FEATURE_EVAL_PERIOD 30 -#define BLD_FEATURE_FLOATING_POINT 1 -#define BLD_FEATURE_IF_MODIFIED 0 -#define BLD_FEATURE_INT64 1 -#define BLD_FEATURE_KEEP_ALIVE 0 -#define BLD_FEATURE_LEGACY_API 0 -#define BLD_FEATURE_LIB_STDCPP 0 -#define BLD_FEATURE_LICENSE 0 -#define BLD_FEATURE_LOG 0 -#define BLD_FEATURE_MULTITHREAD 0 -#define BLD_FEATURE_MALLOC 0 -#define BLD_FEATURE_MALLOC_STATS 0 -#define BLD_FEATURE_MALLOC_LEAK 0 -#define BLD_FEATURE_MALLOC_HOOK 0 -#define BLD_FEATURE_NUM_TYPE int64_t -#define BLD_FEATURE_NUM_TYPE_ID MPR_TYPE_INT64 -#define BLD_FEATURE_ROMFS 0 -#define BLD_FEATURE_RUN_AS_SERVICE 0 -#define BLD_FEATURE_SAFE_STRINGS 0 -#define BLD_FEATURE_SAMPLES 0 -#define BLD_FEATURE_SESSION 1 -#define BLD_FEATURE_SHARED 0 -#define BLD_FEATURE_SQUEEZE 0 -#define BLD_FEATURE_SSL_MODULE 0 -#define BLD_FEATURE_STATIC 1 -#define BLD_FEATURE_STATIC_LINK_LIBC 0 -#define BLD_FEATURE_TEST 0 -#define BLD_FEATURE_UPLOAD_MODULE 0 -#define BLD_FEATURE_XDB_MODULE 0 -#define BLD_FEATURE_ADMIN_MODULE_BUILTIN 0 -#define BLD_FEATURE_ASPNET_MODULE_BUILTIN 0 -#define BLD_FEATURE_AUTH_MODULE_BUILTIN 0 -#define BLD_FEATURE_C_API_MODULE_BUILTIN 0 -#define BLD_FEATURE_CGI_MODULE_BUILTIN 0 -#define BLD_FEATURE_COMPAT_MODULE_BUILTIN 0 -#define BLD_FEATURE_COPY_MODULE_BUILTIN 0 -#define BLD_FEATURE_EGI_MODULE_BUILTIN 0 -#define BLD_FEATURE_ESP_MODULE_BUILTIN 0 -#define BLD_FEATURE_SSL_MODULE_BUILTIN 0 -#define BLD_FEATURE_UPLOAD_MODULE_BUILTIN 0 -#define BLD_FEATURE_XDB_MODULE_BUILTIN 0 -#define BLD_FEATURE_ADMIN_MODULE_LOADABLE 0 -#define BLD_FEATURE_ASPNET_MODULE_LOADABLE 0 -#define BLD_FEATURE_AUTH_MODULE_LOADABLE 0 -#define BLD_FEATURE_C_API_MODULE_LOADABLE 0 -#define BLD_FEATURE_CGI_MODULE_LOADABLE 0 -#define BLD_FEATURE_COMPAT_MODULE_LOADABLE 0 -#define BLD_FEATURE_COPY_MODULE_LOADABLE 0 -#define BLD_FEATURE_EGI_MODULE_LOADABLE 0 -#define BLD_FEATURE_ESP_MODULE_LOADABLE 0 -#define BLD_FEATURE_SSL_MODULE_LOADABLE 0 -#define BLD_FEATURE_UPLOAD_MODULE_LOADABLE 0 -#define BLD_FEATURE_XDB_MODULE_LOADABLE 0 -#define BLD_AR_FOR_BUILD "ar" -#define BLD_CC_FOR_BUILD "cc" -#define BLD_CSC_FOR_BUILD "" -#define BLD_JAVAC_FOR_BUILD "" -#define BLD_LD_FOR_BUILD "ld" -#define BLD_RANLIB_FOR_BUILD "" -#define BLD_NM_FOR_BUILD "nm" -#define BLD_CFLAGS_FOR_BUILD "" -#define BLD_IFLAGS_FOR_BUILD "" -#define BLD_LDFLAGS_FOR_BUILD "" -#define BLD_ARCHIVE_FOR_BUILD ".a" -#define BLD_EXE_FOR_BUILD "" -#define BLD_OBJ_FOR_BUILD ".o" -#define BLD_PIOBJ_FOR_BUILD ".lo" -#define BLD_CLASS_FOR_BUILD ".class" -#define BLD_SHLIB_FOR_BUILD "" -#define BLD_SHOBJ_FOR_BUILD ".so" -#define BLD_AR_FOR_HOST "ar" -#define BLD_CC_FOR_HOST "cc" -#define BLD_CSC_FOR_HOST "csc" -#define BLD_JAVAC_FOR_HOST "javac" -#define BLD_LD_FOR_HOST "ld" -#define BLD_RANLIB_FOR_HOST "true" -#define BLD_NM_FOR_HOST "nm" -#define BLD_CFLAGS_FOR_HOST "" -#define BLD_IFLAGS_FOR_HOST "" -#define BLD_LDFLAGS_FOR_HOST "" -#define BLD_ARCHIVE_FOR_HOST ".a" -#define BLD_EXE_FOR_HOST "" -#define BLD_OBJ_FOR_HOST ".o" -#define BLD_PIOBJ_FOR_HOST ".lo" -#define BLD_CLASS_FOR_HOST ".class" -#define BLD_SHLIB_FOR_HOST "" -#define BLD_SHOBJ_FOR_HOST ".so" -#define BLD_TOOLS_DIR "${BLD_TOP}/bin" -#define BLD_BIN_DIR "${BLD_TOP}/bin" -#define BLD_INC_DIR "/usr/include/${BLD_PRODUCT}" -#define BLD_EXP_OBJ_DIR "${BLD_TOP}/obj" - -#ifndef MAX_FLOAT -#define MAX_FLOAT 3.40282347e+38F -#endif diff --git a/source4/lib/appweb/ejs/ejs.h b/source4/lib/appweb/ejs/ejs.h deleted file mode 100644 index c7b0c54d8e..0000000000 --- a/source4/lib/appweb/ejs/ejs.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * @file ejs.h - * @brief Primary Embedded Javascript (ECMAScript) header. - * @overview This Embedded Javascript (EJS) header defines the - * public API. This API should only be used by those directly - * using EJS without using Embedded Server Pages (ESP). ESP - * wraps all relevant APIs to expose a single consistent API. - * \n\n - * This API requires the mpr/var.h facilities to create and - * manage objects and properties. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#ifndef _h_EJS -#define _h_EJS 1 - -#include "lib/appweb/mpr/miniMpr.h" -#include "lib/appweb/mpr/var.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/********************************* Prototypes *********************************/ - -typedef MprVarHandle EjsId; -typedef MprVarHandle EjsHandle; - -/* - * Multithreaded lock routines - */ -typedef void (*EjsLock)(void *lockData); -typedef void (*EjsUnlock)(void *lockData); - -/********************************* Prototypes *********************************/ -/* - * Module management - */ -extern int ejsOpen(EjsLock lock, EjsUnlock unlock, void *lockData); -extern void ejsClose(void); -extern EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle); -extern void ejsCloseEngine(EjsId eid); - -void *ejs_save_state(void); -void ejs_restore_state(void *ptr); - -/* - * Evaluation functions - */ -extern int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg); -extern int ejsEvalScript(EjsId eid, char *script, MprVar *result, - char **emsg); -extern int ejsRunFunction(int eid, MprVar *obj, const char *functionName, - MprArray *args); - -/* - * Composite variable get / set routines. Can also use the MPR property - * routines on an object variable. - */ -extern MprVar ejsCreateObj(const char *name, int hashSize); -extern MprVar ejsCreateArray(const char *name, int hashSize); -extern bool ejsDestroyVar(MprVar *obj); -extern int ejsCopyVar(EjsId eid, const char *var, MprVar *value, - bool copyRef); -extern int ejsReadVar(EjsId eid, const char *var, MprVar *value); -extern int ejsWriteVar(EjsId eid, const char *var, MprVar *value); -extern int ejsWriteVarValue(EjsId eid, const char *var, MprVar value); -extern int ejsDeleteVar(EjsId eid, const char *var); - -extern MprVar *ejsGetLocalObject(EjsId eid); -extern MprVar *ejsGetGlobalObject(EjsId eid); - -/* - * Function routines - */ -extern void ejsDefineFunction(EjsId eid, const char *functionName, - char *args, char *body); -extern void ejsDefineCFunction(EjsId eid, const char *functionName, - MprCFunction fn, void *thisPtr, int flags); -extern void ejsDefineStringCFunction(EjsId eid, const char *functionName, - MprStringCFunction fn, void *thisPtr, int flags); -extern void *ejsGetThisPtr(EjsId eid); -extern MprVar *ejsGetReturnValue(EjsId eid); -extern int ejsGetLineNumber(EjsId eid); -extern int ejsParseArgs(int argc, char **argv, char *fmt, ...); -extern void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) - PRINTF_ATTRIBUTE(2,3); -extern void ejsSetReturnValue(EjsId eid, MprVar value); -extern void ejsSetReturnString(EjsId eid, const char *str); - -#ifdef __cplusplus -} -#endif -#endif /* _h_EJS */ - -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsInternal.h b/source4/lib/appweb/ejs/ejsInternal.h deleted file mode 100644 index 8b66dafdca..0000000000 --- a/source4/lib/appweb/ejs/ejsInternal.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * @file ejsInternal.h - * @brief Private header for Embedded Javascript (ECMAScript) - * @overview This Embedded Javascript header defines the private Embedded - * Javascript internal structures. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************* Includes ***********************************/ - -#ifndef _h_EJS_INTERNAL -#define _h_EJS_INTERNAL 1 - -#include "ejs.h" - -/********************************** Defines ***********************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Constants - */ - -#if BLD_FEATURE_SQUEEZE - #define EJS_PARSE_INCR 256 /* Growth factor */ - #define EJS_MAX_RECURSE 25 /* Sanity for maximum recursion */ - #define EJS_MAX_ID 128 /* Maximum ID length */ - #define EJS_OBJ_HASH_SIZE 13 /* Object hash table size */ - #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ - #define EJS_LIST_INCR 8 /* Growth increment for lists */ -#else - #define EJS_PARSE_INCR 1024 /* Growth factor */ - #define EJS_MAX_RECURSE 100 /* Sanity for maximum recursion */ - #define EJS_MAX_ID 256 /* Maximum ID length */ - #define EJS_OBJ_HASH_SIZE 29 /* Object hash table size */ - #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ - #define EJS_LIST_INCR 16 /* Growth increment for lists */ -#endif -#define EJS_TOKEN_STACK 4 /* Put back token stack */ - -/* - * Lexical analyser tokens - */ -#define EJS_TOK_ERR -1 /* Any error */ -#define EJS_TOK_LPAREN 1 /* ( */ -#define EJS_TOK_RPAREN 2 /* ) */ -#define EJS_TOK_IF 3 /* if */ -#define EJS_TOK_ELSE 4 /* else */ -#define EJS_TOK_LBRACE 5 /* { */ -#define EJS_TOK_RBRACE 6 /* } */ -#define EJS_TOK_LOGICAL 7 /* ||, &&, ! */ -#define EJS_TOK_EXPR 8 /* +, -, /, % */ -#define EJS_TOK_SEMI 9 /* ; */ -#define EJS_TOK_LITERAL 10 /* literal string */ -#define EJS_TOK_FUNCTION_NAME 11 /* functionName */ -#define EJS_TOK_NEWLINE 12 /* newline white space */ -#define EJS_TOK_ID 13 /* Identifier */ -#define EJS_TOK_EOF 14 /* End of script */ -#define EJS_TOK_COMMA 15 /* Comma */ -#define EJS_TOK_VAR 16 /* var */ -#define EJS_TOK_ASSIGNMENT 17 /* = */ -#define EJS_TOK_FOR 18 /* for */ -#define EJS_TOK_INC_DEC 19 /* ++, -- */ -#define EJS_TOK_RETURN 20 /* return */ -#define EJS_TOK_PERIOD 21 /* . */ -#define EJS_TOK_LBRACKET 22 /* [ */ -#define EJS_TOK_RBRACKET 23 /* ] */ -#define EJS_TOK_NEW 24 /* new */ -#define EJS_TOK_DELETE 25 /* delete */ -#define EJS_TOK_IN 26 /* in */ -#define EJS_TOK_FUNCTION 27 /* function */ -#define EJS_TOK_NUMBER 28 /* Number */ - -/* - * Expression operators - */ -#define EJS_EXPR_LESS 1 /* < */ -#define EJS_EXPR_LESSEQ 2 /* <= */ -#define EJS_EXPR_GREATER 3 /* > */ -#define EJS_EXPR_GREATEREQ 4 /* >= */ -#define EJS_EXPR_EQ 5 /* == */ -#define EJS_EXPR_NOTEQ 6 /* != */ -#define EJS_EXPR_PLUS 7 /* + */ -#define EJS_EXPR_MINUS 8 /* - */ -#define EJS_EXPR_DIV 9 /* / */ -#define EJS_EXPR_MOD 10 /* % */ -#define EJS_EXPR_LSHIFT 11 /* << */ -#define EJS_EXPR_RSHIFT 12 /* >> */ -#define EJS_EXPR_MUL 13 /* * */ -#define EJS_EXPR_ASSIGNMENT 14 /* = */ -#define EJS_EXPR_INC 15 /* ++ */ -#define EJS_EXPR_DEC 16 /* -- */ -#define EJS_EXPR_BOOL_COMP 17 /* ! */ - -/* - * Conditional operators - */ -#define EJS_COND_AND 1 /* && */ -#define EJS_COND_OR 2 /* || */ -#define EJS_COND_NOT 3 /* ! */ - -/* - * States - */ -#define EJS_STATE_ERR -1 /* Error state */ -#define EJS_STATE_EOF 1 /* End of file */ -#define EJS_STATE_COND 2 /* Parsing a "(conditional)" stmt */ -#define EJS_STATE_COND_DONE 3 -#define EJS_STATE_RELEXP 4 /* Parsing a relational expr */ -#define EJS_STATE_RELEXP_DONE 5 -#define EJS_STATE_EXPR 6 /* Parsing an expression */ -#define EJS_STATE_EXPR_DONE 7 -#define EJS_STATE_STMT 8 /* Parsing General statement */ -#define EJS_STATE_STMT_DONE 9 -#define EJS_STATE_STMT_BLOCK_DONE 10 /* End of block "}" */ -#define EJS_STATE_ARG_LIST 11 /* Function arg list */ -#define EJS_STATE_ARG_LIST_DONE 12 -#define EJS_STATE_DEC_LIST 16 /* Declaration list */ -#define EJS_STATE_DEC_LIST_DONE 17 -#define EJS_STATE_DEC 18 /* Declaration statement */ -#define EJS_STATE_DEC_DONE 19 -#define EJS_STATE_RET 20 /* Return statement */ - -#define EJS_STATE_BEGIN EJS_STATE_STMT - -/* - * General parsing flags. - */ -#define EJS_FLAGS_EXE 0x1 /* Execute statements */ -#define EJS_FLAGS_LOCAL 0x2 /* Get local vars only */ -#define EJS_FLAGS_GLOBAL 0x4 /* Get global vars only */ -#define EJS_FLAGS_CREATE 0x8 /* Create var */ -#define EJS_FLAGS_ASSIGNMENT 0x10 /* In assignment stmt */ -#define EJS_FLAGS_DELETE 0x20 /* Deleting a variable */ -#define EJS_FLAGS_FOREACH 0x40 /* In foreach */ -#define EJS_FLAGS_NEW 0x80 /* In a new stmt() */ -#define EJS_FLAGS_EXIT 0x100 /* Must exit */ - -/* - * Putback token - */ - -typedef struct EjsToken { - char *token; /* Token string */ - int id; /* Token ID */ -} EjsToken; - -/* - * EJ evaluation block structure - */ -typedef struct ejEval { - EjsToken putBack[EJS_TOKEN_STACK]; /* Put back token stack */ - int putBackIndex; /* Top of stack index */ - MprStr line; /* Current line */ - int lineLength; /* Current line length */ - int lineNumber; /* Parse line number */ - int lineColumn; /* Column in line */ - MprStr script; /* Input script for parsing */ - char *scriptServp; /* Next token in the script */ - int scriptSize; /* Length of script */ - MprStr tokbuf; /* Current token */ - char *tokEndp; /* Pointer past end of token */ - char *tokServp; /* Pointer to next token char */ - int tokSize; /* Size of token buffer */ - struct ejEval *next; /* used for backtraces */ - const char *procName; /* gives name in backtrace */ -} EjsInput; - -/* - * Function call structure - */ -typedef struct { - MprArray *args; /* Args for function */ - MprVar *fn; /* Function definition */ - char *procName; /* Function name */ -} EjsProc; - -/* - * Per EJS structure - */ -typedef struct ej { - EjsHandle altHandle; /* alternate callback handle */ - MprVar *currentObj; /* Ptr to current object */ - MprVar *currentProperty; /* Ptr to current property */ - EjsId eid; /* Halloc handle */ - char *error; /* Error message */ - int exitStatus; /* Status to exit() */ - int flags; /* Flags */ - MprArray *frames; /* List of variable frames */ - MprVar *global; /* Global object */ - EjsInput *input; /* Input evaluation block */ - MprVar *local; /* Local object */ - EjsHandle primaryHandle; /* primary callback handle */ - EjsProc *proc; /* Current function */ - MprVar result; /* Variable result */ - void *thisPtr; /* C++ ptr for functions */ - int tid; /* Current token id */ - char *token; /* Pointer to token string */ - MprVar tokenNumber; /* Parsed number */ -} Ejs; - -typedef int EjsBlock; /* Scope block id */ - -/* - * Function callback when using Alternate handles. - */ -typedef int (*EjsAltStringCFunction)(EjsHandle userHandle, EjsHandle altHandle, - int argc, char **argv); -typedef int (*EjsAltCFunction)(EjsHandle userHandle, EjsHandle altHandle, - int argc, MprVar **argv); - -/******************************** Prototypes **********************************/ -/* - * Ejs Lex - */ -extern int ejsLexOpenScript(Ejs* ep, char *script); -extern void ejsLexCloseScript(Ejs* ep); -extern int ejsInitInputState(EjsInput *ip); -extern void ejsLexSaveInputState(Ejs* ep, EjsInput* state); -extern void ejsLexFreeInputState(Ejs* ep, EjsInput* state); -extern void ejsLexRestoreInputState(Ejs* ep, EjsInput* state); -extern int ejsLexGetToken(Ejs* ep, int state); -extern void ejsLexPutbackToken(Ejs* ep, int tid, char *string); - -/* - * Parsing - */ -extern MprVar *ejsFindObj(Ejs *ep, int state, const char *property, - int flags); -extern MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, - char *property, int flags); -extern int ejsGetVarCore(Ejs *ep, const char *var, MprVar **obj, - MprVar **varValue, int flags); -extern int ejsParse(Ejs *ep, int state, int flags); -extern Ejs *ejsPtr(EjsId eid); -extern void ejsSetExitStatus(int eid, int status); -extern void ejsSetFlags(int orFlags, int andFlags); - -/* - * Create variable scope blocks - */ -extern EjsBlock ejsOpenBlock(EjsId eid); -extern int ejsCloseBlock(EjsId eid, EjsBlock vid); -extern int ejsEvalBlock(EjsId eid, char *script, MprVar *v, char **err); -extern int ejsDefineStandardProperties(MprVar *objVar); - -/* - * Error handling - */ -extern void ejsError(Ejs *ep, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); - -#ifdef __cplusplus -} -#endif -#endif /* _h_EJS_INTERNAL */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsLex.c b/source4/lib/appweb/ejs/ejsLex.c deleted file mode 100644 index b9a363cfc9..0000000000 --- a/source4/lib/appweb/ejs/ejsLex.c +++ /dev/null @@ -1,923 +0,0 @@ -/* - * @file ejsLex.c - * @brief EJS Lexical Analyser - * @overview EJS lexical analyser. This implementes a lexical analyser - * for a subset of the JavaScript language. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static int getLexicalToken(Ejs *ep, int state); -static int tokenAddChar(Ejs *ep, int c); -static int inputGetc(Ejs *ep); -static void inputPutback(Ejs *ep, int c); -static int charConvert(Ejs *ep, int base, int maxDig); - -/************************************* Code ***********************************/ -/* - * Open a new input script - */ - -int ejsLexOpenScript(Ejs *ep, char *script) -{ - EjsInput *ip; - - mprAssert(ep); - mprAssert(script); - - if ((ip = mprMalloc(sizeof(EjsInput))) == NULL) { - return -1; - } - memset(ip, 0, sizeof(*ip)); - ip->next = ep->input; - ep->input = ip; - ip->procName = ep->proc?ep->proc->procName:NULL; - -/* - * Create the parse token buffer and script buffer - */ - ip->tokbuf = mprMalloc(EJS_PARSE_INCR); - ip->tokSize = EJS_PARSE_INCR; - ip->tokServp = ip->tokbuf; - ip->tokEndp = ip->tokbuf; - - ip->script = mprStrdup(script); - ip->scriptSize = strlen(script); - ip->scriptServp = ip->script; - - ip->lineNumber = 1; - ip->lineLength = 0; - ip->lineColumn = 0; - ip->line = NULL; - - ip->putBackIndex = -1; - - return 0; -} - -/******************************************************************************/ -/* - * Close the input script - */ - -void ejsLexCloseScript(Ejs *ep) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - ep->input = ip->next; - - for (i = 0; i < EJS_TOKEN_STACK; i++) { - mprFree(ip->putBack[i].token); - ip->putBack[i].token = 0; - } - - mprFree(ip->line); - mprFree(ip->tokbuf); - mprFree(ip->script); - - mprFree(ip); -} - -/******************************************************************************/ -/* - * Initialize an input state structure - */ - -int ejsInitInputState(EjsInput *ip) -{ - mprAssert(ip); - - memset(ip, 0, sizeof(*ip)); - ip->putBackIndex = -1; - - return 0; -} -/******************************************************************************/ -/* - * Save the input state - */ - -void ejsLexSaveInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - - *state = *ip; - - for (i = 0; i < ip->putBackIndex; i++) { - state->putBack[i].token = mprStrdup(ip->putBack[i].token); - state->putBack[i].id = ip->putBack[i].id; - } - for (; i < EJS_TOKEN_STACK; i++) { - state->putBack[i].token = 0; - } - - state->line = mprMalloc(ip->lineLength); - mprStrcpy(state->line, ip->lineLength, ip->line); - - state->lineColumn = ip->lineColumn; - state->lineNumber = ip->lineNumber; - state->lineLength = ip->lineLength; -} - -/******************************************************************************/ -/* - * Restore the input state - */ - -void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - mprAssert(state); - - ip = ep->input; - mprAssert(ip); - - ip->tokbuf = state->tokbuf; - ip->tokServp = state->tokServp; - ip->tokEndp = state->tokEndp; - ip->tokSize = state->tokSize; - - ip->script = state->script; - ip->scriptServp = state->scriptServp; - ip->scriptSize = state->scriptSize; - - ip->putBackIndex = state->putBackIndex; - for (i = 0; i < ip->putBackIndex; i++) { - mprFree(ip->putBack[i].token); - ip->putBack[i].id = state->putBack[i].id; - ip->putBack[i].token = mprStrdup(state->putBack[i].token); - } - - mprFree(ip->line); - ip->line = mprMalloc(state->lineLength); - mprStrcpy(ip->line, state->lineLength, state->line); - - ip->lineColumn = state->lineColumn; - ip->lineNumber = state->lineNumber; - ip->lineLength = state->lineLength; -} - -/******************************************************************************/ -/* - * Free a saved input state - */ - -void ejsLexFreeInputState(Ejs *ep, EjsInput *state) -{ - int i; - - mprAssert(ep); - mprAssert(state); - - for (i = 0; i < EJS_TOKEN_STACK; i++) { - mprFree(state->putBack[i].token); - } - state->putBackIndex = -1; - mprFree(state->line); - state->lineLength = 0; - state->lineColumn = 0; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -int ejsLexGetToken(Ejs *ep, int state) -{ - mprAssert(ep); - - ep->tid = getLexicalToken(ep, state); - return ep->tid; -} - -/******************************************************************************/ - -/* - * Check for reserved words "if", "else", "var", "for", "foreach", - * "delete", "function", and "return". "new", "in" and "function" - * done below. "true", "false", "null", "undefined" are handled - * as global objects. - * - * Other reserved words not supported: - * "break", "case", "catch", "continue", "default", "do", - * "finally", "instanceof", "switch", "this", "throw", "try", - * "typeof", "while", "with" - * - * ECMA extensions reserved words (not supported): - * "abstract", "boolean", "byte", "char", "class", "const", - * "debugger", "double", "enum", "export", "extends", - * "final", "float", "goto", "implements", "import", "int", - * "interface", "long", "native", "package", "private", - * "protected", "public", "short", "static", "super", - * "synchronized", "throws", "transient", "volatile" - */ - -static int checkReservedWord(Ejs *ep, int state, int c, int tid) -{ - if (state == EJS_STATE_STMT) { - if (strcmp(ep->token, "if") == 0) { - inputPutback(ep, c); - return EJS_TOK_IF; - } else if (strcmp(ep->token, "else") == 0) { - inputPutback(ep, c); - return EJS_TOK_ELSE; - } else if (strcmp(ep->token, "var") == 0) { - inputPutback(ep, c); - return EJS_TOK_VAR; - } else if (strcmp(ep->token, "for") == 0) { - inputPutback(ep, c); - return EJS_TOK_FOR; - } else if (strcmp(ep->token, "delete") == 0) { - inputPutback(ep, c); - return EJS_TOK_DELETE; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } else if (strcmp(ep->token, "return") == 0) { - if ((c == ';') || (c == '(')) { - inputPutback(ep, c); - } - return EJS_TOK_RETURN; - } - } else if (state == EJS_STATE_EXPR) { - if (strcmp(ep->token, "new") == 0) { - inputPutback(ep, c); - return EJS_TOK_NEW; - } else if (strcmp(ep->token, "in") == 0) { - inputPutback(ep, c); - return EJS_TOK_IN; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } - } - return tid; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -static int getLexicalToken(Ejs *ep, int state) -{ - MprType type; - EjsInput *ip; - int done, tid, c, quote, style, idx; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ep->tid = -1; - tid = -1; - type = BLD_FEATURE_NUM_TYPE_ID; - - /* - * Use a putback tokens first. Don't free strings as caller needs access. - */ - if (ip->putBackIndex >= 0) { - idx = ip->putBackIndex; - tid = ip->putBack[idx].id; - ep->token = (char*) ip->putBack[idx].token; - tid = checkReservedWord(ep, state, 0, tid); - ip->putBackIndex--; - return tid; - } - ep->token = ip->tokServp = ip->tokEndp = ip->tokbuf; - *ip->tokServp = '\0'; - - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - - /* - * Main lexical analyser - */ - for (done = 0; !done; ) { - switch (c) { - case -1: - return EJS_TOK_EOF; - - case ' ': - case '\t': - case '\r': - do { - if ((c = inputGetc(ep)) < 0) - break; - } while (c == ' ' || c == '\t' || c == '\r'); - break; - - case '\n': - return EJS_TOK_NEWLINE; - - case '(': - tokenAddChar(ep, c); - return EJS_TOK_LPAREN; - - case ')': - tokenAddChar(ep, c); - return EJS_TOK_RPAREN; - - case '[': - tokenAddChar(ep, c); - return EJS_TOK_LBRACKET; - - case ']': - tokenAddChar(ep, c); - return EJS_TOK_RBRACKET; - - case '.': - tokenAddChar(ep, c); - return EJS_TOK_PERIOD; - - case '{': - tokenAddChar(ep, c); - return EJS_TOK_LBRACE; - - case '}': - tokenAddChar(ep, c); - return EJS_TOK_RBRACE; - - case '+': - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '+' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_PLUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_INC); - return EJS_TOK_INC_DEC; - - case '-': - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '-' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_MINUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_DEC); - return EJS_TOK_INC_DEC; - - case '*': - tokenAddChar(ep, EJS_EXPR_MUL); - return EJS_TOK_EXPR; - - case '%': - tokenAddChar(ep, EJS_EXPR_MOD); - return EJS_TOK_EXPR; - - case '/': - /* - * Handle the division operator and comments - */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '*' && c != '/') { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_DIV); - return EJS_TOK_EXPR; - } - style = c; - /* - * Eat comments. Both C and C++ comment styles are supported. - */ - while (1) { - if ((c = inputGetc(ep)) < 0) { - if (style == '/') { - return EJS_TOK_EOF; - } - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '\n' && style == '/') { - break; - } else if (c == '*') { - c = inputGetc(ep); - if (style == '/') { - if (c == '\n') { - break; - } - } else { - if (c == '/') { - break; - } - } - } - } - /* - * Continue looking for a token, so get the next character - */ - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - break; - - case '<': /* < and <= */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '<') { - tokenAddChar(ep, EJS_EXPR_LSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_LESSEQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_LESS); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '>': /* > and >= */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '>') { - tokenAddChar(ep, EJS_EXPR_RSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_GREATEREQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_GREATER); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '=': /* "==" */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_EQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - return EJS_TOK_ASSIGNMENT; - - case '!': /* "!=" or "!"*/ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_NOTEQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_BOOL_COMP); - return EJS_TOK_EXPR; - - case ';': - tokenAddChar(ep, c); - return EJS_TOK_SEMI; - - case ',': - tokenAddChar(ep, c); - return EJS_TOK_COMMA; - - case '|': /* "||" */ - if ((c = inputGetc(ep)) < 0 || c != '|') { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_OR); - return EJS_TOK_LOGICAL; - - case '&': /* "&&" */ - if ((c = inputGetc(ep)) < 0 || c != '&') { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_AND); - return EJS_TOK_LOGICAL; - - case '\"': /* String quote */ - case '\'': - quote = c; - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - - while (c != quote) { - /* - * Check for escape sequence characters - */ - if (c == '\\') { - c = inputGetc(ep); - - if (isdigit(c)) { - /* - * Octal support, \101 maps to 65 = 'A'. Put first - * char back so converter will work properly. - */ - inputPutback(ep, c); - c = charConvert(ep, 8, 3); - - } else { - switch (c) { - case 'n': - c = '\n'; break; - case 'b': - c = '\b'; break; - case 'f': - c = '\f'; break; - case 'r': - c = '\r'; break; - case 't': - c = '\t'; break; - case 'x': - /* - * Hex support, \x41 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - break; - case 'u': - /* - * Unicode support, \x0401 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - c = c*16 + charConvert(ep, 16, 2); - - break; - case '\'': - case '\"': - case '\\': - break; - default: - ejsError(ep, "Invalid Escape Sequence"); - return EJS_TOK_ERR; - } - } - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } else { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Unmatched Quote"); - return EJS_TOK_ERR; - } - } - return EJS_TOK_LITERAL; - - case '0': - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (tolower(c) == 'x') { - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - } while (isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f')); - - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - } - if (! isdigit(c)) { -#if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { - /* Fall through */ - type = MPR_TYPE_FLOAT; - } else -#endif - { - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - } - } - /* Fall through to get more digits */ - - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } -#if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || tolower(c) == 'f') { - type = MPR_TYPE_FLOAT; - } - } while (isdigit(c) || c == '.' || tolower(c) == 'e' || tolower(c) == 'f' || - ((type == MPR_TYPE_FLOAT) && (c == '+' || c == '-'))); -#else - } while (isdigit(c)); -#endif - - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - - default: - /* - * Identifiers or a function names - */ - while (1) { - if (c == '\\') { - if ((c = inputGetc(ep)) < 0) { - break; - } - if (c == '\n' || c == '\r') { - break; - } - } else if (tokenAddChar(ep, c) < 0) { - break; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (!isalnum(c) && c != '$' && c != '_' && c != '\\') { - break; - } - } - if (*ep->token == '\0') { - c = inputGetc(ep); - break; - } - if (! isalpha((int) *ep->token) && *ep->token != '$' && - *ep->token != '_') { - ejsError(ep, "Invalid identifier %s", ep->token); - return EJS_TOK_ERR; - } - - tid = checkReservedWord(ep, state, c, EJS_TOK_ID); - if (tid != EJS_TOK_ID) { - return tid; - } - - /* - * Skip white space after token to find out whether this is - * a function or not. - */ - while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - if ((c = inputGetc(ep)) < 0) - break; - } - - tid = EJS_TOK_ID; - done++; - } - } - - /* - * Putback the last extra character for next time - */ - inputPutback(ep, c); - return tid; -} - -/******************************************************************************/ -/* - * Convert a hex or octal character back to binary, return original char if - * not a hex digit - */ - -static int charConvert(Ejs *ep, int base, int maxDig) -{ - int i, c, lval, convChar; - - lval = 0; - for (i = 0; i < maxDig; i++) { - if ((c = inputGetc(ep)) < 0) { - break; - } - /* - * Initialize to out of range value - */ - convChar = base; - if (isdigit(c)) { - convChar = c - '0'; - } else if (c >= 'a' && c <= 'f') { - convChar = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - convChar = c - 'A' + 10; - } - /* - * If unexpected character then return it to buffer. - */ - if (convChar >= base) { - inputPutback(ep, c); - break; - } - lval = (lval * base) + convChar; - } - return lval; -} - -/******************************************************************************/ -/* - * Putback the last token read. Accept at most one push back token. - */ - -void ejsLexPutbackToken(Ejs *ep, int tid, char *string) -{ - EjsInput *ip; - int idx; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ip->putBackIndex += 1; - idx = ip->putBackIndex; - ip->putBack[idx].id = tid; - - if (ip->putBack[idx].token) { - if (ip->putBack[idx].token == string) { - return; - } - mprFree(ip->putBack[idx].token); - } - ip->putBack[idx].token = mprStrdup(string); -} - -/******************************************************************************/ -/* - * Add a character to the token buffer - */ - -static int tokenAddChar(Ejs *ep, int c) -{ - EjsInput *ip; - uchar *oldbuf; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - if (ip->tokEndp >= &ip->tokbuf[ip->tokSize - 1]) { - ip->tokSize += EJS_PARSE_INCR; - oldbuf = ip->tokbuf; - ip->tokbuf = mprRealloc(ip->tokbuf, ip->tokSize); - if (ip->tokbuf == 0) { - ejsError(ep, "Token too big"); - return -1; - } - ip->tokEndp += (int) ((uchar*) ip->tokbuf - oldbuf); - ip->tokServp += (int) ((uchar*) ip->tokbuf - oldbuf); - ep->token += (int) ((uchar*) ip->tokbuf - oldbuf); - } - *ip->tokEndp++ = c; - *ip->tokEndp = '\0'; - - return 0; -} - -/******************************************************************************/ -/* - * Get another input character - */ - -static int inputGetc(Ejs *ep) -{ - EjsInput *ip; - int c; - - mprAssert(ep); - ip = ep->input; - - if (ip->scriptSize <= 0) { - return -1; - } - - c = (uchar) (*ip->scriptServp++); - ip->scriptSize--; - - /* - * For debugging, accumulate the line number and the currenly parsed line - */ - if (c == '\n') { -#if BLD_DEBUG && 0 - if (ip->lineColumn > 0) { - printf("PARSED: %s\n", ip->line); - } -#endif - ip->lineNumber++; - ip->lineColumn = 0; - } else { - if ((ip->lineColumn + 2) >= ip->lineLength) { - ip->lineLength += 80; - ip->line = mprRealloc(ip->line, ip->lineLength * sizeof(char)); - } - ip->line[ip->lineColumn++] = c; - ip->line[ip->lineColumn] = '\0'; - } - return c; -} - -/******************************************************************************/ -/* - * Putback a character onto the input queue - */ - -static void inputPutback(Ejs *ep, int c) -{ - EjsInput *ip; - - mprAssert(ep); - - if (c != 0) { - ip = ep->input; - *--ip->scriptServp = c; - ip->scriptSize++; - ip->lineColumn--; - ip->line[ip->lineColumn] = '\0'; - } -} - -/******************************************************************************/ - -#else -void ejsLexDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c deleted file mode 100644 index 67d0a4e760..0000000000 --- a/source4/lib/appweb/ejs/ejsLib.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * @file ejs.c - * @brief Embedded JavaScript (EJS) - * @overview Main module interface logic. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/********************************** Local Data ********************************/ - -/* - * These fields must be locked before any access when multithreaded - */ -static MprVar master; /* Master object */ -static MprArray *ejsList; /* List of ej handles */ - -#if BLD_FEATURE_MULTITHREAD -static EjsLock lock; -static EjsUnlock unlock; -static void *lockData; -#define ejsLock() if (lock) { (lock)(lockData); } else -#define ejsUnlock() if (unlock) { (unlock)(lockData); } else -#else -#define ejsLock() -#define ejsUnlock() -#endif - - -/* - save/restore global ejs state - used to cope with simultaneous ejs requests - this is a workaround for the use of global variables in ejs -*/ -struct ejs_state_ctx { - MprVar master; - MprArray *ejsList; -}; - -void *ejs_save_state(void) -{ - struct ejs_state_ctx *ctx = talloc(talloc_autofree_context(), struct ejs_state_ctx); - ctx->master = master; - ctx->ejsList = ejsList; - return ctx; -} - -void ejs_restore_state(void *ptr) -{ - struct ejs_state_ctx *ctx = talloc_get_type(ptr, struct ejs_state_ctx); - master = ctx->master; - ejsList = ctx->ejsList; - talloc_free(ctx); -} - - -/****************************** Forward Declarations **************************/ - -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); - -/************************************* Code ***********************************/ -/* - * Initialize the EJ subsystem - */ - -int ejsOpen(EjsLock lockFn, EjsUnlock unlockFn, void *data) -{ - MprVar *np; - -#if BLD_FEATURE_MULTITHREAD - if (lockFn) { - lock = lockFn; - unlock = unlockFn; - lockData = data; - } -#endif - ejsLock(); - - /* - * Master is the top level object (above global). It is used to clone its - * contents into the global scope for each. This is never visible to the - * user, so don't use ejsCreateObj(). - */ - master = mprCreateObjVar("master", EJS_SMALL_OBJ_HASH_SIZE); - if (master.type == MPR_TYPE_UNDEFINED) { - ejsUnlock(); - return MPR_ERR_CANT_ALLOCATE; - } - - ejsList = mprCreateArray(); - ejsDefineStandardProperties(&master); - - /* - * Make these objects immutable - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprSetVarReadonly(np, 1); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - ejsUnlock(); - return 0; -} - -/******************************************************************************/ - -void ejsClose() -{ - ejsLock(); - mprDestroyArray(ejsList); - mprDestroyVar(&master); - ejsUnlock(); -} - -/******************************************************************************/ -/* - * Create and initialize an EJS engine - */ - -EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle) -{ - MprVar *np; - Ejs *ep; - - ep = (Ejs *)mprMalloc(sizeof(Ejs)); - if (ep == 0) { - return (EjsId) -1; - } - memset(ep, 0, sizeof(Ejs)); - - ejsLock(); - ep->eid = (EjsId) mprAddToArray(ejsList, ep); - ejsUnlock(); - - /* - * Create array of local variable frames - */ - ep->frames = mprCreateArray(); - if (ep->frames == 0) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - ep->primaryHandle = primaryHandle; - ep->altHandle = altHandle; - - /* - * Create first frame: global variables - */ - ep->global = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->global = ejsCreateObj("global", EJS_OBJ_HASH_SIZE); - if (ep->global->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->global); - - /* - * Create first local variable frame - */ - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("local", EJS_OBJ_HASH_SIZE); - if (ep->local->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->local); - - /* - * Clone all master variables into the global frame. This does a - * reference copy. - * - * ejsDefineStandardProperties(ep->global); - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprCreateProperty(ep->global, np->name, np); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - - mprCreateProperty(ep->global, "global", ep->global); - mprCreateProperty(ep->global, "this", ep->global); - mprCreateProperty(ep->local, "local", ep->local); - - return ep->eid; -} - -/******************************************************************************/ -/* - * Close an EJS instance - */ - -void ejsCloseEngine(EjsId eid) -{ - Ejs *ep; - MprVar *vp; - void **handles; - int i; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - - mprFree(ep->error); - mprDestroyVar(&ep->result); - mprDestroyVar(&ep->tokenNumber); - - if (ep->local) { - mprDeleteProperty(ep->local, "local"); - } - mprDeleteProperty(ep->global, "this"); - mprDeleteProperty(ep->global, "global"); - - handles = ep->frames->handles; - for (i = 0; i < ep->frames->max; i++) { - vp = handles[i]; - if (vp) { -#if BLD_DEBUG - if (vp->type == MPR_TYPE_OBJECT && vp->properties->refCount > 1) { - mprLog(7, "ejsCloseEngine: %s has ref count %d\n", - vp->name, vp->properties->refCount); - } -#endif - mprDestroyVar(vp); - mprFree(vp); - mprRemoveFromArray(ep->frames, i); - } - } - mprDestroyArray(ep->frames); - - ejsLock(); - mprRemoveFromArray(ejsList, (int) ep->eid); - ejsUnlock(); - - mprFree(ep); -} - -/******************************************************************************/ -/* - * Evaluate an EJS script file - */ - -int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) -{ - struct stat sbuf; - Ejs *ep; - char *script; - int rc, fd; - - mprAssert(path && *path); - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - goto error; - } - - if ((fd = open(path, O_RDONLY | O_BINARY, 0666)) < 0) { - ejsError(ep, "Can't open %s\n", path); - goto error; - } - - if (stat(path, &sbuf) < 0) { - close(fd); - ejsError(ep, "Cant stat %s", path); - goto error; - } - - if ((script = (char*) mprMalloc(sbuf.st_size + 1)) == NULL) { - close(fd); - ejsError(ep, "Cant malloc %d", (int) sbuf.st_size); - goto error; - } - - if (read(fd, script, sbuf.st_size) != (int) sbuf.st_size) { - close(fd); - mprFree(script); - ejsError(ep, "Error reading %s", path); - goto error; - } - - script[sbuf.st_size] = '\0'; - close(fd); - - rc = ejsEvalBlock(eid, script, result, emsg); - mprFree(script); - - return rc; - -/* - * Error return - */ -error: - if(emsg) - *emsg = mprStrdup(ep->error); - return -1; -} - -/******************************************************************************/ -/* - * Create a new variable scope block. This pushes the old local frame down - * the stack and creates a new local variables frame. - */ - -int ejsOpenBlock(EjsId eid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("localBlock", EJS_OBJ_HASH_SIZE); - - mprCreateProperty(ep->local, "local", ep->local); - - return mprAddToArray(ep->frames, ep->local); -} - -/******************************************************************************/ -/* - * Close a variable scope block opened via ejsOpenBlock. Pop back the old - * local variables frame. - */ - -int ejsCloseBlock(EjsId eid, int fid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - /* - * Must remove self-references before destroying "local" - */ - mprDeleteProperty(ep->local, "local"); - - mprDestroyVar(ep->local); - mprFree(ep->local); - - mprRemoveFromArray(ep->frames, fid); - ep->local = (MprVar*) ep->frames->handles[ep->frames->used - 1]; - - return 0; -} - -/******************************************************************************/ -/* - * Create a new variable scope block and evaluate a script. All frames - * created during this context will be automatically deleted when complete. - * vp and emsg are optional. i.e. created local variables will be discarded - * when this routine returns. - */ - -int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - int rc, fid; - - mprAssert(script); - - fid = ejsOpenBlock(eid); - rc = ejsEvalScript(eid, script, vp, emsg); - ejsCloseBlock(eid, fid); - - return rc; -} - -/******************************************************************************/ -/* - * Parse and evaluate a EJS. Return the result in *vp. The result is "owned" - * by EJ and the caller must not free it. Returns -1 on errors and zero - * for success. On errors, emsg will be set to the reason. The caller must - * free emsg. - */ - -int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - Ejs *ep; - int state; - void *endlessLoopTest; - int loopCounter; - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - mprDestroyVar(&ep->result); - - if (script == 0) { - return 0; - } - - /* - * Allocate a new evaluation block, and save the old one - */ - ejsLexOpenScript(ep, script); - - /* - * Do the actual parsing and evaluation - */ - loopCounter = 0; - endlessLoopTest = NULL; - ep->exitStatus = 0; - - do { - state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); - - if (state == EJS_STATE_RET) { - state = EJS_STATE_EOF; - } - /* - * Stuck parser and endless recursion protection. - */ - if (endlessLoopTest == ep->input->scriptServp) { - if (loopCounter++ > 10) { - state = EJS_STATE_ERR; - ejsError(ep, "Syntax error"); - } - } else { - endlessLoopTest = ep->input->scriptServp; - loopCounter = 0; - } - } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); - - ejsLexCloseScript(ep); - - /* - * Return any error string to the user - */ - if (state == EJS_STATE_ERR && emsg) { - *emsg = mprStrdup(ep->error); - } - - if (state == EJS_STATE_ERR) { - return -1; - } - - if (vp) { - *vp = ep->result; - } - - return ep->exitStatus; -} - -/******************************************************************************/ -/* - * Core error handling - */ - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) - PRINTF_ATTRIBUTE(2, 0); - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) -{ - EjsInput *ip; - char *errbuf, *msgbuf; - int frame = 0; - - mprAssert(ep); - - msgbuf = NULL; - mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); - - ip = ep->input; - mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\nBacktrace:\n", msgbuf); - - /* form a backtrace */ - while (ip) { - char *msg2, *ebuf2; - mprAllocSprintf(&msg2, MPR_MAX_STRING, - "\t[%2d] %20s:%-4d -> %s\n", - frame++, ip->procName?ip->procName:"", ip->lineNumber, ip->line); - ebuf2 = mprRealloc(errbuf, strlen(errbuf) + strlen(msg2) + 1); - if (ebuf2 == NULL) break; - errbuf = ebuf2; - memcpy(errbuf+strlen(errbuf), msg2, strlen(msg2)+1); - mprFree(msg2); - ip = ip->next; - } - mprFree(ep->error); - ep->error = errbuf; - mprFree(msgbuf); -} - -/******************************************************************************/ -/* - * Internal use function to set the error message - */ - -void ejsError(Ejs* ep, const char* fmt, ...) -{ - va_list args; - - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Public routine to set the error message - */ - -void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) -{ - va_list args; - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Get the current line number - */ - -int ejsGetLineNumber(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - return ep->input->lineNumber; -} - -/******************************************************************************/ -/* - * Return the local object - */ - -MprVar *ejsGetLocalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->local; -} - -/******************************************************************************/ -/* - * Return the global object - */ - -MprVar *ejsGetGlobalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->global; -} - -/******************************************************************************/ -/* - * Copy the value of an object property. Return value is in "value". - * If deepCopy is true, copy all object/strings. Otherwise, object reference - * counts are incremented. Callers must always call mprDestroyVar on the - * return value to prevent leaks. - * - * Returns: -1 on errors or if the variable is not found. - */ - -int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool deepCopy) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprCopyProperty(value, vp, deepCopy); -} - -/******************************************************************************/ -/* - * Return the value of an object property. Return value is in "value". - * Objects and strings are not copied and reference counts are not modified. - * Callers should NOT call mprDestroyVar. Returns: -1 on errors or if the - * variable is not found. - */ - -int ejsReadVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprReadProperty(vp, value); -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, EJS_FLAGS_CREATE) < 0) { - return -1; - } - mprAssert(vp); - - /* - * Only copy the value. Don't overwrite the object's name - */ - mprWriteProperty(vp, value); - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVarValue(EjsId eid, const char *var, MprVar value) -{ - return ejsWriteVar(eid, var, &value); -} - -/******************************************************************************/ -/* - * Delete a variable - */ - -int ejsDeleteVar(EjsId eid, const char *var) -{ - Ejs *ep; - MprVar *vp; - MprVar *obj; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - if (ejsGetVarCore(ep, var, &obj, &vp, 0) < 0) { - return -1; - } - mprDeleteProperty(obj, vp->name); - return 0; -} - -/******************************************************************************/ -/* - * Set the expression return value - */ - -void ejsSetReturnValue(EjsId eid, MprVar value) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVar(&ep->result, &value, MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Set the expression return value to a string value - */ - -void ejsSetReturnString(EjsId eid, const char *str) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVarValue(&ep->result, mprCreateStringVar(str, 0), MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Get the expression return value - */ - -MprVar *ejsGetReturnValue(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return &ep->result; -} - -/******************************************************************************/ -/* - * Define a C function. If eid < 0, then update the master object with this - * function. NOTE: in this case, functionName must be simple without any "." or - * "[]" elements. If eid >= 0, add to the specified script engine. In this - * case, functionName can be an arbitrary object reference and can contain "." - * or "[]". - */ - -void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, - void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a C function with String arguments - */ - -void ejsDefineStringCFunction(EjsId eid, const char *functionName, - MprStringCFunction fn, void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a JavaScript function. Args should be comma separated. - * Body should not contain braces. - */ - -void ejsDefineFunction(EjsId eid, const char *functionName, char *args, - char *body) -{ - MprVar v; - - v = mprCreateFunctionVar(args, body, 0); - if (eid < 0) { - ejsLock(); - mprCreateProperty(&master, functionName, &v); - ejsUnlock(); - } else { - ejsWriteVar(eid, functionName, &v); - } - mprDestroyVar(&v); -} - -/******************************************************************************/ - -void *ejsGetThisPtr(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->thisPtr; -} - -/******************************************************************************/ -/* - * Find a variable given a variable name and return the parent object and - * the variable itself, the variable . This routine supports variable names - * that may be objects or arrays but may NOT have expressions in the array - * indicies. Returns -1 on errors or if the variable is not found. - */ - -int ejsGetVarCore(Ejs *ep, const char *vname, MprVar **obj, - MprVar **varValue, int flags) -{ - MprVar *currentObj; - MprVar *currentVar; - char tokBuf[EJS_MAX_ID]; - char *propertyName, *token, *next, *cp, *varName; - - if (obj) { - *obj = 0; - } - if (varValue) { - *varValue = 0; - } - currentObj = ejsFindObj(ep, 0, vname, flags); - currentVar = 0; - propertyName = 0; - - next = varName = mprStrdup(vname); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - while (currentObj != 0 && token != 0 && *token) { - - if (*token == '[') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - propertyName = token; - if (*propertyName == '\"') { - propertyName++; - if ((cp = strchr(propertyName, '\"')) != 0) { - *cp = '\0'; - } - } else if (*propertyName == '\'') { - propertyName++; - if ((cp = strchr(propertyName, '\'')) != 0) { - *cp = '\0'; - } - } - - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, propertyName, 0); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (*token != ']') { - mprFree(varName); - return -1; - } - - } else if (*token == '.') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (!isalpha((int) token[0]) && - token[0] != '_' && token[0] != '$') { - mprFree(varName); - return -1; - } - - propertyName = token; - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - - } else { - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - } - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - } - mprFree(varName); - - if (currentVar == 0 && currentObj >= 0 && flags & EJS_FLAGS_CREATE) { - currentVar = mprCreatePropertyValue(currentObj, propertyName, - mprCreateUndefinedVar()); - } - if (obj) { - *obj = currentObj; - } - - /* - * Don't use mprCopyVar as it will copy the data - */ - if (varValue) { - *varValue = currentVar; - } - return currentVar ? 0 : -1; -} - -/******************************************************************************/ -/* - * Get the next token as part of a variable specification. This will return - * a pointer to the next token and will return a pointer to the next token - * (after this one) in "next". The tokBuf holds the parsed token. - */ -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) -{ - char *start, *cp; - int len; - - start = *next; - while (isspace((int) *start) || *start == '\n' || *start == '\r') { - start++; - } - cp = start; - - if (*cp == '.' || *cp == '[' || *cp == ']') { - cp++; - } else { - while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && - !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { - cp++; - } - } - len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); - tokBuf[len] = '\0'; - - *next = cp; - return tokBuf; -} - -/******************************************************************************/ -/* - * Get the EJS structure pointer - */ - -Ejs *ejsPtr(EjsId eid) -{ - Ejs *handle; - int intId; - - intId = (int) eid; - - ejsLock(); - mprAssert(0 <= intId && intId < ejsList->max); - - if (intId < 0 || intId >= ejsList->max || ejsList->handles[intId] == NULL) { - mprAssert(0); - ejsUnlock(); - return NULL; - } - handle = ejsList->handles[intId]; - ejsUnlock(); - return handle; -} - -/******************************************************************************/ -/* - * Utility routine to crack JavaScript arguments. Return the number of args - * seen. This routine only supports %s and %d type args. - * - * Typical usage: - * - * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { - * mprError("Insufficient args\n"); - * return -1; - * } - */ - -int ejsParseArgs(int argc, char **argv, char *fmt, ...) -{ - va_list vargs; - bool *bp; - char *cp, **sp, *s; - int *ip, argn; - - va_start(vargs, fmt); - - if (argv == 0) { - return 0; - } - - for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { - if (*cp++ != '%') { - continue; - } - - s = argv[argn]; - switch (*cp) { - case 'b': - bp = va_arg(vargs, bool*); - if (bp) { - if (strcmp(s, "true") == 0 || s[0] == '1') { - *bp = 1; - } else { - *bp = 0; - } - } else { - *bp = 0; - } - break; - - case 'd': - ip = va_arg(vargs, int*); - *ip = atoi(s); - break; - - case 's': - sp = va_arg(vargs, char**); - *sp = s; - break; - - default: - mprAssert(0); - } - argn++; - } - - va_end(vargs); - return argn; -} - -/******************************************************************************/ - -#else -void ejsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c deleted file mode 100644 index da922a5728..0000000000 --- a/source4/lib/appweb/ejs/ejsParser.c +++ /dev/null @@ -1,2436 +0,0 @@ -/* - * @file ejsParser.c - * @brief EJS Parser and Execution - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static void appendValue(MprVar *v1, MprVar *v2); -static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -#if BLD_FEATURE_FLOATING_POINT -static int evalFloatExpr(Ejs *ep, double l, int rel, double r); -#endif -static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r); -static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r); -static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r); -static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -static int evalFunction(Ejs *ep, MprVar *obj, int flags); -static void freeProc(EjsProc *proc); -static int parseArgs(Ejs *ep, int state, int flags); -static int parseAssignment(Ejs *ep, int state, int flags, char *id, - char *fullName); -static int parseCond(Ejs *ep, int state, int flags); -static int parseDeclaration(Ejs *ep, int state, int flags); -static int parseExpr(Ejs *ep, int state, int flags); -static int parseFor(Ejs *ep, int state, int flags); -static int parseForIn(Ejs *ep, int state, int flags); -static int parseFunctionDec(Ejs *ep, int state, int flags); -static int parseFunction(Ejs *ep, int state, int flags, char *id); -static int parseId(Ejs *ep, int state, int flags, char **id, - char **fullName, int *fullNameLen, int *done); -static int parseInc(Ejs *ep, int state, int flags); -static int parseIf(Ejs *ep, int state, int flags, int *done); -static int parseStmt(Ejs *ep, int state, int flags); -static void removeNewlines(Ejs *ep, int state); -static void updateResult(Ejs *ep, int state, int flags, MprVar *vp); - -/************************************* Code ***********************************/ -/* - * Recursive descent parser for EJS - */ - -int ejsParse(Ejs *ep, int state, int flags) -{ - mprAssert(ep); - - switch (state) { - /* - * Any statement, function arguments or conditional expressions - */ - case EJS_STATE_STMT: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_STMT_DONE && - state != EJS_STATE_EOF && state != EJS_STATE_STMT_BLOCK_DONE && - state != EJS_STATE_RET) { - state = EJS_STATE_ERR; - } - break; - - case EJS_STATE_DEC: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_DEC_DONE && - state != EJS_STATE_EOF) { - state = EJS_STATE_ERR; - } - break; - - case EJS_STATE_EXPR: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_EXPR_DONE && - state != EJS_STATE_EOF) { - state = EJS_STATE_ERR; - } - break; - - /* - * Variable declaration list - */ - case EJS_STATE_DEC_LIST: - state = parseDeclaration(ep, state, flags); - break; - - /* - * Function argument string - */ - case EJS_STATE_ARG_LIST: - state = parseArgs(ep, state, flags); - break; - - /* - * Logical condition list (relational operations separated by &&, ||) - */ - case EJS_STATE_COND: - state = parseCond(ep, state, flags); - break; - - /* - * Expression list - */ - case EJS_STATE_RELEXP: - state = parseExpr(ep, state, flags); - break; - } - - if (state == EJS_STATE_ERR && ep->error == NULL) { - ejsError(ep, "Syntax error"); - } - return state; -} - -/******************************************************************************/ -/* - * Parse any statement including functions and simple relational operations - */ - -static int parseStmt(Ejs *ep, int state, int flags) -{ - EjsProc *saveProc; - MprVar *vp, *saveObj; - char *id, *fullName, *initToken; - int done, expectSemi, tid, fullNameLen, rel; - int initId; - - mprAssert(ep); - - expectSemi = 0; - saveProc = NULL; - id = 0; - fullName = 0; - fullNameLen = 0; - - ep->currentObj = 0; - ep->currentProperty = 0; - - for (done = 0; !done && state != EJS_STATE_ERR; ) { - tid = ejsLexGetToken(ep, state); - - switch (tid) { - default: - ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); - done++; - break; - - case EJS_TOK_EXPR: - rel = (int) *ep->token; - if (state == EJS_STATE_EXPR) { - ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); - } - done++; - break; - - case EJS_TOK_LOGICAL: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_ERR: - state = EJS_STATE_ERR; - done++; - break; - - case EJS_TOK_EOF: - state = EJS_STATE_EOF; - done++; - break; - - case EJS_TOK_NEWLINE: - break; - - case EJS_TOK_SEMI: - /* - * This case is when we discover no statement and just a lone ';' - */ - if (state != EJS_STATE_STMT) { - ejsLexPutbackToken(ep, tid, ep->token); - } - done++; - break; - - case EJS_TOK_PERIOD: - if (flags & EJS_FLAGS_EXE) { - if (ep->currentProperty == 0) { - ejsError(ep, "Undefined object \"%s\"\n", id); - goto error; - } - } - ep->currentObj = ep->currentProperty; - - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - ejsError(ep, "Bad property after '.': %s\n", ep->token); - goto error; - } - mprFree(id); - id = mprStrdup(ep->token); - - vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); - updateResult(ep, state, flags, vp); - -#if BLD_DEBUG - fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen, - 0, ".", NULL); -#endif - - ep->currentProperty = vp; - ejsLexPutbackToken(ep, tid, ep->token); - break; - - case EJS_TOK_LBRACKET: - ep->currentObj = ep->currentProperty; - saveObj = ep->currentObj; - if (ejsParse(ep, EJS_STATE_RELEXP, flags) != EJS_STATE_RELEXP_DONE){ - goto error; - } - ep->currentObj = saveObj; - - mprFree(id); - mprVarToString(&id, MPR_MAX_STRING, 0, &ep->result); - - if (id[0] == '\0') { - if (flags & EJS_FLAGS_EXE) { - ejsError(ep, - "[] expression evaluates to the empty string\n"); - goto error; - } - } else { - vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); - ep->currentProperty = vp; - updateResult(ep, state, flags, vp); - } - -#if BLD_DEBUG - if (id[0] && strlen(id) < (MPR_MAX_VAR / 2)) { - /* - * If not executing yet, id may not be known - */ - fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, - fullNameLen, 0, "[", id, "]", NULL); - } -#endif - - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_RBRACKET) { - ejsError(ep, "Missing ']'\n"); - goto error; - } - break; - - case EJS_TOK_ID: - state = parseId(ep, state, flags, &id, &fullName, &fullNameLen, - &done); - if (done && state == EJS_STATE_STMT) { - expectSemi++; - } - break; - - case EJS_TOK_ASSIGNMENT: - state = parseAssignment(ep, state, flags, id, fullName); - if (state == EJS_STATE_STMT) { - expectSemi++; - done++; - } - break; - - case EJS_TOK_INC_DEC: - state = parseInc(ep, state, flags); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - break; - - case EJS_TOK_NEW: - if (ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_NEW) - != EJS_STATE_EXPR_DONE) { - goto error; - } - break; - - case EJS_TOK_DELETE: - if (ejsParse(ep, EJS_STATE_EXPR, - flags | EJS_FLAGS_DELETE) != EJS_STATE_EXPR_DONE) { - goto error; - } - if (flags & EJS_FLAGS_EXE) { - mprDeleteProperty(ep->currentObj, ep->currentProperty->name); - } - done++; - break; - - case EJS_TOK_FUNCTION: - state = parseFunctionDec(ep, state, flags); - done++; - break; - - case EJS_TOK_LITERAL: - /* - * Set the result to the string literal - */ - mprCopyVarValue(&ep->result, mprCreateStringVar(ep->token, 0), - MPR_SHALLOW_COPY); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - done++; - break; - - case EJS_TOK_NUMBER: - /* - * Set the result to the parsed number - */ - mprCopyVar(&ep->result, &ep->tokenNumber, 0); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - done++; - break; - - case EJS_TOK_FUNCTION_NAME: - state = parseFunction(ep, state, flags, id); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - if (ep->flags & EJS_FLAGS_EXIT) { - state = EJS_STATE_RET; - } - done++; - break; - - case EJS_TOK_IF: - state = parseIf(ep, state, flags, &done); - if (state == EJS_STATE_RET) { - goto doneParse; - } - break; - - case EJS_TOK_FOR: - if (state != EJS_STATE_STMT) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { - goto error; - } - /* - * Need to peek 2-3 tokens ahead and see if this is a - * for ([var] x in set) - * or - * for (init ; whileCond; incr) - */ - initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - if (initId == EJS_TOK_ID && strcmp(ep->token, "var") == 0) { - /* Simply eat var tokens */ - initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - } - initToken = mprStrdup(ep->token); - - tid = ejsLexGetToken(ep, EJS_STATE_EXPR); - - ejsLexPutbackToken(ep, tid, ep->token); - ejsLexPutbackToken(ep, initId, initToken); - mprFree(initToken); - - if (tid == EJS_TOK_IN) { - if ((state = parseForIn(ep, state, flags)) < 0) { - goto error; - } - } else { - if ((state = parseFor(ep, state, flags)) < 0) { - goto error; - } - } - done++; - break; - - case EJS_TOK_VAR: - if (ejsParse(ep, EJS_STATE_DEC_LIST, flags) - != EJS_STATE_DEC_LIST_DONE) { - goto error; - } - done++; - break; - - case EJS_TOK_COMMA: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_LPAREN: - if (state == EJS_STATE_EXPR) { - if (ejsParse(ep, EJS_STATE_RELEXP, flags) - != EJS_STATE_RELEXP_DONE) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - goto error; - } - } - done++; - break; - - case EJS_TOK_RPAREN: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_LBRACE: - /* - * This handles any code in braces except "if () {} else {}" - */ - if (state != EJS_STATE_STMT) { - goto error; - } - - /* - * Parse will return EJS_STATE_STMT_BLOCK_DONE when the RBRACE - * is seen. - */ - do { - state = ejsParse(ep, EJS_STATE_STMT, flags); - } while (state == EJS_STATE_STMT_DONE); - - if (state != EJS_STATE_RET) { - if (ejsLexGetToken(ep, state) != EJS_TOK_RBRACE) { - goto error; - } - state = EJS_STATE_STMT_DONE; - } - done++; - break; - - case EJS_TOK_RBRACE: - if (state == EJS_STATE_STMT) { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_STMT_BLOCK_DONE; - done++; - break; - } - goto error; - - case EJS_TOK_RETURN: - if (ejsParse(ep, EJS_STATE_RELEXP, flags) - != EJS_STATE_RELEXP_DONE) { - goto error; - } - if (flags & EJS_FLAGS_EXE) { - while (ejsLexGetToken(ep, state) != EJS_TOK_EOF) { - ; - } - state = EJS_STATE_RET; - done++; - } - break; - } - } - - if (expectSemi) { - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_SEMI && tid != EJS_TOK_NEWLINE && - tid != EJS_TOK_EOF) { - goto error; - } - - /* - * Skip newline after semi-colon - */ - removeNewlines(ep, state); - } - -/* - * Free resources and return the correct status - */ -doneParse: - mprFree(id); - mprFree(fullName); - - /* - * Advance the state - */ - switch (state) { - case EJS_STATE_STMT: - return EJS_STATE_STMT_DONE; - - case EJS_STATE_DEC: - return EJS_STATE_DEC_DONE; - - case EJS_STATE_EXPR: - return EJS_STATE_EXPR_DONE; - - case EJS_STATE_STMT_DONE: - case EJS_STATE_STMT_BLOCK_DONE: - case EJS_STATE_EOF: - case EJS_STATE_RET: - return state; - - default: - return EJS_STATE_ERR; - } - -/* - * Common error exit - */ -error: - state = EJS_STATE_ERR; - goto doneParse; -} - -/******************************************************************************/ -/* - * Parse function arguments - */ - -static int parseArgs(Ejs *ep, int state, int flags) -{ - int tid; - - mprAssert(ep); - - do { - /* - * Peek and see if there are no args - */ - tid = ejsLexGetToken(ep, state); - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RPAREN) { - break; - } - - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state == EJS_STATE_EOF || state == EJS_STATE_ERR) { - return state; - } - if (state == EJS_STATE_RELEXP_DONE) { - if (flags & EJS_FLAGS_EXE) { - mprAssert(ep->proc->args); - mprAddToArray(ep->proc->args, - mprDupVar(&ep->result, MPR_SHALLOW_COPY)); - } - } - /* - * Peek at the next token, continue if more args (ie. comma seen) - */ - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_COMMA) { - ejsLexPutbackToken(ep, tid, ep->token); - } - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_RPAREN && state != EJS_STATE_RELEXP_DONE) { - return EJS_STATE_ERR; - } - return EJS_STATE_ARG_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse an assignment statement - */ - -static int parseAssignment(Ejs *ep, int state, int flags, char *id, - char *fullName) -{ - MprVar *vp, *saveProperty, *saveObj; - - if (id == 0) { - return -1; - } - - saveObj = ep->currentObj; - saveProperty = ep->currentProperty; - if (ejsParse(ep, EJS_STATE_RELEXP, flags | EJS_FLAGS_ASSIGNMENT) - != EJS_STATE_RELEXP_DONE) { - return -1; - } - ep->currentObj = saveObj; - ep->currentProperty = saveProperty; - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - if (ep->currentProperty) { - /* - * Update the variable. Update the property name if not - * yet defined. - */ - if (ep->currentProperty->name == 0 || - ep->currentProperty->name[0] == '\0') { - mprSetVarName(ep->currentProperty, id); - } - if (mprWriteProperty(ep->currentProperty, &ep->result) < 0){ - ejsError(ep, "Can't write to variable\n"); - return -1; - } - - } else { - /* - * Create the variable - */ - if (ep->currentObj) { - if (ep->currentObj->type != MPR_TYPE_OBJECT) { - if (strcmp(ep->currentObj->name, "session") == 0) { - ejsError(ep, "Variable \"%s\" is not an array or object." - "If using ESP, you need useSession(); in your page.", - ep->currentObj->name); - } else { - ejsError(ep, "Variable \"%s\" is not an array or object", - ep->currentObj->name); - } - return -1; - } - vp = mprCreateProperty(ep->currentObj, id, &ep->result); - - } else { - /* - * Standard says: "var x" means declare locally. - * "x = 2" means declare globally if x is undefined. - */ - if (state == EJS_STATE_DEC) { - vp = mprCreateProperty(ep->local, id, &ep->result); - } else { - vp = mprCreateProperty(ep->global, id, &ep->result); - } - } -#if BLD_DEBUG - mprSetVarFullName(vp, fullName); -#endif - } - return state; -} - -/******************************************************************************/ -/* - * Parse conditional expression (relational ops separated by ||, &&) - */ - -static int parseCond(Ejs *ep, int state, int flags) -{ - MprVar lhs, rhs; - int tid, operator; - - mprAssert(ep); - - mprDestroyVar(&ep->result); - rhs = lhs = mprCreateUndefinedVar(); - operator = 0; - - do { - /* - * Recurse to handle one side of a conditional. Accumulate the - * left hand side and the final result in ep->result. - */ - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state != EJS_STATE_RELEXP_DONE) { - state = EJS_STATE_ERR; - break; - } - - if (operator > 0) { - mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); - if (evalCond(ep, &lhs, operator, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } - mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_LOGICAL) { - operator = (int) *ep->token; - - } else if (tid == EJS_TOK_RPAREN || tid == EJS_TOK_SEMI) { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_COND_DONE; - break; - - } else { - ejsLexPutbackToken(ep, tid, ep->token); - } - tid = (state == EJS_STATE_RELEXP_DONE); - - } while (state == EJS_STATE_RELEXP_DONE); - - mprDestroyVar(&lhs); - mprDestroyVar(&rhs); - return state; -} - -/******************************************************************************/ -/* - * Parse variable declaration list. Declarations can be of the following forms: - * var x; - * var x, y, z; - * var x = 1 + 2 / 3, y = 2 + 4; - * - * We set the variable to NULL if there is no associated assignment. - */ - -static int parseDeclaration(Ejs *ep, int state, int flags) -{ - int tid; - - mprAssert(ep); - - do { - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - return EJS_STATE_ERR; - } - ejsLexPutbackToken(ep, tid, ep->token); - - /* - * Parse the entire assignment or simple identifier declaration - */ - if (ejsParse(ep, EJS_STATE_DEC, flags) != EJS_STATE_DEC_DONE) { - return EJS_STATE_ERR; - } - - /* - * Peek at the next token, continue if comma seen - */ - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_SEMI) { - return EJS_STATE_DEC_LIST_DONE; - } else if (tid != EJS_TOK_COMMA) { - return EJS_STATE_ERR; - } - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_SEMI) { - return EJS_STATE_ERR; - } - return EJS_STATE_DEC_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse expression (leftHandSide operator rightHandSide) - */ - -static int parseExpr(Ejs *ep, int state, int flags) -{ - MprVar lhs, rhs; - int rel, tid; - - mprAssert(ep); - - mprDestroyVar(&ep->result); - rhs = lhs = mprCreateUndefinedVar(); - rel = 0; - tid = 0; - - do { - /* - * This loop will handle an entire expression list. We call parse - * to evalutate each term which returns the result in ep->result. - */ - if (tid == EJS_TOK_LOGICAL) { - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state != EJS_STATE_RELEXP_DONE) { - state = EJS_STATE_ERR; - break; - } - } else { - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_EXPR && (int) *ep->token == EJS_EXPR_MINUS) { - lhs = mprCreateIntegerVar(0); - rel = (int) *ep->token; - } else { - ejsLexPutbackToken(ep, tid, ep->token); - } - - state = ejsParse(ep, EJS_STATE_EXPR, flags); - if (state != EJS_STATE_EXPR_DONE) { - state = EJS_STATE_ERR; - break; - } - } - - if (rel > 0) { - mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); - if (tid == EJS_TOK_LOGICAL) { - if (evalCond(ep, &lhs, rel, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } else { - if (evalExpr(ep, &lhs, rel, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } - } - mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); - - if ((tid = ejsLexGetToken(ep, state)) == EJS_TOK_EXPR || - tid == EJS_TOK_INC_DEC || tid == EJS_TOK_LOGICAL) { - rel = (int) *ep->token; - - } else { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_RELEXP_DONE; - } - - } while (state == EJS_STATE_EXPR_DONE); - - mprDestroyVar(&lhs); - mprDestroyVar(&rhs); - - return state; -} - -/******************************************************************************/ -/* - * Parse the "for ... in" statement. Format for the statement is: - * - * for (var in expr) { - * body; - * } - */ - -static int parseForIn(Ejs *ep, int state, int flags) -{ - EjsInput endScript, bodyScript; - MprVar *iteratorVar, *setVar, *vp, v; - int forFlags, tid; - - mprAssert(ep); - - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ID) { - return -1; - } - ejsLexPutbackToken(ep, tid, ep->token); - - if (ejsParse(ep, EJS_STATE_EXPR, EJS_FLAGS_FOREACH | EJS_FLAGS_EXE) - != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ep->currentProperty == 0) { - return -1; - } - iteratorVar = ep->currentProperty; - - if (ejsLexGetToken(ep, state) != EJS_TOK_IN) { - return -1; - } - - /* - * Get the set - */ - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ID) { - return -1; - } - ejsLexPutbackToken(ep, tid, ep->token); - - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ep->currentProperty == 0 && flags & EJS_FLAGS_EXE) { - return -1; - } - setVar = ep->currentProperty; - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - - /* - * Parse the body and remember the end of the body script - */ - forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &bodyScript); - if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - ejsInitInputState(&endScript); - ejsLexSaveInputState(ep, &endScript); - - /* - * Now actually do the for loop. - */ - if (flags & EJS_FLAGS_EXE) { - if (setVar->type == MPR_TYPE_OBJECT) { - vp = mprGetFirstProperty(setVar, MPR_ENUM_DATA); - while (vp) { - if (strcmp(vp->name, "length") != 0) { - v = mprCreateStringVar(vp->name, 0); - if (mprWriteProperty(iteratorVar, &v) < 0) { - ejsError(ep, "Can't write to variable\n"); - ejsLexFreeInputState(ep, &bodyScript); - ejsLexFreeInputState(ep, &endScript); - return -1; - } - - ejsLexRestoreInputState(ep, &bodyScript); - switch (ejsParse(ep, EJS_STATE_STMT, flags)) { - case EJS_STATE_RET: - return EJS_STATE_RET; - case EJS_STATE_STMT_DONE: - break; - default: - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - } - vp = mprGetNextProperty(setVar, vp, MPR_ENUM_DATA); - } - } else { - ejsError(ep, "Variable \"%s\" is not an array or object", - setVar->name); - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - } - ejsLexRestoreInputState(ep, &endScript); - - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - - return state; -} - -/******************************************************************************/ -/* - * Parse the for statement. Format for the expression is: - * - * for (initial; condition; incr) { - * body; - * } - */ - -static int parseFor(Ejs *ep, int state, int flags) -{ - EjsInput condScript, endScript, bodyScript, incrScript; - int forFlags, cond; - - ejsInitInputState(&endScript); - ejsInitInputState(&bodyScript); - ejsInitInputState(&incrScript); - ejsInitInputState(&condScript); - - mprAssert(ep); - - /* - * Evaluate the for loop initialization statement - */ - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { - return -1; - } - - /* - * The first time through, we save the current input context just prior - * to each step: prior to the conditional, the loop increment and - * the loop body. - */ - ejsLexSaveInputState(ep, &condScript); - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - goto error; - } - cond = (ep->result.boolean != 0); - - if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { - goto error; - } - - /* - * Don't execute the loop increment statement or the body - * first time. - */ - forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &incrScript); - if (ejsParse(ep, EJS_STATE_EXPR, forFlags) != EJS_STATE_EXPR_DONE) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - goto error; - } - - /* - * Parse the body and remember the end of the body script - */ - ejsLexSaveInputState(ep, &bodyScript); - if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { - goto error; - } - ejsLexSaveInputState(ep, &endScript); - - /* - * Now actually do the for loop. Note loop has been rotated - */ - while (cond && (flags & EJS_FLAGS_EXE)) { - /* - * Evaluate the body - */ - ejsLexRestoreInputState(ep, &bodyScript); - - switch (ejsParse(ep, EJS_STATE_STMT, flags)) { - case EJS_STATE_RET: - return EJS_STATE_RET; - case EJS_STATE_STMT_DONE: - break; - default: - goto error; - } - /* - * Evaluate the increment script - */ - ejsLexRestoreInputState(ep, &incrScript); - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE){ - goto error; - } - /* - * Evaluate the condition - */ - ejsLexRestoreInputState(ep, &condScript); - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - goto error; - } - mprAssert(ep->result.type == MPR_TYPE_BOOL); - cond = (ep->result.boolean != 0); - } - - ejsLexRestoreInputState(ep, &endScript); - -done: - ejsLexFreeInputState(ep, &condScript); - ejsLexFreeInputState(ep, &incrScript); - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return state; - -error: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse a function declaration - */ - -static int parseFunctionDec(Ejs *ep, int state, int flags) -{ - EjsInput endScript, bodyScript; - MprVar v, *currentObj, *vp; - char *procName; - int len, tid, bodyFlags; - - mprAssert(ep); - mprAssert(ejsPtr(ep->eid)); - - /* - * function <name>(arg, arg, arg) { body }; - * function name(arg, arg, arg) { body }; - */ - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_ID) { - procName = mprStrdup(ep->token); - tid = ejsLexGetToken(ep, state); - } else { - procName = 0; - } - if (tid != EJS_TOK_LPAREN) { - mprFree(procName); - return EJS_STATE_ERR; - } - - /* - * Hand craft the function value structure. - */ - v = mprCreateFunctionVar(0, 0, 0); - tid = ejsLexGetToken(ep, state); - while (tid == EJS_TOK_ID) { - mprAddToArray(v.function.args, mprStrdup(ep->token)); - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_RPAREN || tid != EJS_TOK_COMMA) { - break; - } - tid = ejsLexGetToken(ep, state); - } - if (tid != EJS_TOK_RPAREN) { - mprFree(procName); - mprDestroyVar(&v); - return EJS_STATE_ERR; - } - - /* Allow new lines before opening brace */ - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - if (tid != EJS_TOK_LBRACE) { - mprFree(procName); - mprDestroyVar(&v); - return EJS_STATE_ERR; - } - - /* - * Register the function name early to allow for recursive - * function calls (see note in ECMA standard, page 71) - */ - if (!(flags & EJS_FLAGS_ASSIGNMENT)) { - currentObj = ejsFindObj(ep, 0, procName, flags); - vp = mprSetProperty(currentObj, procName, &v); - } - - /* - * Parse the function body. Turn execute off. - */ - bodyFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &bodyScript); - - do { - state = ejsParse(ep, EJS_STATE_STMT, bodyFlags); - } while (state == EJS_STATE_STMT_DONE); - - tid = ejsLexGetToken(ep, state); - if (state != EJS_STATE_STMT_BLOCK_DONE || tid != EJS_TOK_RBRACE) { - mprFree(procName); - mprDestroyVar(&v); - ejsLexFreeInputState(ep, &bodyScript); - return EJS_STATE_ERR; - } - ejsLexSaveInputState(ep, &endScript); - - /* - * Save the function body between the starting and ending parse positions. - * Overwrite the trailing '}' with a null. - */ - len = endScript.scriptServp - bodyScript.scriptServp; - v.function.body = mprMalloc(len + 1); - memcpy(v.function.body, bodyScript.scriptServp, len); - - if (len <= 0) { - v.function.body[0] = '\0'; - } else { - v.function.body[len - 1] = '\0'; - } - ejsLexFreeInputState(ep, &bodyScript); - ejsLexFreeInputState(ep, &endScript); - - /* - * If we are in an assignment, don't register the function name, rather - * return the function structure in the parser result. - */ - if (flags & EJS_FLAGS_ASSIGNMENT) { - mprCopyVar(&ep->result, &v, MPR_SHALLOW_COPY); - } else { - currentObj = ejsFindObj(ep, 0, procName, flags); - vp = mprSetProperty(currentObj, procName, &v); - } - - mprFree(procName); - mprDestroyVar(&v); - - return EJS_STATE_STMT; -} - -/******************************************************************************/ -/* - * Parse a function name and invoke the function - */ - -static int parseFunction(Ejs *ep, int state, int flags, char *id) -{ - EjsProc proc, *saveProc; - MprVar *saveObj; - - /* - * Must save any current ep->proc value for the current stack frame - * to allow for recursive function calls. - */ - saveProc = (ep->proc) ? ep->proc: 0; - - memset(&proc, 0, sizeof(EjsProc)); - proc.procName = mprStrdup(id); - proc.fn = ep->currentProperty; - proc.args = mprCreateArray(); - ep->proc = &proc; - - mprDestroyVar(&ep->result); - - saveObj = ep->currentObj; - if (ejsParse(ep, EJS_STATE_ARG_LIST, flags) != EJS_STATE_ARG_LIST_DONE) { - freeProc(&proc); - ep->proc = saveProc; - return -1; - } - ep->currentObj = saveObj; - - /* - * Evaluate the function if required - */ - if (flags & EJS_FLAGS_EXE) { - if (evalFunction(ep, ep->currentObj, flags) < 0) { - freeProc(&proc); - ep->proc = saveProc; - return -1; - } - } - - freeProc(&proc); - ep->proc = saveProc; - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - return state; -} - -/******************************************************************************/ -/* - * Parse an identifier. This is a segment of a fully qualified variable. - * May come here for an initial identifier or for property names - * after a "." or "[...]". - */ - -static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, - int *fullNameLen, int *done) -{ - int tid; - - mprFree(*id); - *id = mprStrdup(ep->token); -#if BLD_DEBUG - *fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen, - 0, *id, NULL); -#endif - if (ep->currentObj == 0) { - ep->currentObj = ejsFindObj(ep, state, *id, flags); - } - - /* - * Find the referenced variable and store it in currentProperty. - */ - ep->currentProperty = ejsFindProperty(ep, state, ep->currentObj, - *id, flags); - updateResult(ep, state, flags, ep->currentProperty); - -#if BLD_DEBUG - if (ep->currentProperty && (ep->currentProperty->name == 0 || - ep->currentProperty->name[0] == '\0')) { - mprSetVarName(ep->currentProperty, *id); - } -#endif - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_LPAREN) { - if (ep->currentProperty == 0 && (flags & EJS_FLAGS_EXE)) { - ejsError(ep, "Function name not defined \"%s\"\n", *id); - return -1; - } - ejsLexPutbackToken(ep, EJS_TOK_FUNCTION_NAME, ep->token); - return state; - } - - if (tid == EJS_TOK_PERIOD || tid == EJS_TOK_LBRACKET || - tid == EJS_TOK_ASSIGNMENT || tid == EJS_TOK_INC_DEC) { - ejsLexPutbackToken(ep, tid, ep->token); - return state; - } - - /* - * Only come here for variable access and declarations. - * Assignment handled elsewhere. - */ - if (flags & EJS_FLAGS_EXE) { - if (state == EJS_STATE_DEC) { - /* - * Declare a variable. Standard allows: var x ; var x ; - */ -#if DISABLED - if (ep->currentProperty != 0) { - ejsError(ep, "Variable already defined \"%s\"\n", *id); - return -1; - } -#endif - /* - * Create or overwrite if it already exists - */ - mprSetPropertyValue(ep->currentObj, *id, - mprCreateUndefinedVar()); - ep->currentProperty = 0; - mprDestroyVar(&ep->result); - - } else if (flags & EJS_FLAGS_FOREACH) { - if (ep->currentProperty == 0) { - ep->currentProperty = - mprCreatePropertyValue(ep->currentObj, *id, - mprCreateUndefinedVar()); - } - - } else { - if (ep->currentProperty == 0) { - if (ep->currentObj == ep->global || - ep->currentObj == ep->local) { - ejsError(ep, "Undefined variable \"%s\"\n", *id); - return -1; - } - ep->currentProperty = mprCreatePropertyValue(ep->currentObj, - *id, mprCreateUndefinedVar()); - } - } - } - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RBRACKET || tid == EJS_TOK_COMMA || - tid == EJS_TOK_IN) { - *done = 1; - } - return state; -} - -/******************************************************************************/ -/* - * Parse an "if" statement - */ - -static int parseIf(Ejs *ep, int state, int flags, int *done) -{ - bool ifResult; - int thenFlags, elseFlags, tid; - - if (state != EJS_STATE_STMT) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { - return -1; - } - - /* - * Evaluate the entire condition list "(condition)" - */ - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - - /* - * This is the "then" case. We need to always parse both cases and - * execute only the relevant case. - */ - ifResult = mprVarToBool(&ep->result); - if (ifResult) { - thenFlags = flags; - elseFlags = flags & ~EJS_FLAGS_EXE; - } else { - thenFlags = flags & ~EJS_FLAGS_EXE; - elseFlags = flags; - } - - /* - * Process the "then" case. - */ - switch (ejsParse(ep, EJS_STATE_STMT, thenFlags)) { - case EJS_STATE_RET: - state = EJS_STATE_RET; - return state; - case EJS_STATE_STMT_DONE: - break; - default: - return -1; - } - - /* - * Check to see if there is an "else" case - */ - removeNewlines(ep, state); - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ELSE) { - ejsLexPutbackToken(ep, tid, ep->token); - *done = 1; - return state; - } - - /* - * Process the "else" case. - */ - switch (ejsParse(ep, EJS_STATE_STMT, elseFlags)) { - case EJS_STATE_RET: - state = EJS_STATE_RET; - return state; - case EJS_STATE_STMT_DONE: - break; - default: - return -1; - } - *done = 1; - return state; -} - -/******************************************************************************/ -/* - * Parse an "++" or "--" statement - */ - -static int parseInc(Ejs *ep, int state, int flags) -{ - MprVar one; - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - if (ep->currentProperty == 0) { - ejsError(ep, "Undefined variable \"%s\"\n", ep->token); - return -1; - } - one = mprCreateIntegerVar(1); - if (evalExpr(ep, ep->currentProperty, (int) *ep->token, - &one) < 0) { - return -1; - } - if (mprWriteProperty(ep->currentProperty, &ep->result) < 0) { - ejsError(ep, "Can't write to variable\n"); - return -1; - } - return state; -} - -/******************************************************************************/ -/* - * Evaluate a condition. Implements &&, ||, !. Returns with a boolean result - * in ep->result. Returns -1 on errors, zero if successful. - */ - -static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - bool l, r, lval; - - mprAssert(rel > 0); - - l = mprVarToBool(lhs); - r = mprVarToBool(rhs); - - switch (rel) { - case EJS_COND_AND: - lval = l && r; - break; - case EJS_COND_OR: - lval = l || r; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - - -/* - return true if this string is a valid number -*/ -static int string_is_number(const char *s) -{ - char *endptr = NULL; - if (s == NULL || *s == 0) { - return 0; - } - strtod(s, &endptr); - if (endptr != NULL && *endptr == 0) { - return 1; - } - return 0; -} - -/******************************************************************************/ -/* - * Evaluate an operation. Returns with the result in ep->result. Returns -1 - * on errors, otherwise zero is returned. - */ - -static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - char *str; - MprNum lval, num; - int rc; - - mprAssert(rel > 0); - str = 0; - lval = 0; - - /* - * Type conversion. This is tricky and must be according to the standard. - * Only numbers (including floats) and strings can be compared. All other - * types are first converted to numbers by preference and if that fails, - * to strings. - * - * First convert objects to comparable types. The "===" operator will - * test the sameness of object references. Here, we coerce to comparable - * types first. - */ - if (lhs->type == MPR_TYPE_OBJECT) { - if (ejsRunFunction(ep->eid, lhs, "toValue", 0) == 0) { - mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); - } else { - if (ejsRunFunction(ep->eid, lhs, "toString", 0) == 0) { - mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); - } - } - /* Nothing more can be done */ - } - - if (rhs->type == MPR_TYPE_OBJECT) { - if (ejsRunFunction(ep->eid, rhs, "toValue", 0) == 0) { - mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); - } else { - if (ejsRunFunction(ep->eid, rhs, "toString", 0) == 0) { - mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); - } - } - /* Nothing more can be done */ - } - - /* undefined and null are special, in that they don't get promoted when - comparing */ - if (rel == EJS_EXPR_EQ || rel == EJS_EXPR_NOTEQ) { - if (lhs->type == MPR_TYPE_UNDEFINED || rhs->type == MPR_TYPE_UNDEFINED) { - return evalBoolExpr(ep, - lhs->type == MPR_TYPE_UNDEFINED, - rel, - rhs->type == MPR_TYPE_UNDEFINED); - } - - if (lhs->type == MPR_TYPE_NULL || rhs->type == MPR_TYPE_NULL) { - return evalBoolExpr(ep, - lhs->type == MPR_TYPE_NULL, - rel, - rhs->type == MPR_TYPE_NULL); - } - } - - /* - * From here on, lhs and rhs may contain allocated data (strings), so - * we must always destroy before overwriting. - */ - - /* - * Only allow a few bool operations. Otherwise convert to number. - */ - if (lhs->type == MPR_TYPE_BOOL && rhs->type == MPR_TYPE_BOOL && - (rel != EJS_EXPR_EQ && rel != EJS_EXPR_NOTEQ && - rel != EJS_EXPR_BOOL_COMP)) { - num = mprVarToNumber(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - } - - /* - * Types do not match, so try to coerce the right operand to match the left - * But first, try to convert a left operand that is a numeric stored as a - * string, into a numeric. - */ - if (lhs->type != rhs->type) { - if (lhs->type == MPR_TYPE_STRING) { - if (string_is_number(lhs->string)) { - num = mprVarToNumber(lhs); - lhs->allocatedVar = 0; - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - /* Examine further below */ - - } else { - /* - * Convert the RHS to a string - */ - mprVarToString(&str, MPR_MAX_STRING, 0, rhs); - rhs->allocatedVar = 0; - mprDestroyVar(rhs); - *rhs = mprCreateStringVar(str, 1); - mprFree(str); - } - -#if BLD_FEATURE_FLOATING_POINT - } else if (lhs->type == MPR_TYPE_FLOAT) { - /* - * Convert rhs to floating - */ - double f = mprVarToFloat(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateFloatVar(f); - -#endif -#if BLD_FEATURE_INT64 - } else if (lhs->type == MPR_TYPE_INT64) { - /* - * Convert the rhs to 64 bit - */ - int64 n = mprVarToInteger64(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateInteger64Var(n); -#endif - } else if (lhs->type == MPR_TYPE_BOOL || lhs->type == MPR_TYPE_INT) { - - if (rhs->type == MPR_TYPE_STRING) { - /* - * Convert to lhs to a string - */ - mprVarToString(&str, MPR_MAX_STRING, 0, lhs); - mprDestroyVar(lhs); - *lhs = mprCreateStringVar(str, 1); - mprFree(str); - -#if BLD_FEATURE_FLOATING_POINT - } else if (rhs->type == MPR_TYPE_FLOAT) { - /* - * Convert lhs to floating - */ - double f = mprVarToFloat(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateFloatVar(f); -#endif - - } else { - /* - * Convert both operands to numbers - */ - num = mprVarToNumber(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - - num = mprVarToNumber(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateNumberVar(num); - } - } - } - - /* - * We have failed to coerce the types to be the same. Special case here - * for undefined and null. We need to allow comparisions against these - * special values. - */ - if (lhs->type == MPR_TYPE_UNDEFINED || lhs->type == MPR_TYPE_NULL) { - switch (rel) { - case EJS_EXPR_EQ: - lval = lhs->type == rhs->type; - break; - case EJS_EXPR_NOTEQ: - lval = lhs->type != rhs->type; - break; - case EJS_EXPR_BOOL_COMP: - lval = ! mprVarToBool(rhs); - break; - default: - lval = 0; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar((bool) lval), 0); - return 0; - } - - /* - * Types are the same here - */ - switch (lhs->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - /* Should be handled above */ - mprAssert(0); - return 0; - - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - mprCopyVarValue(&ep->result, mprCreateBoolVar(0), 0); - return 0; - - case MPR_TYPE_PTR: - rc = evalPtrExpr(ep, lhs->ptr, rel, rhs->ptr); - break; - - case MPR_TYPE_BOOL: - rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - rc = evalFloatExpr(ep, lhs->floating, rel, rhs->floating); - break; -#endif - - case MPR_TYPE_INT: - rc = evalNumericExpr(ep, (MprNum) lhs->integer, rel, - (MprNum) rhs->integer); - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - rc = evalNumericExpr(ep, (MprNum) lhs->integer64, rel, - (MprNum) rhs->integer64); - break; -#endif - - case MPR_TYPE_STRING: - rc = evalStringExpr(ep, lhs, rel, rhs); - } - return rc; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Expressions with floating operands - */ - -static int evalFloatExpr(Ejs *ep, double l, int rel, double r) -{ - double lval; - bool logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - lval = l / r; - break; - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); - - } else { - mprCopyVarValue(&ep->result, mprCreateFloatVar(lval), 0); - } - return 0; -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ -/* - * Expressions with boolean operands - */ - -static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r) -{ - bool lval; - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r) -{ - bool lval; - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == NULL) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -/******************************************************************************/ -/* - * Expressions with numeric operands - */ - -static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r) -{ - MprNum lval; - bool logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - if (r != 0) { - lval = l / r; - } else { - ejsError(ep, "Divide by zero"); - return -1; - } - break; - case EJS_EXPR_MOD: - if (r != 0) { - lval = l % r; - } else { - ejsError(ep, "Modulo zero"); - return -1; - } - break; - case EJS_EXPR_LSHIFT: - lval = l << r; - break; - case EJS_EXPR_RSHIFT: - lval = l >> r; - break; - - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); - - } else { - mprCopyVarValue(&ep->result, mprCreateNumberVar(lval), 0); - } - return 0; -} - -/******************************************************************************/ -/* - * Expressions with string operands - */ - -static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - int lval; - - mprAssert(ep); - mprAssert(lhs); - mprAssert(rhs); - - switch (rel) { - case EJS_EXPR_LESS: - lval = strcmp(lhs->string, rhs->string) < 0; - break; - case EJS_EXPR_LESSEQ: - lval = strcmp(lhs->string, rhs->string) <= 0; - break; - case EJS_EXPR_GREATER: - lval = strcmp(lhs->string, rhs->string) > 0; - break; - case EJS_EXPR_GREATEREQ: - lval = strcmp(lhs->string, rhs->string) >= 0; - break; - case EJS_EXPR_EQ: - lval = strcmp(lhs->string, rhs->string) == 0; - break; - case EJS_EXPR_NOTEQ: - lval = strcmp(lhs->string, rhs->string) != 0; - break; - case EJS_EXPR_PLUS: - /* - * This differs from all the above operations. We append rhs to lhs. - */ - mprDestroyVar(&ep->result); - appendValue(&ep->result, lhs); - appendValue(&ep->result, rhs); - return 0; - - case EJS_EXPR_INC: - case EJS_EXPR_DEC: - case EJS_EXPR_MINUS: - case EJS_EXPR_DIV: - case EJS_EXPR_MOD: - case EJS_EXPR_LSHIFT: - case EJS_EXPR_RSHIFT: - default: - ejsError(ep, "Bad operator"); - return -1; - } - - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a function. obj is set to the current object if a function is being - * run. - */ - -static int evalFunction(Ejs *ep, MprVar *obj, int flags) -{ - EjsProc *proc; - MprVar arguments, callee, thisObject, *prototype, **argValues; - MprArray *formalArgs, *actualArgs; - char buf[16], **argNames, **argBuf; - int i, rc, fid; - - mprAssert(ep); - mprAssert(ejsPtr(ep->eid)); - - rc = -1; - proc = ep->proc; - prototype = proc->fn; - actualArgs = proc->args; - argValues = (MprVar**) actualArgs->handles; - - /* - * Create a new variable stack frame. ie. new local variables. - */ - fid = ejsOpenBlock(ep->eid); - - if (flags & EJS_FLAGS_NEW) { - /* - * Create a new bare object and pass it into the constructor as the - * "this" local variable. - */ - thisObject = ejsCreateObj("this", EJS_OBJ_HASH_SIZE); - mprCreatePropertyValue(ep->local, "this", thisObject); - - } else if (obj) { - mprCreateProperty(ep->local, "this", obj); - } - - switch (prototype->type) { - default: - mprAssert(0); - break; - - case MPR_TYPE_STRING_CFUNCTION: - if (actualArgs->used > 0) { - argBuf = mprMalloc((1+actualArgs->used) * sizeof(char*)); - for (i = 0; i < actualArgs->used; i++) { - mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]); - } - argBuf[i] = NULL; - } else { - argBuf = 0; - } - - /* - * Call the function depending on the various handle flags - */ - ep->thisPtr = prototype->cFunctionWithStrings.thisPtr; - if (prototype->flags & MPR_VAR_ALT_HANDLE) { - rc = ((EjsAltStringCFunction) prototype->cFunctionWithStrings.fn) - (ep->eid, ep->altHandle, actualArgs->used, argBuf); - } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { - rc = (prototype->cFunctionWithStrings.fn)(ep->eid, - actualArgs->used, argBuf); - } else { - rc = (prototype->cFunctionWithStrings.fn)(ep->primaryHandle, - actualArgs->used, argBuf); - } - - if (actualArgs->used > 0) { - for (i = 0; i < actualArgs->used; i++) { - mprFree(argBuf[i]); - } - mprFree(argBuf); - } - ep->thisPtr = 0; - break; - - case MPR_TYPE_CFUNCTION: - /* - * Call the function depending on the various handle flags - */ - ep->thisPtr = prototype->cFunction.thisPtr; - if (prototype->flags & MPR_VAR_ALT_HANDLE) { - rc = ((EjsAltCFunction) prototype->cFunction.fn) - (ep->eid, ep->altHandle, actualArgs->used, argValues); - } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { - rc = (prototype->cFunction.fn)(ep->eid, actualArgs->used, - argValues); - } else { - rc = (prototype->cFunction.fn)(ep->primaryHandle, - actualArgs->used, argValues); - } - ep->thisPtr = 0; - break; - - case MPR_TYPE_FUNCTION: - - formalArgs = prototype->function.args; - argNames = (char**) formalArgs->handles; - - if (formalArgs->used > actualArgs->used) { - ejsError(ep, "Bad number of args. Should be %d", - formalArgs->used); - return -1; - } - - /* - * Create the arguments and callee variables - */ - arguments = ejsCreateObj("arguments", EJS_SMALL_OBJ_HASH_SIZE); - callee = ejsCreateObj("callee", EJS_SMALL_OBJ_HASH_SIZE); - - /* - * Overwrite the length property - */ - mprCreatePropertyValue(&arguments, "length", - mprCreateIntegerVar(actualArgs->used)); - mprCreatePropertyValue(&callee, "length", - mprCreateIntegerVar(formalArgs->used)); - - /* - * Define all the agruments to be set to the actual parameters - */ - for (i = 0; i < formalArgs->used; i++) { - mprCreateProperty(ep->local, argNames[i], argValues[i]); - } - for (i = 0; i < actualArgs->used; i++) { - mprItoa(i, buf, sizeof(buf)); - mprCreateProperty(&arguments, buf, argValues[i]); - } - - mprCreateProperty(&arguments, "callee", &callee); - mprCreateProperty(ep->local, "arguments", &arguments); - - /* - * Can destroy our variables here as they are now referenced via - * "local" - */ - mprDestroyVar(&callee); - mprDestroyVar(&arguments); - - /* - * Actually run the function - */ - rc = ejsEvalScript(ep->eid, prototype->function.body, 0, 0); - break; - } - - ejsCloseBlock(ep->eid, fid); - - /* - * New statements return the newly created object as the result of the - * command - */ - if (flags & EJS_FLAGS_NEW) { - mprDestroyVar(&ep->result); - /* - * Don't copy, we want to assign the actual object into result. - * (mprCopyVar would inc the refCount to 2). - */ - ep->result = thisObject; - } - return rc; -} - -/******************************************************************************/ -/* - * Run a function - */ - -int ejsRunFunction(int eid, MprVar *obj, const char *functionName, - MprArray *args) -{ - EjsProc proc, *saveProc; - Ejs *ep; - int rc; - - mprAssert(obj); - mprAssert(functionName && *functionName); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return MPR_ERR_NOT_FOUND; - } - saveProc = ep->proc; - ep->proc = &proc; - - memset(&proc, 0, sizeof(EjsProc)); - mprDestroyVar(&ep->result); - - proc.fn = mprGetProperty(obj, functionName, 0); - if (proc.fn == 0 || proc.fn->type == MPR_TYPE_UNDEFINED) { - ep->proc = saveProc; - return MPR_ERR_NOT_FOUND; - } - proc.procName = mprStrdup(functionName); - if (args == 0) { - proc.args = mprCreateArray(); - rc = evalFunction(ep, obj, 0); - } else { - proc.args = args; - rc = evalFunction(ep, obj, 0); - proc.args = 0; - } - - freeProc(&proc); - ep->proc = saveProc; - - return rc; -} - -/******************************************************************************/ -/* - * Find which object contains the property given the current context. - * Only used for top level properties. - */ - -MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags) -{ - MprVar *obj; - - mprAssert(ep); - mprAssert(property && *property); - - if (flags & EJS_FLAGS_GLOBAL) { - obj = ep->global; - - } else if (state == EJS_STATE_DEC || flags & EJS_FLAGS_LOCAL) { - obj = ep->local; - - } else { - /* First look local, then look global */ - if (mprGetProperty(ep->local, property, 0)) { - obj = ep->local; - } else { - obj = ep->global; - } - } - return obj; -} - -/******************************************************************************/ -/* - * Find an object property given a object and a property name. We - * intelligently look in the local and global namespaces depending on - * our state. If not found in local or global, try base classes for function - * names only. Returns the property or NULL. - */ - -MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, char *property, - int flags) -{ - MprVar *vp; - - mprAssert(ep); - if (flags & EJS_FLAGS_EXE) { - mprAssert(property && *property); - } - - if (obj != 0) { -#if FUTURE && MB - op = obj; - do { - vp = mprGetProperty(op, property, 0); - if (vp != 0) { - if (op != obj && mprVarIsFunction(vp->type)) { - } - break; - } - op = op->baseObj; - } while (op); -#endif - vp = mprGetProperty(obj, property, 0); - - } else { - if (state == EJS_STATE_DEC) { - vp = mprGetProperty(ep->local, property, 0); - - } else { - /* Look local first, then global */ - vp = mprGetProperty(ep->local, property, 0); - if (vp == NULL) { - vp = mprGetProperty(ep->global, property, 0); - } - } - } - return vp; -} - -/******************************************************************************/ -/* - * Update result - */ - -static void updateResult(Ejs *ep, int state, int flags, MprVar *vp) -{ - if (flags & EJS_FLAGS_EXE && state != EJS_STATE_DEC) { - mprDestroyVar(&ep->result); - if (vp) { - mprCopyProperty(&ep->result, vp, MPR_SHALLOW_COPY); - } - } -} - -/******************************************************************************/ -/* - * Append to the pointer value - */ - -static void appendValue(MprVar *dest, MprVar *src) -{ - char *value, *oldBuf, *buf; - int len, oldLen; - - mprAssert(dest); - - mprVarToString(&value, MPR_MAX_STRING, 0, src); - - if (mprVarIsValid(dest)) { - len = strlen(value); - oldBuf = dest->string; - oldLen = strlen(oldBuf); - buf = mprRealloc(oldBuf, (len + oldLen + 1) * sizeof(char)); - dest->string = buf; - strcpy(&buf[oldLen], value); - - } else { - *dest = mprCreateStringVar(value, 1); - } - mprFree(value); -} - -/******************************************************************************/ -/* - * Exit with status - */ - -void ejsSetExitStatus(int eid, int status) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - ep->exitStatus = status; - ep->flags |= EJS_FLAGS_EXIT; -} - -/******************************************************************************/ -/* - * Free an argument list - */ - -static void freeProc(EjsProc *proc) -{ - MprVar **argValues; - int i; - - if (proc->args) { - argValues = (MprVar**) proc->args->handles; - - for (i = 0; i < proc->args->max; i++) { - if (argValues[i]) { - mprDestroyVar(argValues[i]); - mprFree(argValues[i]); - mprRemoveFromArray(proc->args, i); - } - } - - mprDestroyArray(proc->args); - } - - if (proc->procName) { - mprFree(proc->procName); - proc->procName = NULL; - } -} - -/******************************************************************************/ -/* - * This function removes any new lines. Used for else cases, etc. - */ - -static void removeNewlines(Ejs *ep, int state) -{ - int tid; - - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - ejsLexPutbackToken(ep, tid, ep->token); -} - -/******************************************************************************/ - -#else -void ejsParserDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsProcs.c b/source4/lib/appweb/ejs/ejsProcs.c deleted file mode 100644 index 43fff4a40b..0000000000 --- a/source4/lib/appweb/ejs/ejsProcs.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - * @file ejsProc.c - * @brief EJS support functions - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ -/* - * Object constructors - */ -static int objectConsProc(EjsHandle eid, int argc, MprVar **argv); -static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv); -static int booleanConsProc(EjsHandle eid, int argc, MprVar **agv); -static int numberConsProc(EjsHandle eid, int argc, MprVar **argv); -static int stringConsProc(EjsHandle eid, int argc, MprVar **argv); - -/* - * Core functions - */ -static int toStringProc(EjsHandle eid, int argc, MprVar **argv); -static int valueOfProc(EjsHandle eid, int argc, MprVar **argv); - -/* - * Triggers - */ -static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, - MprProperties *parentProperties, MprVar *prop, MprVar *newValue, - int copyRef); - -/******************************************************************************/ -/* - * Routine to create the base common to all object types - */ - -MprVar ejsCreateObj(const char *name, int hashSize) -{ - MprVar o; - - o = mprCreateObjVar(name, hashSize); - if (o.type == MPR_TYPE_UNDEFINED) { - mprAssert(0); - return o; - } - - mprCreatePropertyValue(&o, "toString", - mprCreateCFunctionVar(toStringProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(&o, "valueOf", - mprCreateCFunctionVar(valueOfProc, 0, MPR_VAR_SCRIPT_HANDLE)); - return o; -} - -/******************************************************************************/ -/* - * Routine to destroy a variable - */ - -bool ejsDestroyVar(MprVar *obj) -{ - return mprDestroyVar(obj); -} - -/******************************************************************************/ -/* - * Routine to create the base array type - */ - -MprVar ejsCreateArray(const char *name, int size) -{ - MprVar obj, *lp, undef; - char idx[16]; - int i; - - /* Sanity limit for size of hash table */ - - obj = ejsCreateObj(name, max(size, 503)); - if (obj.type == MPR_TYPE_UNDEFINED) { - mprAssert(0); - return obj; - } - - undef = mprCreateUndefinedVar(); - for (i = 0; i < size; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(&obj, idx, &undef); - } - - lp = mprCreatePropertyValue(&obj, "length", mprCreateIntegerVar(size)); - mprAssert(lp); - - mprSetVarReadonly(lp, 1); - mprAddVarTrigger(lp, lengthTrigger); - - return obj; -} - -/******************************************************************************/ -/******************************** Constructors ********************************/ -/******************************************************************************/ -/* - * Object constructor. Nothing really done here. For future expansion. - */ - -static int objectConsProc(EjsHandle eid, int argc, MprVar **argv) -{ -#if XX_UNUSED_XX - MprVar *obj; - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); -#endif - return 0; -} - -/******************************************************************************/ -/* - * Array constructor - */ - -static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj, *lp, undef; - Ejs *ep; - char idx[16]; - int i, max; - - objectConsProc(eid, argc, argv); - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - - if (argc == 1 && mprVarIsNumber(argv[0]->type)) { - /* - * x = new Array(size); - */ - undef = mprCreateUndefinedVar(); - max = (int) mprVarToInteger(argv[0]); - for (i = 0; i < max; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(obj, idx, &undef); - } - } else { - /* - * x = new Array(element0, element1, ..., elementN): - */ - max = argc; - for (i = 0; i < max; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(obj, idx, argv[i]); - } - } - - lp = mprCreatePropertyValue(obj, "length", mprCreateIntegerVar(max)); - mprAssert(lp); - - mprSetVarReadonly(lp, 1); - mprAddVarTrigger(lp, lengthTrigger); - - return 0; -} - -/******************************************************************************/ -/* - * Boolean constructor - */ - -static int booleanConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -#if FUTURE -/* - * Date constructor - */ - -static int dateConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -#endif -/******************************************************************************/ -/* - * Number constructor - */ - -static int numberConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -/* - * String constructor - */ - -static int stringConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -/********************************** Functions *********************************/ -/******************************************************************************/ - -static int toStringProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj; - Ejs *ep; - char *buf; - int radix; - - if (argc == 0) { - radix = 10; - - } else if (argc == 1) { - radix = (int) mprVarToInteger(argv[0]); - - } else { - mprAssert(0); - return -1; - } - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - mprVarToString(&buf, MPR_MAX_STRING, 0, obj); - mprCopyVarValue(&ep->result, mprCreateStringVar(buf, 0), MPR_SHALLOW_COPY); - mprFree(buf); - - return 0; -} - -/******************************************************************************/ - -static int valueOfProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj; - Ejs *ep; - - if (argc != 0) { - mprAssert(0); - return -1; - } - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - switch (obj->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_PTR: - mprCopyVar(&ep->result, obj, MPR_SHALLOW_COPY); - break; - - case MPR_TYPE_STRING: - mprCopyVarValue(&ep->result, mprCreateIntegerVar(atoi(obj->string)), 0); - break; - - case MPR_TYPE_BOOL: - case MPR_TYPE_INT: -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: -#endif -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: -#endif - mprCopyVar(&ep->result, obj, 0); - break; - } - return 0; -} - -/******************************************************************************/ -/* - * Var access trigger on the Array.length property. Return the count of - * enumerable properties (don't count functions). - */ - -static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, - MprProperties *parentProperties, MprVar *prop, MprVar *newValue, - int copyRef) -{ - switch (op) { - case MPR_VAR_READ: - /* - * Subtract one for the length property - * FUTURE -- need an API to access parentProperties - * FUTURE -- contradiction to be read-only yet allow USE_NEW_VALUE. - * API needs finer control. - */ - *newValue = mprCreateIntegerVar(parentProperties->numDataItems - 1); - return MPR_TRIGGER_USE_NEW_VALUE; - - case MPR_VAR_WRITE: - return MPR_TRIGGER_ABORT; - - case MPR_VAR_CREATE_PROPERTY: - case MPR_VAR_DELETE_PROPERTY: - case MPR_VAR_DELETE: - default: - break; - } - return MPR_TRIGGER_PROCEED; -} - -/******************************************************************************/ -/**************************** Extension Functions *****************************/ -/******************************************************************************/ -/* - * Assert - */ - -static int assertProc(EjsHandle eid, int argc, MprVar **argv) -{ - bool b; - - if (argc < 1) { - ejsSetErrorMsg(eid, "usage: assert(condition)\n"); - return -1; - } - b = mprVarToBool(argv[0]); - if (b == 0) { - ejsSetErrorMsg(eid, "Assertion failure\n"); - return -1; - } - ejsSetReturnValue(eid, mprCreateBoolVar(b)); - return 0; -} - -/******************************************************************************/ -/* - * Exit - */ - -static int exitProc(EjsHandle eid, int argc, MprVar **argv) -{ - int status; - - if (argc < 1) { - ejsSetErrorMsg(eid, "usage: exit(status)\n"); - return -1; - } - status = (int) mprVarToInteger(argv[0]); - ejsSetExitStatus(eid, status); - - ejsSetReturnValue(eid, mprCreateStringVar("", 0)); - return 0; -} - -/******************************************************************************/ - -static void printVar(MprVar *vp, int recurseCount, int indent) -{ - MprVar *np; - char *buf; - int i; - - if (recurseCount > 5) { - write(1, "Skipping - recursion too deep\n", 29); - return; - } - - for (i = 0; i < indent; i++) { - write(1, " ", 2); - } - - if (vp->type == MPR_TYPE_OBJECT) { - if (vp->name) { - write(1, vp->name, strlen(vp->name)); - } else { - write(1, "unknown", 7); - } - write(1, ": {\n", 4); - np = mprGetFirstProperty(vp, MPR_ENUM_DATA); - while (np) { - if (strcmp(np->name, "local") == 0 || - strcmp(np->name, "global") == 0 || - strcmp(np->name, "this") == 0) { - np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); - continue; - } - printVar(np, recurseCount + 1, indent + 1); - np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); - if (np) { - write(1, ",\n", 2); - } - } - write(1, "\n", 1); - for (i = 0; i < indent; i++) { - write(1, " ", 2); - } - write(1, "}", 1); - - } else { - if (vp->name) { - write(1, vp->name, strlen(vp->name)); - } else { - write(1, "unknown", 7); - } - write(1, ": ", 2); - - /* FUTURE -- other types ? */ - mprVarToString(&buf, MPR_MAX_STRING, 0, vp); - if (vp->type == MPR_TYPE_STRING) { - write(1, "\"", 1); - } - write(1, buf, strlen(buf)); - if (vp->type == MPR_TYPE_STRING) { - write(1, "\"", 1); - } - mprFree(buf); - } -} - -/******************************************************************************/ -/* - * Print the args to stdout - */ - -static int printVarsProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *vp; - char *buf; - int i; - - for (i = 0; i < argc; i++) { - vp = argv[i]; - switch (vp->type) { - case MPR_TYPE_OBJECT: - printVar(vp, 0, 0); - break; - default: - mprVarToString(&buf, MPR_MAX_STRING, 0, vp); - write(1, buf, strlen(buf)); - mprFree(buf); - break; - } - } - write(1, "\n", 1); - - ejsSetReturnValue(eid, mprCreateStringVar("", 0)); - return 0; -} - -/******************************************************************************/ -/* - * Print the args to stdout - */ - -static int printProc(EjsHandle eid, int argc, MprVar **argv) -{ - char *buf; - int i; - - for (i = 0; i < argc; i++) { - mprVarToString(&buf, MPR_MAX_STRING, 0, argv[i]); - write(1, buf, strlen(buf)); - mprFree(buf); - } - return 0; -} - -/******************************************************************************/ -/* - * println - */ - -static int printlnProc(EjsHandle eid, int argc, MprVar **argv) -{ - printProc(eid, argc, argv); - write(1, "\n", 1); - return 0; -} - -/******************************************************************************/ -/* - * Trace - */ - -static int traceProc(EjsHandle eid, int argc, char **argv) -{ - if (argc == 1) { - mprLog(0, "%s", argv[0]); - - } else if (argc == 2) { - mprLog(atoi(argv[0]), "%s", argv[1]); - - } else { - ejsSetErrorMsg(eid, "Usage: trace([level], message)"); - return -1; - } - ejsSetReturnString(eid, ""); - return 0; -} - -/******************************************************************************/ -/* - * Return the object reference count - */ - -static int refCountProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *vp; - int count; - - vp = argv[0]; - if (vp->type == MPR_TYPE_OBJECT) { - count = mprGetVarRefCount(vp); - ejsSetReturnValue(eid, mprCreateIntegerVar(count)); - } else { - ejsSetReturnValue(eid, mprCreateIntegerVar(0)); - } - - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a sub-script. It is evaluated in the same variable scope as - * the calling script / function. - */ - -static int evalScriptProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *arg; - char *emsg; - int i; - - ejsSetReturnValue(eid, mprCreateUndefinedVar()); - - for (i = 0; i < argc; i++) { - arg = argv[i]; - if (arg->type != MPR_TYPE_STRING) { - continue; - } - if (ejsEvalScript(eid, arg->string, 0, &emsg) < 0) { - ejsSetErrorMsg(eid, "%s", emsg); - mprFree(emsg); - return -1; - } - } - /* - * Return with the value of the last expression - */ - return 0; -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* - * Define the standard properties and functions inherited by all script engines. - */ - -int ejsDefineStandardProperties(MprVar *obj) -{ -#if BLD_FEATURE_FLOATING_POINT - double d = 0.0; - - /* FUTURE - this generates warnings on some systems. This is okay. */ - - mprCreatePropertyValue(obj, "NaN", mprCreateFloatVar(0.0 / d)); - d = MAX_FLOAT; - mprCreatePropertyValue(obj, "Infinity", mprCreateFloatVar(d * d)); -#endif - mprCreatePropertyValue(obj, "null", mprCreateNullVar()); - mprCreatePropertyValue(obj, "undefined", mprCreateUndefinedVar()); - mprCreatePropertyValue(obj, "true", mprCreateBoolVar(1)); - mprCreatePropertyValue(obj, "false", mprCreateBoolVar(0)); - mprCreatePropertyValue(obj, "NULL", mprCreatePtrVar(NULL)); - -#if BLD_FEATURE_LEGACY_API - /* - * DEPRECATED: 2.0. - * So that ESP/ASP can ignore "language=javascript" statements - */ - mprCreatePropertyValue(obj, "javascript", mprCreateIntegerVar(0)); -#endif - - /* - * Extension functions - */ - mprCreatePropertyValue(obj, "assert", - mprCreateCFunctionVar(assertProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "eval", - mprCreateCFunctionVar(evalScriptProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "exit", - mprCreateCFunctionVar(exitProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "refCount", - mprCreateCFunctionVar(refCountProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "print", - mprCreateCFunctionVar(printProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "println", - mprCreateCFunctionVar(printlnProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "printVars", - mprCreateCFunctionVar(printVarsProc,0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "trace", - mprCreateStringCFunctionVar(traceProc, 0, MPR_VAR_SCRIPT_HANDLE)); - - /* - * Constructors - */ - mprCreatePropertyValue(obj, "Array", - mprCreateCFunctionVar(arrayConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Boolean", - mprCreateCFunctionVar(booleanConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Object", - mprCreateCFunctionVar(objectConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Number", - mprCreateCFunctionVar(numberConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "String", - mprCreateCFunctionVar(stringConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - - /* mprCreatePropertyValue(obj, "Date", - * mprCreateCFunctionVar(dateConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - * mprCreatePropertyValue(obj, "Regexp", - * mprCreateCFunctionVar(regexpConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - */ - - /* - * Can we use on var x = "string text"; - */ - return 0; -} - -/******************************************************************************/ - -#else -void ejsProcsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ |