shithub: freetype+ttf2subf

Download patch

ref: 48721c11b549480e9d3eaa3671866d9aa9d01ab1
parent: f95a603117672c12ff4a00e680519db17b21cf7b
author: David Turner <[email protected]>
date: Mon Aug 21 19:01:32 EDT 2000

significant updates. The generated HTML is now much
more pleasant..

git/fs: mount .git/fs: mount/attach disallowed
--- a/docs/docmaker.py
+++ b/docs/docmaker.py
@@ -6,8 +6,56 @@
 
 import fileinput, sys, string
 
-# This function is used to parse a source file, and extract comment blocks
-# from it. The following comment block formats are recognized :
+html_header = """
+<html>
+<header>
+<title>FreeType 2 API Reference</title>
+<basefont face="Georgia, Arial, Helvetica, Geneva">
+<style content="text/css">
+  P { text-align=justify }
+  H1 { text-align=center }
+  H2 { text-align=center }
+  LI { text-align=justify }
+</style>
+</header>
+<body text="#000000"
+      bgcolor="#FFFFFF"
+      link="#0000EF"
+      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>
+"""
+
+code_header = """
+<font color=blue><pre>
+"""
+
+code_footer = """
+</pre></font>
+"""
+
+para_header = "<p>"
+para_footer = "</p>"
+
+block_header = """<table width="100%"><tr><td>"""
+block_footer = "</table>"
+
+source_header = """<table width="100%"><tr bgcolor="#D6E8FF" width="100%"><td><pre>
+"""
+source_footer = """</pre></table>
+<br><br>
+"""
+
+# The FreeType 2 reference is extracted from the source files. These contain
+# various comment blocks that follow one of the following formats:
 #
 #  /**************************
 #   *
@@ -35,10 +83,32 @@
 #  /*                        */
 #  /**************************/
 #
-# Each block is modeled as a simple list of text strings
-# The function returns a list of blocks, i.e. a list of strings lists
+# Each block contains a list of markers, each one can be followed by
+# some arbitrary text or a list of fields. Here's an example:
 #
+#    <Struct>
+#       MyStruct
+#
+#    <Description>
+#       this structure holds some data
+#
+#    <Fields>
+#       x :: horizontal coordinate
+#       y :: vertical coordinate
+#
+#
+# This example defines three markers: 'Struct', 'Description' & 'Fields'
+# The first two markers contain arbitrary text, while the last one contains
+# a list of field
+#
+#
+# each field is simple of the format:  WORD :: TEXT....
+#
+# Note that typically, each comment block is followed by some source
+# code declaration that may need to be kept in the reference..
+#
 
+
 def make_block_list():
     """parse a file and extract comments blocks from it"""
 
@@ -45,16 +115,43 @@
     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():
 
-	line = string.strip(line)
-	l    = len(line)
+        # remove trailing CR
+        l = len(line)
+        if l > 0 and line[l-1] == '\012':
+            line = line[0:l-1]
 
-	if format == 0:
-	    if l > 3 and line[0:3] == '/**':
+        # stripped version of the line
+        line2 = string.strip(line)
+        l     = len(line2)
+
+        # if this line begins with a comment and we're processing some source, exit
+        # to state 0
+        #
+        if format >= 4 and l > 2 and line2[0:2] == '/*':
+            list.append( (block,source) )
+            format = 0
+        
+        if format == 0:  ##################### wait beginning of comment ###########
+	    if l > 3 and line2[0:3] == '/**':
 		i = 3
-		while (i < l) and (line[i] == '*'):
+		while (i < l) and (line2[i] == '*'):
 		    i = i+1
 
 		if i == l:
@@ -61,16 +158,18 @@
 		    # this is '/**' followed by any number of '*', the
 		    # beginning of a Format 1 block
 		    #
-		    block  = [];
-		    format = 1;
+		    block  = []
+		    source = []
+		    format = 1
 
-		elif (i == l-1) and (line[i] == '/'):
+		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  = [];
-		    format = 2;
-				
+		    block  = []
+		    source = []
+		    format = 2
+
 	##############################################################
 	#
 	# FORMAT 1
@@ -79,7 +178,7 @@
 
 	    # if the line doesn't begin with a "*", something went
 	    # wrong, and we must exit, and forget the current block..
-	    if (l == 0) or (line[0] != '*'):
+	    if (l == 0) or (line2[0] != '*'):
 		block  = []
 		format = 0
 		
@@ -87,17 +186,19 @@
 	    # arbitrary number of '*', followed by '/'
 	    else:
 		i = 1
-		while (i < l) and (line[i] == '*'):
+		while (i < l) and (line2[i] == '*'):
 		    i = i+1
 
 		# test for the end of the block
-		if (i < l) and (line[i] == '/'):
-		    if block != []: list.append( block )
-		    format = 0
-		    block  = []
-
+		if (i < l) and (line2[i] == '/'):
+		    if block != []:
+		        format = 4
+		    else:
+		        format = 0
 		else:
-		    block.append( line[1:] )
+		    # otherwise simply append line to current block
+                    block.append(line2)
+                continue
 
 	##############################################################
 	#
@@ -107,28 +208,48 @@
 
 	    # if the line doesn't begin with '/*' and end with '*/',
 	    # this is the end of the format 2 format..
-	    if (l < 4 ) or (line[:2] != '/*') or (line[-2:] != '*/'):
-		if block != []: list.append(block)
-		block  = []
-		format = 0
-		continue
+	    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])
 
-	    # remove the start and end comment delimiters, then right-strip
-	    # the line
-	    line = string.rstrip(line[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
 
-	    # check for end of a format2 block, i.e. a run of '*'
-	    if string.count(line,'*') == l-4:
-		if block != []: list.append(block)
-		block = []
-		format = 0
-	    else:
-		# otherwise, add the line to the current block
-		block.append(line)
 
+
+        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 ):
@@ -135,43 +256,29 @@
     """dump a comment block list"""
     for block in list:
 	print "----------------------------------------"
-	for line in block:
-	    print line
+	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
 #
-# The DocParagraph is used to store either simple text paragraph or
-# source code lines
-#
-#
-# If the paragraph contains source code (use code=1 when initializing the
-# object), self.lines is a list of source code strings
-#
-# Otherwise, self.lines is simply a list of words for the paragraph
-#
-class DocParagraph:
+class DocCode:
 
-    def __init__(self,code=0,margin=0):
+    def __init__(self,margin=0):
 	self.lines  = []
-	self.code   = code
 	self.margin = margin 
 	
     def	add(self,line):
-    
-	if self.code==0:
-	    # get rid of unwanted spaces in the paragraph
-	    self.lines.extend( string.split(line) )
-	
-	else:
-	    # remove margin whitespace
-	    if string.strip( line[:self.margin] ) == "": line = line[self.margin:]
-	    self.lines.append(line)
+        # remove margin whitespace
+        if string.strip( line[:self.margin] ) == "": line = line[self.margin:]
+        self.lines.append(line)
 
     
     def dump(self):
@@ -178,75 +285,88 @@
 
 	max_width = 50
 
-	if self.code == 0:
-	    cursor = 0
-	    line   = ""
-	    
-	    for word in self.lines:
+        for line in self.lines:
+            print "--" + line
 
-		if cursor+len(word)+1 > max_width:
-		    print line
-		    cursor = 0
-		    line = ""
+	print ""
 
-		line   = line + word + " "
-		cursor = cursor + len(word) + 1
-		
-	    if cursor > 0:
-		print line
 
-	else:
-	    for line in self.lines:
-		print "--" + line
-		
-	print ""
+    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
 
+        print code_header
+        for line in self.lines[0:len]:
+            print lines
+        print code_footer
 
-######################################################################################
+
+##############################################################################
 #
+# The DocParagraph is used to store either simple text paragraphs
+# self.words is simply a list of words for the paragraph
 #
-# The DocContent class is used to store the content of a given marker
-# Each DocContent can have its own text, plus a list of fields. Each field
-# has its own text too
+class DocParagraph:
+
+    def __init__(self):
+	self.words  = []
+	
+    def	add(self,line):
+        # get rid of unwanted spaces in the paragraph
+        self.words.extend( string.split(line) )
+	
+    
+    def dump(self):
+
+	max_width = 50
+        cursor    = 0
+        line      = ""
+        
+        for word in self.words:
+    
+	    if cursor+len(word)+1 > max_width:
+	        print line
+	        cursor = 0
+	        line = ""
+    
+	    line   = line + word + " "
+	    cursor = cursor + len(word) + 1
+	    
+        if cursor > 0:
+	    print line
+
+	print ""
+
+
+    def dump_html(self):
+    
+        print para_header
+        self.dump()
+        print para_footer
+
+
+###########################################################################
 #
-# Hence, the following lines :
+# DocContent is used to store the content of a given marker.
 #
-#    """  
-#    Some arbitraty text:
 #
-#      fieldone :: some arbitraty text for this field,
-#                  note that the text stretches to several lines
 #
-#      fieldtwo :: some other text
-#
-#    """
-#
-# will be stored as (each text is a list of string:
-#
-#    self.fields = [ "", "fieldone", "fieldtwo" ]
-#    self.texts  = [
-#                    [ "some arbitraty text for this field," ,
-#                      "note that the text stretches to several lines" ],
-#
-#                    [ "some other text" ]
-#                  ]
-#
-#
 class DocContent:
 
-    def __init__(self, paragraph_lines=[]):
-    
-	self.fields = []
-	self.texts  = []
-	
-	code_mode   = 0
-	code_margin = 0
-	
-	field       = ""
-	text        = []
-	paragraph   = None 
+    def  __init__(self,lines_list):
+        self.items    = []
+        code_mode     = 0
+        code_margin   = 0
+        text          = []
+        paragraph     = None
+        code          = None
+        elements      = []
+        field         = None
 
-	for aline in paragraph_lines:
+	for aline in lines_list:
 	
 	    if code_mode == 0:
 		line   = string.lstrip(aline) 
@@ -255,39 +375,35 @@
 
 		# if the line is empty, this is the end of the current
 		# paragraph
-		if line == "":
+		if l == 0 or line == '{':
+                
 		    if paragraph:
-			text.append(paragraph)
-			paragraph = None
-		    continue
+                        elements.append(paragraph)
+                        paragraph = None
+                    
+                    if line == "":
+                        continue
+                        
+                    code_mode   = 1
+                    code_margin = margin
+                    code        = None
+                    continue
 	    
-		# test for the beginning of a code block, i.e.'{' is the first
-		# and only character on the line..
-		#
-		if line == '{':
-		    code_mode   = 1
-		    code_margin = margin
-		    if paragraph:
-			text.append(paragraph)
-		    paragraph = DocParagraph( 1, margin )
-		    continue
-	    
 		words = string.split(line)
 		
 		# test for a field delimiter on the start of the line, i.e.
-		# the oken `::'
+		# the token `::'
 		#
 		if len(words) >= 2 and words[1] == "::":
 		    if paragraph:
-			text.append(paragraph)
-			paragraph = None
-			
-		    self.fields.append(field)
-		    self.texts.append(text)
+                        elements.append(paragraph)
+                        paragraph = None
+
+                    self.items.append( (field,elements) )
 		
-		    field = words[0]
-		    text  = []
-		    words = words[2:]
+		    field    = words[0]
+		    elements = []
+		    words    = words[2:]
 			
 		if len(words) > 0:
 		    line = string.join(words)
@@ -300,61 +416,74 @@
 		
 		# the code block ends with a line that has a single '}' on it
 		if line == " "*code_margin+'}':
-		    text.append(paragraph)
-		    paragraph   = None
+                
+                    if code:
+                        elements.append(code)
+                        code = None
+                        
 		    code_mode   = 0
 		    code_margin = 0
 		
 		# otherwise, add the line to the current paragraph
 		else:
-		    paragraph.add(line)
+                    if not code:
+                        code = DocCode()
+		    code.add(line)
 	
 	if paragraph:
-	    text.append(paragraph)
+	    elements.append(paragraph)
+
+        if code:
+            elements.append(code)
 	    
-	self.fields.append( field )
-	self.texts.append( text )    
+	self.items.append( (field,elements) )
 
 
-    
+
     def dump(self):
-	for i in range(len(self.fields)):
-	    field = self.fields[i]
-	    if field: print "<field "+field+">"
+	for item in self.items:
+            field = item[0]
+	    if field:
+                print "<field "+field+">"
 
-	    for paras in self.texts[i]:
-		paras.dump()
+	    for element in item[1]:
+                element.dump()
 	    
-	    if field: print "</field>	"
+	    if field:
+                print "</field>	"
 
     def dump_html(self):
-        n = len(self.fields)
+        
+        n        = len(self.items)
+        in_table = 0
+        
         for i in range(n):
-            field = self.fields[i]
-            if field==[]:
-                print "<p>"
-                for paras in self.texts[i]:
-                    print "<p>"
-                    paras.dump()
-                    print "</p>"
+            item  = self.items[i]
+            field = item[0]
+            
+            if not field:
+            
+                if in_table:
+                  print "</td></tr></table>"
+                  in_table = 0
+                  
+                for element in item[1]:
+                  element.dump_html()
             else:
-                if i==1:
+                if not in_table:
                     print "<table cellpadding=4><tr valign=top><td>"
+                    in_table = 1
                 else:
                     print "</td></tr><tr valign=top><td>"
                 
                 print "<b>"+field+"</b></td><td>"
                 
-                for paras in self.texts[i]:
-                    print "<p>"
-                    paras.dump()
-                    print "</p>"
-                    
-                print "</td></tr>"
-        if n > 1:
-            print "</table>"
-              
+                for element in item[1]:
+                    element.dump_html()
 
+        if in_table:
+            print "</td></tr></table>"
+
 ######################################################################################
 #
 #
@@ -364,9 +493,10 @@
 #
 class DocBlock:
 
-    def __init__(self, block_line_list=[]):
+    def __init__(self, block_line_list=[], source_line_list=[]):
 	self.markers  = []
 	self.contents = []
+        self.source   = source_line_list
     
         marker   = ""
         content  = []
@@ -468,11 +598,18 @@
 
 def dump_html_1( block_list ):
     
-    print "<html><body>"
+    print html_header
+    
     types = [ 'Type', 'Struct', 'FuncType', 'Function', 'Constant', 'Enumeration' ]
     for block in block_list:
-          docblock = DocBlock(block)
-          print "<hr>"
+    
+          docblock = DocBlock(block[0],block[1])
+          
+          if len(docblock.markers) == 0:
+              continue
+
+          print block_header
+
           for i in range(len(docblock.markers)):
               marker   = docblock.markers[i]
               content  = docblock.contents[i]
@@ -492,25 +629,32 @@
                   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 "<hr></body></html>"
-              
+    print html_footer
 
+    
+    
+
+
 def main(argv):
     """main program loop"""
     print "extracting comment blocks from sources .."
     list = make_block_list()
     
-#    dump_block_list( list )
+    dump_html_1( list )
 
-#    dump_doc_blocks( list )
-
-#    print "dumping block contents .."
-#    dump_doc_contents(list)
-
-    dump_html_1(list)
-     
-#    dump_single_content(list)
 
 # If called from the command line
 if __name__=='__main__': main(sys.argv)