#! /bin/sh
#
# Generates a tag file for TCL code. Slow, but gets the job done.
#
# Written by Darren Hiebert <darren@hiebert.com>

program_name="tcltags"
program_version="0.2"
program_author="Darren Hiebert"
author_email="darren@hiebert.com"
tmp_tagfile=/tmp/${program_name}.$$

usage="\
Usage: $program_name [-au] [-o tagfile] file(s)
  -a          append to current tag file
  -o tagfile  specify output tag file name (default=tags)
  -u          unsorted"

# defaults
#
append=0
format=2
sorted=1
tagfile=tags

# read options
#
finished=0
while [ $# -gt 0  -a  $finished -eq 0 ]
do
    case "$1" in
	--*)
	    opt=`echo "$1" | cut -c 3-`
	    shift
	    opt_name=`echo "$opt" | awk -F= '{print $1}'`
	    opt_value=`echo "$opt" | awk -F= '{print $2}'`
	    case "$opt_name" in
		format) case "$opt_value" in
			    1|2) format=$opt_value;;
			    *) echo "--$opt: unsupported value" >&2; exit 1;;
			esac
			;;
		*)   	echo "$opt_name: unsupported option" >&2; exit 1;;
	    esac
	    ;;
	-*)
	    # chop off leading '-'
	    opt=`echo "$1" | cut -c 2-`
	    shift
	    while [ -n "$opt" ]
	    do
		opt_char=`echo "$opt" | cut -c 1`
		opt=`echo "$opt" | cut -c 2-`
		case "$opt_char" in
		    a) append=1;;
		    u) sorted=0;;
		    o|f)
			if [ -n "$opt" ]; then
			    tagfile="$opt"
			    opt=""
			else
			    tagfile="$1"
			    shift
			fi
			;;
		    *) echo "$usage" >&2; exit 1;;
		esac
	    done
	    ;;
	*)  finished=1;;
    esac
done

if [ $# -eq 0 ] ;then
    echo "$usage" >&2
    exit 1
fi

# awk program for generating tags
#
ext_flags=""
ttype=""
if [ $format -eq 2 ] ;then
    ext_flags=';\"	%s'
    ttype=", type"
fi
awkprg='
function trim_comment(string) {
    comment = index(string, "#")
    if (comment != 0)
	string = substr(string, 0, comment-1)
    return string
}
function maketag(tagname, pattern, type, line_end) {
    gsub(/\\/, "\\\\", pattern)
    gsub(/\//, "\\/", pattern)
    if (line_end)
	terminator="$"
    else
	terminator=""
    printf("%s\t%s\t/^%s%s/'"$ext_flags"'\n", \
    	tagname, FILENAME, pattern, terminator'"$ttype"')
}
$1 == "proc"  &&  $3 ~ /^{/  {
    pattern = substr($0, 0, index($0, "{"))
    maketag($2, pattern, "f", 0)
}
/^set[ \t]/  &&  $2 !~ /\(/ {
    pattern = substr($0, 0, index($0, $2) + length($2))
    maketag($2, pattern, "v", 0)
}
/^array[ \t]*set[ \t]/  &&  $3 !~ /\(/ {
    pattern = substr($0, 0, index($0, $3) + length($3))
    maketag($3, pattern, "v", 0)
}'

# add or correct the pseudo tags
#
if [ "$tagfile" != "-" ] ;then
    if [ $append -eq 1 ]; then
	# ensure existing sort flag is correct
	sed -e "/^!_TAG_FILE_SORTED/s/	[01]	/	$sorted	/" \
	    -e "/^!_TAG_FILE_FORMAT/s/	1	/	$format	/" \
	    $tagfile > $tmp_tagfile
    else
	echo -n "\
!_TAG_FILE_FORMAT	$format	/extended format; --format=1 will not append ;\" to lines/
!_TAG_FILE_SORTED	$sorted	/0=unsorted, 1=sorted/
!_TAG_PROGRAM_AUTHOR	$program_author	/$author_email/
!_TAG_PROGRAM_NAME	$program_name	//
!_TAG_PROGRAM_VERSION	$program_version	//
" > $tmp_tagfile
    fi
fi

# generate tags
#
awk "$awkprg" $* >> $tmp_tagfile

if [ $sorted -eq 1 ] ;then
    sort -u -o $tmp_tagfile $tmp_tagfile
fi

if [ "$tagfile" = '-' ] ;then
    cat $tmp_tagfile
else
    cp $tmp_tagfile $tagfile
fi
rm $tmp_tagfile

exit 0
