00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00040 #include "TclXPCOMPrivate.h"
00041
00042
00043 #define STUBS_BUFFERSIZE 16
00044
00045
00051 typedef struct CurrentStubInfo {
00052 nsISupports *currentstub;
00053 nsIInterfaceInfo *interfaceinfo;
00054 int nestlevel;
00055 nsresult returnCode;
00056 } CurrentStubInfo;
00057
00061 static Tcl_ThreadDataKey currentStubKey;
00062
00063
00069 void
00070 TclXPCOM_GetCurrentComponentContext(
00071 nsIInterfaceInfo **interfaceinfo,
00072 nsISupports **isupports
00073 )
00074 {
00075 NS_PRECONDITION(interfaceinfo, "null pointer");
00076 NS_PRECONDITION(isupports, "null pointer");
00077
00078 CurrentStubInfo *stubinfo;
00079 stubinfo = (CurrentStubInfo *)Tcl_GetThreadData(¤tStubKey, sizeof(CurrentStubInfo));
00080 *isupports = stubinfo->currentstub;
00081 *interfaceinfo = stubinfo->interfaceinfo;
00082 }
00083
00084
00091 int
00092 TclXPCOM_SetReturnCode(
00093 nsresult res
00094 )
00095 {
00096 CurrentStubInfo *stubinfo;
00097
00098 stubinfo = (CurrentStubInfo *)Tcl_GetThreadData(¤tStubKey, sizeof(CurrentStubInfo));
00099
00100 if (stubinfo->currentstub)
00101 {
00102 stubinfo->returnCode = res;
00103 return 1;
00104 } else
00105 {
00106 return 0;
00107 }
00108 }
00109
00110
00115 void
00116 CleanupOutParameters(
00117 void **params,
00118 nsXPTParamInfo *paraminfos,
00119 PRUint8 paramcount,
00120 nsIInterfaceInfo *interfaceinfo,
00121 PRUint16 methodindex
00122 )
00123 {
00124 PRUint8 i;
00125 nsXPTType type;
00126
00127 NS_PRECONDITION(params, "null pointer");
00128 NS_PRECONDITION(paraminfos, "null pointer");
00129 NS_PRECONDITION(interfaceinfo, "null pointer");
00130
00131 for (i = 0; i < paramcount; i++)
00132 {
00133 if (paraminfos[i].IsOut())
00134 {
00135 type = paraminfos[i].GetType();
00136 CleanupParam(params, params[i], &type, interfaceinfo, methodindex, ¶minfos[i]);
00137 if (type.IsPointer())
00138 {
00139 *(void **)params[i] = NULL;
00140 }
00141 }
00142 }
00143 }
00144
00145
00152 Tcl_Obj *
00153 NewOutParam(
00154 int stubid,
00155 int paramindex
00156 )
00157 {
00158 char str[128];
00159 sprintf(str, "::xpcom::outparams(%u-%u)", stubid, paramindex);
00160 return Tcl_NewStringObj(str, -1);
00161 }
00162
00163
00168 void
00169 CleanupTclOutVariables(
00170 int stubid,
00171 Tcl_Interp *interp,
00172 nsXPTParamInfo *paraminfos,
00173 PRUint8 paramcount,
00174 PRUint16 *tclparams
00175 )
00176 {
00177 PRUint8 i;
00178 Tcl_Obj *paramname;
00179
00180 NS_PRECONDITION(interp, "null pointer");
00181 NS_PRECONDITION(paraminfos, "null pointer");
00182 NS_PRECONDITION(tclparams, "null pointer");
00183
00184 for (i = 0; i < paramcount; i++)
00185 {
00186 if (!(tclparams[i] & PARAM_IS_SKIPPED)
00187 && (paraminfos[i].IsOut() || paraminfos[i].IsDipper())
00188 && !(paraminfos[i].IsRetval()))
00189 {
00190 paramname = NewOutParam(stubid, i);
00191 Tcl_UnsetVar2(interp, Tcl_GetString(paramname), NULL, TCL_GLOBAL_ONLY);
00192 Tcl_DecrRefCount(paramname);
00193 }
00194 }
00195 }
00196
00197
00202 void
00203 AddObjErrorInfoForBinding(
00204 Tcl_Interp *interp,
00205 nsISupports *isupports,
00206 nsIInterfaceInfo *interfaceinfo,
00207 PRUint16 methodindex,
00208 Tcl_Obj *script
00209 )
00210 {
00211 const char *name;
00212 const nsXPTMethodInfo *methodinfo;
00213 Tcl_Obj *isupportsobj;
00214
00215 NS_PRECONDITION(interp, "null pointer");
00216 NS_PRECONDITION(isupports, "null pointer");
00217 NS_PRECONDITION(interfaceinfo, "null pointer");
00218 NS_PRECONDITION(script, "null pointer");
00219
00220 Tcl_AddObjErrorInfo(interp, "\nwhile executing binding:\n\"", -1);
00221 Tcl_AddObjErrorInfo(interp, Tcl_GetString(script), -1);
00222 Tcl_AddObjErrorInfo(interp, "\"\nfor interface ", -1);
00223
00224 interfaceinfo->GetMethodInfo(methodindex, &methodinfo);
00225
00226 if (methodinfo->IsGetter())
00227 {
00228 Tcl_AddObjErrorInfo(interp, "attribute getter \"", -1);
00229 } else if (methodinfo->IsSetter())
00230 {
00231 Tcl_AddObjErrorInfo(interp, "attribute setter \"", -1);
00232 } else
00233 {
00234 Tcl_AddObjErrorInfo(interp, "method \"", -1);
00235 }
00236
00237 interfaceinfo->GetNameShared(&name);
00238 Tcl_AddObjErrorInfo(interp, name, -1);
00239 Tcl_AddObjErrorInfo(interp, "::", -1);
00240 name = methodinfo->GetName();
00241 Tcl_AddObjErrorInfo(interp, name, -1);
00242 Tcl_AddObjErrorInfo(interp, "\"", -1);
00243
00244 Tcl_AddObjErrorInfo(interp, "\nin component context \"", -1);
00245
00246 isupportsobj = TclXPCOM_NewISupportsObj(isupports, interfaceinfo);
00247 Tcl_AddObjErrorInfo(interp, Tcl_GetString(isupportsobj), -1);
00248 Tcl_DecrRefCount(isupportsobj);
00249
00250 Tcl_AddObjErrorInfo(interp, "\"", -1);
00251 }
00252
00253
00259 nsresult
00260 TclXPCOM_CallMethod(
00261 Tcl_Interp *interp,
00262 nsXPTCMiniVariant *variants,
00263 nsISupports *isupports,
00264 nsIInterfaceInfo *interfaceinfo,
00265 PRUint16 methodindex,
00266 Tcl_Obj *script
00267 )
00268 {
00269 int rv;
00270 nsresult res;
00271 nsXPTType type;
00272 char str[128];
00273
00274 Tcl_SavedResult savedresult;
00275 Tcl_Obj *errorcode, *errorinfo;
00276 Tcl_Obj *param, *paramname;
00277 void **params;
00278 void *stackedparams[STUBS_BUFFERSIZE];
00279
00280 PRUint16 j, *tclparams;
00281 PRUint8 i, paramcount;
00282 nsXPTParamInfo *paraminfos;
00283 MethodInfo *minfo;
00284
00285 int bgerror;
00286 int stubid;
00287 CurrentStubInfo *stubinfo, savedstubinfo;
00288
00289 NS_PRECONDITION(interp, "null pointer");
00290 NS_PRECONDITION(variants, "null pointer");
00291 NS_PRECONDITION(isupports, "null pointer");
00292 NS_PRECONDITION(interfaceinfo, "null pointer");
00293 NS_PRECONDITION(script, "null pointer");
00294
00295 minfo = GetMethodInfo(interfaceinfo, methodindex);
00296 tclparams = minfo->tclparams;
00297 paramcount = minfo->paramcount;
00298 paraminfos = minfo->paraminfos;
00299
00300 if (paramcount > STUBS_BUFFERSIZE)
00301 {
00302 params = (void **)memmgr->Alloc(sizeof(void *) * paramcount);
00303 } else
00304 {
00305 params = stackedparams;
00306 }
00307
00308
00309 Tcl_Preserve(interp);
00310 Tcl_SaveResult(interp, &savedresult);
00311 errorcode = Tcl_GetVar2Ex(interp, "errorCode", NULL, TCL_GLOBAL_ONLY);
00312 errorinfo = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
00313
00314 if (errorcode)
00315 {
00316 Tcl_IncrRefCount(errorcode);
00317 }
00318
00319 if (errorinfo)
00320 {
00321 Tcl_IncrRefCount(errorinfo);
00322 }
00323
00324 script = Tcl_DuplicateObj(script);
00325 Tcl_IncrRefCount(script);
00326
00327 stubinfo = (CurrentStubInfo *)Tcl_GetThreadData(¤tStubKey, sizeof(CurrentStubInfo));
00328 savedstubinfo = *stubinfo;
00329
00330 stubinfo->currentstub = isupports;
00331 stubinfo->interfaceinfo = interfaceinfo;
00332 stubinfo->returnCode = NS_OK;
00333 stubinfo->nestlevel++;
00334
00335 stubid = stubinfo->nestlevel;
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 bgerror = 0;
00351
00352 for (i = 0; i < paramcount; i++)
00353 {
00354 if (paraminfos[i].IsOut())
00355 {
00356 params[i] = variants[i].val.p;
00357
00358 if (!params[i])
00359 {
00360
00361 res = NS_ERROR_NULL_POINTER;
00362 goto done;
00363 }
00364
00365 if (!paraminfos[i].IsIn() && paraminfos[i].GetType().IsPointer())
00366 {
00367 *(void **)params[i] = NULL;
00368 }
00369 } else
00370 {
00371 params[i] = &variants[i];
00372 }
00373 }
00374
00375
00376 for (i = 0; i < paramcount; i++)
00377 {
00378 if ((tclparams[i] & PARAM_IS_SKIPPED) || (tclparams[i] & PARAM_IS_RETVAL))
00379 {
00380 continue;
00381 }
00382
00383 j = (tclparams[i] & PARAM_INDEX_MASK);
00384
00385 if (paraminfos[i].IsIn() && !paraminfos[i].IsDipper())
00386 {
00387
00388 type = paraminfos[i].GetType();
00389
00390 res = Native2Tcl(params, params[i], (nsXPTType *)¶minfos[i].type, interfaceinfo, methodindex, ¶minfos[i], ¶m);
00391 if (NS_FAILED(res))
00392 {
00393 goto done;
00394 }
00395
00396
00397 if (paraminfos[i].IsOut())
00398 {
00399
00400 paramname = NewOutParam(stubid, i);
00401 Tcl_ObjSetVar2(interp, paramname, NULL, param, TCL_GLOBAL_ONLY);
00402 param = paramname;
00403 }
00404 } else
00405 {
00406 param = NewOutParam(stubid, i);
00407 Tcl_UnsetVar2(interp, Tcl_GetString(param), NULL, TCL_GLOBAL_ONLY);
00408 }
00409
00410 rv = Tcl_ListObjAppendElement(NULL, script, param);
00411 NS_ASSERTION((rv == TCL_OK), "script is not a valid list");
00412 }
00413
00414
00415
00416 CleanupOutParameters(params, paraminfos, paramcount, interfaceinfo, methodindex);
00417
00418
00419 rv = Tcl_EvalObjEx(interp, script, TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
00420
00421 if (rv == TCL_OK)
00422 {
00423 res = stubinfo->returnCode;
00424 } else
00425 {
00426 if (!TclXPCOM_GetErrorCode(interp, &res))
00427 {
00428 res = NS_ERROR_FAILURE;
00429 bgerror = 1;
00430 }
00431 }
00432
00433 if (NS_FAILED(res))
00434 {
00435 goto done;
00436 }
00437
00438
00439 for (i = 0; i < paramcount; i++)
00440 {
00441 if (tclparams[i] & PARAM_IS_SKIPPED)
00442 {
00443 continue;
00444 }
00445
00446 j = (tclparams[i] & PARAM_INDEX_MASK);
00447
00448 if (paraminfos[i].IsOut() || paraminfos[i].IsDipper())
00449 {
00450 if (paraminfos[i].IsRetval())
00451 {
00452 param = Tcl_GetObjResult(interp);
00453 } else
00454 {
00455 paramname = NewOutParam(stubid, i);
00456 param = Tcl_ObjGetVar2(interp, paramname, NULL, TCL_GLOBAL_ONLY);
00457 Tcl_DecrRefCount(paramname);
00458 if (!param)
00459 {
00460
00461 Tcl_ResetResult(interp);
00462 Tcl_AppendResult(interp, "out parameter was not set", NULL);
00463 rv = TCL_ERROR;
00464 }
00465 }
00466
00467 if (rv == TCL_OK)
00468 {
00469 type = paraminfos[i].GetType();
00470 rv = Tcl2Native(interp, param, params, params[i], &type, tclparams[i] & PARAM_IS_SHARED_OUT, interfaceinfo, methodindex, ¶minfos[i]);
00471 }
00472
00473
00474 if (rv != TCL_OK)
00475 {
00476
00477 if (paraminfos[i].IsRetval())
00478 {
00479 sprintf(str, "\nwhile writing return parameter");
00480 } else
00481 {
00482 sprintf(str, "\nwhile writing out parameter #%d", j);
00483 }
00484 Tcl_AddObjErrorInfo(interp, str, -1);
00485
00486 CleanupOutParameters(params, paraminfos, paramcount, interfaceinfo, methodindex);
00487 res = NS_ERROR_FAILURE;
00488 bgerror = 1;
00489 goto done;
00490 }
00491 }
00492 }
00493
00494 done:
00495
00496 CleanupTclOutVariables(stubid, interp, paraminfos, paramcount, tclparams);
00497
00498 if (bgerror)
00499 {
00500 AddObjErrorInfoForBinding(interp, isupports, interfaceinfo, methodindex, script);
00501 TclXPCOM_BackgroundError(interp);
00502 }
00503
00504 if (paramcount > STUBS_BUFFERSIZE)
00505 {
00506 memmgr->Free(params);
00507 }
00508
00509 *stubinfo = savedstubinfo;
00510 Tcl_DecrRefCount(script);
00511
00512 if (errorcode)
00513 {
00514 Tcl_SetVar2Ex(interp, "errorCode", NULL, errorcode, TCL_GLOBAL_ONLY);
00515 Tcl_DecrRefCount(errorcode);
00516 }
00517
00518 if (errorinfo)
00519 {
00520 Tcl_SetVar2Ex(interp, "errorInfo", NULL, errorinfo, TCL_GLOBAL_ONLY);
00521 Tcl_DecrRefCount(errorinfo);
00522 }
00523
00524 Tcl_RestoreResult(interp, &savedresult);
00525 Tcl_Release(interp);
00526 return res;
00527 }
00528