@ -28,12 +28,9 @@ html_header = """
vlink = " #51188E "
alink = " #FF0000 " >
< center > < h1 > FreeType 2 API Reference < / h1 > < / center >
< center > < table width = " 80 % " > < tr > < td >
"""
html_footer = """
< / td > < / tr >
< / table > < / center >
< / body >
< / html >
"""
@ -49,12 +46,12 @@ code_footer = """
para_header = " <p> "
para_footer = " </p> "
block_header = """ <table width= " 100 % " ><tr><td> """
block_footer = " </table> "
block_header = """ <center><hr width= " 550 " ><table width= " 550 " ><tr><td> """
block_footer = " </table></center> "
source_header = """ <table width= " 100 % " ><tr bgcolor= " #D6E8FF " width= " 100 % " ><td><pre>
source_header = """ <center>< table width= " 550 " ><tr bgcolor= " #D6E8FF " width= " 100 % " ><td><pre>
"""
source_footer = """ </pre></table>
source_footer = """ </pre></table></center>
< br > < br >
"""
@ -144,175 +141,18 @@ source_footer = """</pre></table>
#
def make_block_list ( ) :
""" parse a file and extract comments blocks from it """
list = [ ]
block = [ ]
format = 0
# we use "format" to store the state of our parser:
#
# 0 - wait for beginning of comment
# 1 - parse comment format 1
# 2 - parse comment format 2
#
# 4 - wait for beginning of source (or comment ??)
# 5 - process source
#
comment = [ ]
source = [ ]
state = 0
for line in fileinput . input ( ) :
l = len ( line )
if l > 0 and line [ l - 1 ] == ' \012 ' :
line = line [ 0 : l - 1 ]
# stripped version of the line
line2 = string . strip ( line )
l = len ( line2 )
# if this line begins with a comment and we are processing some
# source, exit to state 0
#
# unless we encounter something like:
#
# /*@.....
# /*#.....
#
# /* @.....
# /* #.....
#
if format > = 4 and l > 2 and line2 [ 0 : 2 ] == ' /* ' :
if l < 4 or ( line2 [ 3 ] != ' @ ' and line2 [ 3 : 4 ] != ' @ ' and
line2 [ 3 ] != ' # ' and line2 [ 3 : 4 ] != ' # ' ) :
list . append ( ( block , source ) )
format = 0
if format == 0 : #### wait for beginning of comment ####
if l > 3 and line2 [ 0 : 3 ] == ' /** ' :
i = 3
while i < l and line2 [ i ] == ' * ' :
i = i + 1
if i == l :
# this is '/**' followed by any number of '*', the
# beginning of a Format 1 block
#
block = [ ]
source = [ ]
format = 1
elif i == l - 1 and line2 [ i ] == ' / ' :
# this is '/**' followed by any number of '*', followed
# by a '/', i.e. the beginning of a Format 2 or 3 block
#
block = [ ]
source = [ ]
format = 2
##############################################################
#
# FORMAT 1
#
elif format == 1 :
# if the line doesn't begin with a "*", something went
# wrong, and we must exit, and forget the current block..
if l == 0 or line2 [ 0 ] != ' * ' :
block = [ ]
format = 0
# otherwise, we test for an end of block, which is an
# arbitrary number of '*', followed by '/'
else :
i = 1
while i < l and line2 [ i ] == ' * ' :
i = i + 1
# test for the end of the block
if i < l and line2 [ i ] == ' / ' :
if block != [ ] :
format = 4
else :
format = 0
else :
# otherwise simply append line to current block
block . append ( line2 )
continue
##############################################################
#
# FORMAT 2
#
elif format == 2 :
# if the line doesn't begin with '/*' and end with '*/',
# this is the end of the format 2 format
if l < 4 or line2 [ : 2 ] != ' /* ' or line2 [ - 2 : ] != ' */ ' :
if block != [ ] :
format = 4
else :
format = 0
else :
# remove the start and end comment delimiters, then
# right-strip the line
line2 = string . rstrip ( line2 [ 2 : - 2 ] )
# check for end of a format2 block, i.e. a run of '*'
if string . count ( line2 , ' * ' ) == l - 4 :
if block != [ ] :
format = 4
else :
format = 0
else :
# otherwise, add the line to the current block
block . append ( line2 )
continue
if format > = 4 : #### source processing ####
if l > 0 :
format = 5
if format == 5 :
source . append ( line )
if format > = 4 :
list . append ( [ block , source ] )
return list
# This function is only used for debugging
#
def dump_block_list ( list ) :
""" dump a comment block list """
for block in list :
print " ---------------------------------------- "
for line in block [ 0 ] :
print line
for line in block [ 1 ] :
print line
print " ---------the end----------------------- "
##############################################################################
#
# 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 = 0 ) :
@ -325,27 +165,26 @@ class DocCode:
line = line [ self . margin : ]
self . lines . append ( line )
def dump ( self ) :
max_width = 50
def dump ( self ) :
for line in self . lines :
print " -- " + line
print " "
def get_identifier ( self ) :
# this function should never be called
return " UNKNOWN_CODE_IDENTIFIER!! "
def dump_html ( self ) :
# clean the last empty lines
l = len ( self . lines ) - 1
while len > 0 and string . strip ( lines [ len - 1 ] ) == " " :
len = len - 1
while l > 0 and string . strip ( self . lines [ l - 1 ] ) == " " :
l = l - 1
print code_header
for line in self . lines [ 0 : len ] :
print lines
for line in self . lines [ 0 : l ] :
print line
print code_footer
@ -354,6 +193,8 @@ class DocCode:
# The DocParagraph is used to store text paragraphs
# self.words is simply a list of words for the paragraph
#
# the paragraph is filled line by line by the parser..
#
class DocParagraph :
def __init__ ( self ) :
@ -370,7 +211,16 @@ class DocParagraph:
#
last = len ( self . words )
self . words [ last : last ] = string . split ( line )
# this function is used to retrieve the first word of a given
# paragraph..
def get_identifier ( self ) :
if self . words :
return self . words [ 0 ]
# should never happen
return " UNKNOWN_PARA_IDENTIFIER!! "
def dump ( self ) :
@ -391,7 +241,7 @@ class DocParagraph:
if cursor > 0 :
print line
print " "
#print "§" #for debugging only
def dump_html ( self ) :
@ -428,6 +278,11 @@ class DocParagraph:
# ( "x", [ DocParagraph ] ),
# ( "y", [ DocParagraph, DocCode ] ) ]
#
# in self.items
#
# the DocContent object is entirely built at creation time, you must
# pass a list of input text lines lin the "lines_list" parameter..
#
#
class DocContent :
@ -436,10 +291,13 @@ class DocContent:
code_mode = 0
code_margin = 0
text = [ ]
paragraph = None
code = None
elements = [ ]
field = None
paragraph = None # represents the current DocParagraph
code = None # represents the current DocCode
elements = [ ] # the list of elements for the current field,
# contains DocParagraph or DocCode objects
field = None # the current field
for aline in lines_list :
@ -470,16 +328,21 @@ class DocContent:
# the token `::'
#
if len ( words ) > = 2 and words [ 1 ] == " :: " :
# start a new field - complete current paragraph if any
if paragraph :
elements . append ( paragraph )
paragraph = None
# append previous "field" to self.items
self . items . append ( ( field , elements ) )
# start new field and elements list
field = words [ 0 ]
elements = [ ]
words = words [ 2 : ]
# append remaining words to current paragraph
if len ( words ) > 0 :
line = string . join ( words )
if not paragraph :
@ -487,9 +350,12 @@ class DocContent:
paragraph . add ( line )
else :
# we're in code mode..
line = aline
# the code block ends with a line that has a single '}' on it
# that is located at the same column that the opening
# accolade..
if line == " " * code_margin + ' } ' :
if code :
@ -514,6 +380,15 @@ class DocContent:
self . items . append ( ( field , elements ) )
def get_identifier ( self ) :
if self . items :
item = self . items [ 0 ]
for element in item [ 1 ] :
return element . get_identifier ( )
# should never happen
return " UNKNOWN_CONTENT_IDENTIFIER!! "
def dump ( self ) :
for item in self . items :
@ -566,44 +441,67 @@ class DocContent:
# The DocBlock class is used to store a given comment block. It contains
# a list of markers, as well as a list of contents for each marker.
#
# "self.items" is a list of ( marker, contents ) elements, where
# 'marker' is a lowercase marker string, and 'contents' is a DocContent
# object
#
# "self.source" is simply a list of text lines taken from the
# uncommented source itself..
#
# finally, "self.identifier" is a simple identifier used to
# uniquely identify the block
#
class DocBlock :
def __init__ ( self , block_line_list = [ ] , source_line_list = [ ] ) :
self . markers = [ ]
self . contents = [ ]
self . source = source_line_list
marker = " "
content = [ ]
alphanum = string . letters + string . digits + " _ "
self . items = [ ] # current ( marker, contents ) list
self . identifier = None
marker = None # current marker
content = [ ] # current content lines list
alphanum = string . letters + string . digits + " _ "
for line in block_line_list :
line2 = string . lstrip ( line )
l = len ( line2 )
margin = len ( line ) - l
if l > 3 and line2 [ 0 ] == ' < ' :
i = 1
while i < l and line2 [ i ] in alphanum :
i = i + 1
if i < l and line2 [ i ] == ' > ' :
if marker or content :
self . add ( marker , content )
marker = line2 [ 1 : i ]
content = [ ]
line2 = string . lstrip ( line2 [ i + 1 : ] )
l = len ( line2 )
line = " " * margin + line2
if l > 3 :
ender = None
if line2 [ 0 ] == ' < ' :
ender = ' > '
elif line2 [ 0 ] == ' @ ' :
ender = ' : '
if ender :
i = 1
while i < l and line2 [ i ] in alphanum :
i = i + 1
if i < l and line2 [ i ] == ender :
if marker and content :
self . add ( marker , content )
marker = line2 [ 1 : i ]
content = [ ]
line2 = string . lstrip ( line2 [ i + 1 : ] )
l = len ( line2 )
line = " " * margin + line2
content . append ( line )
if marker or content :
if marker and content :
self . add ( marker , content )
self . source = [ ]
if self . items :
self . source = source_line_list
# this function is used to add a new element to self.items
# 'marker' is a marker string, or None
# 'lines' is a list of text lines used to compute a list of
# DocContent objects
#
def add ( self , marker , lines ) :
# remove the first and last empty lines from the content list
l = len ( lines )
if l > 0 :
@ -617,115 +515,289 @@ class DocBlock:
# add a new marker only if its marker and its content list aren't empty
if l > 0 and marker :
self . markers . append ( marker )
self . contents . append ( lines )
content = DocContent ( lines )
self . items . append ( ( string . lower ( marker ) , content ) )
if not self . identifier :
self . identifier = content . get_identifier ( )
def dump ( self ) :
for i in range ( len ( self . markers ) ) :
print " [ " + self . markers [ i ] + " ] "
for line in self . contents [ i ] :
print " -- " + line
for i in range ( len ( self . item s ) ) :
print " [ " + self . items [ i ] [ 0 ] + " ] "
content = self . items [ i ] [ 1 ]
content . dump ( )
def doc_contents ( self ) :
contents = [ ]
for item in self . contents :
contents . append ( DocContent ( item ) )
return contents
def dump_html ( self ) :
types = [ ' type ' , ' struct ' , ' functype ' , ' function ' , ' constant ' ,
' enum ' , ' macro ' ]
if not self . items :
return
# start of a block
print block_header
print " <h2> " + self . identifier + " </h2> "
def dump_doc_blocks ( block_list ) :
for block in block_list :
docblock = DocBlock ( block )
docblock . dump ( )
print " <<------------------->> "
# print source code
if not self . source :
return
lines = self . source
l = len ( lines ) - 1
while l > = 0 and string . strip ( lines [ l ] ) == " " :
l = l - 1
print source_header
for line in lines [ 0 : l + 1 ] :
print line
print source_footer
# dump each (marker,content) element
for element in self . items :
marker = element [ 0 ]
content = element [ 1 ]
if marker == " description " :
print " <ul> "
content . dump_html ( )
print " </ul> "
elif not ( marker in types ) :
print " <h4> " + marker + " </h4> "
print " <ul> "
content . dump_html ( )
print " </ul> "
print " "
print block_footer
# filter a given list of DocBlocks. Returns a new list
# of DocBlock objects that only contains element whose
# "type" (i.e. first marker) is in the "types" parameter
#
#
#
def dump_single_content ( block_list ) :
def filter_blocks ( block_list , types ) :
new_list = [ ]
for block in block_list :
if block . items :
element = block . items [ 0 ]
marker = element [ 0 ]
if marker in types :
new_list . append ( block )
block = block_list [ 0 ]
docblock = DocBlock ( block )
return new_list
print " <block> "
for i in range ( len ( docblock . markers ) ) :
marker = docblock . markers [ i ]
contents = docblock . contents [ i ]
print " <marker " + marker + " > "
doccontent = DocContent ( contents )
doccontent . dump ( )
print " </marker> "
# perform a lexicographical comparison of two DocBlock
# objects. Returns -1, 0 or 1
#
def block_lexicographical_compare ( b1 , b2 ) :
if not b1 . identifier :
return - 1
if not b2 . identifier :
return 1
print " </block> "
id1 = string . lower ( b1 . identifier )
id2 = string . lower ( b2 . identifier )
if id1 < id2 :
return - 1
elif id1 == id2 :
return 0
else :
return 1
def block_make_list ( source_block_list ) :
list = [ ]
def dump_doc_contents ( block_list ) :
for block in source_block_list :
docblock = DocBlock ( block [ 0 ] , block [ 1 ] )
list . append ( docblock )
for block in block_list :
docblock = DocBlock ( block )
print " <block> "
for i in range ( len ( docblock . markers ) ) :
print " <marker " + docblock . markers [ i ] + " > "
content = DocContent ( docblock . contents [ i ] )
content . dump ( )
print " </marker> "
print " </block> "
return list
# dump a list block as a single HTML page
#
def dump_html_1 ( block_list ) :
print html_header
types = [ ' Type ' , ' Struct ' , ' FuncType ' , ' Function ' , ' Constant ' ,
' Enumeration ' ]
for block in block_list :
block . dump_html ( )
docblock = DocBlock ( block [ 0 ] , block [ 1 ] )
if len ( docblock . markers ) == 0 :
continue
print html_footer
print block_header
for i in range ( len ( docblock . markers ) ) :
marker = docblock . markers [ i ]
content = docblock . contents [ i ]
dcontent = DocContent ( content )
if marker == " Description " :
print " <ul><p> "
dcontent . dump ( )
print " </p></ul> "
elif marker in types :
print " <h3><font color=blue> " + content [ 0 ] + " </font></h3> "
else :
print " <h4> " + marker + " </h4> "
print " <ul><p> "
dcontent . dump_html ( )
print " </p></ul> "
print " "
print block_footer
# print source code
lines = block [ 1 ]
l = len ( lines ) - 1
while l > = 0 and string . strip ( lines [ l ] ) == " " :
l = l - 1
print source_header
for line in lines [ 0 : l + 1 ] :
print line
print source_footer
print html_footer
def make_block_list ( ) :
""" parse a file and extract comments blocks from it """
list = [ ]
block = [ ]
format = 0
# we use "format" to store the state of our parser:
#
# 0 - wait for beginning of comment
# 1 - parse comment format 1
# 2 - parse comment format 2
#
# 4 - wait for beginning of source (or comment ??)
# 5 - process source
#
comment = [ ]
source = [ ]
state = 0
for line in fileinput . input ( ) :
l = len ( line )
if l > 0 and line [ l - 1 ] == ' \012 ' :
line = line [ 0 : l - 1 ]
# stripped version of the line
line2 = string . strip ( line )
l = len ( line2 )
# if this line begins with a comment and we are processing some
# source, exit to state 0
#
# unless we encounter something like:
#
# /*@.....
# /*#.....
#
# /* @.....
# /* #.....
#
if format > = 4 and l > 2 and line2 [ 0 : 2 ] == ' /* ' :
if l < 4 or ( line2 [ 3 ] != ' @ ' and line2 [ 3 : 4 ] != ' @ ' and
line2 [ 3 ] != ' # ' and line2 [ 3 : 4 ] != ' # ' ) :
list . append ( ( block , source ) )
format = 0
if format == 0 : #### wait for beginning of comment ####
if l > 3 and line2 [ 0 : 3 ] == ' /** ' :
i = 3
while i < l and line2 [ i ] == ' * ' :
i = i + 1
if i == l :
# this is '/**' followed by any number of '*', the
# beginning of a Format 1 block
#
block = [ ]
source = [ ]
format = 1
elif i == l - 1 and line2 [ i ] == ' / ' :
# this is '/**' followed by any number of '*', followed
# by a '/', i.e. the beginning of a Format 2 or 3 block
#
block = [ ]
source = [ ]
format = 2
##############################################################
#
# FORMAT 1
#
elif format == 1 :
# if the line doesn't begin with a "*", something went
# wrong, and we must exit, and forget the current block..
if l == 0 or line2 [ 0 ] != ' * ' :
block = [ ]
format = 0
# otherwise, we test for an end of block, which is an
# arbitrary number of '*', followed by '/'
else :
i = 1
while i < l and line2 [ i ] == ' * ' :
i = i + 1
# test for the end of the block
if i < l and line2 [ i ] == ' / ' :
if block != [ ] :
format = 4
else :
format = 0
else :
# otherwise simply append line to current block
block . append ( line2 [ i : ] )
continue
##############################################################
#
# FORMAT 2
#
elif format == 2 :
# if the line doesn't begin with '/*' and end with '*/',
# this is the end of the format 2 format
if l < 4 or line2 [ : 2 ] != ' /* ' or line2 [ - 2 : ] != ' */ ' :
if block != [ ] :
format = 4
else :
format = 0
else :
# remove the start and end comment delimiters, then
# right-strip the line
line2 = string . rstrip ( line2 [ 2 : - 2 ] )
# check for end of a format2 block, i.e. a run of '*'
if string . count ( line2 , ' * ' ) == l - 4 :
if block != [ ] :
format = 4
else :
format = 0
else :
# otherwise, add the line to the current block
block . append ( line2 )
continue
if format > = 4 : #### source processing ####
if l > 0 :
format = 5
if format == 5 :
source . append ( line )
if format > = 4 :
list . append ( [ block , source ] )
return list
# This function is only used for debugging
#
def dump_block_list ( list ) :
""" dump a comment block list """
for block in list :
print " ---------------------------------------- "
for line in block [ 0 ] :
print line
for line in block [ 1 ] :
print line
print " ---------the end----------------------- "
@ -733,8 +805,16 @@ def main( argv ):
""" main program loop """
sys . stderr . write ( " extracting comment blocks from sources... \n " )
list = make_block_list ( )
list = block_make_list ( list )
dump_html_1 ( list )
list2 = filter_blocks ( list , [ ' type ' , ' macro ' , ' enum ' , ' constant ' , ' functype ' ] )
#list2 = list
list2 . sort ( block_lexicographical_compare )
dump_html_1 ( list2 )
#dump_doc_blocks( list )
#dump_block_lists( list )
#dump_html_1( list )
# If called from the command line