source: trunk/third/bash/examples/functions/autoload.v2 @ 18290

Revision 18290, 3.9 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18289, which included commits to RCS files with non-trunk default branches.
Line 
1#
2# An almost ksh-compatible `autoload'.  A function declared as `autoload' will
3# be read in from a file the same name as the function found by searching the
4# $FPATH (which works the same as $PATH), then that definition will be run.
5#
6# To do this without source support, we define a dummy function that, when
7# executed, will load the file (thereby re-defining the function), then
8# execute that newly-redefined function with the original arguments.
9#
10# It's not identical to ksh because ksh apparently does lazy evaluation
11# and looks for the file to load from only when the function is referenced.
12# This one requires that the file exist when the function is declared as
13# `autoload'.
14#
15# usage: autoload [-pu] [func ...]
16#
17# options:
18#       -p      print in a format that can be reused as input
19#       -u      unset each function and remove it from the autoload list
20#
21# The first cut of this was by Bill Trost, trost@reed.edu
22#
23# Chet Ramey
24# chet@ins.CWRU.Edu
25
26unset _AUTOLOADS
27_aindex=0
28
29#
30# Declare a function ($1) to be autoloaded from a file ($2) when it is first
31# called.  This defines a `temporary' function that will `.' the file
32# containg the real function definition, then execute that new definition with
33# the arguments given to this `fake' function.  The autoload function defined
34# by the file and the file itself *must* be named identically.
35#
36
37_aload()
38{
39        eval $1 '() {  . '$2' ; '$1' "$@" ; return $? ; }'
40        _autoload_addlist "$1"
41}
42
43_autoload_addlist()
44{
45        local i=0
46
47        while (( i < $_aindex )); do
48                case "${_AUTOLOADS[i]}" in
49                "$1")   return 1 ;;
50                esac
51                (( i += 1 ))
52        done
53        _AUTOLOADS[_aindex]="$1"
54        (( _aindex += 1 ))
55        return 0
56}
57
58_autoload_dump()
59{
60        local func
61
62        for func in ${_AUTOLOADS[@]}; do
63                [ -n "$1" ] && echo -n "autoload "
64                echo "$func"
65        done
66}
67
68# Remove $1 from the list of autoloaded functions
69_autoload_remove_one()
70{
71        local i=0 nnl=0
72        local -a nlist
73
74        while (( i < _aindex )); do
75                case "${_AUTOLOADS[i]}" in
76                "$1")   ;;
77                *)      nlist[nnl]="${_AUTOLOADS[i]}" ; (( nnl += 1 ));;
78                esac
79                (( i += 1 ))
80        done
81        unset _AUTOLOADS _aindex
82        eval _AUTOLOADS=( ${nlist[@]} )
83        _aindex=$nnl
84}
85
86# Remove all function arguments from the list of autoloaded functions
87_autoload_remove()
88{
89        local func i es=0
90       
91        # first unset the autoloaded functions
92        for func; do
93                i=0
94                while (( i < _aindex )); do
95                        case "${_AUTOLOADS[i]}" in
96                        "$func")        unset -f $func ; break ;;
97                        esac
98                        (( i += 1 ))
99                done
100                if (( i == _aindex )); then
101                        echo "autoload: $func: not an autoloaded function" >&2
102                        es=1
103                fi
104        done
105
106        # then rebuild the list of autoloaded functions
107        for func ; do
108                _autoload_remove_one "$func"
109        done
110
111        return $es
112}
113
114#
115# Search $FPATH for a file the same name as the function given as $1, and
116# autoload the function from that file.  There is no default $FPATH.
117#
118
119autoload()
120{
121        local -a fp
122        local _autoload_unset nfp i
123
124        if (( $# == 0 )) ; then
125                _autoload_dump
126                return 0
127        fi
128
129        OPTIND=1
130        while getopts pu opt
131        do
132                case "$opt" in
133                p)      _autoload_dump printable; return 0;;
134                u)      _autoload_unset=y ;;
135                *)      echo "autoload: usage: autoload [-pu] [function ...]" >&2
136                        return 1 ;;
137                esac
138        done
139
140        shift $(( $OPTIND - 1 ))
141
142        if [ -n "$_autoload_unset" ]; then
143                _autoload_remove "$@"
144                return $?
145        fi
146
147        #
148        # If there is no $FPATH, there is no work to be done
149        #
150
151        if [ -z "$FPATH" ] ; then
152                echo "autoload: FPATH not set or null" >&2
153                return 1
154        fi
155
156        #
157        # This treats FPATH exactly like PATH: a null field anywhere in the
158        # FPATH is treated the same as the current directory.
159        #
160        # This turns $FPATH into an array, substituting `.' for `'
161        #
162        eval fp=( $(
163                        IFS=':'
164                        set -- ${FPATH}
165                        for p in "$@" ; do echo -n "${p:-.} "; done
166                   )
167                )
168
169        nfp=${#fp[@]}
170
171        for FUNC ; do
172                i=0;
173                while (( i < nfp )) ; do
174                        if [ -f ${fp[i]}/$FUNC ] ; then
175                                break                   # found it!
176                        fi
177                        (( i += 1 ))
178                done
179
180                if (( i == nfp )) ; then
181                        echo "autoload: $FUNC: autoload function not found" >&2
182                        es=1
183                        continue
184                fi
185
186#               echo auto-loading $FUNC from ${fp[i]}/$FUNC
187                _aload $FUNC ${fp[i]}/$FUNC
188                es=0
189        done
190
191        return $es
192}
Note: See TracBrowser for help on using the repository browser.