testkjs.cpp
00001 // -*- c-basic-offset: 2 -*- 00002 /* 00003 * This file is part of the KDE libraries 00004 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public License 00017 * along with this library; see the file COPYING.LIB. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 */ 00022 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 #include <string.h> 00026 00027 #include "value.h" 00028 #include "object.h" 00029 #include "types.h" 00030 #include "interpreter.h" 00031 00032 using namespace KJS; 00033 00034 class TestFunctionImp : public ObjectImp { 00035 public: 00036 TestFunctionImp(int i, int length); 00037 virtual bool implementsCall() const { return true; } 00038 virtual Value call(ExecState *exec, Object &thisObj, const List &args); 00039 00040 enum { Print, Debug, Quit }; 00041 00042 private: 00043 int id; 00044 }; 00045 00046 TestFunctionImp::TestFunctionImp(int i, int length) : ObjectImp(), id(i) 00047 { 00048 putDirect(lengthPropertyName,length,DontDelete|ReadOnly|DontEnum); 00049 } 00050 00051 Value TestFunctionImp::call(ExecState *exec, Object &/*thisObj*/, const List &args) 00052 { 00053 switch (id) { 00054 case Print: 00055 case Debug: 00056 fprintf(stderr,"--> %s\n",args[0].toString(exec).ascii()); 00057 return Undefined(); 00058 case Quit: 00059 exit(0); 00060 return Undefined(); 00061 default: 00062 break; 00063 } 00064 00065 return Undefined(); 00066 } 00067 00068 class VersionFunctionImp : public ObjectImp { 00069 public: 00070 VersionFunctionImp() : ObjectImp() {} 00071 virtual bool implementsCall() const { return true; } 00072 virtual Value call(ExecState *exec, Object &thisObj, const List &args); 00073 }; 00074 00075 Value VersionFunctionImp::call(ExecState */*exec*/, Object &/*thisObj*/, const List &/*args*/) 00076 { 00077 // We need this function for compatibility with the Mozilla JS tests but for now 00078 // we don't actually do any version-specific handling 00079 return Undefined(); 00080 } 00081 00082 class GlobalImp : public ObjectImp { 00083 public: 00084 virtual UString className() const { return "global"; } 00085 }; 00086 00087 int main(int argc, char **argv) 00088 { 00089 // expecting a filename 00090 if (argc < 2) { 00091 fprintf(stderr, "You have to specify at least one filename\n"); 00092 return -1; 00093 } 00094 00095 bool ret = true; 00096 { 00097 Object global(new GlobalImp()); 00098 00099 // create interpreter 00100 Interpreter interp(global); 00101 // add debug() function 00102 global.put(interp.globalExec(), "debug", Object(new TestFunctionImp(TestFunctionImp::Debug,1))); 00103 // add "print" for compatibility with the mozilla js shell 00104 global.put(interp.globalExec(), "print", Object(new TestFunctionImp(TestFunctionImp::Print,1))); 00105 // add "quit" for compatibility with the mozilla js shell 00106 global.put(interp.globalExec(), "quit", Object(new TestFunctionImp(TestFunctionImp::Quit,0))); 00107 // add "version" for compatibility with the mozilla js shell 00108 global.put(interp.globalExec(), "version", Object(new VersionFunctionImp())); 00109 00110 for (int i = 1; i < argc; i++) { 00111 int code_len = 0; 00112 int code_alloc = 1024; 00113 char *code = (char*)malloc(code_alloc); 00114 00115 const char *file = argv[i]; 00116 if (strcmp(file, "-f") == 0) 00117 continue; 00118 FILE *f = fopen(file, "r"); 00119 if (!f) { 00120 fprintf(stderr, "Error opening %s.\n", file); 00121 return 2; 00122 } 00123 00124 while (!feof(f) && !ferror(f)) { 00125 size_t len = fread(code+code_len,1,code_alloc-code_len,f); 00126 code_len += len; 00127 if (code_len >= code_alloc) { 00128 code_alloc *= 2; 00129 code = (char*)realloc(code,code_alloc); 00130 } 00131 } 00132 code = (char*)realloc(code,code_len+1); 00133 code[code_len] = '\0'; 00134 00135 // run 00136 Completion comp(interp.evaluate(code)); 00137 00138 fclose(f); 00139 00140 if (comp.complType() == Throw) { 00141 ExecState *exec = interp.globalExec(); 00142 Value exVal = comp.value(); 00143 char *msg = exVal.toString(exec).ascii(); 00144 int lineno = -1; 00145 if (exVal.type() == ObjectType) { 00146 Value lineVal = Object::dynamicCast(exVal).get(exec,"line"); 00147 if (lineVal.type() == NumberType) 00148 lineno = int(lineVal.toNumber(exec)); 00149 } 00150 if (lineno != -1) 00151 fprintf(stderr,"Exception, line %d: %s\n",lineno,msg); 00152 else 00153 fprintf(stderr,"Exception: %s\n",msg); 00154 ret = false; 00155 } 00156 else if (comp.complType() == ReturnValue) { 00157 char *msg = comp.value().toString(interp.globalExec()).ascii(); 00158 fprintf(stderr,"Return value: %s\n",msg); 00159 } 00160 00161 free(code); 00162 } 00163 00164 } // end block, so that Interpreter and global get deleted 00165 00166 if (ret) 00167 fprintf(stderr, "OK.\n"); 00168 00169 #ifdef KJS_DEBUG_MEM 00170 Interpreter::finalCheck(); 00171 #endif 00172 return ret ? 0 : 3; 00173 }