[docmaker] Formatting, copyright, improved documentation.

* src/tools/docmaker/*: No code changes besides trivial
modifications.
This commit is contained in:
Werner Lemberg 2014-11-24 06:44:45 +01:00
parent f1094c0951
commit a7a4207d10
7 changed files with 422 additions and 271 deletions

View File

@ -1,3 +1,10 @@
2014-11-24 Werner Lemberg <wl@gnu.org>
[docmaker] Formatting, copyright, improved documentation.
* src/tools/docmaker/*: No code changes besides trivial
modifications.
2014-11-22 Werner Lemberg <wl@gnu.org>
[bdf] Fix Savannah bug #43660.

View File

@ -1,57 +1,81 @@
# Content (c) 2002, 2004, 2006-2009, 2012, 2013
# David Turner <david@freetype.org>
#
# 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 <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 <PRE> 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 <PRE> 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 + "</" + self.tag + ">"
################################################################
##
## 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 ):

View File

@ -1,16 +1,26 @@
#!/usr/bin/env python
#
# DocMaker (c) 2002, 2004, 2008, 2013 David Turner <david@freetype.org>
# 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

View File

@ -1,19 +1,37 @@
# Formatter (c) 2002, 2004, 2007, 2008 David Turner <david@freetype.org>
#
# 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

View File

@ -1,62 +1,70 @@
# Sources (c) 2002-2004, 2006-2009, 2012, 2013
# David Turner <david@freetype.org>
#
# 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
# "<Function>", "<Type>", 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 `<Function>',
# `<Type>', 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|-)*)>''' ) # <xxxx> 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()

View File

@ -1,5 +1,19 @@
# ToHTML (c) 2002, 2003, 2005-2008, 2013
# David Turner <david@freetype.org>
#
# 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 = """\
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
@ -158,7 +172,7 @@ toc_footer_end = """\
"""
# source language keyword coloration/styling
# Source language keyword coloration and styling.
keyword_prefix = '<span class="keyword">'
keyword_suffix = '</span>'
@ -166,16 +180,20 @@ section_synopsis_header = '<h2>Synopsis</h2>'
section_synopsis_footer = ''
# Translate a single line of source to HTML. This will convert
# a "<" into "&lt.", ">" into "&gt.", etc.
# Translate a single line of source to HTML. This converts `<', `>', and
# `&' into `&lt;',`&gt;', and `&amp;'.
#
def html_quote( line ):
result = string.replace( line, "&", "&amp;" )
result = string.replace( result, "<", "&lt;" )
result = string.replace( result, ">", "&gt;" )
result = string.replace( line, "&", "&amp;" )
result = string.replace( result, "<", "&lt;" )
result = string.replace( result, ">", "&gt;" )
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 = "<center><font size=""-2"">generated on " + \
time.asctime( time.localtime( time.time() ) ) + \
"</font></center>" + 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 = (
"<center><font size=""-2"">generated on "
+ time.asctime( time.localtime( time.time() ) )
+ "</font></center>" + 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 '<a href="' + url + '">' + name + '</a>' + 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'<a href="\1">\1</a>', line )
# convert `...' quotations into real left and right single quotes
line = re.sub( r"(^|\W)`(.*?)'(\W|$)", \
r'\1&lsquo;\2&rsquo;\3', \
line = re.sub( r"(^|\W)`(.*?)'(\W|$)",
r'\1&lsquo;\2&rsquo;\3',
line )
# convert tilde into non-breakable space
line = string.replace( line, "~", "&nbsp;" )
@ -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 "<table><tr valign=top><td><b>" + field.name + "</b></td><td>"
print( "<table><tr valign=top><td><b>"
+ field.name
+ "</b></td><td>" )
print self.make_html_items( field.items )
@ -318,12 +340,14 @@ class HtmlFormatter( Formatter ):
result = result + prefix + '<b>' + name + '</b>'
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 + '<a href="' + \
self.make_block_url( block ) + '">' + name + '</a>'
result = ( result + prefix
+ '<a href="' + self.make_block_url( block )
+ '">' + name + '</a>' )
else:
result = result + html_quote( line[:length] )
@ -339,10 +363,14 @@ class HtmlFormatter( Formatter ):
print "<table cellpadding=3 border=0>"
for field in fields:
if len( field.name ) > 22:
print "<tr valign=top><td colspan=0><b>" + field.name + "</b></td></tr>"
print( "<tr valign=top><td colspan=0><b>"
+ field.name
+ "</b></td></tr>" )
print "<tr valign=top><td></td><td>"
else:
print "<tr valign=top><td><b>" + field.name + "</b></td><td>"
print( "<tr valign=top><td><b>"
+ field.name
+ "</b></td><td>" )
self.print_html_items( field.items )
print "</td></tr>"
@ -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 + '<td><a href="' + url + '">' + bname + '</a></td>'
line = ( line + '<td><a href="' + url + '">'
+ bname + '</a></td>' )
else:
line = line + '<td></td>'
line = line + "</tr>"
@ -400,9 +428,9 @@ class HtmlFormatter( Formatter ):
print "</table>"
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 "<center><h1>Table of Contents</h1></center>"
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 "<table cellpadding=5>"
def toc_section_enter( self, section ):
print '<tr valign=top><td class="left">'
print '<a href="' + self.make_section_url( section ) + '">' + \
section.title + '</a></td><td>'
print( '<a href="' + self.make_section_url( section ) + '">'
+ section.title + '</a></td><td>' )
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 + \
'<a href="' + index_filename + '">Global Index</a>' + \
chapter_inter + chapter_footer
print( chapter_header
+ '<a href="' + index_filename + '">Global Index</a>'
+ 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 + '<td></td><td>'
if i < count:
name = section.block_names[i]
line = line + '<a href="#' + name + '">' + name + '</a>'
line = ( line + '<a href="#' + name + '">'
+ name + '</a>' )
line = line + '</td>'
line = line + "</tr>"
@ -513,7 +542,8 @@ class HtmlFormatter( Formatter ):
# place html anchor if needed
if block.name:
print '<h4><a name="' + block.name + '">' + block.name + '</a></h4>'
print( '<h4><a name="' + block.name + '">'
+ block.name + '</a></h4>' )
# 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

View File

@ -1,15 +1,28 @@
# Utils (c) 2002, 2004, 2007, 2008 David Turner <david@freetype.org>
#
# 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: