#!/usr/bin/perl -w
#
# genref.pl
# David Rowe 14/1/03
# Generates reference library from vpb-driver source code
#

use strict;

my $sgml_file = "refguide.sgm";
my $dir_name = "../src";
my $SRCDIR;
my @srcfiles;
my $srcfile;
my $cnt;
my @src_ignore = ("genericwin32.cpp");

sub process_file($); 

open(SGML, ">$sgml_file") or die "Can't open sgm file: $sgml_file: $!";
print SGML "<sect1>\n";
print SGML "<title>Function Reference</title>\n\n";

# scan all .cpp files and generate reference guide sgml

opendir(SRCDIR, $dir_name) or die "Can't open src dir $dir_name: $!";
@srcfiles = readdir(SRCDIR);
closedir(SRCDIR);

# remove the files we dont want to scan as they upset the processing!

my %count;
my $e;
my @isect;
my @union;
my @diff;

foreach $e (@srcfiles, @src_ignore) { $count{$e}++ }

foreach $e (keys %count) {
    push(@union, $e);
    if ($count{$e} == 2) {
        push @isect, $e;
    } else {
        push @diff, $e;
    }
}
@srcfiles = @diff;

# OK - process files to generate docbook SGML

#single file used for testing
#@srcfiles = ("vpbapi.cpp");

$cnt = 0;

foreach $srcfile (@srcfiles) {
    if ($srcfile =~ /cpp$/) {
	print "\nprocessing: $srcfile\n";
	$cnt = $cnt + process_file($dir_name . "/" . $srcfile);
    }
}

print SGML "\n</sect1>\n";
close(SGML);

print "\n$cnt functions documented - Bye!\n";

sub process_file($) {
    my ($file_name) = @_;
    my $SRC;
    my @src;
    my $state;
    my $next_state;
    my $line;    
    my $func_name;
    my $func_id;
    my @func_synopsis;
    my @func_info;
    my $cnt;
    my $line_cnt;

    open(SRC, $file_name) or die "Can't open src file $file_name: $!";
    @src = <SRC>;
    close(SRC);

    $cnt = 0;
    $state = 0;
    $line_cnt = 0;

    foreach $line (@src) {
	$line_cnt = $line_cnt + 1;

	if (0) {
	    if (($line_cnt > 174) && ($line_cnt < 201)) {
	    print "line = $line  state = $state\n";
	    if ($line =~ /WINAPI/) {
		print "WINAPI matches!\n";
	    }
	    if ($line =~ /vpb_/) {
		print "vpb_ matches!\n";
	    }
	}
	}

	$next_state = $state;
	if ($state == 0) {
	    # looking for start of VPBAPI function header

	    if (($line =~ /FUNCTION/) && ($line =~ /vpb_/)) {
		$line =~ s/FUNCTION.*://;
		$line =~ s/\s+//;
		$line =~ s/\(|\)//g;
		chop($line);
		$func_name = $line;
		$next_state = 1;
		print "found: $line\n";
	    }
	    elsif ($line =~ /WINAPI/) {
		# error condition, decl before hdr
		print "Oops - WINAPI found in state 0, line $line_cnt\n";
		print "Should find FUNCTION.: vpb_xxx first!\n";
		exit;
	    }
	    elsif (($line =~ /FUNCTION/) && ($line =~ /vbp_/)) {
		# error condition, typo
		print "Oops - mis-spelt vpb as vbp, line $line_cnt\n";
		exit;
	    }
		
	}
	elsif ($state == 1) {
	    # looking for last line in function header
	    if ($line =~ /DATE/) {
		$next_state = 2;
	    }
	}
	elsif ($state == 2) {
	    # extract all header comment lines until end of header
	    if ($line =~ /----/) {
		$next_state = 3;
	    }
	    else {
		@func_info = (@func_info, $line);
	    }
	}
	elsif ($state == 3) {
	    # look for actual func declaration
	    if ($line =~ /WINAPI/) {
		@func_synopsis = ($line);
		if ($line =~ /\)/) {
		    $next_state = 5;
		}
		else {
		    $next_state = 4;
		}
	    }
	    elsif ($line =~ /----/) {
		# detect error condition
		
		print "Oops - hit hdr in state 3, line $line_cnt\n";
		exit;
	    }
	}
	elsif ($state == 4) {
	    # print all lines until we hit the end 
	    @func_synopsis = (@func_synopsis, $line);
	    if ($line =~ /\)/) {
		$next_state = 5;
	    }
	}
	elsif ($state == 5) {
	    # OK, we have everything we need, so generate SGML for this func

	    $func_id = $func_name;
	    $func_id =~ s/\_/\-/g;
	    print SGML "<sect2 id=\"$func_id\">\n";
	    print SGML "<title><function>" . $func_name . "()";
	    print SGML "</function></title>\n\n";
	    
	    print SGML "<para><emphasis>Synopsis</emphasis></para>\n\n";

	    print SGML "<screen>\n";
	    print SGML @func_synopsis;
	    print SGML "</screen>\n\n";

	    print SGML "<para><emphasis>Function</emphasis></para>\n\n";

	    print SGML "<para>\n";
	    print SGML @func_info;
	    print SGML "</para>\n\n";
	    print SGML "</sect2>\n\n";

	    $cnt = $cnt + 1;

	    # reset for next iteration
	    @func_info = ();
	    @func_synopsis = ();
	    $next_state = 0;
	}

	$state = $next_state;
    }

    return $cnt;
}

