#!/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';
}
