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
00048 void
00049 InterpDeletedCallback(
00050 ClientData clientData,
00051 Tcl_Interp *interp
00052 )
00053 {
00054 NS_PRECONDITION(clientData, "null pointer");
00055 NS_PRECONDITION(interp, "null pointer");
00056
00057 char str[128];
00058 sprintf(str, "Interpreter for Component %p has been killed", clientData);
00059 NS_WARNING(str);
00060
00061 ((TclXPCOMComponent *)clientData)->interp = NULL;
00062 }
00063
00064
00070 TclXPCOMComponent *
00071 NewTclXPCOMComponent(
00072 Tcl_Interp *interp,
00073 Tcl_ThreadId thread,
00074 ClassInfo *cinfo
00075 )
00076 {
00077 int i;
00078 TclXPCOMComponent *component;
00079
00080 NS_PRECONDITION(interp, "null pointer");
00081
00082 NS_PRECONDITION(cinfo, "null pointer");
00083
00084 component = (TclXPCOMComponent *)memmgr->Alloc(sizeof(TclXPCOMComponent));
00085
00086 component->stubs = (TclXPCOMStub **)memmgr->Alloc(sizeof(TclXPCOMStub *) * cinfo->signature.infocount);
00087
00088 for (i = 0; i < cinfo->signature.infocount; i++)
00089 {
00090 component->stubs[i] = new TclXPCOMStub(cinfo->signature.infolist[i]);
00091 }
00092
00093 component->refcount = 0;
00094 component->interp = interp;
00095 component->thread = thread;
00096 component->cinfo = cinfo;
00097 component->destructor = NULL;
00098 component->nesting = 0;
00099
00100 for (i = 0; i < cinfo->signature.infocount; i++)
00101 {
00102 component->stubs[i]->component = component;
00103 }
00104
00105 Tcl_CallWhenDeleted(interp, InterpDeletedCallback, (ClientData)component);
00106
00107 return component;
00108 }
00109
00110
00114 void
00115 UnsetDestructorBinding(
00116 TclXPCOMComponent *component
00117 )
00118 {
00119 NS_PRECONDITION(component, "null pointer");
00120
00121 if (component->destructor)
00122 {
00123 Tcl_DecrRefCount(component->destructor);
00124 component->destructor = NULL;
00125 }
00126 }
00127
00128
00133 void
00134 SetDestructorBinding(
00135 TclXPCOMComponent *component,
00136 Tcl_Obj *script
00137 )
00138 {
00139 NS_PRECONDITION(component, "null pointer");
00140 NS_PRECONDITION(script, "null pointer");
00141
00142 if (component->destructor)
00143 {
00144 UnsetDestructorBinding(component);
00145 }
00146
00147 component->destructor = script;
00148 Tcl_IncrRefCount(component->destructor);
00149 }
00150
00151
00155 void
00156 FreeTclXPCOMComponent(
00157 TclXPCOMComponent *component
00158 )
00159 {
00160 int i;
00161
00162 NS_PRECONDITION(component, "null pointer");
00163
00164 if (component->interp)
00165 {
00166 Tcl_DontCallWhenDeleted(component->interp, InterpDeletedCallback, (ClientData)component);
00167 }
00168
00169 UnsetDestructorBinding(component);
00170
00171 for (i = 0; i < component->cinfo->signature.infocount; i++)
00172 {
00173 delete component->stubs[i];
00174 }
00175
00176 memmgr->Free(component->stubs);
00177 }
00178
00179
00189 int
00190 BindScript(
00191 Tcl_Interp *interp,
00192 TclXPCOMComponent *component,
00193 Tcl_Obj *identifier,
00194 Tcl_Obj *script,
00195 int flags
00196 )
00197 {
00198 int rv;
00199 int i;
00200 int length;
00201
00202 int index;
00203 PRUint16 identifiercount;
00204 PRUint16 methodindex, getterindex, setterindex;
00205
00206 nsIInterfaceInfo *info;
00207 IdentifierInfo *idinfo;
00208 ClassIdentifierInfo *identifiers;
00209
00210 NS_PRECONDITION(interp, "null pointer");
00211 NS_PRECONDITION(component, "null pointer");
00212 NS_PRECONDITION(identifier, "null pointer");
00213 NS_PRECONDITION(script, "null pointer");
00214 NS_PRECONDITION(!(flags & ~(FORCE_HIDDEN | FORCE_NOTXPCOM | FORCE_NOTSCRIPTABLE)), "invalid flags");
00215
00216 if (strlen(Tcl_GetString(identifier)) == 0)
00217 {
00218 if (component->destructor)
00219 {
00220 Tcl_ResetResult(interp);
00221 Tcl_AppendResult(interp, "destructor is already bound", NULL);
00222 return TCL_ERROR;
00223 }
00224
00225 SetDestructorBinding(component, script);
00226 return TCL_OK;
00227 }
00228
00229 rv = Tcl_ListObjLength(interp, script, &length);
00230 if (rv != TCL_OK)
00231 {
00232 Tcl_ResetResult(interp);
00233 Tcl_AppendResult(interp, "binding \"", Tcl_GetString(script), "\" is not a valid list", NULL);
00234 return TCL_ERROR;
00235 }
00236
00237 identifiercount = component->cinfo->attributecount + component->cinfo->methodcount;
00238 if (identifiercount)
00239 {
00240 identifiers = (ClassIdentifierInfo *)memmgr->Alloc(sizeof(ClassIdentifierInfo) * identifiercount + sizeof(char *));
00241 memcpy(&identifiers[0], &component->cinfo->attributes[0], sizeof(ClassIdentifierInfo) * component->cinfo->attributecount);
00242 memcpy(&identifiers[component->cinfo->attributecount], &component->cinfo->methods[0], sizeof(ClassIdentifierInfo) * component->cinfo->methodcount);
00243 identifiers[identifiercount].idinfo.name = NULL;
00244
00245 rv = Tcl_GetIndexFromObjStruct(interp, identifier, (char **)&identifiers[0].idinfo.name, sizeof(ClassIdentifierInfo), "method or attribute", 0, &index);
00246
00247 if (rv == TCL_OK)
00248 {
00249 idinfo = &identifiers[index].idinfo;
00250 info = identifiers[index].info;
00251 rv = TclXPCOM_CheckInterfaceIsReflectable(interp, info, flags);
00252 }
00253
00254 if (rv == TCL_OK)
00255 {
00256 if ((idinfo->type & INTERFACEINFO_METHOD)
00257 || (idinfo->type & INTERFACEINFO_GETTER))
00258 {
00259 methodindex = idinfo->indices.methodindex;
00260 getterindex = idinfo->indices.attributeindices.getterindex;
00261 rv = TclXPCOM_CheckMethodIsReflectable(interp, info, methodindex, flags);
00262 }
00263 }
00264
00265 if (rv == TCL_OK)
00266 {
00267 if (idinfo->type & INTERFACEINFO_SETTER)
00268 {
00269 setterindex = idinfo->indices.attributeindices.setterindex;
00270 rv = TclXPCOM_CheckMethodIsReflectable(interp, info, setterindex, flags);
00271 }
00272 }
00273
00274 if (rv == TCL_OK)
00275 {
00276 if (idinfo->type & INTERFACEINFO_METHOD)
00277 {
00278 for (i = 0; i < component->cinfo->signature.infocount; i++)
00279 {
00280 if (IsInInterface(info, component->cinfo->signature.infolist[i]))
00281 {
00282 component->stubs[i]->SetBinding(methodindex, script);
00283 }
00284 }
00285 } else
00286 {
00287 for (i = 0; i < component->cinfo->signature.infocount; i++)
00288 {
00289 if (IsInInterface(info, component->cinfo->signature.infolist[i]))
00290 {
00291 if (idinfo->type & INTERFACEINFO_GETTER)
00292 {
00293 component->stubs[i]->SetBinding(getterindex, script);
00294 }
00295
00296 if (idinfo->type & INTERFACEINFO_SETTER)
00297 {
00298 component->stubs[i]->SetBinding(setterindex, script);
00299 }
00300 }
00301 }
00302 }
00303 }
00304
00305 memmgr->Free(identifiers);
00306 return rv;
00307 } else
00308 {
00309 Tcl_AppendResult(interp, "no methods or attributes in class", NULL);
00310 return TCL_ERROR;
00311 }
00312 }
00313