#!/usr/bin/perl -w
# texdef
# History: tired of typing "\newcommand{\foo}{bar}" instead of just "foo bar"
# and I wanted a method to automatically a symbol table for my book.
#
# Usage:
#	texdef
#		-tab table.tex		# output for symbol table
#		files[s]		# input files
#		> deffile.tex		# stdout with definitions
#
# Each line of the form FIRST{tab[s]}REST in def.raw is replaced
# in the output file with \newcommand{\FIRST}{REST}.
# If the subsuquent line is nonempty and does not have a {tab}\ in it,
# then that line is treated as a symbol table entry.
#
# If the definition is "!" then just add it to glossary. (I forget why.)
# Other exceptions based on first letter:
#	*	use \renewcommand instead
#	+	use \providecommand instead
#	#	comments are ignored
#	%	comments copied to output
#
# Copyright 2002-9-11, Jeff Fessler, The University of Michigan

$files[0] = ""; #"def.raw";
$nfiles = 0;
$filetab = ""; #"def,tab.tex";

while ($#ARGV >= 0) {
	if (($ARGV[0] eq "-tab") & ($#ARGV > 0)) {
		$filetab = $ARGV[1];
		shift(@ARGV);
	} else {
		$files[$nfiles] = $ARGV[0];
		$nfiles += 1;
	}
	shift(@ARGV);
}

die "no files?" if ($nfiles == 0);


#
# open each file and process it
#

$ntab = 0;	# how many entries in symbol table
$table_key[0] = "";	# start with empty table of keys
$table_exp[0] = "";	# start with empty table of explanations
$keepblank = 1;

$ii = 0;
while ($ii < $nfiles) {

	$file = $files[$ii];
	$ii += 1;

	open(File, $file) || die "cannot open `$file' error: $!";

	print "% from $file\n\n";

	$lastkey = "";
	$lastarg = "";

	while (<File>) {

		next if /^#/;		# skip '#' comments
		if (/^%/) {		# echo '%' comments
			print;
			next;
		}

		if (/^\s*$/) {		# replicate blank lines
			if ($keepblank) {
				print "\n";
			} else {	# unless right after an explanation line
				$keepblank = 1;
			}
			next;
		}

		chop;
		s/([^\\])%.*$/$1/;		# strip tailing comments

		# parse 'key TAB rest' with tab(s) separator
		undef(@rest);
		($key, @rest) = split(/\t+/);	# split on one-or-more tabs

		#
		# if no tab, then it is a symbol explanation line!
		#
		if (!defined(@rest)) {
#			die "bad line `$_'" unless defined(@rest);

			die "bad line `$_'" unless ($lastkey ne "98765431");

			
			$table_key[$ntab] = $lastkey;
			$table_arg[$ntab] = $lastarg;
			$table_exp[$ntab] = $_;
			$ntab += 1;
			$lastkey = "98765431";
			$lastarg = "";
			$keepblank = 0;
			next;
		}

		die "typo: `$_' should not start with /\n" if /^\\/;

		$_ = "@rest";		# rejoin in case more tabs in "rest"

#		next if ($_ eq "!");	# ignore (just for glossary)
		die "'!' not implemented" if ($_ eq "!");

		#
		# first letter is "*" means use renewcommand
		# first letter is "+" means use providecommand
		# otherwise ordinary newcommand
		#
		if ($key =~ /^\*/) {
			($key) = $key =~ /\*(.*)/;
			$command = "\\renewcommand";
		} elsif ($key =~ /^\+/) {
			($key) = $key =~ /\+(.*)/;
			$command = "\\providecommand";
		} else {
			$command = "\\newcommand";		# default
		}

		#
		# deal with optional arguments
		#
		$arg = "";
		if ($key =~ /\[/) {
			$arg = "TODO?";		# bug alert
			($key, $arg) = $key =~ /(\w+)(.*)/;
			print "$command" . "{\\$key}$arg\t{$_}\n";
		} else {
			print "$command" . "{\\$key}\t{$_}\n";
		}

		$lastkey = $key;
		$lastarg = $arg;
	}
	close(File);

}


#
# print explanations to glossary file, if any.
# for the commands that go in the glossary
#

exit if ($filetab eq "");	# done if no table file

open(Tab, "> $filetab") || die "cannot write `$filetab' error: $!";

$ii = 0;
while ($ii < $nfiles) {
	print Tab "% from $files[$ii]\n\n";
	$ii += 1;
}

#
# header for symbol table
#
#print Tab "\\providecommand{\\defitem}[3]{\\ty{#1} & #2 & #3\\\\}\n";
print Tab "\\providecommand{\\defitem}[3]{\\makebox[10em][l]{\\ty{#1}} "
	. " \\makebox[20em][l]{#2} #3\\\\}\n";
print Tab "\\providecommand{\\defstart}{\n";
#print Tab "\t\\begin{tabular}{l|l|l}\n";
print Tab "\t\\defitem{Macro}{Symbol}{Meaning}\n";
print Tab "}\n";
#print Tab "\\providecommand{\\defstop}{\\end{tabular}}\n";
print Tab "\\providecommand{\\defstop}{}\n";
print Tab "\n\\defstart\n";

$ii = 0;
while ($ii < $ntab) {

#	if ($rest eq "!") {
#		print "\\defitem{$key}{\\$key}{$what}\n";

	$key = $table_key[$ii];
	$what = $table_exp[$ii];
	if ($table_arg[$ii] ne "") {
		print Tab "\\defitem{$key}{\\$key\{\}{}{}{}}{$what}\n";
	} else {
		print Tab "\\defitem{$key}{\\$key}{$what}\n";
	}

	$ii += 1;
}

print Tab "\\defstop\n";
close(Tab);

exit(0);
