added cross-reference generation
diff --git a/ChangeLog b/ChangeLog
index c5a2e4f..5f67e90 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2001-01-11 David Turner <david.turner@freetype.org>
+
+ * docs/docmaker.py: Added cross-references generation as well as
+ more robust handling of pathname wildward matching
+
2001-01-10 Werner Lemberg <wl@gnu.org>
* docs/docmaker.py: Minor improvements to reduce unwanted spaces
diff --git a/docs/docmaker.py b/docs/docmaker.py
index 752be46..f39ef78 100644
--- a/docs/docmaker.py
+++ b/docs/docmaker.py
@@ -45,14 +45,14 @@
block_header = "<center><hr width=75%><table width=75%><tr><td>"
block_footer = "</td></tr></table></center>"
-description_header = "<center><table width=65%><tr><td>"
+description_header = "<center><table width=87%><tr><td>"
description_footer = "</td></tr></table></center><br>"
-marker_header = "<center><table width=65% cellpadding=5><tr bgcolor=#EEEEFF><td><em><b>"
+marker_header = "<center><table width=87% cellpadding=5><tr bgcolor=#EEEEFF><td><em><b>"
marker_inter = "</b></em></td></tr><tr><td>"
marker_footer = "</td></tr></table></center>"
-source_header = "<center><table width=65%><tr bgcolor=#D6E8FF width=100%><td><pre>"
+source_header = "<center><table width=87%><tr bgcolor=#D6E8FF width=100%><td><pre>"
source_footer = "</pre></table></center><br>"
@@ -184,7 +184,7 @@
return "UNKNOWN_CODE_IDENTIFIER!"
- def dump_html( self ):
+ def dump_html( self, identifiers = None ):
# clean the last empty lines
#
l = len( self.lines ) - 1
@@ -239,20 +239,56 @@
return "UNKNOWN_PARA_IDENTIFIER!"
- def dump( self ):
+ def dump( self, identifiers = None ):
max_width = 50
cursor = 0
line = ""
+ extra = None
+ alphanum = string.lowercase + string.uppercase + string.digits + '_'
for word in self.words:
+
+ # process cross references when needed
+ if identifiers and word and word[0] == '@':
+ word = word[1:]
+
+ # we need to find non alpha numeric charaters
+ i = len(word)
+ while i > 0 and not word[i-1] in alphanum:
+ i = i-1
+
+ if i > 0:
+ extra = word[i:]
+ word = word[0:i]
+
+ block = identifiers.get( word )
+ if block:
+ word = '<a href="'+block.html_address()+'">' + word + '</a>'
+ else:
+ word = '?'+word
+
if cursor + len( word ) + 1 > max_width:
print line
cursor = 0
line = ""
- line = line + word + " "
+ line = line + word
+ if not extra:
+ line = line + " "
cursor = cursor + len( word ) + 1
+ # handle trailing periods, commas, etc.. at the end of
+ # cross references..
+ if extra:
+ if cursor + len( extra ) + 1 > max_width:
+ print line
+ cursor = 0
+ line = ""
+
+ line = line + extra + " "
+ cursor = cursor + len( extra ) + 1
+ extra = None
+
if cursor > 0:
print line
@@ -269,9 +305,9 @@
return s
- def dump_html( self ):
+ def dump_html( self, identifiers = None ):
print para_header
- self.dump()
+ self.dump( identifiers )
print para_footer
@@ -444,7 +480,7 @@
print "</field>"
- def dump_html( self ):
+ def dump_html( self, identifiers = None ):
n = len( self.items )
in_table = 0
@@ -458,7 +494,7 @@
in_table = 0
for element in item[1]:
- element.dump_html()
+ element.dump_html( identifiers )
else:
if not in_table:
@@ -470,13 +506,13 @@
print "<b>" + field + "</b></td><td>"
for element in item[1]:
- element.dump_html()
+ element.dump_html( identifiers )
if in_table:
print "</td></tr></table>"
- def dump_html_in_table( self ):
+ def dump_html_in_table( self, identifiers = None ):
n = len( self.items )
in_table = 0
@@ -488,14 +524,14 @@
if item[1]:
print "<tr><td colspan=2>"
for element in item[1]:
- element.dump_html()
+ element.dump_html( identifiers )
print "</td></tr>"
else:
print "<tr><td><b>" + field + "</b></td><td>"
for element in item[1]:
- element.dump_html()
+ element.dump_html( identifiers )
print "</td></tr>"
@@ -526,8 +562,10 @@
class DocBlock:
def __init__( self, block_line_list = [], source_line_list = [] ):
- self.items = [] # current ( marker, contents ) list
- self.section = None # section this block belongs to
+ self.items = [] # current ( marker, contents ) list
+ self.section = None # section this block belongs to
+ self.filename = "unknown" # filename defining this block
+ self.lineno = 0 # line number in filename
marker = None # current marker
content = [] # current content lines list
@@ -607,6 +645,17 @@
return item[1]
return None
+ def html_address( self ):
+ section = self.section
+ if section and section.filename:
+ return section.filename+'#'+self.name
+
+ return "" # this block is not in a section ??
+
+
+ def location( self ):
+ return self.filename + ':' + str(self.lineno)
+
def dump( self ):
for i in range( len( self.items ) ):
@@ -615,9 +664,9 @@
content.dump()
- def dump_html( self ):
+ def dump_html( self, identifiers = None ):
types = [ 'type', 'struct', 'functype', 'function',
- 'constant', 'enum', 'macro' ]
+ 'constant', 'enum', 'macro', 'structure', 'also' ]
parameters = [ 'input', 'inout', 'output', 'return' ]
@@ -638,6 +687,7 @@
# print source code
#
if not self.source:
+ print block_footer
return
lines = self.source
@@ -660,14 +710,14 @@
if marker == "description":
print description_header
- content.dump_html()
+ content.dump_html( identifiers )
print description_footer
elif not ( marker in types ):
sys.stdout.write( marker_header )
sys.stdout.write( marker )
sys.stdout.write( marker_inter + '\n' )
- content.dump_html()
+ content.dump_html( identifiers )
print marker_footer
print ""
@@ -716,14 +766,14 @@
if self.elements.has_key( block.name ):
sys.stderr.write( "ERROR - duplicate element definition for " +
"'" + block.name + "' in section '" +
- section.name + "'" )
- sys.quit()
+ self.name + "'" )
+ sys.exit()
self.elements[ block.name ] = block
self.list.append( block )
- def dump_html( self ):
+ def dump_html( self, identifiers = None ):
"""make an HTML page from a given DocSection"""
# print HTML header
@@ -739,13 +789,13 @@
# print description
#
print block_header
- self.description.dump_html()
+ self.description.dump_html( identifiers )
print block_footer
# print elements
#
for element in self.list:
- element.dump_html()
+ element.dump_html( identifiers )
print html_footer
@@ -753,12 +803,11 @@
class DocSectionList:
def __init__( self ):
- self.sections = {}
- self.list = []
- self.current_section = None
- self.index = [] # sorted list of blocks that
- # are not sections
-
+ self.sections = {} # map section names to section objects
+ self.list = [] # list of sections (in creation order)
+ self.current_section = None # current section
+ self.identifiers = {} # map identifiers to blocks
+
def append_section( self, block ):
name = string.lower( block.name )
abstract = block.find_content( "abstract" )
@@ -776,6 +825,10 @@
if abstract:
stderr.write( "ERROR - duplicate section definition" +
" for '" + name + "'" )
+ stderr.write( "previous definition in" +
+ " '" + section.location() )
+ stderr.write( "second definition in" +
+ " '" + block.location() )
sys.quit()
else:
# The old section didn't contain an abstract; we are
@@ -802,10 +855,9 @@
self.append_section( block )
elif self.current_section:
- # sys.stderr.write( " new block" )
self.current_section.add_element( block )
block.section = self.current_section
- self.index.append( block )
+ self.identifiers[block.name] = block
def prepare_files( self, file_prefix = None ):
@@ -834,9 +886,10 @@
self.toc_filename = prefix + "toc.html"
self.index_filename = prefix + "index.html"
- # compute the sorted block list for the index
+ # compute the sorted list of identifiers for the index
#
- self.index.sort( block_lexicographical_compare )
+ self.index = self.identifiers.keys()
+ self.index.sort()
def dump_html_toc( self ):
@@ -857,7 +910,7 @@
sys.stdout.write( '<a href="' + section.filename + '">' )
sys.stdout.write( section.title )
sys.stdout.write( "</a></td><td>" + '\n' )
- section.abstract.dump_html()
+ section.abstract.dump_html( self.identifiers )
print "</td></tr>"
print "</table></center>"
@@ -874,7 +927,7 @@
if section.filename:
new_file = open( section.filename, "w" )
sys.stdout = new_file
- section.dump_html()
+ section.dump_html( self.identifiers )
new_file.close()
sys.stdout = old_stdout
@@ -893,17 +946,20 @@
print "<center><h1>General Index</h1></center>"
print "<center><table cellpadding=5><tr valign=top><td>"
- for block in self.index:
- sys.stdout.write( '<a href="' + block.section.filename +
- '#' + block.name + '">' )
- sys.stdout.write( block.name )
- sys.stdout.write( "</a><br>" + '\n' )
+ for ident in self.index:
+ block = self.identifiers[ident]
+ if block:
+ sys.stdout.write( '<a href="' + block.html_address() + '">' )
+ sys.stdout.write( block.name )
+ sys.stdout.write( '</a><br>' + '\n' )
- if line * num_columns >= total:
- print "</td><td>"
- line = 0
+ if line * num_columns >= total:
+ print "</td><td>"
+ line = 0
+ else:
+ line = line + 1
else:
- line = line + 1
+ sys.stderr.write( "identifier '"+ident+"' has no definition" + '\n' )
print "</tr></table></center>"
print html_footer
@@ -962,24 +1018,51 @@
print html_footer
-def make_block_list_inner():
+def file_exists( pathname ):
+ result = 1
+ try:
+ file = open( pathname, "r" )
+ file.close()
+ except:
+ result = None
+
+ return result
+
+
+def add_new_block( list, filename, lineno, block_lines, source_lines ):
+ """add a new block to the list"""
+ block = DocBlock( block_lines, source_lines )
+ block.filename = filename
+ block.lineno = lineno
+ list.append( block )
+
+
+def make_block_list():
"""parse a file and extract comments blocks from it"""
file_list = []
sys.stderr.write( repr( sys.argv[1:] ) + '\n' )
for pathname in sys.argv[1:]:
- newpath = glob.glob( pathname )
- sys.stderr.write( repr(newpath) + '\n' )
+ if string.find( pathname, '*' ) >= 0:
+ newpath = glob.glob( pathname )
+ newpath.sort() # sort files, this is important because the order of files
+ else:
+ newpath = [ pathname ]
+
last = len( file_list )
file_list[last:last] = newpath
if len( file_list ) == 0:
file_list = None
+ else:
+ # now filter the file list to remove non-existing ones
+ file_list = filter( file_exists, file_list )
list = []
block = []
format = 0
+ lineno = 0
# We use "format" to store the state of our parser:
#
@@ -1018,7 +1101,7 @@
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 ) )
+ add_new_block( list, fileinput.filename(), lineno, block, source )
format = 0
if format == 0: #### wait for beginning of comment ####
@@ -1034,6 +1117,7 @@
block = []
source = []
format = 1
+ lineno = fileinput.lineno()
elif i == l - 1 and line2[i] == '/':
# this is '/**' followed by any number of '*', followed
@@ -1042,6 +1126,7 @@
block = []
source = []
format = 2
+ lineno = fileinput.lineno()
##############################################################
#
@@ -1120,23 +1205,11 @@
source.append( line )
if format >= 4:
- list.append( [block, source] )
+ add_new_block( list, fileinput.filename(), lineno, block, source )
return list
-# create a list of DocBlock elements
-#
-def make_block_list():
- source_block_list = make_block_list_inner()
- list = []
-
- for block in source_block_list:
- docblock = DocBlock( block[0], block[1] )
- list.append( docblock )
-
- return list
-
# This function is only used for debugging
#