home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2005 December
/
PCWorld_2005-12_cd.bin
/
komunikace
/
netscape
/
nsb-install-8-0.exe
/
components
/
nsInterfaceInfoToIDL.js
< prev
next >
Wrap
Text File
|
2005-09-26
|
19KB
|
590 lines
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* The nsInterfaceInfoToIDL implementation.*/
/***************************************************************************/
// nsInterfaceInfoToIDL part...
const IInfo = new Components.Constructor("@mozilla.org/scriptableInterfaceInfo;1",
"nsIScriptableInterfaceInfo",
"init");
const nsIDataType = Components.interfaces.nsIDataType;
const nsISupports = Components.interfaces.nsISupports;
const PARAM_NAME_PREFIX = "arg";
const MISSING_INTERFACE = "@"; // flag to indicate missing interfaceinfo
// helpers...
/********************************************************/
// accumulate a string with a stream-ish abstraction
function Buffer() {
this.buffer = "";
}
Buffer.prototype = {
write : function(s) {
if(s)
this.buffer += s;
},
writeln : function(s) {
if(s)
this.buffer += s + "\n";
else
this.buffer += "\n";
}
}
/********************************************************/
/**
* takes: {xxx}
* returns: uuid(xxx)
*/
function formatID(str)
{
return "uuid("+str.substring(1,str.length-1)+")";
}
function formatConstType(type)
{
switch(type)
{
case nsIDataType.VTYPE_INT16:
return "PRInt16";
case nsIDataType.VTYPE_INT32:
return "PRInt32";
case nsIDataType.VTYPE_UINT16:
return "PRUint16";
case nsIDataType.VTYPE_UINT32:
return "PRUint32";
default:
return "!!!! bad const type !!!";
}
}
function formatTypeName(info, methodIndex, param, dimension)
{
var type = info.getTypeForParam(methodIndex, param, dimension);
switch(type.dataType)
{
case nsIDataType.VTYPE_INT8 :
return "PRInt8";
case nsIDataType.VTYPE_INT16:
return "PRInt16";
case nsIDataType.VTYPE_INT32:
return "PRInt32";
case nsIDataType.VTYPE_INT64:
return "PRInt64";
case nsIDataType.VTYPE_UINT8:
return "PRUint8";
case nsIDataType.VTYPE_UINT16:
return "PRUint16";
case nsIDataType.VTYPE_UINT32:
return "PRUint32";
case nsIDataType.VTYPE_UINT64:
return "PRUint64";
case nsIDataType.VTYPE_FLOAT:
return "float";
case nsIDataType.VTYPE_DOUBLE:
return "double";
case nsIDataType.VTYPE_BOOL:
return "PRBool";
case nsIDataType.VTYPE_CHAR:
return "char";
case nsIDataType.VTYPE_WCHAR:
return "PRUnichar";
case nsIDataType.VTYPE_VOID:
if(type.isPointer)
return "voidPtr";
return "void";
case nsIDataType.VTYPE_ID:
// order matters here...
if(type.isReference)
return "nsIDRef";
if(type.isPointer)
return "nsIDPtr";
return "nsID";
case nsIDataType.VTYPE_DOMSTRING:
return "DOMString";
case nsIDataType.VTYPE_CHAR_STR:
return "string";
case nsIDataType.VTYPE_WCHAR_STR:
return "wstring";
case nsIDataType.VTYPE_INTERFACE:
try {
return info.getInfoForParam(methodIndex, param).name;
} catch(e) {
return "/*!!! missing interface info, guessing!!!*/ nsISupports";
}
case nsIDataType.VTYPE_INTERFACE_IS:
return "nsQIResult";
case nsIDataType.VTYPE_ARRAY:
return formatTypeName(info, methodIndex, param, dimension+1);
case nsIDataType.VTYPE_STRING_SIZE_IS:
return "string";
case nsIDataType.VTYPE_WSTRING_SIZE_IS:
return "wstring";
case nsIDataType.VTYPE_UTF8STRING:
return "AUTF8String";
case nsIDataType.VTYPE_CSTRING:
return "ACString";
case nsIDataType.VTYPE_ASTRING:
return "AString";
default:
return "!!!! bad data type !!!";
}
}
function formatBracketForParam(info, methodIndex, param)
{
var type = param.type;
var str = "[";
var found = 0;
var size_is_ArgNum;
var length_is_ArgNum;
if(param.isRetval)
{
if(found++)
str += ", ";
str += "retval"
}
if(param.isShared)
{
if(found++)
str += ", ";
str += "shared"
}
if(type.isArray)
{
if(found++)
str += ", ";
str += "array"
}
if(type.dataType == nsIDataType.VTYPE_INTERFACE_IS)
{
if(found++)
str += ", ";
str += "iid_is("+
PARAM_NAME_PREFIX +
info.getInterfaceIsArgNumberForParam(methodIndex, param) + ")";
}
if(type.isArray ||
type.dataType == nsIDataType.VTYPE_STRING_SIZE_IS ||
type.dataType == nsIDataType.VTYPE_WSTRING_SIZE_IS)
{
if(found++)
str += ", ";
size_is_ArgNum =
info.getSizeIsArgNumberForParam(methodIndex, param, 0);
str += "size_is("+ PARAM_NAME_PREFIX + size_is_ArgNum + ")";
length_is_ArgNum =
info.getLengthIsArgNumberForParam(methodIndex, param, 0);
if(length_is_ArgNum != size_is_ArgNum)
{
str += ", ";
str += "length_is("+ PARAM_NAME_PREFIX + length_is_ArgNum + ")";
}
}
if(!found)
return "";
str += "] ";
return str
}
function doInterface(out, iid)
{
var i, k, t, m, m2, c, p, readonly, bracketed, paramCount, retvalTypeName;
var info = new IInfo(iid);
var parent = info.parent;
var constBaseIndex = parent ? parent.constantCount : 0;
var constTotalCount = info.constantCount;
var constLocalCount = constTotalCount - constBaseIndex;
var methodBaseIndex = parent ? parent.methodCount : 0;
var methodTotalCount = info.methodCount;
var methodLocalCount = methodTotalCount - methodBaseIndex;
// maybe recurring to emit parent declarations is not a good idea...
// if(parent)
// doInterface(parent.interfaceID);
out.writeln();
// comment out nsISupports
// if(iid.equals(nsISupports))
// out.writeln("/*\n");
out.writeln("[" + (info.isScriptable ? "scriptable, " : "") +
formatID(info.interfaceID.number) + "]");
out.writeln("interface "+ info.name +
(parent ? (" : "+parent.name) : "") + " {");
if(constLocalCount)
{
for(i = constBaseIndex; i < constTotalCount; i++)
{
c = info.getConstant(i);
out.writeln(" const " + formatConstType(c.type.dataType) + " " +
c.name + " = " + c.value + ";");
}
}
if(constLocalCount && methodLocalCount)
out.writeln();
if(methodLocalCount)
{
for(i = methodBaseIndex; i < methodTotalCount; i++)
{
m = info.getMethodInfo(i);
if(m.isNotXPCOM)
bracketed = "[notxpcom] "
else if(m.isHidden)
bracketed = "[noscript] "
else
bracketed = "";
if(m.isGetter)
{
// Is an attribute
// figure out if this is readonly
m2 = i+1 < methodTotalCount ? info.getMethodInfo(i+1) : null;
readonly = !m2 || m2.name != m.name;
out.writeln(" " + bracketed + (readonly ? "readonly " : "") +
"attribute " +
formatTypeName(info, i, m.getParam(0), 0) +
" " + m.name + ";\n");
if(!readonly)
i++; // skip the next one, we have it covered.
continue;
}
// else...
paramCount = m.paramCount;
// 'last' param is used to figure out retvalTypeName
p = paramCount ? m.getParam(paramCount-1) : null;
if(m.isNotXPCOM)
retvalTypeName = formatTypeName(info, i, m.result, 0);
else if(p && "[retval] " == formatBracketForParam(info, i, p))
{
// Check for the exact string above because anything else
// indicates that there either is no expilict retval
// or there are additional braketed attributes (meaning that
// the retval must appear in the param list and not
// preceeding the method name).
retvalTypeName = formatTypeName(info, i, p, 0);
// no need to print it in the param list
paramCount-- ;
}
else
retvalTypeName = "void";
// print method name
out.writeln(" " + bracketed + retvalTypeName + " " + m.name +
"(" + (paramCount ? "" : ");"));
// print params
for(k = 0; k < paramCount; k++)
{
p = m.getParam(k);
out.writeln(" "+
formatBracketForParam(info, i, p) +
(p.isOut ? p.isIn ? "inout " : "out " : "in ") +
formatTypeName(info, i, p, 0) + " " +
PARAM_NAME_PREFIX+k +
(k+1 == paramCount ? ");\n" : ", "));
}
}
}
out.writeln("};\n");
// comment out nsISupports
// if(iid.equals(nsISupports))
// out.writeln("\n*/\n");
}
function appendForwardDeclarations(list, info)
{
list.push(info.name);
if(info.parent)
appendForwardDeclarations(list, info.parent);
var i, k, m, p;
for(i = 0; i < info.methodCount; i++)
{
m = info.getMethodInfo(i);
for(k = 0; k < m.paramCount; k++)
{
p = m.getParam(k);
if(p.type.dataType == nsIDataType.VTYPE_INTERFACE)
{
var name;
try {
name = info.getInfoForParam(i, p).name;
} catch(e) {
name = MISSING_INTERFACE;
}
list.push(name);
}
}
}
}
function doForwardDeclarations(out, iid)
{
var i, cur, prev;
var list = [];
appendForwardDeclarations(list, new IInfo(iid));
list.sort();
out.writeln("// forward declarations...");
for(i = 0; i < list.length; i++)
{
cur = list[i];
if(cur != prev && cur != "nsISupports")
{
if(cur == MISSING_INTERFACE)
out.writeln("/*\n * !!! Unable to find details for a declared "+
"interface (name unknown)!!!\n */");
else
out.writeln("interface " + cur +";");
prev = cur;
}
}
}
function buildForwardDeclarationsList(iid)
{
var i, cur, prev;
var list = [];
var outList = [];
appendForwardDeclarations(list, new IInfo(iid));
list.sort();
for(i = 0; i < list.length; i++)
{
cur = list[i];
if(cur != prev && cur != "nsISupports")
{
if(cur != MISSING_INTERFACE)
outList.push(cur);
prev = cur;
}
}
return outList;
}
/*********************************************************/
/* Our Componenent ctor */
function nsInterfaceInfoToIDL() {}
/* decorate prototype to provide ``class'' methods and property accessors */
nsInterfaceInfoToIDL.prototype =
{
// nsIInterfaceInfoToIDL methods...
// string generateIDL(in nsIIDRef aIID,
// in PRBool withIncludes,
// in PRBool withForwardDeclarations);
generateIDL : function(aIID, withIncludes, withForwardDeclarations) {
var out = new Buffer;
out.writeln();
if(withIncludes)
{
out.writeln('#include "nsISupports.idl"');
out.writeln();
}
if(withForwardDeclarations)
{
doForwardDeclarations(out, aIID);
out.writeln("");
}
doInterface(out, aIID);
return out.buffer;
},
// void getReferencedInterfaceNames(in nsIIDRef aIID,
// out PRUint32 aArrayLength,
// [retval, array, size_is(aArrayLength)]
// out string aNames);
getReferencedInterfaceNames : function(aIID, aArrayLength) {
var list = buildForwardDeclarationsList(aIID);
aArrayLength.value = list.length;
return list;
},
// nsISupports methods...
QueryInterface: function (iid) {
if (!iid.equals(Components.interfaces.nsIInterfaceInfoToIDL) &&
!iid.equals(Components.interfaces.nsISupports)) {
throw Components.results.NS_ERROR_NO_INTERFACE;
}
return this;
}
}
/***************************************************************************/
/***************************************************************************/
// parts specific to my use of the the generic module code...
const MODULE_NAME = "nsInterfaceInfoToIDL";
const MODULE_CONTRACT_ID = "@mozilla.org/interfaceinfotoidl;1";
const MODULE_CID = "{47d98974-a1b7-46a6-bc99-8abc374bba3f}";
const MODULE_CTOR = nsInterfaceInfoToIDL;
/***************************************************************************/
/***************************************************************************/
// generic nsIModule part...
function NSGetModule(compMgr, fileSpec) {
return new GenericModule(MODULE_NAME, MODULE_CONTRACT_ID,
MODULE_CID, MODULE_CTOR);
}
function GenericModule (name, contractID, CID, ctor) {
this.name = name;
this.contractID = contractID;
this.CID = Components.ID(CID);
this.ctor = ctor;
}
GenericModule.prototype = {
/*
* RegisterSelf is called at registration time (component installation
* or the only-until-release startup autoregistration) and is responsible
* for notifying the component manager of all components implemented in
* this module. The fileSpec, location and type parameters are mostly
* opaque, and should be passed on to the registerComponent call
* unmolested.
*/
registerSelf: function (compMgr, fileSpec, location, type) {
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compMgr.registerFactoryLocation(this.CID, this.name, this.contractID,
fileSpec, location, type);
},
/*
* The GetClassObject method is responsible for producing Factory and
* SingletonFactory objects (the latter are specialized for services).
*/
getClassObject: function (compMgr, cid, iid) {
if (!cid.equals(this.CID))
throw Components.results.NS_ERROR_NO_INTERFACE;
if (!iid.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
this.myFactory.ctor = this.ctor;
return this.myFactory;
},
/* factory object */
myFactory: {
/*
* Construct an instance of the interface specified by iid, possibly
* aggregating it with the provided outer. (If you don't know what
* aggregation is all about, you don't need to. It reduces even the
* mightiest of XPCOM warriors to snivelling cowards.)
*/
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return (new this.ctor()).QueryInterface(iid);
}
},
/*
* The canUnload method signals that the component is about to be unloaded.
* C++ components can return false to indicate that they don't wish to be
* unloaded, but the return value from JS components' canUnload is ignored:
* mark-and-sweep will keep everything around until it's no longer in use,
* making unconditional ``unload'' safe.
*
* You still need to provide a (likely useless) canUnload method, though:
* it's part of the nsIModule interface contract, and the JS loader _will_
* call it.
*/
canUnload: function(compMgr) {
return true;
}
}
/***************************************************************************/