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
00044 Tcl_HashTable infohash;
00045
00046
00052 IdentifierInfo
00053 GetIdentifierInfo(
00054 nsIInterfaceInfo *interfaceinfo,
00055 PRUint16 methodindex
00056 )
00057 {
00058 NS_PRECONDITION(interfaceinfo, "null pointer");
00059
00060 IdentifierInfo idinfo;
00061 PRUint16 methodcount;
00062 const nsXPTMethodInfo *methodinfo;
00063 const nsXPTMethodInfo *methodinfo1;
00064
00065 interfaceinfo->GetMethodInfo(methodindex, &methodinfo);
00066 interfaceinfo->GetMethodCount(&methodcount);
00067
00068 idinfo.name = (char *)methodinfo->GetName();
00069 idinfo.type = 0;
00070
00071 if (methodinfo->IsGetter())
00072 {
00073 idinfo.type |= INTERFACEINFO_GETTER;
00074 idinfo.indices.attributeindices.getterindex = methodindex;
00075
00076 if (methodindex + 1 < methodcount)
00077 {
00078 interfaceinfo->GetMethodInfo(methodindex + 1, &methodinfo1);
00079 if (methodinfo1->IsSetter())
00080 {
00081 idinfo.type |= INTERFACEINFO_SETTER;
00082 idinfo.indices.attributeindices.setterindex = methodindex + 1;
00083 }
00084 }
00085 } else if (methodinfo->IsSetter())
00086 {
00087 idinfo.type |= INTERFACEINFO_SETTER;
00088 idinfo.indices.attributeindices.setterindex = methodindex;
00089 } else
00090 {
00091 idinfo.type |= INTERFACEINFO_METHOD;
00092 idinfo.indices.methodindex = methodindex;
00093 }
00094
00095 return idinfo;
00096 }
00097
00098
00104 InterfaceInfo *
00105 NewInterfaceInfo(
00106 nsIInterfaceInfo *interfaceinfo
00107 )
00108 {
00109 PRUint16 i;
00110
00111 InterfaceInfo *iinfo;
00112 nsIInterfaceInfo *parent;
00113
00114 PRUint16 imethodcount, baseimethodindex;
00115 PRUint16 constantcount, baseconstantindex;
00116 PRUint16 methodcount, basemethodindex;
00117 PRUint16 attributecount, baseattributeindex;
00118
00119 MethodInfo *imethods;
00120 Tcl_Obj **constantvalues;
00121
00122 IdentifierInfo idinfo;
00123 IdentifierInfo *methods;
00124 IdentifierInfo *attributes;
00125 const char **constantnames;
00126
00127 const nsXPTConstant *constantinfo;
00128
00129
00130 NS_PRECONDITION(interfaceinfo, "null pointer");
00131
00132 iinfo = (InterfaceInfo *)memmgr->Alloc(sizeof(InterfaceInfo));
00133
00134 interfaceinfo->GetParent(&parent);
00135 if (parent)
00136 {
00137 parent->GetMethodCount(&baseimethodindex);
00138 parent->GetConstantCount(&baseconstantindex);
00139 } else
00140 {
00141 baseimethodindex = 0;
00142 baseconstantindex = 0;
00143 }
00144
00145 interfaceinfo->GetMethodCount(&imethodcount);
00146 interfaceinfo->GetConstantCount(&constantcount);
00147
00148 if (imethodcount - baseimethodindex)
00149 {
00150 imethods = (MethodInfo *)memmgr->Alloc(sizeof(MethodInfo) * (imethodcount - baseimethodindex));
00151 memset(imethods, 0, sizeof(MethodInfo) * (imethodcount - baseimethodindex));
00152 } else
00153 {
00154 imethods = NULL;
00155 }
00156
00157
00158 baseattributeindex = 0;
00159 basemethodindex = 0;
00160 attributecount = 0;
00161 methodcount = 0;
00162
00163 for (i = 0; i < imethodcount; i++)
00164 {
00165 idinfo = GetIdentifierInfo(interfaceinfo, i);
00166
00167 if (idinfo.type & INTERFACEINFO_METHOD)
00168 {
00169 methodcount++;
00170 if (i < baseimethodindex)
00171 {
00172 basemethodindex++;
00173 }
00174
00175 } else
00176 {
00177 if ((idinfo.type & INTERFACEINFO_GETTER)
00178 && (idinfo.type & INTERFACEINFO_SETTER))
00179 {
00180 i++;
00181 }
00182
00183 attributecount++;
00184 if (i < baseimethodindex)
00185 {
00186 baseattributeindex++;
00187 }
00188 }
00189 }
00190
00191
00192 if (attributecount)
00193 {
00194 attributes = (IdentifierInfo *)memmgr->Alloc(sizeof(IdentifierInfo) * attributecount + sizeof(char *));
00195 attributes[attributecount].name = NULL;
00196 } else
00197 {
00198 attributes = NULL;
00199 }
00200
00201 if (methodcount)
00202 {
00203 methods = (IdentifierInfo *)memmgr->Alloc(sizeof(IdentifierInfo) * methodcount + sizeof(char *));
00204 methods[methodcount].name = NULL;
00205 } else
00206 {
00207 methods = NULL;
00208 }
00209
00210
00211 attributecount = 0;
00212 methodcount = 0;
00213
00214 for (i = 0; i < imethodcount; i++)
00215 {
00216 idinfo = GetIdentifierInfo(interfaceinfo, i);
00217
00218 if (idinfo.type & INTERFACEINFO_METHOD)
00219 {
00220 methods[methodcount] = idinfo;
00221 methodcount++;
00222 } else
00223 {
00224 if ((idinfo.type & INTERFACEINFO_GETTER)
00225 && (idinfo.type & INTERFACEINFO_SETTER))
00226 {
00227 i++;
00228 }
00229
00230 attributes[attributecount] = idinfo;
00231 attributecount++;
00232 }
00233 }
00234
00235
00236 if (constantcount)
00237 {
00238 constantnames = (const char **)memmgr->Alloc(sizeof(char *) * (constantcount + 1));
00239 constantnames[constantcount] = NULL;
00240 } else
00241 {
00242 constantnames = NULL;
00243 }
00244
00245 if (constantcount - baseconstantindex)
00246 {
00247 constantvalues = (Tcl_Obj **)memmgr->Alloc(sizeof(Tcl_Obj *) * (constantcount - baseconstantindex));
00248 memset(constantvalues, 0, sizeof(Tcl_Obj *) * (constantcount - baseconstantindex));
00249 } else
00250 {
00251 constantvalues = NULL;
00252 }
00253
00254 for (i = 0; i < constantcount; i++)
00255 {
00256 interfaceinfo->GetConstant(i, &constantinfo);
00257 constantnames[i] = constantinfo->GetName();
00258 }
00259
00260
00261 NS_ADDREF(interfaceinfo);
00262
00263
00264 iinfo->info = interfaceinfo;
00265 iinfo->parentinfo = parent;
00266
00267 iinfo->imethodcount = imethodcount;
00268 iinfo->methodcount = methodcount;
00269 iinfo->attributecount = attributecount;
00270 iinfo->constantcount = constantcount;
00271
00272 iinfo->baseimethodindex = baseimethodindex;
00273 iinfo->baseconstantindex = baseconstantindex;
00274 iinfo->baseattributeindex = baseattributeindex;
00275 iinfo->basemethodindex = basemethodindex;
00276
00277 iinfo->imethods = imethods;
00278 iinfo->methods = methods;
00279 iinfo->attributes = attributes;
00280 iinfo->constantnames = (char **)constantnames;
00281 iinfo->constantvalues = constantvalues;
00282
00283 return iinfo;
00284 }
00285
00286
00290 void
00291 FreeInterfaceInfo(
00292 InterfaceInfo *iinfo
00293 )
00294 {
00295 PRUint16 i;
00296 MethodInfo *minfo;
00297
00298 NS_PRECONDITION(iinfo, "null pointer");
00299
00300 for (i = 0; i < iinfo->imethodcount; i++)
00301 {
00302 minfo = &iinfo->imethods[i];
00303 if (minfo->tclparams)
00304 {
00305 memmgr->Free(minfo->tclparams);
00306 memmgr->Free(minfo->paraminfos);
00307 }
00308 }
00309
00310 for (i = 0; i < iinfo->constantcount; i++)
00311 {
00312 if (iinfo->constantvalues[i])
00313 {
00314 Tcl_DecrRefCount(iinfo->constantvalues[i]);
00315 }
00316 }
00317
00318 if (iinfo->imethods)
00319 {
00320 memmgr->Free(iinfo->imethods);
00321 }
00322
00323 if (iinfo->attributes)
00324 {
00325 memmgr->Free(iinfo->attributes);
00326 }
00327
00328 if (iinfo->methods)
00329 {
00330 memmgr->Free(iinfo->methods);
00331 }
00332
00333 if (iinfo->constantnames)
00334 {
00335 memmgr->Free(iinfo->constantnames);
00336 }
00337
00338 if (iinfo->constantvalues)
00339 {
00340 memmgr->Free(iinfo->constantvalues);
00341 }
00342
00343 NS_RELEASE(iinfo->info);
00344
00345 if (iinfo->parentinfo)
00346 {
00347 NS_RELEASE(iinfo->parentinfo);
00348 }
00349
00350 memmgr->Free(iinfo);
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00378 void
00379 CalculateSharedParams(
00380 nsXPTParamInfo *indep,
00381 nsXPTParamInfo *dep,
00382 PRUint8 indepindex,
00383 PRUint8 depindex,
00384 PRUint16 *tclparams
00385 )
00386 {
00387 NS_PRECONDITION(indep, "null pointer");
00388 NS_PRECONDITION(dep, "null pointer");
00389 NS_PRECONDITION(tclparams, "null pointer");
00390
00391 if (dep->IsIn())
00392 {
00393 tclparams[indepindex] |= PARAM_IS_SKIPPED_IN;
00394 }
00395
00396 if (dep->IsOut())
00397 {
00398 tclparams[indepindex] |= PARAM_IS_SKIPPED_OUT;
00399 }
00400
00401 if (indep->IsIn() && dep->IsIn())
00402 {
00403 if (tclparams[indepindex] & PARAM_IS_SHARED_IN)
00404 {
00405 tclparams[depindex] |= PARAM_IS_SHARED_IN;
00406 }
00407 tclparams[indepindex] |= PARAM_IS_SHARED_IN;
00408 }
00409
00410 if (indep->IsOut() && dep->IsOut())
00411 {
00412 if (tclparams[indepindex] & PARAM_IS_SHARED_OUT)
00413 {
00414 tclparams[depindex] |= PARAM_IS_SHARED_OUT;
00415 }
00416 tclparams[indepindex] |= PARAM_IS_SHARED_OUT;
00417 }
00418
00419 if (indep->IsIn() && !indep->IsOut() && dep->IsOut())
00420 {
00421 tclparams[depindex] |= PARAM_IS_SHARED_OUT;
00422 }
00423 }
00424
00425
00431 PRUint8
00432 PrepareParamInfo(
00433 PRUint16 *tclparams,
00434 nsXPTParamInfo *paraminfos,
00435 PRUint8 paramcount,
00436 nsIInterfaceInfo *interfaceinfo,
00437 PRUint16 methodindex
00438 )
00439 {
00440 PRUint8 i;
00441 PRUint8 tclparamcount;
00442 PRUint8 iidindex, lengthindex, sizeindex;
00443
00444 NS_PRECONDITION(tclparams, "null pointer");
00445 NS_PRECONDITION(paraminfos, "null pointer");
00446 NS_PRECONDITION(interfaceinfo, "null pointer");
00447
00448 for (i = 0; i < paramcount; i++)
00449 {
00450 tclparams[i] = 0;
00451
00452 if (!paraminfos[i].IsIn())
00453 {
00454 tclparams[i] |= PARAM_IS_SKIPPED_IN;
00455 }
00456
00457 if (!paraminfos[i].IsOut())
00458 {
00459 tclparams[i] |= PARAM_IS_SKIPPED_OUT;
00460 }
00461 }
00462
00463 for (i = 0; i < paramcount; i++)
00464 {
00465 if (paraminfos[i].GetType().IsDependent())
00466 {
00467 if (paraminfos[i].GetType().IsInterfacePointer())
00468 {
00469 interfaceinfo->GetInterfaceIsArgNumberForParam(methodindex, ¶minfos[i], &iidindex);
00470 CalculateSharedParams(¶minfos[iidindex], ¶minfos[i], iidindex, i, tclparams);
00471 } else
00472 {
00473 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, ¶minfos[i], 0, &lengthindex);
00474 interfaceinfo->GetSizeIsArgNumberForParam(methodindex, ¶minfos[i], 0, &sizeindex);
00475 CalculateSharedParams(¶minfos[lengthindex], ¶minfos[i], lengthindex, i, tclparams);
00476 if (lengthindex != sizeindex)
00477 {
00478 CalculateSharedParams(¶minfos[sizeindex], ¶minfos[i], sizeindex, i, tclparams);
00479 }
00480 }
00481 }
00482 }
00483
00484 tclparamcount = 0;
00485
00486 for (i = 0; i < paramcount; i++)
00487 {
00488 if ((tclparams[i] & PARAM_IS_SKIPPED_IN) && (tclparams[i] & PARAM_IS_SKIPPED_OUT))
00489 {
00490 tclparams[i] |= PARAM_IS_SKIPPED;
00491 } else
00492 {
00493 if (paraminfos[i].IsRetval())
00494 {
00495 tclparams[i] |= PARAM_IS_RETVAL;
00496 } else
00497 {
00498 tclparams[i] |= (tclparamcount & PARAM_INDEX_MASK);
00499 tclparamcount++;
00500 }
00501 }
00502 }
00503
00504 return tclparamcount;
00505 }
00506
00507
00511 void
00512 PrepareMethodInfo(
00513 nsIInterfaceInfo *interfaceinfo,
00514 MethodInfo *minfo,
00515 PRUint16 methodindex
00516 )
00517 {
00518 PRUint8 i, paramcount;
00519 const nsXPTMethodInfo *methodinfo;
00520
00521 NS_PRECONDITION(interfaceinfo, "null pointer");
00522 NS_PRECONDITION(minfo, "null pointer");
00523
00524 if (minfo->tclparams)
00525 {
00526 return;
00527 }
00528
00529 interfaceinfo->GetMethodInfo(methodindex, &methodinfo);
00530 paramcount = methodinfo->GetParamCount();
00531
00532 minfo->paramcount = paramcount;
00533 minfo->paraminfos = (nsXPTParamInfo *)memmgr->Alloc(sizeof(nsXPTParamInfo) * paramcount);
00534 minfo->tclparams = (PRUint16 *)memmgr->Alloc(sizeof(PRUint16) * paramcount);
00535
00536 for (i = 0; i < paramcount; i++)
00537 {
00538 minfo->paraminfos[i] = methodinfo->GetParam(i);
00539 }
00540
00541 minfo->tclparamcount = PrepareParamInfo(minfo->tclparams, minfo->paraminfos, paramcount, interfaceinfo, methodindex);
00542 }
00543
00544
00548 void
00549 PrepareInterfaceConstantValue(
00550 nsIInterfaceInfo *interfaceinfo,
00551 Tcl_Obj **constantvalue,
00552 PRUint16 constantindex
00553 )
00554 {
00555 const nsXPTCMiniVariant *variant;
00556 const nsXPTConstant *constantinfo;
00557 nsXPTType type;
00558
00559 NS_PRECONDITION(interfaceinfo, "null pointer");
00560 NS_PRECONDITION(constantvalue, "null pointer");
00561
00562 if (*constantvalue)
00563 {
00564 return;
00565 }
00566
00567 interfaceinfo->GetConstant(constantindex, &constantinfo);
00568 variant = constantinfo->GetValue();
00569 type = constantinfo->GetType();
00570
00571
00572 Native2Tcl((void **)&variant, (void *)variant, &type, NULL, 0, NULL, constantvalue);
00573 Tcl_IncrRefCount(*constantvalue);
00574 }
00575
00576
00582 InterfaceInfo *
00583 GetInterfaceInfo(
00584 nsIInterfaceInfo *interfaceinfo
00585 )
00586 {
00587 int newentry;
00588 Tcl_HashEntry *entry;
00589
00590 NS_PRECONDITION(interfaceinfo, "null pointer");
00591
00592 entry = Tcl_CreateHashEntry(&infohash, (char *)interfaceinfo, &newentry);
00593 if (newentry)
00594 {
00595 Tcl_SetHashValue(entry, NewInterfaceInfo(interfaceinfo));
00596 }
00597
00598 return (InterfaceInfo *)Tcl_GetHashValue(entry);
00599 }
00600
00601
00607 MethodInfo *
00608 GetMethodInfo(
00609 nsIInterfaceInfo *interfaceinfo,
00610 PRUint16 methodindex
00611 )
00612 {
00613 InterfaceInfo *iinfo;
00614
00615 NS_PRECONDITION(interfaceinfo, "null pointer");
00616
00617 iinfo = GetInterfaceInfo(interfaceinfo);
00618
00619 while (methodindex < iinfo->baseimethodindex)
00620 {
00621 iinfo = GetInterfaceInfo(iinfo->parentinfo);
00622 }
00623
00624 PrepareMethodInfo(interfaceinfo, &iinfo->imethods[methodindex - iinfo->baseimethodindex], methodindex);
00625 return &iinfo->imethods[methodindex - iinfo->baseimethodindex];
00626 }
00627
00628
00634 Tcl_Obj *
00635 GetInterfaceConstantValue(
00636 nsIInterfaceInfo *interfaceinfo,
00637 PRUint16 constantindex
00638 )
00639 {
00640 InterfaceInfo *iinfo;
00641 iinfo = GetInterfaceInfo(interfaceinfo);
00642
00643 NS_PRECONDITION(interfaceinfo, "null pointer");
00644
00645 while (constantindex < iinfo->baseconstantindex)
00646 {
00647 iinfo = GetInterfaceInfo(iinfo->parentinfo);
00648 }
00649
00650 PrepareInterfaceConstantValue(interfaceinfo, &iinfo->constantvalues[constantindex - iinfo->baseconstantindex], constantindex);
00651 return iinfo->constantvalues[constantindex - iinfo->baseconstantindex];
00652 }
00653
00654
00660 int
00661 TclXPCOM_GetIdentifierInfoFromInterface(
00662 Tcl_Interp *interp,
00663 nsIInterfaceInfo *interfaceinfo,
00664 Tcl_Obj *identifier,
00665 int type,
00666 IdentifierInfo **idinfo
00667 )
00668 {
00669 int rv;
00670 int index;
00671 PRUint16 count;
00672 char *name;
00673 IdentifierInfo *idinfos;
00674 InterfaceInfo *iinfo;
00675
00676 NS_PRECONDITION(interp, "null pointer");
00677 NS_PRECONDITION(interfaceinfo, "null pointer");
00678 NS_PRECONDITION(identifier, "null pointer");
00679 NS_PRECONDITION(((type == INTERFACEINFO_METHOD) || (type == INTERFACEINFO_SETTER) || (type == INTERFACEINFO_GETTER)), "invalid identifier type code");
00680 NS_PRECONDITION(idinfo, "null pointer");
00681
00682 iinfo = GetInterfaceInfo(interfaceinfo);
00683
00684 switch (type)
00685 {
00686 case INTERFACEINFO_METHOD:
00687 count = iinfo->methodcount;
00688 idinfos = iinfo->methods;
00689 name = "method";
00690 break;
00691
00692 case INTERFACEINFO_SETTER:
00693 case INTERFACEINFO_GETTER:
00694 count = iinfo->attributecount;
00695 idinfos = iinfo->attributes;
00696 name = "attribute";
00697 break;
00698 }
00699
00700 Tcl_ResetResult(interp);
00701 if (count)
00702 {
00703 rv = Tcl_GetIndexFromObjStruct(interp, identifier, (char **)&idinfos[0].name, sizeof(IdentifierInfo), name, 0, &index);
00704 if (rv != TCL_OK)
00705 {
00706 return rv;
00707 }
00708
00709 } else
00710 {
00711 Tcl_AppendResult(interp, "no ", name, "s in interface", NULL);
00712 return TCL_ERROR;
00713 }
00714
00715 *idinfo = &idinfos[index];
00716 return TCL_OK;
00717 }
00718
00719
00725 int
00726 TclXPCOM_GetMethodIndex(
00727 Tcl_Interp *interp,
00728 IdentifierInfo *idinfo,
00729 int type,
00730 PRUint16 *methodindex
00731 )
00732 {
00733 PRUint16 index;
00734
00735 NS_PRECONDITION(interp, "null pointer");
00736 NS_PRECONDITION(idinfo, "null pointer");
00737 NS_PRECONDITION(((type == INTERFACEINFO_METHOD) || (type == INTERFACEINFO_SETTER) || (type == INTERFACEINFO_GETTER)), "invalid identifier type code");
00738 NS_PRECONDITION(methodindex, "null pointer");
00739
00740 switch (type)
00741 {
00742 case INTERFACEINFO_METHOD:
00743 index = idinfo->indices.methodindex;
00744 break;
00745
00746 case INTERFACEINFO_GETTER:
00747 index = idinfo->indices.attributeindices.getterindex;
00748 if (!(idinfo->type & INTERFACEINFO_GETTER))
00749 {
00750 Tcl_AppendResult(interp, "attribute is write-only", NULL);
00751 return TCL_ERROR;
00752 }
00753 break;
00754
00755 case INTERFACEINFO_SETTER:
00756 index = idinfo->indices.attributeindices.setterindex;
00757 if (!(idinfo->type & INTERFACEINFO_SETTER))
00758 {
00759 Tcl_AppendResult(interp, "attribute is read-only", NULL);
00760 return TCL_ERROR;
00761 }
00762 break;
00763 }
00764
00765 *methodindex = index;
00766 return TCL_OK;
00767 }
00768
00769
00775 int
00776 TclXPCOM_GetConstant(
00777 Tcl_Interp *interp,
00778 nsIInterfaceInfo *interfaceinfo,
00779 Tcl_Obj *constantname,
00780 Tcl_Obj **result
00781 )
00782 {
00783 int rv;
00784 int index;
00785 InterfaceInfo *iinfo;
00786
00787 NS_PRECONDITION(interp, "null pointer");
00788 NS_PRECONDITION(interfaceinfo, "null pointer");
00789 NS_PRECONDITION(constantname, "null pointer");
00790 NS_PRECONDITION(result, "null pointer");
00791
00792 iinfo = GetInterfaceInfo(interfaceinfo);
00793
00794 Tcl_ResetResult(interp);
00795 if (iinfo->constantcount)
00796 {
00797 rv = Tcl_GetIndexFromObj(interp, constantname, iinfo->constantnames, "constant", 0, &index);
00798 if (rv != TCL_OK)
00799 {
00800 return rv;
00801 }
00802
00803 } else
00804 {
00805 Tcl_AppendResult(interp, "no constants in interface", NULL);
00806 return TCL_ERROR;
00807 }
00808
00809 *result = GetInterfaceConstantValue(interfaceinfo, (PRUint16)index);
00810 return TCL_OK;
00811 }
00812
00813
00819 int
00820 IsInInterface(
00821 nsIInterfaceInfo *infoa,
00822 nsIInterfaceInfo *infob
00823 )
00824 {
00825 InterfaceInfo *iinfo;
00826
00827 NS_PRECONDITION(infoa, "null pointer");
00828 NS_PRECONDITION(infob, "null pointer");
00829
00830 do
00831 {
00832 if (infoa == infob)
00833 {
00834 return 1;
00835 }
00836
00837 iinfo = GetInterfaceInfo(infob);
00838 infob = iinfo->parentinfo;
00839
00840 } while (infob);
00841
00842 return 0;
00843 }
00844
00845
00849 void
00850 TclXPCOM_InitInterfaceInfo(void)
00851 {
00852 Tcl_InitHashTable(&infohash, TCL_ONE_WORD_KEYS);
00853 }