From a7a4207d1087a33521f9d76a0a2271141ebd73c8 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Mon, 24 Nov 2014 06:44:45 +0100 Subject: [PATCH] [docmaker] Formatting, copyright, improved documentation. * src/tools/docmaker/*: No code changes besides trivial modifications. --- ChangeLog | 7 ++ src/tools/docmaker/content.py | 175 +++++++++++++++++++---------- src/tools/docmaker/docmaker.py | 37 +++--- src/tools/docmaker/formatter.py | 52 ++++++--- src/tools/docmaker/sources.py | 190 ++++++++++++++++--------------- src/tools/docmaker/tohtml.py | 192 +++++++++++++++++++------------- src/tools/docmaker/utils.py | 40 ++++--- 7 files changed, 422 insertions(+), 271 deletions(-) diff --git a/ChangeLog b/ChangeLog index aa2828997..9cf9416c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2014-11-24 Werner Lemberg + + [docmaker] Formatting, copyright, improved documentation. + + * src/tools/docmaker/*: No code changes besides trivial + modifications. + 2014-11-22 Werner Lemberg [bdf] Fix Savannah bug #43660. diff --git a/src/tools/docmaker/content.py b/src/tools/docmaker/content.py index 98025e67e..9aa85ba96 100644 --- a/src/tools/docmaker/content.py +++ b/src/tools/docmaker/content.py @@ -1,57 +1,81 @@ -# Content (c) 2002, 2004, 2006-2009, 2012, 2013 -# David Turner # -# This file contains routines used to parse the content of documentation -# comment blocks and build more structured objects out of them. +# content.py +# +# Parse comment blocks to build content blocks (library file). +# +# Copyright 2002, 2004, 2006-2009, 2012-2014 by +# David Turner. +# +# This file is part of the FreeType project, and may only be used, +# modified, and distributed under the terms of the FreeType project +# license, LICENSE.TXT. By continuing to use, modify, or distribute +# this file you indicate that you have read the license and +# understand and accept it fully. + +# +# This file contains routines to parse documentation comment blocks, +# building more structured objects out of them. # + from sources import * -from utils import * +from utils import * + import string, re -# this regular expression is used to detect code sequences. these -# are simply code fragments embedded in '{' and '}' like in: # -# { -# x = y + z; -# if ( zookoo == 2 ) -# { -# foobar(); -# } -# } +# Regular expressions to detect code sequences. `Code sequences' are simply +# code fragments embedded in '{' and '}', as demonstrated in the following +# example. # -# note that indentation of the starting and ending accolades must be -# exactly the same. the code sequence can contain accolades at greater -# indentation +# { +# x = y + z; +# if ( zookoo == 2 ) +# { +# foobar(); +# } +# } +# +# Note that the indentation of the first opening brace and the last closing +# brace must be exactly the same. The code sequence itself should have a +# larger indentation than the surrounding braces. # re_code_start = re.compile( r"(\s*){\s*$" ) re_code_end = re.compile( r"(\s*)}\s*$" ) -# this regular expression is used to isolate identifiers from -# other text +# +# A regular expression to isolate identifiers from other text. # re_identifier = re.compile( r'((?:\w|-)*)' ) -# we collect macros ending in `_H'; while outputting the object data, we use -# this info together with the object's file location to emit the appropriate -# header file macro and name before the object itself +# +# We collect macro names ending in `_H' (group 1), as defined in +# `config/ftheader.h'. While outputting the object data, we use this info +# together with the object's file location (group 2) to emit the appropriate +# header file macro and its associated file name before the object itself. +# +# Example: +# +# #define FT_FREETYPE_H # re_header_macro = re.compile( r'^#define\s{1,}(\w{1,}_H)\s{1,}<(.*)>' ) -############################################################################# -# -# The DocCode class is used to store source code lines. -# -# 'self.lines' contains a set of source code lines that will be dumped as -# HTML in a
 tag.
-#
-#   The object is filled line by line by the parser; it strips the leading
-#   "margin" space from each input line before storing it in 'self.lines'.
-#
+################################################################
+##
+##  DOC CODE CLASS
+##
+##  The `DocCode' class is used to store source code lines.
+##
+##  `self.lines' contains a set of source code lines that will be dumped as
+##  HTML in a 
 tag.
+##
+##  The object is filled line by line by the parser; it strips the leading
+##  `margin' space from each input line before storing it in `self.lines'.
+##
 class  DocCode:
 
     def  __init__( self, margin, lines ):
@@ -77,12 +101,14 @@ class  DocCode:
 
 
 
-#############################################################################
-#
-# The DocPara class is used to store "normal" text paragraph.
-#
-#   'self.words' contains the list of words that make up the paragraph
-#
+################################################################
+##
+##  DOC PARA CLASS
+##
+##  `Normal' text paragraphs are stored in the `DocPara' class.
+##
+##  `self.words' contains the list of words that make up the paragraph.
+##
 class  DocPara:
 
     def  __init__( self, lines ):
@@ -123,17 +149,18 @@ class  DocPara:
         return result
 
 
-
-#############################################################################
-#
-#  The DocField class is used to store a list containing either DocPara or
-#  DocCode objects. Each DocField also has an optional "name" which is used
-#  when the object corresponds to a field or value definition
-#
+################################################################
+##
+##  DOC FIELD CLASS
+##
+##  The `DocField' class stores a list containing either `DocPara' or
+##  `DocCode' objects.  Each DocField object also has an optional `name'
+##  that is used when the object corresponds to a field or value definition.
+##
 class  DocField:
 
     def  __init__( self, name, lines ):
-        self.name  = name  # can be None for normal paragraphs/sources
+        self.name  = name  # can be `None' for normal paragraphs/sources
         self.items = []    # list of items
 
         mode_none  = 0     # start parsing mode
@@ -143,14 +170,14 @@ class  DocField:
         margin     = -1    # current code sequence indentation
         cur_lines  = []
 
-        # now analyze the markup lines to see if they contain paragraphs,
-        # code sequences or fields definitions
+        # analyze the markup lines to check whether they contain paragraphs,
+        # code sequences, or fields definitions
         #
         start = 0
         mode  = mode_none
 
         for l in lines:
-            # are we parsing a code sequence ?
+            # are we parsing a code sequence?
             if mode == mode_code:
                 m = re_code_end.match( l )
                 if m and len( m.group( 1 ) ) <= margin:
@@ -161,10 +188,10 @@ class  DocField:
                     cur_lines = []
                     mode      = mode_none
                 else:
-                    # nope, continue the code sequence
+                    # otherwise continue the code sequence
                     cur_lines.append( l[margin:] )
             else:
-                # start of code sequence ?
+                # start of code sequence?
                 m = re_code_start.match( l )
                 if m:
                     # save current lines
@@ -222,13 +249,29 @@ class  DocField:
         return result
 
 
-
-# this regular expression is used to detect field definitions
 #
-re_field = re.compile( r"\s*(\w*|\w(\w|\.)*\w)\s*::" )
-
+# A regular expression to detect field definitions.
+#
+# Examples:
+#
+#   foo     ::
+#   foo.bar ::
+#
+re_field = re.compile( r"""
+                         \s*
+                           (
+                             \w*
+                           |
+                             \w (\w | \.)* \w
+                           )
+                         \s* ::
+                       """, re.VERBOSE )
 
 
+################################################################
+##
+##  DOC MARKUP CLASS
+##
 class  DocMarkup:
 
     def  __init__( self, tag, lines ):
@@ -242,7 +285,7 @@ class  DocMarkup:
         for l in lines:
             m = re_field.match( l )
             if m:
-                # we detected the start of a new field definition
+                # We detected the start of a new field definition.
 
                 # first, save the current one
                 if cur_lines:
@@ -275,7 +318,10 @@ class  DocMarkup:
         print " " * margin + ""
 
 
-
+################################################################
+##
+##  DOC CHAPTER CLASS
+##
 class  DocChapter:
 
     def  __init__( self, block ):
@@ -291,7 +337,10 @@ class  DocChapter:
             self.order = []
 
 
-
+################################################################
+##
+##  DOC SECTION CLASS
+##
 class  DocSection:
 
     def  __init__( self, name = "Other" ):
@@ -327,7 +376,10 @@ class  DocSection:
         self.block_names = sort_order_list( self.block_names, self.order )
 
 
-
+################################################################
+##
+##  CONTENT PROCESSOR CLASS
+##
 class  ContentProcessor:
 
     def  __init__( self ):
@@ -463,7 +515,10 @@ class  ContentProcessor:
             self.chapters.append( chap )
 
 
-
+################################################################
+##
+##  DOC BLOCK CLASS
+##
 class  DocBlock:
 
     def  __init__( self, source, follow, processor ):
diff --git a/src/tools/docmaker/docmaker.py b/src/tools/docmaker/docmaker.py
index bf75c5d5f..4df0c98c3 100644
--- a/src/tools/docmaker/docmaker.py
+++ b/src/tools/docmaker/docmaker.py
@@ -1,16 +1,26 @@
 #!/usr/bin/env python
 #
-#  DocMaker (c) 2002, 2004, 2008, 2013 David Turner 
+#  docmaker.py
 #
-# This program is a re-write of the original DocMaker tool used
-# to generate the API Reference of the FreeType font engine
-# by converting in-source comments into structured HTML.
+#    Convert source code markup to HTML documentation.
 #
-# This new version is capable of outputting XML data, as well
-# as accepts more liberal formatting options.
+#  Copyright 2002, 2004, 2008, 2013, 2014 by
+#  David Turner.
 #
-# It also uses regular expression matching and substitution
-# to speed things significantly.
+#  This file is part of the FreeType project, and may only be used,
+#  modified, and distributed under the terms of the FreeType project
+#  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+#  this file you indicate that you have read the license and
+#  understand and accept it fully.
+
+#
+# This program is a re-write of the original DocMaker tool used to generate
+# the API Reference of the FreeType font rendering engine by converting
+# in-source comments into structured HTML.
+#
+# This new version is capable of outputting XML data as well as accepting
+# more liberal formatting options.  It also uses regular expression matching
+# and substitution to speed up operation significantly.
 #
 
 from sources   import *
@@ -44,8 +54,8 @@ def  main( argv ):
     global output_dir
 
     try:
-        opts, args = getopt.getopt( sys.argv[1:], \
-                                    "ht:o:p:",    \
+        opts, args = getopt.getopt( sys.argv[1:],
+                                    "ht:o:p:",
                                     ["help", "title=", "output=", "prefix="] )
     except getopt.GetoptError:
         usage()
@@ -56,7 +66,6 @@ def  main( argv ):
         sys.exit( 1 )
 
     # process options
-    #
     project_title  = "Project"
     project_prefix = None
     output_dir     = None
@@ -90,7 +99,9 @@ def  main( argv ):
     # process sections
     content_processor.finish()
 
-    formatter = HtmlFormatter( content_processor, project_title, project_prefix )
+    formatter = HtmlFormatter( content_processor,
+                               project_title,
+                               project_prefix )
 
     formatter.toc_dump()
     formatter.index_dump()
@@ -98,9 +109,7 @@ def  main( argv ):
 
 
 # if called from the command line
-#
 if __name__ == '__main__':
     main( sys.argv )
 
-
 # eof
diff --git a/src/tools/docmaker/formatter.py b/src/tools/docmaker/formatter.py
index f62ce676c..7cb68b2b7 100644
--- a/src/tools/docmaker/formatter.py
+++ b/src/tools/docmaker/formatter.py
@@ -1,19 +1,37 @@
-#  Formatter (c) 2002, 2004, 2007, 2008 David Turner 
 #
+#  formatter.py
+#
+#    Convert parsed content blocks to a structured document (library file).
+#
+#  Copyright 2002, 2004, 2007, 2008, 2014 by
+#  David Turner.
+#
+#  This file is part of the FreeType project, and may only be used,
+#  modified, and distributed under the terms of the FreeType project
+#  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+#  this file you indicate that you have read the license and
+#  understand and accept it fully.
+
+#
+# This is the base Formatter class.  Its purpose is to convert a content
+# processor's data into specific documents (i.e., table of contents, global
+# index, and individual API reference indices).
+#
+# You need to sub-class it to output anything sensible.  For example, the
+# file `tohtml.py' contains the definition of the `HtmlFormatter' sub-class
+# to output HTML.
+#
+
 
 from sources import *
 from content import *
 from utils   import *
 
-# This is the base Formatter class.  Its purpose is to convert
-# a content processor's data into specific documents (i.e., table of
-# contents, global index, and individual API reference indices).
-#
-# You need to sub-class it to output anything sensible.  For example,
-# the file tohtml.py contains the definition of the HtmlFormatter sub-class
-# used to output -- you guessed it -- HTML.
-#
 
+################################################################
+##
+##  FORMATTER CLASS
+##
 class  Formatter:
 
     def  __init__( self, processor ):
@@ -41,15 +59,17 @@ class  Formatter:
     def  add_identifier( self, name, block ):
         if self.identifiers.has_key( name ):
             # duplicate name!
-            sys.stderr.write(                                           \
-               "WARNING: duplicate definition for '" + name + "' in " + \
-               block.location() + ", previous definition in " +         \
-               self.identifiers[name].location() + "\n" )
+            sys.stderr.write( "WARNING: duplicate definition for"
+                              + " '" + name + "' "
+                              + "in " + block.location() + ", "
+                              + "previous definition in "
+                              + self.identifiers[name].location()
+                              + "\n" )
         else:
             self.identifiers[name] = block
 
     #
-    #  Formatting the table of contents
+    # formatting the table of contents
     #
     def  toc_enter( self ):
         pass
@@ -97,7 +117,7 @@ class  Formatter:
             close_output( output )
 
     #
-    #  Formatting the index
+    # formatting the index
     #
     def  index_enter( self ):
         pass
@@ -128,7 +148,7 @@ class  Formatter:
             close_output( output )
 
     #
-    #  Formatting a section
+    # formatting a section
     #
     def  section_enter( self, section ):
         pass
diff --git a/src/tools/docmaker/sources.py b/src/tools/docmaker/sources.py
index dab834978..61af985ea 100644
--- a/src/tools/docmaker/sources.py
+++ b/src/tools/docmaker/sources.py
@@ -1,62 +1,70 @@
-#  Sources (c) 2002-2004, 2006-2009, 2012, 2013
-#    David Turner 
 #
+#  sources.py
 #
-# this file contains definitions of classes needed to decompose
-# C sources files into a series of multi-line "blocks". There are
-# two kinds of blocks:
+#    Convert source code comments to multi-line blocks (library file).
 #
-#   - normal blocks, which contain source code or ordinary comments
+#  Copyright 2002-2004, 2006-2009, 2012-2014 by
+#  David Turner.
 #
-#   - documentation blocks, which have restricted formatting, and
-#     whose text always start with a documentation markup tag like
-#     "", "", etc..
+#  This file is part of the FreeType project, and may only be used,
+#  modified, and distributed under the terms of the FreeType project
+#  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+#  this file you indicate that you have read the license and
+#  understand and accept it fully.
+
 #
-# the routines used to process the content of documentation blocks
-# are not contained here, but in "content.py"
+# This library file contains definitions of classes needed to decompose C
+# source code files into a series of multi-line `blocks'.  There are two
+# kinds of blocks.
 #
-# the classes and methods found here only deal with text parsing
-# and basic documentation block extraction
+#   - Normal blocks, which contain source code or ordinary comments.
 #
+#   - Documentation blocks, which have restricted formatting, and whose text
+#     always start with a documentation markup tag like `',
+#     `', etc.
+#
+# The routines to process the content of documentation blocks are contained
+# in file `content.py'; the classes and methods found here only deal with
+# text parsing and basic documentation block extraction.
+#
+
 
 import fileinput, re, sys, os, string
 
 
-
 ################################################################
 ##
-##  BLOCK FORMAT PATTERN
+##  SOURCE BLOCK FORMAT CLASS
 ##
-##   A simple class containing compiled regular expressions used
-##   to detect potential documentation format block comments within
-##   C source code
+##  A simple class containing compiled regular expressions to detect
+##  potential documentation format block comments within C source code.
 ##
-##   note that the 'column' pattern must contain a group that will
-##   be used to "unbox" the content of documentation comment blocks
+##  The `column' pattern must contain a group to `unbox' the content of
+##  documentation comment blocks.
+##
+##  Later on, paragraphs are converted to long lines, which simplifies the
+##  regular expressions that act upon the text.
 ##
 class  SourceBlockFormat:
 
     def  __init__( self, id, start, column, end ):
-        """create a block pattern, used to recognize special documentation blocks"""
+        """Create a block pattern, used to recognize special documentation
+           blocks."""
         self.id     = id
         self.start  = re.compile( start, re.VERBOSE )
         self.column = re.compile( column, re.VERBOSE )
         self.end    = re.compile( end, re.VERBOSE )
 
 
-
 #
-# format 1 documentation comment blocks look like the following:
+# Format 1 documentation comment blocks.
 #
-#    /************************************/
+#    /************************************/ (at least 2 asterisks)
 #    /*                                  */
 #    /*                                  */
 #    /*                                  */
-#    /************************************/
+#    /************************************/ (at least 2 asterisks)
 #
-# we define a few regular expressions here to detect them
-#
-
 start = r'''
   \s*      # any number of whitespace
   /\*{2,}/ # followed by '/' and at least two asterisks then '/'
@@ -75,16 +83,13 @@ re_source_block_format1 = SourceBlockFormat( 1, start, column, start )
 
 
 #
-# format 2 documentation comment blocks look like the following:
+# Format 2 documentation comment blocks.
 #
 #    /************************************ (at least 2 asterisks)
 #     *
+#     *                                    (1 asterisk)
 #     *
-#     *
-#     *
-#     **/       (1 or more asterisks at the end)
-#
-# we define a few regular expressions here to detect them
+#     */                                   (1 or more asterisks)
 #
 start = r'''
   \s*     # any number of whitespace
@@ -107,47 +112,56 @@ re_source_block_format2 = SourceBlockFormat( 2, start, column, end )
 
 
 #
-# the list of supported documentation block formats, we could add new ones
-# relatively easily
+# The list of supported documentation block formats.  We could add new ones
+# quite easily.
 #
 re_source_block_formats = [re_source_block_format1, re_source_block_format2]
 
 
 #
-# the following regular expressions corresponds to markup tags
-# within the documentation comment blocks. they're equivalent
-# despite their different syntax
+# The following regular expressions correspond to markup tags within the
+# documentation comment blocks.  They are equivalent despite their different
+# syntax.
 #
-# notice how each markup tag _must_ begin a new line
+# A markup tag consists of letters or character `-', to be found in group 1.
+#
+# Notice that a markup tag _must_ begin a new paragraph.
 #
 re_markup_tag1 = re.compile( r'''\s*<((?:\w|-)*)>''' )  #  format
 re_markup_tag2 = re.compile( r'''\s*@((?:\w|-)*):''' )  # @xxxx: format
 
 #
-# the list of supported markup tags, we could add new ones relatively
-# easily
+# The list of supported markup tags.  We could add new ones quite easily.
 #
 re_markup_tags = [re_markup_tag1, re_markup_tag2]
 
+
 #
-# used to detect a cross-reference, after markup tags have been stripped
+# A regular expression to detect a cross reference, after markup tags have
+# been stripped off.  Group 1 is the reference, group 2 the rest of the
+# line.
+#
+# A cross reference consists of letters, digits, or characters `-' and `_'.
 #
 re_crossref = re.compile( r'@((?:\w|-)*)(.*)' )    #  @foo
 
 #
-# used to detect italic and bold styles in paragraph text
+# Two regular expressions to detect italic and bold markup, respectively.
+# Group 1 is the markup, group 3 the rest of the line.
+#
+# Note that the markup is limited to words consisting of letters, digits,
+# the character `_', or an apostrophe (but not as the first character).
 #
 re_italic = re.compile( r"_(\w(\w|')*)_(.*)" )     #  _italic_
 re_bold   = re.compile( r"\*(\w(\w|')*)\*(.*)" )   #  *bold*
 
 #
-# this regular expression code to identify an URL has been taken from
+# This regular expression code to identify an URL has been taken from
 #
 #   http://mail.python.org/pipermail/tutor/2002-September/017228.html
 #
-# (with slight modifications)
+# (with slight modifications).
 #
-
 urls = r'(?:https?|telnet|gopher|file|wais|ftp)'
 ltrs = r'\w'
 gunk = r'/#~:.?+=&%@!\-'
@@ -177,17 +191,22 @@ url  = r"""
 re_url = re.compile( url, re.VERBOSE | re.MULTILINE )
 
 #
-# used to detect the end of commented source lines
+# A regular expression that stops collection of comments for the current
+# block.
 #
-re_source_sep = re.compile( r'\s*/\*\s*\*/' )
+re_source_sep = re.compile( r'\s*/\*\s*\*/' )   #  /* */
 
 #
-# used to perform cross-reference within source output
+# A regular expression to find possible C identifiers while outputting
+# source code verbatim, covering things like `*foo' or `(bar'.  Group 1 is
+# the prefix, group 2 the identifier -- since we scan lines from left to
+# right, sequentially splitting the source code into prefix and identifier
+# is fully sufficient for our purposes.
 #
 re_source_crossref = re.compile( r'(\W*)(\w*)' )
 
 #
-# a list of reserved source keywords
+# A regular expression that matches a list of reserved C source keywords.
 #
 re_source_keywords = re.compile( '''\\b ( typedef   |
                                           struct    |
@@ -215,24 +234,16 @@ re_source_keywords = re.compile( '''\\b ( typedef   |
 ##
 ##  SOURCE BLOCK CLASS
 ##
-##   A SourceProcessor is in charge of reading a C source file
-##   and decomposing it into a series of different "SourceBlocks".
-##   each one of these blocks can be made of the following data:
+##  There are two important fields in a `SourceBlock' object.
 ##
-##   - A documentation comment block that starts with "/**" and
-##     whose exact format will be discussed later
+##    self.lines
+##      A list of text lines for the corresponding block.
 ##
-##   - normal sources lines, including comments
-##
-##   the important fields in a text block are the following ones:
-##
-##     self.lines   : a list of text lines for the corresponding block
-##
-##     self.content : for documentation comment blocks only, this is the
-##                    block content that has been "unboxed" from its
-##                    decoration. This is None for all other blocks
-##                    (i.e. sources or ordinary comments with no starting
-##                     markup tag)
+##    self.content
+##      For documentation comment blocks only, this is the block content
+##      that has been `unboxed' from its decoration.  This is `None' for all
+##      other blocks (i.e., sources or ordinary comments with no starting
+##      markup tag)
 ##
 class  SourceBlock:
 
@@ -269,7 +280,7 @@ class  SourceBlock:
     def  location( self ):
         return "(" + self.filename + ":" + repr( self.lineno ) + ")"
 
-    # debugging only - not used in normal operations
+    # debugging only -- not used in normal operations
     def  dump( self ):
         if self.content:
             print "{{{content start---"
@@ -286,39 +297,38 @@ class  SourceBlock:
             print line
 
 
-
 ################################################################
 ##
 ##  SOURCE PROCESSOR CLASS
 ##
-##   The SourceProcessor is in charge of reading a C source file
-##   and decomposing it into a series of different "SourceBlock"
-##   objects.
+##  The `SourceProcessor' is in charge of reading a C source file and
+##  decomposing it into a series of different `SourceBlock' objects.
 ##
-##   each one of these blocks can be made of the following data:
+##  A SourceBlock object consists of the following data.
 ##
-##   - A documentation comment block that starts with "/**" and
-##     whose exact format will be discussed later
+##    - A documentation comment block using one of the layouts above.  Its
+##      exact format will be discussed later.
 ##
-##   - normal sources lines, include comments
+##    - Normal sources lines, including comments.
 ##
 ##
 class  SourceProcessor:
 
     def  __init__( self ):
-        """initialize a source processor"""
+        """Initialize a source processor."""
         self.blocks   = []
         self.filename = None
         self.format   = None
         self.lines    = []
 
     def  reset( self ):
-        """reset a block processor, clean all its blocks"""
+        """Reset a block processor and clean up all its blocks."""
         self.blocks = []
         self.format = None
 
     def  parse_file( self, filename ):
-        """parse a C source file, and add its blocks to the processor's list"""
+        """Parse a C source file and add its blocks to the processor's
+           list."""
         self.reset()
 
         self.filename = filename
@@ -337,16 +347,16 @@ class  SourceProcessor:
                 self.process_normal_line( line )
             else:
                 if self.format.end.match( line ):
-                    # that's a normal block end, add it to 'lines' and
-                    # create a new block
+                    # A normal block end.  Add it to `lines' and create a
+                    # new block
                     self.lines.append( line )
                     self.add_block_lines()
                 elif self.format.column.match( line ):
-                    # that's a normal column line, add it to 'lines'
+                    # A normal column line.  Add it to `lines'.
                     self.lines.append( line )
                 else:
-                    # humm.. this is an unexpected block end,
-                    # create a new block, but don't process the line
+                    # An unexpected block end.  Create a new block, but
+                    # don't process the line.
                     self.add_block_lines()
 
                     # we need to process the line again
@@ -356,7 +366,8 @@ class  SourceProcessor:
         self.add_block_lines()
 
     def  process_normal_line( self, line ):
-        """process a normal line and check whether it is the start of a new block"""
+        """Process a normal line and check whether it is the start of a new
+           block."""
         for f in re_source_block_formats:
             if f.start.match( line ):
                 self.add_block_lines()
@@ -366,9 +377,12 @@ class  SourceProcessor:
         self.lines.append( line )
 
     def  add_block_lines( self ):
-        """add the current accumulated lines and create a new block"""
+        """Add the current accumulated lines and create a new block."""
         if self.lines != []:
-            block = SourceBlock( self, self.filename, self.lineno, self.lines )
+            block = SourceBlock( self,
+                                 self.filename,
+                                 self.lineno,
+                                 self.lines )
 
             self.blocks.append( block )
             self.format = None
@@ -376,7 +390,7 @@ class  SourceProcessor:
 
     # debugging only, not used in normal operations
     def  dump( self ):
-        """print all blocks in a processor"""
+        """Print all blocks in a processor."""
         for b in self.blocks:
             b.dump()
 
diff --git a/src/tools/docmaker/tohtml.py b/src/tools/docmaker/tohtml.py
index 7944f1c99..2e44f848b 100644
--- a/src/tools/docmaker/tohtml.py
+++ b/src/tools/docmaker/tohtml.py
@@ -1,5 +1,19 @@
-#  ToHTML (c) 2002, 2003, 2005-2008, 2013
-#    David Turner 
+#
+#  tohtml.py
+#
+#    A sub-class container of the `Formatter' class to produce HTML.
+#
+#  Copyright 2002, 2003, 2005-2008, 2013, 2014 by
+#  David Turner.
+#
+#  This file is part of the FreeType project, and may only be used,
+#  modified, and distributed under the terms of the FreeType project
+#  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+#  this file you indicate that you have read the license and
+#  understand and accept it fully.
+
+# The parent class is contained in file `formatter.py'.
+
 
 from sources import *
 from content import *
@@ -8,7 +22,7 @@ from formatter import *
 import time
 
 
-# The following defines the HTML header used by all generated pages.
+# The following strings define the HTML header used by all generated pages.
 html_header_1 = """\
 
@@ -158,7 +172,7 @@ toc_footer_end = """\
 """
 
 
-# source language keyword coloration/styling
+# Source language keyword coloration and styling.
 keyword_prefix = ''
 keyword_suffix = ''
 
@@ -166,16 +180,20 @@ section_synopsis_header = '

Synopsis

' section_synopsis_footer = '' -# Translate a single line of source to HTML. This will convert -# a "<" into "<.", ">" into ">.", etc. +# Translate a single line of source to HTML. This converts `<', `>', and +# `&' into `<',`>', and `&'. +# def html_quote( line ): - result = string.replace( line, "&", "&" ) - result = string.replace( result, "<", "<" ) - result = string.replace( result, ">", ">" ) + result = string.replace( line, "&", "&" ) + result = string.replace( result, "<", "<" ) + result = string.replace( result, ">", ">" ) return result - +################################################################ +## +## HTML FORMATTER CLASS +## class HtmlFormatter( Formatter ): def __init__( self, processor, project_title, file_prefix ): @@ -189,31 +207,32 @@ class HtmlFormatter( Formatter ): else: file_prefix = "" - self.headers = processor.headers - self.project_title = project_title - self.file_prefix = file_prefix - self.html_header = html_header_1 + project_title + \ - html_header_2 + \ - html_header_3 + file_prefix + "index.html" + \ - html_header_4 + file_prefix + "toc.html" + \ - html_header_5 + project_title + \ - html_header_6 - - self.html_index_header = html_header_1 + project_title + \ - html_header_2 + \ - html_header_3i + file_prefix + "toc.html" + \ - html_header_5 + project_title + \ - html_header_6 - - self.html_toc_header = html_header_1 + project_title + \ - html_header_2 + \ - html_header_3 + file_prefix + "index.html" + \ - html_header_5t + project_title + \ - html_header_6 - - self.html_footer = "
generated on " + \ - time.asctime( time.localtime( time.time() ) ) + \ - "
" + html_footer + self.headers = processor.headers + self.project_title = project_title + self.file_prefix = file_prefix + self.html_header = ( + html_header_1 + project_title + + html_header_2 + + html_header_3 + file_prefix + "index.html" + + html_header_4 + file_prefix + "toc.html" + + html_header_5 + project_title + + html_header_6 ) + self.html_index_header = ( + html_header_1 + project_title + + html_header_2 + + html_header_3i + file_prefix + "toc.html" + + html_header_5 + project_title + + html_header_6 ) + self.html_toc_header = ( + html_header_1 + project_title + + html_header_2 + + html_header_3 + file_prefix + "index.html" + + html_header_5t + project_title + + html_header_6 ) + self.html_footer = ( + "
generated on " + + time.asctime( time.localtime( time.time() ) ) + + "
" + html_footer ) self.columns = 3 @@ -224,8 +243,8 @@ class HtmlFormatter( Formatter ): return self.make_section_url( block.section ) + "#" + block.name def make_html_word( self, word ): - """analyze a simple word to detect cross-references and styling""" - # look for cross-references + """Analyze a simple word to detect cross-references and markup.""" + # handle cross-references m = re_crossref.match( word ) if m: try: @@ -236,11 +255,11 @@ class HtmlFormatter( Formatter ): return '' + name + '' + rest except: # we detected a cross-reference to an unknown item - sys.stderr.write( \ - "WARNING: undefined cross reference '" + name + "'.\n" ) + sys.stderr.write( "WARNING: undefined cross reference" + + " '" + name + "'.\n" ) return '?' + name + '?' + rest - # look for italics and bolds + # handle markup for italic and bold m = re_italic.match( word ) if m: name = m.group( 1 ) @@ -256,7 +275,8 @@ class HtmlFormatter( Formatter ): return html_quote( word ) def make_html_para( self, words ): - """ convert words of a paragraph into tagged HTML text, handle xrefs """ + """Convert words of a paragraph into tagged HTML text. Also handle + cross references.""" line = "" if words: line = self.make_html_word( words[0] ) @@ -265,8 +285,8 @@ class HtmlFormatter( Formatter ): # handle hyperlinks line = re_url.sub( r'\1', line ) # convert `...' quotations into real left and right single quotes - line = re.sub( r"(^|\W)`(.*?)'(\W|$)", \ - r'\1‘\2’\3', \ + line = re.sub( r"(^|\W)`(.*?)'(\W|$)", + r'\1‘\2’\3', line ) # convert tilde into non-breakable space line = string.replace( line, "~", " " ) @@ -274,7 +294,7 @@ class HtmlFormatter( Formatter ): return para_header + line + para_footer def make_html_code( self, lines ): - """ convert a code sequence to HTML """ + """Convert a code sequence to HTML.""" line = code_header + '\n' for l in lines: line = line + html_quote( l ) + '\n' @@ -282,7 +302,7 @@ class HtmlFormatter( Formatter ): return line + code_footer def make_html_items( self, items ): - """ convert a field's content into some valid HTML """ + """Convert a field's content into HTML.""" lines = [] for item in items: if item.lines: @@ -297,7 +317,9 @@ class HtmlFormatter( Formatter ): def print_html_field( self, field ): if field.name: - print "
" + field.name + "" + print( "
" + + field.name + + "" ) print self.make_html_items( field.items ) @@ -318,12 +340,14 @@ class HtmlFormatter( Formatter ): result = result + prefix + '' + name + '' elif re_source_keywords.match( name ): # this is a C keyword - result = result + prefix + keyword_prefix + name + keyword_suffix + result = ( result + prefix + + keyword_prefix + name + keyword_suffix ) elif self.identifiers.has_key( name ): # this is a known identifier block = self.identifiers[name] - result = result + prefix + '' + name + '' + result = ( result + prefix + + '' + name + '' ) else: result = result + html_quote( line[:length] ) @@ -339,10 +363,14 @@ class HtmlFormatter( Formatter ): print "" for field in fields: if len( field.name ) > 22: - print "" + print( "" ) print "" @@ -352,10 +380,9 @@ class HtmlFormatter( Formatter ): table_fields = [] for field in markup.fields: if field.name: - # we begin a new series of field or value definitions, we - # will record them in the 'table_fields' list before outputting - # all of them as a single table - # + # We begin a new series of field or value definitions. We + # record them in the `table_fields' list before outputting + # all of them as a single table. table_fields.append( field ) else: if table_fields: @@ -368,7 +395,7 @@ class HtmlFormatter( Formatter ): self.print_html_field_list( table_fields ) # - # Formatting the index + # formatting the index # def index_enter( self ): print self.html_index_header @@ -380,7 +407,7 @@ class HtmlFormatter( Formatter ): self.index_items[name] = url def index_exit( self ): - # block_index already contains the sorted list of index names + # `block_index' already contains the sorted list of index names count = len( self.block_index ) rows = ( count + self.columns - 1 ) / self.columns @@ -392,7 +419,8 @@ class HtmlFormatter( Formatter ): if i < count: bname = self.block_index[r + c * rows] url = self.index_items[bname] - line = line + '' + line = ( line + '' ) else: line = line + '' line = line + "" @@ -400,9 +428,9 @@ class HtmlFormatter( Formatter ): print "
" + field.name + "
" + + field.name + + "
" else: - print "
" + field.name + "" + print( "
" + + field.name + + "" ) self.print_html_items( field.items ) print "
' + bname + '' + + bname + '
" - print index_footer_start + \ - self.file_prefix + "toc.html" + \ - index_footer_end + print( index_footer_start + + self.file_prefix + "toc.html" + + index_footer_end ) print self.html_footer @@ -415,20 +443,20 @@ class HtmlFormatter( Formatter ): Formatter.index_dump( self, index_filename ) # - # Formatting the table of content + # formatting the table of contents # def toc_enter( self ): print self.html_toc_header print "

Table of Contents

" def toc_chapter_enter( self, chapter ): - print chapter_header + string.join( chapter.title ) + chapter_inter + print chapter_header + string.join( chapter.title ) + chapter_inter print "" def toc_section_enter( self, section ): print '' line = line + "" @@ -513,7 +542,8 @@ class HtmlFormatter( Formatter ): # place html anchor if needed if block.name: - print '

' + block.name + '

' + print( '

' + + block.name + '

' ) # dump the block C source lines now if block.code: @@ -524,8 +554,9 @@ class HtmlFormatter( Formatter ): break; # if not header: -# sys.stderr.write( \ -# 'WARNING: No header macro for ' + block.source.filename + '.\n' ) +# sys.stderr.write( +# "WARNING: No header macro for" +# + " '" + block.source.filename + "'.\n" ) if header: print header_location_header @@ -552,15 +583,16 @@ class HtmlFormatter( Formatter ): print marker_footer def block_exit( self, block ): - print block_footer_start + self.file_prefix + "index.html" + \ - block_footer_middle + self.file_prefix + "toc.html" + \ - block_footer_end + print( block_footer_start + self.file_prefix + "index.html" + + block_footer_middle + self.file_prefix + "toc.html" + + block_footer_end ) def section_exit( self, section ): print html_footer def section_dump_all( self ): for section in self.sections: - self.section_dump( section, self.file_prefix + section.name + '.html' ) + self.section_dump( section, + self.file_prefix + section.name + '.html' ) # eof diff --git a/src/tools/docmaker/utils.py b/src/tools/docmaker/utils.py index 1d96658c7..c75dd2d98 100644 --- a/src/tools/docmaker/utils.py +++ b/src/tools/docmaker/utils.py @@ -1,15 +1,28 @@ -# Utils (c) 2002, 2004, 2007, 2008 David Turner # +# utils.py +# +# Auxiliary functions for the `docmaker' tool (library file). +# +# Copyright 2002, 2004, 2007, 2008, 2014 by +# David Turner. +# +# This file is part of the FreeType project, and may only be used, +# modified, and distributed under the terms of the FreeType project +# license, LICENSE.TXT. By continuing to use, modify, or distribute +# this file you indicate that you have read the license and +# understand and accept it fully. + import string, sys, os, glob + # current output directory # output_dir = None -# This function is used to sort the index. It is a simple lexicographical -# sort, except that it places capital letters before lowercase ones. +# A function to sort the index. It is a simple lexicographical sort, except +# that it places capital letters before lowercase ones. # def index_sort( s1, s2 ): if not s1: @@ -42,7 +55,7 @@ def index_sort( s1, s2 ): return 0 -# Sort input_list, placing the elements of order_list in front. +# Sort `input_list', placing the elements of `order_list' in front. # def sort_order_list( input_list, order_list ): new_list = order_list[:] @@ -52,9 +65,9 @@ def sort_order_list( input_list, order_list ): return new_list -# Open the standard output to a given project documentation file. Use -# "output_dir" to determine the filename location if necessary and save the -# old stdout in a tuple that is returned by this function. +# Divert standard output to a given project documentation file. Use +# `output_dir' to determine the filename location if necessary and save the +# old stdout handle in a tuple that is returned by this function. # def open_output( filename ): global output_dir @@ -69,7 +82,7 @@ def open_output( filename ): return ( new_file, old_stdout ) -# Close the output that was returned by "close_output". +# Close the output that was returned by `open_output'. # def close_output( output ): output[0].close() @@ -83,15 +96,16 @@ def check_output(): if output_dir: if output_dir != "": if not os.path.isdir( output_dir ): - sys.stderr.write( "argument" + " '" + output_dir + "' " + \ - "is not a valid directory" ) + sys.stderr.write( "argument" + + " '" + output_dir + "' " + + "is not a valid directory" ) sys.exit( 2 ) else: output_dir = None def file_exists( pathname ): - """checks that a given file exists""" + """Check that a given file exists.""" result = 1 try: file = open( pathname, "r" ) @@ -104,12 +118,12 @@ def file_exists( pathname ): def make_file_list( args = None ): - """builds a list of input files from command-line arguments""" + """Build a list of input files from command-line arguments.""" file_list = [] # sys.stderr.write( repr( sys.argv[1 :] ) + '\n' ) if not args: - args = sys.argv[1 :] + args = sys.argv[1:] for pathname in args: if string.find( pathname, '*' ) >= 0:
' - print '' + \ - section.title + '' + print( '' + + section.title + '' ) print self.make_html_para( section.abstract ) @@ -440,14 +468,14 @@ class HtmlFormatter( Formatter ): print chapter_footer def toc_index( self, index_filename ): - print chapter_header + \ - 'Global Index' + \ - chapter_inter + chapter_footer + print( chapter_header + + 'Global Index' + + chapter_inter + chapter_footer ) def toc_exit( self ): - print toc_footer_start + \ - self.file_prefix + "index.html" + \ - toc_footer_end + print( toc_footer_start + + self.file_prefix + "index.html" + + toc_footer_end ) print self.html_footer @@ -461,7 +489,7 @@ class HtmlFormatter( Formatter ): Formatter.toc_dump( self, toc_filename, index_filename ) # - # Formatting sections + # formatting sections # def section_enter( self, section ): print self.html_header @@ -495,7 +523,8 @@ class HtmlFormatter( Formatter ): line = line + '' if i < count: name = section.block_names[i] - line = line + '' + name + '' + line = ( line + '' + + name + '' ) line = line + '