home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 July & August / PCWorld_2003-07-08_cd.bin / Komunik / firebird / MozillaFirebird-0.6-win32.exe / MozillaFirebird / components / nsInterfaceInfoToIDL.js < prev    next >
Text File  |  2002-10-15  |  19KB  |  590 lines

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: NPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Netscape Public License
  6.  * Version 1.1 (the "License"); you may not use this file except in
  7.  * compliance with the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/NPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is 
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 2002
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or 
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the NPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the NPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. /* The nsInterfaceInfoToIDL implementation.*/
  39.  
  40.  
  41. /***************************************************************************/
  42. // nsInterfaceInfoToIDL part...
  43.  
  44. const IInfo = new Components.Constructor("@mozilla.org/scriptableInterfaceInfo;1",
  45.                                          "nsIScriptableInterfaceInfo",
  46.                                          "init");
  47.  
  48. const nsIDataType = Components.interfaces.nsIDataType;
  49. const nsISupports = Components.interfaces.nsISupports;
  50.  
  51. const PARAM_NAME_PREFIX = "arg";
  52. const MISSING_INTERFACE = "@";  // flag to indicate missing interfaceinfo
  53.  
  54. // helpers...
  55.  
  56. /********************************************************/
  57. // accumulate a string with a stream-ish abstraction
  58.  
  59. function Buffer() {
  60.     this.buffer = "";        
  61. }
  62.  
  63. Buffer.prototype = {
  64.     write : function(s)  {
  65.         if(s)
  66.             this.buffer += s;    
  67.     },
  68.  
  69.     writeln : function(s)  {
  70.         if(s)
  71.             this.buffer += s + "\n";
  72.         else        
  73.             this.buffer += "\n";
  74.     }
  75. }
  76.  
  77. /********************************************************/
  78.  
  79. /**
  80. * takes:   {xxx}
  81. * returns: uuid(xxx)
  82. */
  83. function formatID(str) 
  84. {
  85.     return "uuid("+str.substring(1,str.length-1)+")";
  86. }
  87.  
  88. function formatConstType(type)
  89. {
  90.     switch(type) 
  91.     {
  92.         case nsIDataType.VTYPE_INT16:
  93.             return "PRInt16";
  94.         case nsIDataType.VTYPE_INT32:
  95.             return "PRInt32";
  96.         case nsIDataType.VTYPE_UINT16:
  97.             return "PRUint16";
  98.         case nsIDataType.VTYPE_UINT32:
  99.             return "PRUint32";
  100.         default:
  101.             return "!!!! bad const type !!!";
  102.     }
  103. }
  104.  
  105. function formatTypeName(info, methodIndex, param, dimension) 
  106. {
  107.     var type = info.getTypeForParam(methodIndex, param, dimension);
  108.      
  109.     switch(type.dataType)
  110.     {
  111.         case nsIDataType.VTYPE_INT8 :
  112.             return "PRInt8";
  113.         case nsIDataType.VTYPE_INT16:
  114.             return "PRInt16";
  115.         case nsIDataType.VTYPE_INT32:
  116.             return "PRInt32";
  117.         case nsIDataType.VTYPE_INT64:
  118.             return "PRInt64";
  119.         case nsIDataType.VTYPE_UINT8:
  120.             return "PRUint8";
  121.         case nsIDataType.VTYPE_UINT16:
  122.             return "PRUint16";
  123.         case nsIDataType.VTYPE_UINT32:
  124.             return "PRUint32";
  125.         case nsIDataType.VTYPE_UINT64:
  126.             return "PRUint64";
  127.         case nsIDataType.VTYPE_FLOAT:
  128.             return "float";
  129.         case nsIDataType.VTYPE_DOUBLE:
  130.             return "double";
  131.         case nsIDataType.VTYPE_BOOL:
  132.             return "PRBool";
  133.         case nsIDataType.VTYPE_CHAR:
  134.             return "char";
  135.         case nsIDataType.VTYPE_WCHAR:
  136.             return "PRUnichar";
  137.         case nsIDataType.VTYPE_VOID:
  138.             if(type.isPointer)
  139.                 return "voidPtr";
  140.             return "void";
  141.         case nsIDataType.VTYPE_ID:
  142.             // order matters here...
  143.             if(type.isReference)
  144.                 return "nsIDRef";
  145.             if(type.isPointer)
  146.                 return "nsIDPtr";
  147.             return "nsID";
  148.         case nsIDataType.VTYPE_DOMSTRING:
  149.             return "DOMString";
  150.         case nsIDataType.VTYPE_CHAR_STR:
  151.             return "string";
  152.         case nsIDataType.VTYPE_WCHAR_STR:
  153.             return "wstring";
  154.         case nsIDataType.VTYPE_INTERFACE:
  155.             try  {
  156.                 return info.getInfoForParam(methodIndex, param).name;
  157.             } catch(e) {
  158.                 return "/*!!! missing interface info, guessing!!!*/ nsISupports";    
  159.             }
  160.         case nsIDataType.VTYPE_INTERFACE_IS:
  161.             return "nsQIResult";
  162.         case nsIDataType.VTYPE_ARRAY:
  163.             return formatTypeName(info, methodIndex, param, dimension+1); 
  164.         case nsIDataType.VTYPE_STRING_SIZE_IS:
  165.             return "string";
  166.         case nsIDataType.VTYPE_WSTRING_SIZE_IS:
  167.             return "wstring";
  168.         case nsIDataType.VTYPE_UTF8STRING:
  169.             return "AUTF8String";
  170.         case nsIDataType.VTYPE_CSTRING:
  171.             return "ACString";
  172.         case nsIDataType.VTYPE_ASTRING:
  173.             return "AString";
  174.         default:
  175.             return "!!!! bad data type !!!";
  176.     }
  177. }
  178.  
  179. function formatBracketForParam(info, methodIndex, param)
  180. {
  181.     var type = param.type;
  182.     var str = "[";
  183.     var found = 0;
  184.     var size_is_ArgNum;
  185.     var length_is_ArgNum;
  186.  
  187.     if(param.isRetval)
  188.     {
  189.         if(found++)    
  190.             str += ", ";
  191.         str += "retval"
  192.     }
  193.  
  194.     if(param.isShared)
  195.     {
  196.         if(found++)    
  197.             str += ", ";
  198.         str += "shared"
  199.     }
  200.  
  201.     if(type.isArray)
  202.     {
  203.         if(found++)    
  204.             str += ", ";
  205.         str += "array"
  206.     }
  207.  
  208.     if(type.dataType == nsIDataType.VTYPE_INTERFACE_IS)
  209.     {
  210.         if(found++)    
  211.             str += ", ";
  212.         str += "iid_is("+ 
  213.                  PARAM_NAME_PREFIX + 
  214.                  info.getInterfaceIsArgNumberForParam(methodIndex, param) + ")";
  215.     }
  216.  
  217.     if(type.isArray ||
  218.        type.dataType == nsIDataType.VTYPE_STRING_SIZE_IS ||
  219.        type.dataType == nsIDataType.VTYPE_WSTRING_SIZE_IS)
  220.     {
  221.         if(found++)    
  222.             str += ", ";
  223.  
  224.         size_is_ArgNum =
  225.             info.getSizeIsArgNumberForParam(methodIndex, param, 0);
  226.  
  227.         str += "size_is("+ PARAM_NAME_PREFIX + size_is_ArgNum + ")";
  228.  
  229.         length_is_ArgNum =
  230.             info.getLengthIsArgNumberForParam(methodIndex, param, 0);
  231.  
  232.         if(length_is_ArgNum != size_is_ArgNum)
  233.         {
  234.             str += ", ";
  235.             str += "length_is("+ PARAM_NAME_PREFIX + length_is_ArgNum + ")";
  236.         }
  237.     }
  238.  
  239.     if(!found)
  240.         return "";
  241.     str += "] ";
  242.     return str
  243. }
  244.  
  245. function doInterface(out, iid)
  246. {
  247.     var i, k, t, m, m2, c, p, readonly, bracketed, paramCount, retvalTypeName;
  248.  
  249.     var info = new IInfo(iid);
  250.     var parent = info.parent;
  251.  
  252.     var constBaseIndex = parent ? parent.constantCount : 0;
  253.     var constTotalCount =  info.constantCount;
  254.     var constLocalCount = constTotalCount - constBaseIndex;
  255.     
  256.     var methodBaseIndex = parent ? parent.methodCount : 0;
  257.     var methodTotalCount =  info.methodCount;
  258.     var methodLocalCount = methodTotalCount - methodBaseIndex;
  259.  
  260.     
  261.     // maybe recurring to emit parent declarations is not a good idea...
  262. //    if(parent)
  263. //        doInterface(parent.interfaceID);
  264.  
  265.     out.writeln();
  266.     
  267.     // comment out nsISupports
  268. //    if(iid.equals(nsISupports))
  269. //        out.writeln("/*\n");
  270.  
  271.     out.writeln("[" + (info.isScriptable ? "scriptable, " : "") +
  272.                 formatID(info.interfaceID.number) + "]");
  273.  
  274.     out.writeln("interface "+ info.name + 
  275.                    (parent ? (" : "+parent.name) : "") + " {");
  276.  
  277.     if(constLocalCount)
  278.     {
  279.         for(i = constBaseIndex; i < constTotalCount; i++)
  280.         {
  281.             c = info.getConstant(i);
  282.             out.writeln("  const " + formatConstType(c.type.dataType) + " " +
  283.                         c.name + " = " + c.value + ";");
  284.         }
  285.     }    
  286.  
  287.     if(constLocalCount && methodLocalCount)
  288.         out.writeln();
  289.  
  290.     if(methodLocalCount)
  291.     {
  292.         for(i = methodBaseIndex; i < methodTotalCount; i++)
  293.         {
  294.             m = info.getMethodInfo(i);
  295.  
  296.             if(m.isNotXPCOM)
  297.                 bracketed = "[notxpcom] " 
  298.             else if(m.isHidden)
  299.                 bracketed = "[noscript] " 
  300.             else
  301.                 bracketed = "";
  302.  
  303.             if(m.isGetter)
  304.             {
  305.                 // Is an attribute
  306.  
  307.                 // figure out if this is readonly
  308.                 m2 = i+1 < methodTotalCount ? info.getMethodInfo(i+1) : null;
  309.                 readonly = !m2 || m2.name != m.name;
  310.  
  311.                 out.writeln("  " + bracketed + (readonly ? "readonly " : "") +
  312.                             "attribute " +
  313.                             formatTypeName(info, i, m.getParam(0), 0) +
  314.                             " " + m.name + ";\n");
  315.  
  316.                 if(!readonly)
  317.                     i++; // skip the next one, we have it covered.    
  318.             
  319.                 continue;
  320.             }
  321.             // else...
  322.  
  323.             paramCount = m.paramCount;
  324.  
  325.             // 'last' param is used to figure out retvalTypeName
  326.  
  327.             p = paramCount ? m.getParam(paramCount-1) : null;
  328.  
  329.             if(m.isNotXPCOM)
  330.                 retvalTypeName = formatTypeName(info, i, m.result, 0);
  331.             else if(p && "[retval] " == formatBracketForParam(info, i, p))
  332.             {
  333.                 // Check for the exact string above because anything else
  334.                 // indicates that there either is no expilict retval
  335.                 // or there are additional braketed attributes (meaning that
  336.                 // the retval must appear in the param list and not
  337.                 // preceeding the method name).
  338.                 retvalTypeName = formatTypeName(info, i, p, 0);
  339.                 // no need to print it in the param list
  340.                 paramCount-- ;
  341.             }       
  342.             else    
  343.                 retvalTypeName = "void";
  344.             
  345.             // print method name
  346.  
  347.             out.writeln("  " + bracketed + retvalTypeName + " " + m.name + 
  348.                         "(" + (paramCount ? "" : ");"));
  349.  
  350.             // print params
  351.  
  352.             for(k = 0; k < paramCount; k++)
  353.             {
  354.                 p = m.getParam(k);
  355.                 out.writeln("              "+ 
  356.                             formatBracketForParam(info, i, p) +
  357.                             (p.isOut ? p.isIn ? "inout " : "out " : "in ") +
  358.                             formatTypeName(info, i, p, 0) + " " +
  359.                             PARAM_NAME_PREFIX+k +
  360.                             (k+1 == paramCount ? ");\n" : ", "));
  361.             }
  362.         }
  363.     }
  364.  
  365.     out.writeln("};\n");
  366.  
  367.     // comment out nsISupports
  368. //    if(iid.equals(nsISupports))
  369. //        out.writeln("\n*/\n");
  370. }
  371.  
  372. function appendForwardDeclarations(list, info)
  373. {
  374.     list.push(info.name);
  375.     if(info.parent)
  376.         appendForwardDeclarations(list, info.parent);
  377.  
  378.     var i, k, m, p;
  379.  
  380.     for(i = 0; i < info.methodCount; i++)
  381.     {
  382.         m = info.getMethodInfo(i);
  383.         
  384.         for(k = 0; k < m.paramCount; k++)
  385.         {
  386.             p = m.getParam(k);
  387.             
  388.             if(p.type.dataType == nsIDataType.VTYPE_INTERFACE)
  389.             {
  390.                 var name;
  391.                 try {
  392.                     name = info.getInfoForParam(i, p).name;
  393.                 } catch(e)  {
  394.                     name = MISSING_INTERFACE;                  
  395.                 }
  396.                 list.push(name);
  397.             }
  398.         }
  399.     }
  400. }    
  401.  
  402. function doForwardDeclarations(out, iid)
  403. {
  404.     var i, cur, prev;
  405.     var list = [];
  406.     appendForwardDeclarations(list, new IInfo(iid));
  407.     list.sort();
  408.     
  409.     out.writeln("// forward declarations...");
  410.  
  411.     for(i = 0; i < list.length; i++) 
  412.     {
  413.         cur = list[i];
  414.         if(cur != prev && cur != "nsISupports") 
  415.         {
  416.             if(cur == MISSING_INTERFACE)                 
  417.                 out.writeln("/*\n * !!! Unable to find details for a declared "+
  418.                             "interface (name unknown)!!!\n */");
  419.             else
  420.                 out.writeln("interface " + cur +";");
  421.             prev = cur;    
  422.         }    
  423.     }
  424. }    
  425.  
  426. function buildForwardDeclarationsList(iid)
  427. {
  428.     var i, cur, prev;
  429.     var list = [];
  430.     var outList = [];
  431.     appendForwardDeclarations(list, new IInfo(iid));
  432.     list.sort();
  433.     
  434.     for(i = 0; i < list.length; i++) 
  435.     {
  436.         cur = list[i];
  437.         if(cur != prev && cur != "nsISupports") 
  438.         {
  439.             if(cur != MISSING_INTERFACE)                 
  440.                 outList.push(cur);   
  441.             prev = cur;    
  442.         }    
  443.     }
  444.     return outList;    
  445. }       
  446.  
  447. /*********************************************************/
  448.  
  449. /* Our Componenent ctor */
  450. function nsInterfaceInfoToIDL() {}
  451.  
  452. /* decorate prototype to provide ``class'' methods and property accessors */
  453. nsInterfaceInfoToIDL.prototype =
  454. {
  455.     // nsIInterfaceInfoToIDL methods...
  456.  
  457.     // string generateIDL(in nsIIDRef aIID, 
  458.     //                    in PRBool withIncludes,
  459.     //                    in PRBool withForwardDeclarations);
  460.     generateIDL : function(aIID, withIncludes, withForwardDeclarations) {
  461.         var out = new Buffer;
  462.         out.writeln();    
  463.  
  464.         if(withIncludes)
  465.         {
  466.             out.writeln('#include "nsISupports.idl"');    
  467.             out.writeln();    
  468.         }
  469.  
  470.         if(withForwardDeclarations)
  471.         {
  472.             doForwardDeclarations(out, aIID);
  473.             out.writeln("");
  474.         }
  475.         
  476.         doInterface(out, aIID);
  477.  
  478.         return out.buffer;
  479.     },
  480.  
  481.     // void getReferencedInterfaceNames(in nsIIDRef aIID, 
  482.     //                                  out PRUint32 aArrayLength,
  483.     //                                  [retval, array, size_is(aArrayLength)]
  484.     //                                  out string aNames);
  485.  
  486.     getReferencedInterfaceNames : function(aIID, aArrayLength) {
  487.         var list = buildForwardDeclarationsList(aIID);
  488.         aArrayLength.value = list.length;
  489.         return list;
  490.     },
  491.  
  492.     // nsISupports methods...
  493.     QueryInterface: function (iid) {
  494.         if (!iid.equals(Components.interfaces.nsIInterfaceInfoToIDL) &&
  495.             !iid.equals(Components.interfaces.nsISupports)) {
  496.             throw Components.results.NS_ERROR_NO_INTERFACE;
  497.         }
  498.         return this;
  499.     }
  500. }
  501.  
  502. /***************************************************************************/
  503. /***************************************************************************/
  504. // parts specific to my use of the the generic module code...
  505.  
  506. const MODULE_NAME        = "nsInterfaceInfoToIDL";
  507. const MODULE_CONTRACT_ID = "@mozilla.org/interfaceinfotoidl;1";
  508. const MODULE_CID         = "{47d98974-a1b7-46a6-bc99-8abc374bba3f}";
  509. const MODULE_CTOR        = nsInterfaceInfoToIDL;
  510.  
  511. /***************************************************************************/
  512. /***************************************************************************/
  513. // generic nsIModule part...
  514.  
  515. function NSGetModule(compMgr, fileSpec) {
  516.     return new GenericModule(MODULE_NAME, MODULE_CONTRACT_ID, 
  517.                              MODULE_CID, MODULE_CTOR); 
  518. }
  519.  
  520. function GenericModule (name, contractID, CID, ctor) {
  521.     this.name       = name;
  522.     this.contractID = contractID;
  523.     this.CID        = Components.ID(CID);
  524.     this.ctor       = ctor;
  525. }
  526.  
  527. GenericModule.prototype = {
  528.     /*
  529.      * RegisterSelf is called at registration time (component installation
  530.      * or the only-until-release startup autoregistration) and is responsible
  531.      * for notifying the component manager of all components implemented in
  532.      * this module.  The fileSpec, location and type parameters are mostly
  533.      * opaque, and should be passed on to the registerComponent call
  534.      * unmolested.
  535.      */
  536.     registerSelf: function (compMgr, fileSpec, location, type) {
  537.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  538.         compMgr.registerFactoryLocation(this.CID, this.name, this.contractID, 
  539.                                         fileSpec, location, type);
  540.     },
  541.  
  542.     /*
  543.      * The GetClassObject method is responsible for producing Factory and
  544.      * SingletonFactory objects (the latter are specialized for services).
  545.      */
  546.     getClassObject: function (compMgr, cid, iid) {
  547.         if (!cid.equals(this.CID))
  548.             throw Components.results.NS_ERROR_NO_INTERFACE;
  549.  
  550.         if (!iid.equals(Components.interfaces.nsIFactory))
  551.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  552.  
  553.         this.myFactory.ctor = this.ctor;
  554.         return this.myFactory;
  555.     },
  556.  
  557.     /* factory object */
  558.     myFactory: {
  559.         
  560.         /*
  561.          * Construct an instance of the interface specified by iid, possibly
  562.          * aggregating it with the provided outer.  (If you don't know what
  563.          * aggregation is all about, you don't need to.  It reduces even the
  564.          * mightiest of XPCOM warriors to snivelling cowards.)
  565.          */
  566.         createInstance: function (outer, iid) {
  567.             if (outer != null)
  568.                 throw Components.results.NS_ERROR_NO_AGGREGATION;
  569.             return (new this.ctor()).QueryInterface(iid);
  570.         }
  571.     },
  572.  
  573.     /*
  574.      * The canUnload method signals that the component is about to be unloaded.
  575.      * C++ components can return false to indicate that they don't wish to be
  576.      * unloaded, but the return value from JS components' canUnload is ignored:
  577.      * mark-and-sweep will keep everything around until it's no longer in use,
  578.      * making unconditional ``unload'' safe.
  579.      *
  580.      * You still need to provide a (likely useless) canUnload method, though:
  581.      * it's part of the nsIModule interface contract, and the JS loader _will_
  582.      * call it.
  583.      */
  584.     canUnload: function(compMgr) {
  585.         return true;
  586.     }
  587. }
  588.  
  589. /***************************************************************************/
  590.