[gtk-doc] parsing: have simillar support for unions like we have for structs



commit 43c15f2b4e0ba34292902292f28deca82def1a76
Author: Philip Chimento <philip chimento gmail com>
Date:   Fri Dec 25 00:02:01 2009 +0200

    parsing: have simillar support for unions like we have for structs
    
    Improve the scanner to handle unions and mkdb to output better docbook fragments.

 gtkdoc-common.pl.in |    6 ++--
 gtkdoc-mkdb.in      |   71 ++++++++++++++++++++++++++++++++++++++++++-
 gtkdoc-scan.in      |   82 +++++++++++++++++++++++++--------------------------
 3 files changed, 112 insertions(+), 47 deletions(-)
---
diff --git a/gtkdoc-common.pl.in b/gtkdoc-common.pl.in
index 188d4ac..04571b5 100644
--- a/gtkdoc-common.pl.in
+++ b/gtkdoc-common.pl.in
@@ -97,7 +97,7 @@ sub ParseStructDeclaration {
     my ($declaration, $is_object, $output_function_params, $typefunc, $namefunc) = @_;
 
     # For forward struct declarations just return an empty array.
-    if ($declaration =~ m/struct\s+\S+\s*;/msg) {
+    if ($declaration =~ m/(?:struct|union)\s+\S+\s*;/msg) {
       return ();
     }
 
@@ -105,7 +105,7 @@ sub ParseStructDeclaration {
 
     # For objects, assume private
     if ($is_object) {
-	$declaration =~ s!(struct\s+\w*\s*\{)
+	$declaration =~ s!((?:struct|union)\s+\w*\s*\{)
 	                  .*?
 			  (?:/\*\s*<\s*public\s*>\s*\*/|(?=\}))!$1!msgx;
     }
@@ -125,7 +125,7 @@ sub ParseStructDeclaration {
     }
 
     # Prime match after "struct {" declaration
-    if (!scalar($declaration =~ m/struct\s+\w*\s*\{/msg)) {
+    if (!scalar($declaration =~ m/(?:struct|union)\s+\w*\s*\{/msg)) {
 	die "Structure declaration '$declaration' does not begin with struct [NAME] {\n";
     }
 
diff --git a/gtkdoc-mkdb.in b/gtkdoc-mkdb.in
index 6000db8..5cc6f62 100755
--- a/gtkdoc-mkdb.in
+++ b/gtkdoc-mkdb.in
@@ -1629,13 +1629,29 @@ sub OutputUnion {
     my ($symbol, $declaration) = @_;
     my $id = &CreateValidSGMLID ($symbol);
     my $condition = &MakeConditionDescription ($symbol);
-    my $synop = &MakeReturnField("union") . "<link linkend=\"$id\">$symbol</link>;\n";
-    my $desc = "<refsect2 id=\"$id\" role=\"union\"$condition>\n<title>union $symbol</title>\n";
+
+    # Determine if it is a simple struct or it also has a typedef.
+    my $has_typedef = 0;
+    if ($StructHasTypedef{$symbol} || $declaration =~ m/^\s*typedef\s+/) {
+      $has_typedef = 1;
+    }
+
+    my $synop;
+    my $desc;
+    if ($has_typedef) {
+        # For unions with typedefs we just output the union name.
+        $synop = &MakeReturnField("") . "<link linkend=\"$id\">$symbol</link>;\n";
+        $desc = "<refsect2 id=\"$id\" role=\"union\"$condition>\n<title>$symbol</title>\n";
+    } else {
+        $synop = &MakeReturnField("union") . "<link linkend=\"$id\">$symbol</link>;\n";
+        $desc = "<refsect2 id=\"$id\" role=\"union\"$condition>\n<title>union $symbol</title>\n";
+    }
 
     $desc .= MakeIndexterms($symbol, $id);
     $desc .= "\n";
     $desc .= OutputSymbolExtraLinks($symbol);
 
+    # FIXME: we do more for structs
     my $decl_out = &CreateValidSGML ($declaration);
     $desc .= "<programlisting>$decl_out</programlisting>\n";
 
@@ -1644,6 +1660,57 @@ sub OutputUnion {
     if (defined ($SymbolDocs{$symbol})) {
 	$desc .= &ExpandAbbreviations($symbol, $SymbolDocs{$symbol});
     }
+
+    # Create a table of fields and descriptions
+
+    # FIXME: Inserting &#160's into the produced type declarations here would
+    #        improve the output in most situations ... except for function
+    #        members of structs!
+    my @fields = ParseStructDeclaration($declaration, 0,
+					0, \&MakeXRef,
+					sub {
+					    "<structfield id=\"".&CreateValidSGMLID("$id.$_[0]")."\">$_[0]</structfield>";
+					});
+    my $params = $SymbolParams{$symbol};
+
+    # If no parameters are filled in, we don't generate the description
+    # table, for backwards compatibility
+
+    my $found = 0;
+    if (defined $params) {
+	for (my $i = 1; $i <= $#$params; $i += $PARAM_FIELD_COUNT) {
+	    if ($params->[$i] =~ /\S/) {
+		$found = 1;
+		last;
+	    }
+	}
+    }
+
+    if ($found) {
+	my %field_descrs = @$params;
+
+	    $desc .= <<EOF;
+<variablelist role="struct">
+EOF
+	while (@fields) {
+	    my $field_name = shift @fields;
+	    my $text = shift @fields;
+	    my $field_descr = $field_descrs{$field_name};
+            my $param_annotations = "";
+
+	    $desc .= "<varlistentry><term>$text</term>\n";
+	    if (defined $field_descr) {
+                ($field_descr,$param_annotations) = &ExpandAnnotation($symbol, $field_descr);
+                $field_descr = &ExpandAbbreviations($symbol, $field_descr);
+		$desc .= "<listitem><simpara>$field_descr$param_annotations</simpara></listitem>\n";
+	    } else {
+		$desc .= "<listitem><simpara /></listitem>\n";
+	    }
+            $desc .= "</varlistentry>\n";
+	}
+
+	$desc .= "</variablelist>";
+    }
     $desc .= OutputSymbolTraits ($symbol);
     $desc .= "</refsect2>\n";
     return ($synop, $desc);
diff --git a/gtkdoc-scan.in b/gtkdoc-scan.in
index 93d1705..87a73fe 100755
--- a/gtkdoc-scan.in
+++ b/gtkdoc-scan.in
@@ -201,7 +201,7 @@ if ($REBUILD_SECTIONS || ! -e $sections_file) {
 
 sub ScanHeaders {
     my ($source_dir, $object_list, $main_list) = @_;
-#    print "Scanning source directory: $source_dir\n";
+    #print "Scanning source directory: $source_dir\n";
 
     # This array holds any subdirectories found.
     my (@subdirs) = ();
@@ -262,8 +262,8 @@ sub ScanHeader {
 				  #   and the rest of the declaration after.
     my ($first_macro) = 1;	  # Used to try to skip the standard #ifdef XXX
 				  #   #define XXX at the start of headers.
-    my ($level);			  # Used to handle structs which contain nested
-				  #   structs or unions.
+    my ($level);			  # Used to handle structs/unions which contain
+				  #   nested structs or unions.
     my @objects = ();		  # Holds declarations that look like GtkObject
 				  #   subclasses, which we remove from the list.
 
@@ -425,40 +425,42 @@ sub ScanHeader {
 		$in_declaration = "enum";
 
 
-	    # STRUCTS
+	    # STRUCTS AND UNIONS
 
-	    } elsif (m/^\s*typedef\s+struct\s+_(\w+)\s+\1\s*;/) {
+	    } elsif (m/^\s*typedef\s+(struct|union)\s+_(\w+)\s+\2\s*;/) {
 		# We've found a 'typedef struct _<name> <name>;'
 		# This could be an opaque data structure, so we output an
 		# empty declaration. If the structure is actually found that
 		# will override this.
-		#print "DEBUG: struct typedef: $1\n";
-		&AddSymbolToList (\$list, $1);
-		print DECL "<STRUCT>\n<NAME>$1</NAME>\n$deprecated</STRUCT>\n";
+		my $structsym = uc $1;
+		#print "DEBUG: $structsym typedef: $2\n";
+		&AddSymbolToList (\$list, $2);
+		print DECL "<$structsym>\n<NAME>$2</NAME>\n$deprecated</$structsym>\n";
 
-	    } elsif (m/^\s*struct\s+_(\w+)\s*;/) {
-		# Skip private structs.
-                #print "DEBUG: private struct\n";
+	    } elsif (m/^\s*(?:struct|union)\s+_(\w+)\s*;/) {
+		# Skip private structs/unions.
+                #print "DEBUG: private struct/union\n";
 
-	    } elsif (m/^\s*struct\s+(\w+)\s*;/) {
+	    } elsif (m/^\s*(struct|union)\s+(\w+)\s*;/) {
 	        # Do a similar thing for normal structs as for typedefs above.
 	        # But we output the declaration as well in this case, so we
 	        # can differentiate it from a typedef.
-	        #print "DEBUG: struct: $1\n";
-		&AddSymbolToList (\$list, $1);
-		print DECL "<STRUCT>\n<NAME>$1</NAME>\n$_$deprecated</STRUCT>\n";
+	        my $structsym = uc $1;
+	        #print "DEBUG: $structsym: $2\n";
+		&AddSymbolToList (\$list, $2);
+		print DECL "<$structsym>\n<NAME>$2</NAME>\n$_$deprecated</$structsym>\n";
 
-	    } elsif (m/^\s*typedef\s+struct\s*\w*\s*{/) {
+	    } elsif (m/^\s*typedef\s+(struct|union)\s*\w*\s*{/) {
 		$symbol = "";
  		$decl = $_;
 		$level = 0;
-		$in_declaration = "struct";
-                #print "DEBUG: struct\n";
+		$in_declaration = $1;
+		#print "DEBUG: $1\n";
 
 	    # OTHER TYPEDEFS
 
-	    } elsif (m/^\s*typedef\s+struct\s+\w+[\s\*]+(\w+)\s*;/) {
-		#print "DEBUG: Found struct* typedef: $_";
+	    } elsif (m/^\s*typedef\s+(?:struct|union)\s+\w+[\s\*]+(\w+)\s*;/) {
+		#print "DEBUG: Found struct/union(*) typedef $1: $_";
 		&AddSymbolToList (\$list, $1);
 		print DECL "<TYPEDEF>\n<NAME>$1</NAME>\n$deprecated$_</TYPEDEF>\n";
 
@@ -486,16 +488,16 @@ sub ScanHeader {
 
 	    # We assume that functions which start with '_' are private, so
 	    # we skip them.
-	    #                                                                        $1                                                                                                                                                  $2
-	    } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|long\s+|short\s+|struct\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*\(\s*\*+\s*([A-Za-z]\w*)\s*\)\s*\(/o) {
+	    #                                                                        $1                                                                                                                                                           $2
+	    } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|long\s+|short\s+|struct\s+|union\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*\(\s*\*+\s*([A-Za-z]\w*)\s*\)\s*\(/o) {
 		$ret_type = $1;
 		$symbol = $2;
 		$decl = $';
 		#print "DEBUG: internal Function: $symbol, Returns: $ret_type\n";
 		$in_declaration = "function";
 
-	    #                                                                        $1                                                                                                                                       $2
-	    } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|long\s+|short\s+|struct\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*([A-Za-z]\w*)\s*\(/o) {
+	    #                                                                        $1                                                                                                                                                $2
+	    } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|long\s+|short\s+|struct\s+|union\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*([A-Za-z]\w*)\s*\(/o) {
 		$ret_type = $1;
 		$symbol = $2;
 		$decl = $';
@@ -512,8 +514,8 @@ sub ScanHeader {
 
 		if ($previous_line !~ m/^\s*G_INLINE_FUNC/) {
 		    if ($previous_line !~ m/^\s*static\s+/) {
-                        #                                                                       $1                                                                $2
-                        if ($previous_line =~ m/^\s*(?:\b(?:extern|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
+                        #                                                                       $1                                                                         $2
+                        if ($previous_line =~ m/^\s*(?:\b(?:extern|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|union\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
                             $ret_type = $1;
                             if (defined ($2)) { $ret_type .= " $2"; }
                             #print "DEBUG: Function: $symbol, Returns: $ret_type\n";
@@ -526,8 +528,8 @@ sub ScanHeader {
                         #print "DEBUG: skip block after inline function\n";
                         # now we we need to skip a whole { } block
                         $skip_block = 1;
-                        #                                                                       $1                                                                $2
-                        if ($previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
+                        #                                                                       $1                                                                         $2
+                        if ($previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|union\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
                             $ret_type = $1;
                             if (defined ($2)) { $ret_type .= " $2"; }
                             #print "DEBUG: Function: $symbol, Returns: $ret_type\n";
@@ -549,7 +551,7 @@ sub ScanHeader {
 		    $in_declaration = "function";
 
 		} elsif ($previous_line =~ m/^\s*\w+\s*$/
-			 && $pre_previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*$/o) {
+			 && $pre_previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|union\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*$/o) {
                     $ret_type = $1;
                     $ret_type =~ s/\s*\n//;
                     $in_declaration = "function";
@@ -583,11 +585,14 @@ sub ScanHeader {
 
 	    # UNIONS
 
-	    } elsif (s/^\s*union\s+_(\w+)/union $1/) {
+	    } elsif (m/^\s*union\s+_(\w+)\s*\*/) {
+	    	# Skip 'union _<union_name> *' (see above)
+	    } elsif (m/^\s*union\s+_(\w+)/) {
 		$symbol = $1;
 		$decl = $_;
+		$level = 0;
 		$in_declaration = "union";
-                #print "DEBUG: Union: $symbol\n";
+                #print "DEBUG: Union(_): $symbol\n";
 	    }
 
 	} else {
@@ -598,7 +603,7 @@ sub ScanHeader {
 	}
 
         #if ($in_declaration ne '') {
-        #    print "= $decl\n";
+        #    print "$in_declaration = $decl\n";
         #}
 
 	# Note that sometimes functions end in ') G_GNUC_PRINTF (2, 3);' or
@@ -653,7 +658,7 @@ sub ScanHeader {
 
 	# We try to handle nested stucts/unions, but unmatched brackets in
 	# comments will cause problems.
-	if ($in_declaration eq 'struct') {
+	if ($in_declaration eq 'struct' or $in_declaration eq 'union') {
 	    if ($level <= 1 && $decl =~ m/\}\s*(\w*);\s*$/) {
 		if ($symbol eq "") {
 		    $symbol = $1;
@@ -667,7 +672,8 @@ sub ScanHeader {
 		#print "Store struct: $symbol\n";
 		&AddSymbolToList (\$list, $symbol);
 
-		print DECL "<STRUCT>\n<NAME>$symbol</NAME>\n$deprecated$decl</STRUCT>\n";
+		my $structsym = uc $in_declaration;
+		print DECL "<$structsym>\n<NAME>$symbol</NAME>\n$deprecated$decl</$structsym>\n";
 		$in_declaration = "";
 	    } else {
 		# We use tr to count the brackets in the line, and adjust
@@ -678,14 +684,6 @@ sub ScanHeader {
 	    }
 	}
 
-	if ($in_declaration eq 'union') {
-	    if ($decl =~ m/\}\s*;\s*$/) {
-		&AddSymbolToList (\$list, $symbol);
-		print DECL "<UNION>\n<NAME>$symbol</NAME>\n$deprecated$decl</UNION>\n";
-		$in_declaration = "";
-	    }
-	}
-
 	$pre_previous_line = $previous_line;
 	$previous_line = $_;
     }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]