home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Shareware / Comunicatii / jyte / jyte.exe / combrowse.py < prev    next >
Text File  |  2001-10-27  |  17KB  |  530 lines

  1. """A utility for browsing COM objects.
  2.  
  3.  Usage:
  4.  
  5.   Command Prompt
  6.  
  7.     Use the command *"python.exe catbrowse.py"*.  This will display
  8.     display a fairly small, modal dialog.
  9.  
  10.   Pythonwin
  11.  
  12.     Use the "Run Script" menu item, and this will create the browser in an
  13.     MDI window.  This window can be fully resized.
  14.  
  15.  Details
  16.  
  17.    This module allows browsing of registered Type Libraries, COM categories, 
  18.    and running COM objects.  The display is similar to the Pythonwin object
  19.    browser, and displays the objects in a hierarchical window.
  20.  
  21.    Note that this module requires the win32ui (ie, Pythonwin) diestribution to
  22.    work.
  23.  
  24. """
  25. import win32con
  26. import win32api, win32ui
  27. import string, sys
  28. import pythoncom
  29. from win32com.client import util
  30. from pywin.tools import browser
  31.  
  32. class HLIRoot(browser.HLIPythonObject):
  33.     def __init__(self, title):
  34.         self.name = title
  35.     def GetSubList(self):
  36.         return [HLIHeadingCategory(), HLI_IEnumMoniker(pythoncom.GetRunningObjectTable().EnumRunning(), "Running Objects"), HLIHeadingRegisterdTypeLibs()]
  37.     def __cmp__(self, other):
  38.         return cmp(self.name, other.name)
  39.  
  40. class HLICOM(browser.HLIPythonObject):
  41.     def GetText(self):
  42.         return self.name
  43.     def CalculateIsExpandable(self):
  44.         return 1
  45.  
  46. class HLICLSID(HLICOM):
  47.     def __init__(self, myobject, name=None ):
  48.         if type(myobject)==type(''):
  49.             myobject = pythoncom.MakeIID(myobject)
  50.         if name is None:
  51.             try:
  52.                 name = pythoncom.ProgIDFromCLSID(myobject)
  53.             except pythoncom.com_error: 
  54.                 name = str(myobject)
  55.             name = "IID: " + name
  56.         HLICOM.__init__(self, myobject, name)
  57.     def CalculateIsExpandable(self):
  58.         return 0
  59.     def GetSubList(self):
  60.         return []
  61.  
  62. class HLI_Interface(HLICOM):
  63.     pass
  64.  
  65. class HLI_Enum(HLI_Interface):
  66.     def GetBitmapColumn(self):
  67.         return 0 # Always a folder.
  68.     def CalculateIsExpandable(self):
  69.         if self.myobject is not None:
  70.             rc = len(self.myobject.Next(1))>0
  71.             self.myobject.Reset()
  72.         else:
  73.             rc = 0
  74.         return rc
  75.     pass
  76.  
  77. class HLI_IEnumMoniker(HLI_Enum):
  78.     def GetSubList(self):
  79.         ctx = pythoncom.CreateBindCtx()
  80.         ret = []
  81.         for mon in util.Enumerator(self.myobject):
  82.             ret.append(HLI_IMoniker(mon, mon.GetDisplayName(ctx, None)))
  83.         return ret
  84.  
  85. class HLI_IMoniker(HLI_Interface):
  86.     def GetSubList(self):
  87.         ret = []
  88.         ret.append(browser.MakeHLI(self.myobject.Hash(), "Hash Value"))
  89.         subenum = self.myobject.Enum(1)
  90.         ret.append(HLI_IEnumMoniker(subenum, "Sub Monikers"))
  91.         return ret
  92.  
  93. class HLIHeadingCategory(HLICOM):
  94.     "A tree heading for registered categories"
  95.     def GetText(self):
  96.         return "Registered Categories"
  97.     def GetSubList(self):
  98.         catinf=pythoncom.CoCreateInstance(pythoncom.CLSID_StdComponentCategoriesMgr,None,pythoncom.CLSCTX_INPROC,pythoncom.IID_ICatInformation)
  99.         enum=util.Enumerator(catinf.EnumCategories())
  100.         ret = []
  101.         try:
  102.             for catid, lcid, desc in enum:
  103.                 ret.append(HLICategory((catid, lcid, desc)))
  104.         except pythoncom.com_error:
  105.             # Registered categories occasionally seem to give spurious errors.
  106.             pass # Use what we already have.
  107.         return ret
  108.  
  109. class HLICategory(HLICOM):
  110.     "An actual Registered Category"
  111.     def GetText(self):
  112.         desc =  self.myobject[2]
  113.         if not desc: desc = "(unnamed category)"
  114.         return desc
  115.     def GetSubList(self):
  116.         win32ui.DoWaitCursor(1)
  117.         catid, lcid, desc = self.myobject
  118.         catinf=pythoncom.CoCreateInstance(pythoncom.CLSID_StdComponentCategoriesMgr,None,pythoncom.CLSCTX_INPROC,pythoncom.IID_ICatInformation)
  119.         ret = []
  120.         for clsid in util.Enumerator(catinf.EnumClassesOfCategories((catid,),())):
  121.             ret.append(HLICLSID(clsid))
  122.         win32ui.DoWaitCursor(0)
  123.  
  124.         return ret
  125.  
  126. class HLIHelpFile(HLICOM):
  127.     def CalculateIsExpandable(self):
  128.         return 0
  129.     def GetText(self):
  130.         import os
  131.         fname, ctx = self.myobject
  132.         base = os.path.split(fname)[1]
  133.         return "Help reference in %s" %( base)
  134.  
  135.     def TakeDefaultAction(self):
  136.         fname, ctx = self.myobject
  137.         if ctx:
  138.             cmd = win32con.HELP_CONTEXT
  139.         else:
  140.             cmd = win32con.HELP_FINDER
  141.         win32api.WinHelp(win32ui.GetMainFrame().GetSafeHwnd(), fname, cmd, ctx)
  142.     def GetBitmapColumn(self):
  143.         return 6
  144.  
  145. class HLIRegisteredTypeLibrary(HLICOM):
  146.     def GetSubList(self):
  147.         import os
  148.         clsidstr, versionStr = self.myobject
  149.         collected = []
  150.         helpPath = ""
  151.         key = win32api.RegOpenKey(win32con.HKEY_CLASSES_ROOT, "TypeLib\\%s\\%s" % (clsidstr, versionStr))
  152.         win32ui.DoWaitCursor(1)
  153.         try:
  154.             num = 0
  155.             while 1:
  156.                 try:
  157.                     subKey = win32api.RegEnumKey(key, num)
  158.                 except win32api.error:
  159.                     break
  160.                 value = win32api.RegQueryValue(key, subKey)
  161.                 if subKey=="HELPDIR":
  162.                     helpPath = value
  163.                 elif subKey=="Flags":
  164.                     flags = value
  165.                 else:
  166.                     try:
  167.                         lcid = string.atof(subKey)
  168.                         lcidkey = win32api.RegOpenKey(key, subKey)
  169.                         # Enumerate the platforms
  170.                         lcidnum = 0
  171.                         while 1:
  172.                             try:
  173.                                 platform = win32api.RegEnumKey(lcidkey, lcidnum)
  174.                             except win32api.error:
  175.                                 break
  176.                             fname = win32api.RegQueryValue(lcidkey, platform)
  177.                             collected.append((lcid, platform, fname))
  178.                             lcidnum = lcidnum + 1
  179.                         win32api.RegCloseKey(lcidkey)
  180.                     except ValueError:
  181.                         pass
  182.                 num = num + 1
  183.         finally:
  184.             win32ui.DoWaitCursor(0)
  185.             win32api.RegCloseKey(key)
  186.         # Now, loop over my collected objects, adding a TypeLib and a HelpFile
  187.         ret = []
  188. #        if helpPath: ret.append(browser.MakeHLI(helpPath, "Help Path"))
  189.         ret.append(HLICLSID(clsidstr))
  190.         for lcid, platform, fname in collected:
  191.             extraDescs = []
  192.             if platform!="win32":
  193.                 extraDescs.append(platform)
  194.             if lcid:
  195.                 extraDescs.append("locale=%s"%lcid)
  196.             extraDesc = ""
  197.             if extraDescs: extraDesc = " (%s)" % string.join(extraDescs, ", ")
  198.             ret.append(HLITypeLib(fname, "Type Library" + extraDesc))
  199.         ret.sort()
  200.         return ret
  201.  
  202. class HLITypeLibEntry(HLICOM):
  203.     def GetText(self):
  204.         tlb, index = self.myobject
  205.         name, doc, ctx, helpFile = tlb.GetDocumentation(index)
  206.         try:
  207.             typedesc = HLITypeKinds[tlb.GetTypeInfoType(index)][1]
  208.         except KeyError:
  209.             typedesc = "Unknown!"
  210.         return name + " - " + typedesc
  211.     def GetSubList(self):
  212.         tlb, index = self.myobject
  213.         name, doc, ctx, helpFile = tlb.GetDocumentation(index)
  214.         ret = []
  215.         if doc: ret.append(browser.HLIDocString(doc, "Doc"))
  216.         if helpFile: ret.append(HLIHelpFile(    (helpFile, ctx) ))
  217.         return ret
  218.  
  219. class HLICoClass(HLITypeLibEntry):
  220.     def GetSubList(self):
  221.         ret = HLITypeLibEntry.GetSubList(self)
  222.         tlb, index = self.myobject
  223.         typeinfo = tlb.GetTypeInfo(index)
  224.         attr = typeinfo.GetTypeAttr()
  225.         for j in range(attr[8]):
  226.             flags = typeinfo.GetImplTypeFlags(j)
  227.             refType = typeinfo.GetRefTypeInfo(typeinfo.GetRefTypeOfImplType(j))
  228.             refAttr = refType.GetTypeAttr()
  229.             ret.append(browser.MakeHLI(refAttr[0], "Name=%s, Flags = %d" % (refAttr[0], flags)))
  230.         return ret
  231.  
  232.  
  233. class HLITypeLibMethod(HLITypeLibEntry):
  234.     def __init__(self, ob, name = None):
  235.         self.entry_type = "Method"
  236.         HLITypeLibEntry.__init__(self, ob, name)
  237.     def GetSubList(self):
  238.         ret = HLITypeLibEntry.GetSubList(self)
  239.         tlb, index = self.myobject
  240.         typeinfo = tlb.GetTypeInfo(index)
  241.         attr = typeinfo.GetTypeAttr()
  242.         for i in range(attr[7]):
  243.             ret.append(HLITypeLibProperty((typeinfo, i)))
  244.         for i in range(attr[6]):
  245.             ret.append(HLITypeLibFunction((typeinfo, i)))
  246.         return ret
  247.  
  248. class HLITypeLibEnum(HLITypeLibEntry):
  249.     def __init__(self, myitem):
  250.         typelib, index = myitem
  251.         typeinfo = typelib.GetTypeInfo(index)
  252.         self.id = typeinfo.GetVarDesc(index)[0]
  253.         name = typeinfo.GetNames(self.id)[0]
  254.         HLITypeLibEntry.__init__(self, myitem, name)
  255.     def GetText(self):
  256.         return self.name + " - Enum/Module"
  257.     def GetSubList(self):
  258.         ret = []
  259.         typelib, index = self.myobject
  260.         typeinfo = typelib.GetTypeInfo(index)
  261.         attr = typeinfo.GetTypeAttr()
  262.         for j in range(attr[7]):
  263.             vdesc = typeinfo.GetVarDesc(j)
  264.             name = typeinfo.GetNames(vdesc[0])[0]
  265.             ret.append(browser.MakeHLI(vdesc[1], name))
  266.         return ret
  267.  
  268. class HLITypeLibProperty(HLICOM):
  269.     def __init__(self, myitem):
  270.         typeinfo, index = myitem
  271.         self.id = typeinfo.GetVarDesc(index)[0]
  272.         name = typeinfo.GetNames(self.id)[0]
  273.         HLICOM.__init__(self, myitem, name)
  274.     def GetText(self):
  275.         return self.name + " - Property"
  276.     def GetSubList(self):
  277.         ret = []
  278.         typeinfo, index = self.myobject
  279.         names = typeinfo.GetNames(self.id)
  280.         if len(names)>1:
  281.             ret.append(browser.MakeHLI(names[1:], "Named Params"))
  282.         vd = typeinfo.GetVarDesc(index)
  283.         ret.append(browser.MakeHLI(self.id, "Dispatch ID"))
  284.         ret.append(browser.MakeHLI(vd[1], "Value"))
  285.         ret.append(browser.MakeHLI(vd[2], "Elem Desc"))
  286.         ret.append(browser.MakeHLI(vd[3], "Var Flags"))
  287.         ret.append(browser.MakeHLI(vd[4], "Var Kind"))
  288.         return ret
  289.  
  290. class HLITypeLibFunction(HLICOM):
  291.     funckinds = {pythoncom.FUNC_VIRTUAL : "Virtual",
  292.                  pythoncom.FUNC_PUREVIRTUAL : "Pure Virtual",
  293.                  pythoncom.FUNC_STATIC : "Static",
  294.                  pythoncom.FUNC_DISPATCH : "Dispatch",
  295.         }
  296.     invokekinds = {pythoncom.INVOKE_FUNC: "Function",
  297.                  pythoncom.INVOKE_PROPERTYGET : "Property Get",
  298.                  pythoncom.INVOKE_PROPERTYPUT : "Property Put",
  299.                  pythoncom.INVOKE_PROPERTYPUTREF : "Property Put by reference",
  300.         }
  301.     funcflags = [(pythoncom.FUNCFLAG_FRESTRICTED, "Restricted"),
  302.                    (pythoncom.FUNCFLAG_FSOURCE, "Source"),
  303.                    (pythoncom.FUNCFLAG_FBINDABLE, "Bindable"),
  304.                    (pythoncom.FUNCFLAG_FREQUESTEDIT, "Request Edit"),
  305.                    (pythoncom.FUNCFLAG_FDISPLAYBIND, "Display Bind"),
  306.                    (pythoncom.FUNCFLAG_FDEFAULTBIND, "Default Bind"),
  307.                    (pythoncom.FUNCFLAG_FHIDDEN, "Hidden"),
  308.                    (pythoncom.FUNCFLAG_FUSESGETLASTERROR, "Uses GetLastError"),
  309.                    ]
  310.  
  311.     vartypes = {pythoncom.VT_EMPTY: "Empty",
  312.                 pythoncom.VT_NULL: "NULL",
  313.                 pythoncom.VT_I2: "Integer 2",
  314.                 pythoncom.VT_I4: "Integer 4",
  315.                 pythoncom.VT_R4: "Real 4",
  316.                 pythoncom.VT_R8: "Real 8",
  317.                 pythoncom.VT_CY: "CY",
  318.                 pythoncom.VT_DATE: "Date",
  319.                 pythoncom.VT_BSTR: "String",
  320.                 pythoncom.VT_DISPATCH: "IDispatch",
  321.                 pythoncom.VT_ERROR: "Error",
  322.                 pythoncom.VT_BOOL: "BOOL",
  323.                 pythoncom.VT_VARIANT: "Variant",
  324.                 pythoncom.VT_UNKNOWN: "IUnknown",
  325.                 pythoncom.VT_DECIMAL: "Decimal",
  326.                 pythoncom.VT_I1: "Integer 1",
  327.                 pythoncom.VT_UI1: "Unsigned integer 1",
  328.                 pythoncom.VT_UI2: "Unsigned integer 2",
  329.                 pythoncom.VT_UI4: "Unsigned integer 4",
  330.                 pythoncom.VT_I8: "Integer 8",
  331.                 pythoncom.VT_UI8: "Unsigned integer 8",
  332.                 pythoncom.VT_INT: "Integer",
  333.                 pythoncom.VT_UINT: "Unsigned integer",
  334.                 pythoncom.VT_VOID: "Void",
  335.                 pythoncom.VT_HRESULT: "HRESULT",
  336.                 pythoncom.VT_PTR: "Pointer",
  337.                 pythoncom.VT_SAFEARRAY: "SafeArray",
  338.                 pythoncom.VT_CARRAY: "C Array",
  339.                 pythoncom.VT_USERDEFINED: "User Defined",
  340.                 pythoncom.VT_LPSTR: "Pointer to string",
  341.                 pythoncom.VT_LPWSTR: "Pointer to Wide String",
  342.                 pythoncom.VT_FILETIME: "File time",
  343.                 pythoncom.VT_BLOB: "Blob",
  344.                 pythoncom.VT_STREAM: "IStream",
  345.                 pythoncom.VT_STORAGE: "IStorage",
  346.                 pythoncom.VT_STORED_OBJECT: "Stored object",
  347.                 pythoncom.VT_STREAMED_OBJECT: "Streamed object",
  348.                 pythoncom.VT_BLOB_OBJECT: "Blob object",
  349.                 pythoncom.VT_CF: "CF",
  350.                 pythoncom.VT_CLSID: "CLSID",
  351.         }
  352.  
  353.     type_flags = [ (pythoncom.VT_VECTOR, "Vector"),
  354.                    (pythoncom.VT_ARRAY, "Array"),
  355.                    (pythoncom.VT_BYREF, "ByRef"),
  356.                    (pythoncom.VT_RESERVED, "Reserved"),
  357.         ]               
  358.         
  359.     def __init__(self, myitem):
  360.         typeinfo, index = myitem
  361.         self.id = typeinfo.GetFuncDesc(index)[0]
  362.         name = typeinfo.GetNames(self.id)[0]
  363.         HLICOM.__init__(self, myitem, name)
  364.     def GetText(self):
  365.         return self.name + " - Function"
  366.     def MakeReturnTypeName(self, typ):
  367.         justtyp = typ & pythoncom.VT_TYPEMASK
  368.         try:
  369.             typname = self.vartypes[justtyp]
  370.         except KeyError:
  371.             typname = "?Bad type?"
  372.         for (flag, desc) in self.type_flags:
  373.             if flag & typ:
  374.                 typname = "%s(%s)" % (desc, typname)
  375.         return typname            
  376.     def MakeReturnType(self, returnTypeDesc):
  377.         if type(returnTypeDesc)==type(()):
  378.             first = returnTypeDesc[0]
  379.             result = self.MakeReturnType(first)
  380.             if first != pythoncom.VT_USERDEFINED:
  381.                 result = result + " " + self.MakeReturnType(returnTypeDesc[1])
  382.             return result
  383.         else:
  384.             return self.MakeReturnTypeName(returnTypeDesc)
  385.             
  386.     def GetSubList(self):
  387.         ret = []
  388.         typeinfo, index = self.myobject
  389.         names = typeinfo.GetNames(self.id)
  390.         ret.append(browser.MakeHLI(self.id, "Dispatch ID"))
  391.         if len(names)>1:
  392.             ret.append(browser.MakeHLI(string.join(names[1:], ", "), "Named Params"))
  393.         fd = typeinfo.GetFuncDesc(index)
  394.         if fd[1]:
  395.             ret.append(browser.MakeHLI(fd[1], "Possible result values"))
  396.         if fd[8]:
  397.             typ, flags, default = fd[8]
  398.             val = self.MakeReturnType(typ)
  399.             if flags:
  400.                 val = "%s (Flags=%d, default=%s)" % (val, flags, default)
  401.             ret.append(browser.MakeHLI(val, "Return Type"))
  402.                 
  403.         for argDesc in fd[2]:
  404.             typ, flags, default = argDesc
  405.             val = self.MakeReturnType(typ)
  406.             if flags:
  407.                 val = "%s (Flags=%d)" % (val, flags)
  408.             if default is not None:
  409.                 val = "%s (Default=%s)" % (val, default)
  410.             ret.append(browser.MakeHLI(val, "Argument"))
  411.         
  412.         try:
  413.             fkind = self.funckinds[fd[3]]
  414.         except KeyError:
  415.             fkind = "Unknown"
  416.         ret.append(browser.MakeHLI(fkind, "Function Kind"))
  417.         try:
  418.             ikind = self.invokekinds[fd[4]]
  419.         except KeyError:
  420.             ikind = "Unknown"
  421.         ret.append(browser.MakeHLI(ikind, "Invoke Kind"))
  422.         # 5 = call conv
  423.         # 5 = offset vtbl
  424.         ret.append(browser.MakeHLI(fd[6], "Number Optional Params"))
  425.         flagDescs = []
  426.         for flag, desc in self.funcflags:
  427.             if flag & fd[9]:
  428.                 flagDescs.append(desc)
  429.         if flagDescs:
  430.             ret.append(browser.MakeHLI(string.join(flagDescs, ", "), "Function Flags"))
  431.         return ret
  432.     
  433. HLITypeKinds = {
  434.         pythoncom.TKIND_ENUM : (HLITypeLibEnum, 'Enumeration'),
  435.         pythoncom.TKIND_RECORD : (HLITypeLibEntry, 'Record'),
  436.         pythoncom.TKIND_MODULE : (HLITypeLibEnum, 'Module'),
  437.         pythoncom.TKIND_INTERFACE : (HLITypeLibMethod, 'Interface'),
  438.         pythoncom.TKIND_DISPATCH : (HLITypeLibMethod, 'Dispatch'),
  439.         pythoncom.TKIND_COCLASS : (HLICoClass, 'CoClass'),
  440.         pythoncom.TKIND_ALIAS : (HLITypeLibEntry, 'Alias'),
  441.         pythoncom.TKIND_UNION : (HLITypeLibEntry, 'Union')
  442.     }
  443.  
  444. class HLITypeLib(HLICOM):
  445.     def GetSubList(self):
  446.         ret = []
  447.         ret.append(browser.MakeHLI(self.myobject, "Filename"))
  448.         try:
  449.             tlb = pythoncom.LoadTypeLib(self.myobject)
  450.         except pythoncom.com_error:
  451.             return [browser.MakeHLI("%s can not be loaded" % self.myobject)]
  452.             
  453.         for i in range(tlb.GetTypeInfoCount()):
  454.             try:
  455.                 ret.append(HLITypeKinds[tlb.GetTypeInfoType(i)][0]( (tlb, i) ) )
  456.             except pythoncom.com_error:
  457.                 ret.append(browser.MakeHLI("The type info can not be loaded!"))
  458.         ret.sort()
  459.         return ret
  460.         
  461. class HLIHeadingRegisterdTypeLibs(HLICOM):
  462.     "A tree heading for registered type libraries"
  463.     def GetText(self):
  464.         return "Registered Type Libraries"
  465.     def GetSubList(self):
  466.         # Explicit lookup in the registry.
  467.         ret = []
  468.         key = win32api.RegOpenKey(win32con.HKEY_CLASSES_ROOT, "TypeLib")
  469.         win32ui.DoWaitCursor(1)
  470.         try:
  471.             num = 0
  472.             while 1:
  473.                 try:
  474.                     keyName = win32api.RegEnumKey(key, num)
  475.                 except win32api.error:
  476.                     break
  477.                 # Enumerate all version info
  478.                 subKey = win32api.RegOpenKey(key, keyName)
  479.                 name = None
  480.                 try:
  481.                     subNum = 0
  482.                     bestVersion = 0.0
  483.                     while 1:
  484.                         try:
  485.                             versionStr = win32api.RegEnumKey(subKey, subNum)
  486.                         except win32api.error:
  487.                             break
  488.                         try:
  489.                             versionFlt = string.atof(versionStr)
  490.                         except ValueError:
  491.                             versionFlt = 0 # ????
  492.                         if versionFlt > bestVersion:
  493.                             bestVersion = versionFlt
  494.                             name = win32api.RegQueryValue(subKey, versionStr)
  495.                         subNum = subNum + 1
  496.                 finally:
  497.                     win32api.RegCloseKey(subKey)
  498.                 if name is not None:
  499.                     ret.append(HLIRegisteredTypeLibrary((keyName, versionStr), name))
  500.                 num = num + 1
  501.         finally:
  502.             win32api.RegCloseKey(key)
  503.             win32ui.DoWaitCursor(0)
  504.         ret.sort()
  505.         return ret
  506.  
  507. def main():
  508.     from pywin.tools import hierlist
  509.     root = HLIRoot("COM Browser")
  510.     if sys.modules.has_key("app"):
  511.         # do it in a window
  512.         browser.MakeTemplate()
  513.         browser.template.OpenObject(root)
  514.     else:
  515. #        list=hierlist.HierListWithItems( root, win32ui.IDB_BROWSER_HIER )
  516. #        dlg=hierlist.HierDialog("COM Browser",list)
  517.         dlg = browser.dynamic_browser(root)
  518.         dlg.DoModal()
  519.  
  520.  
  521.  
  522. if __name__=='__main__':
  523.     main()
  524.  
  525.     ni = pythoncom._GetInterfaceCount()
  526.     ng = pythoncom._GetGatewayCount()
  527.     if ni or ng:
  528.         print "Warning - exiting with %d/%d objects alive" % (ni,ng)
  529.  
  530.