#!/usr/bin/perl -w use strict; use warnings; use diagnostics; use Getopt::Std; my $HELP = "Usage: $0 [FILE]... Parses [FILE], outputing the result to stdout."; sub usage { print "@_\n"; exit; } our($opt_h, $opt_v, $title, $body, $indent, $idpath, $inblock); getopts("hv") or usage($HELP); $opt_v and usage("Copyleft (c) 2006, Russ Rowan (See `COPYING')"); usage($HELP) if $opt_h or @ARGV < 1; sub put_section { if ($title) { print "\n$title\n"; $title =~ s/[^-]/-/g; print "$title\n" if not $indent; } if ($body) { $body =~ s/#newline#/$indent/g; print "$body\n"; } $title = $body = undef; } $idpath = $title = $body = ""; while (<>) { my $end = s/\s*\*+\//\n/ ? 'yes' : undef; if ($end and /[^=]*[\s*](\w+)[\s:,;].*\/\*:\s*(.*)([.]\s*)?$/) { # Implicit id for enum values and struct members. print "\nid:[$idpath$1]::\n\t$2.\n"; } elsif ($inblock) { # Redo the indentation, preserve empty lines. s/^(\s|\*)*//; s/^$/\n/; $body .= "#newline#" . $_; } elsif (s/\s*\/\*\*+\s*(.*)/$1/) { # Found magic header; flush, record title and set indentation. put_section; $title = "$1"; $indent = /::/ ? "\t" : ""; } else { next if not ($title or $body) or /^\s$/; my $orig_title = $title; # Combine multi-line declarations to one. Break at empty # for #define ... while (not /(struct|enum|typedef|[^=])*[\s*](\w+).*[\[:,;{]/) { my $line = $_; $_ .= <>; last if $_ eq $line; } if (/struct\s+(\w+)\s*{/) { $title = "struct:$1" . "[$title]"; $idpath = "$1."; } elsif (/enum\s+(\w+)\s*{/) { $title = "enum:$1" . "[$title]"; $idpath = ""; } elsif (/#define/) { if (/#define\s+(\w+)[(]/) { $title = "func:$1" . "[$title]"; } elsif (/#define\s+(\w+)/) { $title = "macro:$1" . "[$title]"; } $idpath = ""; } elsif (/typedef/) { if (/.*\(\*(\w+)\)\(/) { $title = "typedef:$1" . "[$title]"; } elsif (/typedef.*\s(\w+);/) { $title = "typedef:$1" . "[$title]"; } $idpath = ""; } elsif (/.*[\s*](\w+)\(/) { $title = "func:$1" . "[$title]"; $idpath = ""; } elsif (/.*\(\*(\w+)\)\(/) { $body = "#newline#" . $title if not $body; $title = "id:[$idpath$1]::"; $indent = "\t"; } elsif (/[^=]*[\s*](\w+)[\[\s,:;]/) { $body = "#newline#" . $title if not $body; $title = "id:[$idpath$1]::"; $indent = "\t"; } put_section if $orig_title ne $title; next; } $inblock = $end ? undef : 'yes'; }