1 // -*- c-basic-offset: 2 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
30 #include "interpreter.h"
32 #include "npruntime_internal.h"
35 #include "runtime_object.h"
38 #define LOG(formatAndArgs...) { \
39 fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
40 fprintf(stderr, formatAndArgs); \
44 // ------------------ NP Interface definition --------------------
50 NPVariant stringValue
;
55 static bool identifiersInitialized
= false;
57 #define ID_DOUBLE_VALUE 0
58 #define ID_INT_VALUE 1
59 #define ID_STRING_VALUE 2
60 #define ID_BOOLEAN_VALUE 3
61 #define ID_NULL_VALUE 4
62 #define ID_UNDEFINED_VALUE 5
63 #define NUM_PROPERTY_IDENTIFIERS 6
65 static NPIdentifier myPropertyIdentifiers
[NUM_PROPERTY_IDENTIFIERS
];
66 static const NPUTF8
*myPropertyIdentifierNames
[NUM_PROPERTY_IDENTIFIERS
] = {
75 #define ID_LOG_MESSAGE 0
76 #define ID_SET_DOUBLE_VALUE 1
77 #define ID_SET_INT_VALUE 2
78 #define ID_SET_STRING_VALUE 3
79 #define ID_SET_BOOLEAN_VALUE 4
80 #define ID_GET_DOUBLE_VALUE 5
81 #define ID_GET_INT_VALUE 6
82 #define ID_GET_STRING_VALUE 7
83 #define ID_GET_BOOLEAN_VALUE 8
84 #define NUM_METHOD_IDENTIFIERS 9
86 static NPIdentifier myMethodIdentifiers
[NUM_METHOD_IDENTIFIERS
];
87 static const NPUTF8
*myMethodIdentifierNames
[NUM_METHOD_IDENTIFIERS
] = {
99 static void initializeIdentifiers()
101 NPN_GetStringIdentifiers (myPropertyIdentifierNames
, NUM_PROPERTY_IDENTIFIERS
, myPropertyIdentifiers
);
102 NPN_GetStringIdentifiers (myMethodIdentifierNames
, NUM_METHOD_IDENTIFIERS
, myMethodIdentifiers
);
105 bool myHasProperty (NPClass
*theClass
, NPIdentifier name
)
108 for (i
= 0; i
< NUM_PROPERTY_IDENTIFIERS
; i
++) {
109 if (name
== myPropertyIdentifiers
[i
]){
116 bool myHasMethod (NPClass
*theClass
, NPIdentifier name
)
119 for (i
= 0; i
< NUM_METHOD_IDENTIFIERS
; i
++) {
120 if (name
== myMethodIdentifiers
[i
]){
128 void logMessage (const NPVariant
*message
)
130 if (message
->type
== NPVariantStringType
) {
132 strncpy (msgBuf
, message
->value
.stringValue
.UTF8Characters
, message
->value
.stringValue
.UTF8Length
);
133 msgBuf
[message
->value
.stringValue
.UTF8Length
] = 0;
134 printf ("%s\n", msgBuf
);
136 else if (message
->type
== NPVariantDoubleType
)
137 printf ("%f\n", (float)message
->value
.doubleValue
);
138 else if (message
->type
== NPVariantInt32Type
)
139 printf ("%d\n", message
->value
.intValue
);
140 else if (message
->type
== NPVariantObjectType
)
141 printf ("%p\n", message
->value
.objectValue
);
144 void setDoubleValue (MyObject
*obj
, const NPVariant
*variant
)
146 if (!NPN_VariantToDouble (variant
, &obj
->doubleValue
)) {
147 NPUTF8
*msg
= "Attempt to set double value with invalid type.";
149 aString
.UTF8Characters
= msg
;
150 aString
.UTF8Length
= strlen (msg
);
151 NPN_SetException ((NPObject
*)obj
, &aString
);
155 void setIntValue (MyObject
*obj
, const NPVariant
*variant
)
157 if (!NPN_VariantToInt32 (variant
, &obj
->intValue
)) {
158 NPUTF8
*msg
= "Attempt to set int value with invalid type.";
160 aString
.UTF8Characters
= msg
;
161 aString
.UTF8Length
= strlen (msg
);
162 NPN_SetException ((NPObject
*)obj
, &aString
);
166 void setStringValue (MyObject
*obj
, const NPVariant
*variant
)
168 NPN_ReleaseVariantValue (&obj
->stringValue
);
169 NPN_InitializeVariantWithVariant (&obj
->stringValue
, variant
);
172 void setBooleanValue (MyObject
*obj
, const NPVariant
*variant
)
174 if (!NPN_VariantToBool (variant
, (NPBool
*)&obj
->boolValue
)) {
175 NPUTF8
*msg
= "Attempt to set bool value with invalid type.";
177 aString
.UTF8Characters
= msg
;
178 aString
.UTF8Length
= strlen (msg
);
179 NPN_SetException ((NPObject
*)obj
, &aString
);
183 void getDoubleValue (MyObject
*obj
, NPVariant
*variant
)
185 NPN_InitializeVariantWithDouble (variant
, obj
->doubleValue
);
188 void getIntValue (MyObject
*obj
, NPVariant
*variant
)
190 NPN_InitializeVariantWithInt32 (variant
, obj
->intValue
);
193 void getStringValue (MyObject
*obj
, NPVariant
*variant
)
195 NPN_InitializeVariantWithVariant (variant
, &obj
->stringValue
);
198 void getBooleanValue (MyObject
*obj
, NPVariant
*variant
)
200 NPN_InitializeVariantWithBool (variant
, obj
->boolValue
);
203 void myGetProperty (MyObject
*obj
, NPIdentifier name
, NPVariant
*variant
)
205 if (name
== myPropertyIdentifiers
[ID_DOUBLE_VALUE
]){
206 getDoubleValue (obj
, variant
);
208 else if (name
== myPropertyIdentifiers
[ID_INT_VALUE
]){
209 getIntValue (obj
, variant
);
211 else if (name
== myPropertyIdentifiers
[ID_STRING_VALUE
]){
212 getStringValue (obj
, variant
);
214 else if (name
== myPropertyIdentifiers
[ID_BOOLEAN_VALUE
]){
215 getBooleanValue (obj
, variant
);
217 else if (name
== myPropertyIdentifiers
[ID_NULL_VALUE
]){
218 return NPN_InitializeVariantAsNull (variant
);
220 else if (name
== myPropertyIdentifiers
[ID_UNDEFINED_VALUE
]){
221 return NPN_InitializeVariantAsUndefined (variant
);
224 NPN_InitializeVariantAsUndefined(variant
);
227 void mySetProperty (MyObject
*obj
, NPIdentifier name
, const NPVariant
*variant
)
229 if (name
== myPropertyIdentifiers
[ID_DOUBLE_VALUE
]) {
230 setDoubleValue (obj
, variant
);
232 else if (name
== myPropertyIdentifiers
[ID_INT_VALUE
]) {
233 setIntValue (obj
, variant
);
235 else if (name
== myPropertyIdentifiers
[ID_STRING_VALUE
]) {
236 setStringValue (obj
, variant
);
238 else if (name
== myPropertyIdentifiers
[ID_BOOLEAN_VALUE
]) {
239 setBooleanValue (obj
, variant
);
241 else if (name
== myPropertyIdentifiers
[ID_NULL_VALUE
]) {
244 else if (name
== myPropertyIdentifiers
[ID_UNDEFINED_VALUE
]) {
249 void myInvoke (MyObject
*obj
, NPIdentifier name
, NPVariant
*args
, unsigned argCount
, NPVariant
*result
)
251 if (name
== myMethodIdentifiers
[ID_LOG_MESSAGE
]) {
252 if (argCount
== 1 && NPN_VariantIsString(&args
[0]))
253 logMessage (&args
[0]);
254 NPN_InitializeVariantAsVoid (result
);
256 else if (name
== myMethodIdentifiers
[ID_SET_DOUBLE_VALUE
]) {
257 if (argCount
== 1 && NPN_VariantIsDouble (&args
[0]))
258 setDoubleValue (obj
, &args
[0]);
259 NPN_InitializeVariantAsVoid (result
);
261 else if (name
== myMethodIdentifiers
[ID_SET_INT_VALUE
]) {
262 if (argCount
== 1 && (NPN_VariantIsDouble (&args
[0]) || NPN_VariantIsInt32 (&args
[0])))
263 setIntValue (obj
, &args
[0]);
264 NPN_InitializeVariantAsVoid (result
);
266 else if (name
== myMethodIdentifiers
[ID_SET_STRING_VALUE
]) {
267 if (argCount
== 1 && NPN_VariantIsString (&args
[0]))
268 setStringValue (obj
, &args
[0]);
269 NPN_InitializeVariantAsVoid (result
);
271 else if (name
== myMethodIdentifiers
[ID_SET_BOOLEAN_VALUE
]) {
272 if (argCount
== 1 && NPN_VariantIsBool (&args
[0]))
273 setBooleanValue (obj
, &args
[0]);
274 NPN_InitializeVariantAsVoid (result
);
276 else if (name
== myMethodIdentifiers
[ID_GET_DOUBLE_VALUE
]) {
277 getDoubleValue (obj
, result
);
279 else if (name
== myMethodIdentifiers
[ID_GET_INT_VALUE
]) {
280 getIntValue (obj
, result
);
282 else if (name
== myMethodIdentifiers
[ID_GET_STRING_VALUE
]) {
283 getStringValue (obj
, result
);
285 else if (name
== myMethodIdentifiers
[ID_GET_BOOLEAN_VALUE
]) {
286 getBooleanValue (obj
, result
);
289 NPN_InitializeVariantAsUndefined (result
);
292 NPObject
*myAllocate ()
294 MyObject
*newInstance
= (MyObject
*)malloc (sizeof(MyObject
));
296 if (!identifiersInitialized
) {
297 identifiersInitialized
= true;
298 initializeIdentifiers();
302 newInstance
->doubleValue
= 666.666;
303 newInstance
->intValue
= 1234;
304 newInstance
->boolValue
= true;
305 newInstance
->stringValue
.type
= NPVariantType_String
;
306 newInstance
->stringValue
.value
.stringValue
.UTF8Length
= strlen ("Hello world");
307 newInstance
->stringValue
.value
.stringValue
.UTF8Characters
= strdup ("Hello world");
309 return (NPObject
*)newInstance
;
314 // Make sure we've released any remaining references to JavaScript objects.
317 void myDeallocate (MyObject
*obj
)
322 static NPClass _myFunctionPtrs
= {
323 kNPClassStructVersionCurrent
,
324 (NPAllocateFunctionPtr
) myAllocate
,
325 (NPDeallocateFunctionPtr
) myDeallocate
,
326 (NPInvalidateFunctionPtr
) myInvalidate
,
327 (NPHasMethodFunctionPtr
) myHasMethod
,
328 (NPInvokeFunctionPtr
) myInvoke
,
329 (NPHasPropertyFunctionPtr
) myHasProperty
,
330 (NPGetPropertyFunctionPtr
) myGetProperty
,
331 (NPSetPropertyFunctionPtr
) mySetProperty
,
333 static NPClass
*myFunctionPtrs
= &_myFunctionPtrs
;
335 // --------------------------------------------------------
338 using namespace KJS::Bindings
;
340 class GlobalImp
: public ObjectImp
{
342 virtual UString
className() const { return "global"; }
345 #define BufferSize 200000
346 static char code
[BufferSize
];
348 const char *readJavaScriptFromFile (const char *file
)
350 FILE *f
= fopen(file
, "r");
352 fprintf(stderr
, "Error opening %s.\n", file
);
356 int num
= fread(code
, 1, BufferSize
, f
);
358 if(num
>= BufferSize
)
359 fprintf(stderr
, "Warning: File may have been too long.\n");
366 int main(int argc
, char **argv
)
368 // expecting a filename
370 fprintf(stderr
, "You have to specify at least one filename\n");
378 // create interpreter w/ global object
379 Object
global(new GlobalImp());
381 interp
.setGlobalObject(global
);
382 ExecState
*exec
= interp
.globalExec();
384 MyObject
*myObject
= (MyObject
*)NPN_CreateObject (myFunctionPtrs
);
386 global
.put(exec
, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage
, (void *)myObject
));
388 for (int i
= 1; i
< argc
; i
++) {
389 const char *code
= readJavaScriptFromFile(argv
[i
]);
393 Completion
comp(interp
.evaluate(code
));
395 if (comp
.complType() == Throw
) {
396 Value exVal
= comp
.value();
397 char *msg
= exVal
.toString(exec
).ascii();
399 if (exVal
.type() == ObjectType
) {
400 Value lineVal
= Object::dynamicCast(exVal
).get(exec
,Identifier("line"));
401 if (lineVal
.type() == NumberType
)
402 lineno
= int(lineVal
.toNumber(exec
));
405 fprintf(stderr
,"Exception, line %d: %s\n",lineno
,msg
);
407 fprintf(stderr
,"Exception: %s\n",msg
);
410 else if (comp
.complType() == ReturnValue
) {
411 char *msg
= comp
.value().toString(interp
.globalExec()).ascii();
412 fprintf(stderr
,"Return value: %s\n",msg
);
417 NPN_ReleaseObject ((NPObject
*)myObject
);
419 } // end block, so that Interpreter and global get deleted