#!/bin/sh
# mkautoloads --- make autoload database for shell libraries
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-09-26
# Last modified: 1993-09-26
# Version: 1.2
# Public domain

# Commentary:
# Code:

# Name by which this script was invoked. 
progname=`basename $0`

# Substitute your usage string here. 
usage="${progname} {-D} {-a} {-f afile} {-h} {-v} [file1] {...}
       {--absolute} {--debug} {--autoload-file=afile} {--help} {--verbose}

-D, --debug                  Turn on shell debugging (\"set -x\").
-a, --absolute               Put absolute pathnames in autoload file
-f, --autoload-file FILE     Pathname of autoload database
-h, --help                   You're looking at it.
-v, --verbose                Print filenames as they are processed.
"

# To prevent hairy quoting and escaping later.
bq="\`"
eq="'"

# Since we don't have shell functions, this is a kludge that at least
# reduces some of the redunancy therefore necessary.  Yes, this is evil.
# Get a shell with functions and you won't have to contemplate this
# horror.
#
# Usage: value="`(set - \"$1\" \"$2\"; eval \"${get_option_argument}\")`"
#    Long option syntax is `--foo=bar' or `--foo bar'.  3rd argument ARG
#    won't get used if first long option syntax was used. 
#
# Returns number of positions caller should shift.
# If retval > 2, caller should exit.
# Only use this if option is supposed to have a mandatory argument. 
get_option_argument='
    option="$1";
    arg="$2";

    # All long options must be at least 3 characters long (--o*), whereas
    # short options are only two chars (-o) and arguments are separate.
    option_length="`awk \"END { print length(option); }\" option=\"${option}\" /dev/null`"
    arg="`echo ${option} | sed \"s/^[^=]*=//\"`" # Strip off anything before and including = char
    if [ ${option_length} -ge 3 -a "z${option}" != "z${arg}" ]; then
       echo "${arg}"
       exit 1
    else
       if [ -z "${2}" ]; then
          echo "${progname}: option ${bq}${option}${eq} requires argument." 1>&2
          echo "${usage}" 1>&2
          exit 3
       fi
       echo "${2}"
       exit 2
    fi
  '

# *sigh* this is annoying.  Some bourne shells don't allow a
# numeric argument to shift.
# Usage: 'eval "shift_num=n; ${shift_n_times}"'
shift_n_times='
   while [ ${shift_num} -gt 0 ]; do
      shift_num="`expr ${shift_num} - 1`"
      shift
   done;
  '

# Unset any variables set by options below, if you don't want to take the
# chance that they may be exported from the environment
# Don't actually use `unset' since old bourne shells don't have this
# command.  Instead, assign them an empty value. 
#unset debug
debug=""
verbosep=""
absolutep=""

# Parse command line arguments. 
# If you add new options be sure to change the wildcards below to make
# sure they are unambiguous (i.e. only match one possible long option)
# Be sure to show at least one instance of the full long option name to
# document what the long option is canonically called. 
# Long options which take arguments will need a `*' appended to the
# canonical name to match the value appended after the `=' character. 
while [ "$#" != "0" ]; do
   case z$1 in 
      z-D | z--debug | z--d* )
         debug=t
         shift
        ;;
      z-a | z--absolute | z--ab* )
         absolutep=t
         shift
        ;;
      z-h | z--help | z--h )
         echo "${usage}" 1>&2
         exit 1
        ;;
      z-v | z--verbose | z--v* )
         verbose=t
         shift
        ;;
      z-f | z--autoload-file* | z--au* )
         autoload_file="`(set - \"$1\" \"$2\"; eval \"${get_option_argument}\")`"
         retval=$?
         if [ ${retval} -gt 2 ]; then
            # Already printed usage
            exit 1
         fi
         eval "shift_num=${retval}; ${shift_n_times}"
        ;;
      z-- )     # Stop option processing
        shift
        break
       ;;
      z-* )
        echo "${progname}: unknown option \`$1'" 1>&2
        echo "${usage}" 1>&2
        exit 1
       ;;
      * )
        break
       ;;
   esac
done

test "${debug}" = "t" && set -x

if test $# = 0 ; then
   echo "${usage}" 1>&2
   exit 1
fi

echo '#
# This file is automatically generated from mkautoloads; do not edit.
#
' > "${autoload_file}"

awk 'BEGIN {
        tick = "'\''";
        old_FILENAME = "";
        prev_line_cookie_p = 0;
     }

     { 
       if (old_FILENAME != FILENAME) 
         {
           basename = FILENAME;
           while (match(basename, "/")) 
                basename = substr(basename, RSTART + 1);

           if (absolutep)
              file_name = FILENAME;
           else
              file_name = basename;

           if (verbosep)
              print "Looking for autoload cookies in " basename "...";
           old_FILENAME = FILENAME;
         }
     }

     /^###;;;autoload/ {
        prev_line_cookie_p = 1;
        next;
     }

     prev_line_cookie_p == 1 {
        while (match($0, tick))
           $0 = substr($0, 0, RSTART - 1) substr($0, RSTART + 1);
     }

     # For es or rc
     prev_line_cookie_p == 1 && /^fn-/ {
        match($0, /^fn-/);
     }

     # For es or rc
     prev_line_cookie_p == 1 && /^fn[ \t][ \t]*./ {
        match($0, /^fn[ \t][ \t]*/);
     }

     # for bash
     prev_line_cookie_p == 1 && /^function[ \t][ \t]*./ {
        match($0, /^function[ \t][ \t]*/);
     }

     prev_line_cookie_p == 1 {
        startpos = RSTART + RLENGTH;
        fn_name = substr($0, startpos, length($0) - startpos);
        if (match(fn_name, /[ \t{=]/))
          fn_name = substr(fn_name, 0, RSTART - 1 );
        print "autoload " tick fn_name tick " " tick file_name tick >> autoload_file;
        prev_line_cookie_p = 0;
     }

     END { 
       print "# End of automatically generated autoloads" >> autoload_file;
     }' absolutep=${absolutep} autoload_file="${autoload_file}" verbosep="${verbose}" ${1+"$@"}

if test -n "${verbose}" ; then
   echo "Done."
fi

# mkautoloads ends here
