Modules | Files | Inheritance Tree | Inheritance Graph | Name Index | Config
File: Synopsis/Formatter/DUMP.py
    1| # $Id: DUMP.py,v 1.14 2002/12/12 17:25:32 chalky Exp $
    2| #
    3| # This file is a part of Synopsis.
    4| # Copyright (C) 2000, 2001 Stephen Davies
    5| #
    6| # Synopsis is free software; you can redistribute it and/or modify it
    7| # under the terms of the GNU General Public License as published by
    8| # the Free Software Foundation; either version 2 of the License, or
    9| # (at your option) any later version.
   10| #
   11| # This program is distributed in the hope that it will be useful,
   12| # but WITHOUT ANY WARRANTY; without even the implied warranty of
   13| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14| # General Public License for more details.
   15| #
   16| # You should have received a copy of the GNU General Public License
   17| # along with this program; if not, write to the Free Software
   18| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   19| # 02111-1307, USA.
   20| #
   21| # $Log: DUMP.py,v $
   22| # Revision 1.14  2002/12/12 17:25:32  chalky
   23| # Implemented Include support for C++ parser. A few other minor fixes.
   24| #
   25| # Revision 1.13  2002/12/09 04:00:58  chalky
   26| # Added multiple file support to parsers, changed AST datastructure to handle
   27| # new information, added a demo to demo/C++. AST Declarations now have a
   28| # reference to a SourceFile (which includes a filename) instead of a filename.
   29| #
   30| # Revision 1.12  2002/04/26 01:21:13  chalky
   31| # Bugs and cleanups
   32| #
   33| # Revision 1.11  2001/07/19 04:00:39  chalky
   34| # New .syn file format. Added -d, -t and -f flags
   35| #
   36| # Revision 1.10  2001/05/25 13:45:49  stefan
   37| # fix problem with getopt error reporting
   38| #
   39| # Revision 1.9  2001/02/13 06:55:23  chalky
   40| # Made synopsis -l work again
   41| #
   42| # Revision 1.8  2001/01/31 06:51:24  stefan
   43| # add support for '-v' to all modules; modified toc lookup to use additional url as prefix
   44| #
   45| # Revision 1.7  2001/01/24 01:38:36  chalky
   46| # Added docstrings to all modules
   47| #
   48| # Revision 1.6  2001/01/22 19:54:41  stefan
   49| # better support for help message
   50| #
   51| # Revision 1.5  2001/01/22 17:06:15  stefan
   52| # added copyright notice, and switched on logging
   53| #
   54| """
   55| Verbose attribute-oriented dump of AST. Pipe into less -r
   56| """
   57| 
   58| # THIS-IS-A-FORMATTER
   59| import sys, getopt, os, os.path, string, types
   60| from Synopsis.Core import Type, AST
   61| 
   62| verbose = 0
   63| 
   64| class Dumper:
   65|     def __init__(self):
   66|         self.handlers = {
   67|             types.NoneType : self.visitNone,
   68|             types.TypeType : self.visitType,
   69|             types.IntType : self.visitInt,
   70|             types.LongType : self.visitLong,
   71|             types.FloatType : self.visitFloat,
   72|             types.StringType : self.visitString,
   73|             types.TupleType : self.visitTuple,
   74|             types.ListType : self.visitList,
   75|             types.DictType : self.visitDict,
   76|             types.InstanceType : self.visitInstance,
   77|         }
   78|         self.clear()
   79|     def clear(self):
   80|         self.indent_level = 0
   81|         self.indent_string = ""
   82|         self.newline = 1
   83|         self.visited = {}
   84|     def writeln(self, text):
   85|         self.write(text)
   86|         self.newline = 1
   87|     def lnwrite(self, text):
   88|         self.newline = 1
   89|         self.write(text)
   90|     def write(self, text):
   91|         if self.newline:
   92|             sys.stdout.write("\n")
   93|             sys.stdout.write(self.indent_string)
   94|             self.newline = 0
   95|         sys.stdout.write(str(text))
   96|     def indent(self, str="  "):
   97|         self.indent_level = self.indent_level + 1
   98|         self.indent_string = self.indent_string+str
   99|     def outdent(self):
  100|         self.indent_level = self.indent_level - 1
  101|         self.indent_string = self.indent_string[:-2]
  102| 
  103|     def visit(self, obj):
  104|         i,t = id(obj), type(obj)
  105|         if self.visited.has_key(i):
  106|             if t == types.InstanceType: t = obj.__class__.__name__+" instance"
  107|             if hasattr(obj, 'name'):
  108|                self.write("<already visited %s ( %d ) '%s'>"%(t,i,string.join(obj.name(),"::")))
  109|             elif hasattr(obj, 'filename'):
  110|                self.write("<already visited %s ( %d ) '%s'>"%(t,i,obj.filename()))
  111|          else:
  112|                self.write("<already visited %s ( %d )>"%(t,i))
  113|           return
  114|         if self.handlers.has_key(t):
  115|             self.handlers[t](obj)
  116|         else:
  117|             self.write("Unknown type %s for object: '%s'"%(t,obj))
  118| 
  119|     def visitNone(self, obj):
  120|         self.write(obj)
  121|     def visitType(self, obj):
  122|         self.write(obj)
  123|     def visitInt(self, obj):
  124|         self.write(obj)
  125|     def visitLong(self, obj):
  126|         self.write(obj)
  127|     def visitFloat(self, obj):
  128|         self.write(obj)
  129|     def visitString(self, obj):
  130|         import string
  131|         self.write('"%s"'%string.replace(obj,"\n","\\n"))
  132|     def visitTuple(self, obj):
  133|         if len(obj) == 0:
  134|             self.write("()")
  135|           return
  136|         # Check if all strings
  137|         strings = 1
  138|         for elem in obj:
  139|             if type(elem) != types.StringType:
  140|                strings = 0
  141|         break
  142|         if strings:
  143|             self.write("( "+string.join(obj,"::")+" )")
  144|           return
  145|         # Else write one per line
  146|         self.writeln("( ")
  147|         self.indent()
  148|         if len(obj): self.visit(obj[0])
  149|         for elem in obj[1:]:
  150|             self.write(", ")
  151|             self.visit(elem)
  152|         self.outdent()
  153|         self.lnwrite(")")
  154|     def visitList(self, obj):
  155|         if len(obj) == 0:
  156|             self.write("[]")
  157|           return
  158|         # Check if all strings
  159|         strings = 1
  160|         for elem in obj:
  161|             if type(elem) != types.StringType:
  162|                strings = 0
  163|         break
  164|         if strings:
  165|             self.write("[ "+string.join(obj,"::")+" ]")
  166|           return
  167|         self.writeln("[ ")
  168|         self.indent()
  169|         if len(obj): self.visit(obj[0])
  170|         for elem in obj[1:]:
  171|             self.writeln(", ")
  172|             self.visit(elem)
  173|         self.outdent()
  174|         self.lnwrite("]")
  175|     def _dictKey(self, key):
  176|         self.visit(key)
  177|         self.write(":")
  178|     def visitDict(self, dict, namefunc=None):
  179|         items = dict.items()
  180|         if len(items) == 0:
  181|             self.write("{}")
  182|           return
  183|         items.sort()
  184|         self.writeln("{ ")
  185|         if namefunc is None:
  186|             self.indent()
  187|             namefunc = self._dictKey
  188|         else:
  189|             self.indent(". ")
  190|         if len(items):
  191|             namefunc(items[0][0])
  192|             self.visit(items[0][1])
  193|         for item in items[1:]:
  194|             self.writeln(", ")
  195|             namefunc(item[0])
  196|             self.visit(item[1])
  197|         self.outdent()
  198|         self.lnwrite("}")
  199|     def _instAttr(self, name):
  200|         if type(name) != types.StringType:
  201|             return self.visit(name)
  202|         if name[0] != '_':
  203|             return self.write(name+" = ")
  204|         index = string.find(name, '__')
  205|         if index < 0:
  206|             return self.write(name+" = ")
  207|         self.write("%s::%s = "%(
  208|             name[1:index],
  209|             name[index+2:]
  210|         ))
  211|         
  212|     def visitInstance(self, obj):
  213|         global show_forwards
  214|         if isinstance(obj, AST.Forward) and not show_forwards: return
  215|         if isinstance(obj, AST.SourceFile) and not show_sourcefiles:
  216|             self.write("SourceFile: '%s'"%obj.filename())
  217|           return
  218|         if isinstance(obj, AST.Include):
  219|             self.write("Include: (macro:%d, next:%d) '%s'"%(obj.is_macro(),
  220|                obj.is_next(), obj.target().filename()))
  221|           return
  222|         self.visited[id(obj)] = None
  223|         self.write("%s.%s = "%(
  224|             obj.__class__.__module__,
  225|             obj.__class__.__name__
  226|         ))
  227|         self.visitDict(obj.__dict__, self._instAttr)
  228| 
  229| def usage():
  230|     """Print usage to stdout"""
  231|     print \
  232| """
  233|   -o <file>                            Output file
  234|   -d                                   Show declarations
  235|   -t                                   Show types
  236|   -f                                   Show forwards also
  237|  (If none of -d, -t or -f specified, will default to -d, -t)
  238| """
  239| 
  240| def __parseArgs(args):
  241|     global output, verbose, show_decls, show_types, show_forwards, show_files
  242|     # Set defaults
  243|     output = sys.stdout
  244|     show_decls = 0
  245|     show_types = 0
  246|     show_forwards = 0
  247|     show_files = 1
  248| 
  249|     try:
  250|         opts,remainder = getopt.getopt(args, "o:vdtf")
  251|     except getopt.error, e:
  252|         sys.stderr.write("Error in arguments: " + str(e) + "\n")
  253|         sys.exit(1)
  254| 
  255|     for opt in opts:
  256|         o,a = opt
  257| 
  258|         if o == "-o": output = open(a, "w")
  259|         elif o == "-v": verbose = 1
  260|         elif o == "-d": show_decls = 1
  261|         elif o == "-t": show_types = 1
  262|         elif o == "-f": show_forwards = 1
  263| 
  264|     # Consolidate - if no show_ selected, show decls and types
  265|     if not (show_decls or show_types or show_forwards):
  266|         show_decls = 1
  267|         show_types = 1
  268| 
  269| def format(args, ast, config_obj):
  270|     global output, show_sourcefiles
  271|     __parseArgs(args)
  272|     #formatter = ASCIIFormatter(output)
  273|     #for type in dictionary:
  274|     #    type.output(formatter)
  275|     dumper = Dumper()
  276|     show_sourcefiles = 0
  277|     if show_decls:
  278|         print "*** Declarations:"
  279|         dumper.visit(ast.declarations())
  280|     if show_types:
  281|         if show_decls: print "\n\n\n"
  282|         print "*** Types:"
  283|         dumper.visit(ast.types())
  284|     if show_files:
  285|         show_sourcefiles = 1
  286|         print "\n\n\n"
  287|         print "*** Files:"
  288|         dumper.visit(ast.files())