| #!/bin/sh |
| # vim:ts=4: |
| # Generates a tag file for TCL code. Slow, but gets the job done. |
| # |
| # Written by Darren Hiebert <darren@hiebert.com> |
| |
| program_name=`basename $0` |
| program_version="0.3" |
| program_author="Darren Hiebert" |
| author_email="darren@hiebert.com" |
| tmp_tagfile=/tmp/${program_name}.$$ |
| |
| usage="\ |
| Usage: $program_name [-au] [-{f|o} tagfile] [--format=n] file(s) |
| -a append to current tag file |
| -f tagfile specify output tag file name (default=tags) |
| -o alternative for -f |
| -u unsorted |
| --format=n specify tag file format (default=2) |
| --help print this help message |
| " |
| |
| # defaults |
| # |
| append=0 |
| format=2 |
| sorted=1 |
| tagfile=tags |
| filelist= |
| |
| # read options |
| # |
| getparam() |
| { |
| if [ -n "$1" ]; then |
| # set variable to word passed in |
| echo "$2='$1'; opt=" |
| else |
| # set variable to next word on command line |
| echo "$2="'$1'"; shift" |
| fi |
| } |
| |
| 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 |
| ;; |
| help) echo "$usage"; exit 0;; |
| *) 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) eval `getparam "$opt" tagfile`;; |
| *) echo "$opt: unsupported option" >&2; exit 1;; |
| esac |
| done |
| ;; |
| *) filelist="$*"; break;; |
| esac |
| done |
| |
| if [ -z "$filelist" ] ;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 -ne "\ |
| !_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" $filelist >> $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 |