Korn Shell "Modules" - request for comments

Korn Shell "Modules" - request for comments

Post by Erik Max Franci » Sat, 10 Jun 2000 04:00:00




> My question is:

>     Is it possible to write Korn shell library functions that
>     may be used as easily as perl modules?

zsh supports an "autoload" feature, where the definition of functions
can be put in a specified directory, and then listed with autoload,
which results in the appropriate function being used dynamically when it
is requested.  The function definitions can also be standalone shell
scripts, doubling their usefulness.

Perhaps ksh supports something similar.

--

 __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/  \ There is nothing stronger in the world than gentleness.
\__/ Han Suyin
    REALpolitik / http://www.realpolitik.com/
 Get your own customized newsfeed online in realtime ... for free!

 
 
 

Korn Shell "Modules" - request for comments

Post by Erik Max Franci » Sat, 10 Jun 2000 04:00:00




> > zsh supports an "autoload" feature, [...]
> > Perhaps ksh supports something similar.

> In fact, zsh has borrowed this feature from ksh.

Well there you go!  All you need to do then is to come up with a system
which has a standard place to put function definitions as individual
files, and a central pool from which to get these definitions and some
organizing principles which contributors agree to.  Viola!

--

 __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/  \ The love we give away is the only love we keep.
\__/ Elbert Hubbard
    Alcyone Systems / http://www.alcyone.com/
 Alcyone Systems, San Jose, California.

 
 
 

Korn Shell "Modules" - request for comments

Post by Heiner Steve » Sun, 11 Jun 2000 04:00:00


Probably every shell scripting fan (like me), has sometimes looked
with envy at the perl community: the CPAN ("Comprehensive Perl Archive
Network") lists hundreds of ready-to-use perl modules. Each module
is a package or library of functions (or objects) that may be used
without change for own perl scripts. This increases the productivity
of programmers using the perl language dramatically, they don't
have to re-invent the wheel for common problems others already
solved. [refer to permod(1) for details if you already have perl
installed, or http://www.perl.com/pub/doc/manual/html/pod/perlmod.html].

Shell programmers solve a problem writing little scripts or
functions. Unfortunately these scripts normally are not as
reusable as a library would be.

My question is:

    Is it possible to write Korn shell library functions that
    may be used as easily as perl modules?

In particular, I see the following open questions and problems
regarding ksh libraries (kshlibs):

 o  How can kshlibs be included?
    Should they be "dotted in" (. libfuncs.ksh) or is
    the "autoload" functionality more appropriate?
    [Perl: "use" or "require"]

 o  How can name space conflics be avoided?
    (i.e. if the calling script has a function named "error",
    an included library may define the function, too, causing
    problems).

    Workaround: kshlibs may use a reasonable unique prefix,
    i.e. "_nntp_open", "_nntp_close", ...

 o  How should library functions return a value?

    Simple values or "scalar values" (i.e. a string or a number)
    could just be printed to stdout, i.e.

        welcomemsg=$(nntp_open $newsserver)

    But how should a function i.e. return an array of strings?

        set -A groupnames $(nntp_getgroups)

    would not preserver whitespace characters.

    [Perl: has comfortable array functions]

    And how could a function return more than one value, with
    a meaningful name?

    i.e. if a NNTP library function returns the number articles in
    a group, the first and the last article number, it would be
    very cryptic to assign the values to an array, i.e.

        set -A ginfo $(nntp_getgroup comp.unix.shell)
        artcount=${ginfo[0]}
        firstart=${ginfo[1]}
        lastart=${ginfo[2]}

    [Perl: uses "hashes" or associative arrays, like "awk" has, i.e.
        ginfo{"count"}, ginfo{"first"}, ginfo{"last"}
    ]

If we could find satisfactory answers to these questions,
maybe we could define a "Korn Shell Library Writer's Guide",
some hints, how a Korn Shell Library could be written in a
standard way to make it easy to use.

Did somebody already try to write Korn shell libraries?
I appreciate any comments on this matter ;-)

Heiner

[BTW: the examples come from a Korn Shell library for NNTP
("Network News Transfer Protocol"). If somebody needs some
kshlib test terrain, I will be glad to send it.]
--
 ___ _                          

\__ \  _/ -_) V / -_) ' \    UNIX Shell Script Programmers: visit
|___/\__\___|\_/\___|_||_|   http://www.oase-shareware.org/shell/

 
 
 

Korn Shell "Modules" - request for comments

Post by Christian Weisgerb » Sun, 11 Jun 2000 04:00:00



Quote:> zsh supports an "autoload" feature, [...]
> Perhaps ksh supports something similar.

In fact, zsh has borrowed this feature from ksh.

--

 
 
 

Korn Shell "Modules" - request for comments

Post by Heiner Steve » Tue, 13 Jun 2000 04:00:00



[...]
 >>     Is it possible to write Korn shell library functions that
 >>     may be used as easily as perl modules?
[...]
 >> In particular, I see the following open questions and problems
 >> regarding ksh libraries (kshlibs):
 >>
 >>  o  How can kshlibs be included?
 >>     Should they be "dotted in" (. libfuncs.ksh) or is
 >>     the "autoload" functionality more appropriate?
 >>     [Perl: "use" or "require"]
 >>

 > The FPATH is more useful,  since you only load what is necessary.
 > See below for a detailed explanation.

Your excellent explanation describes in detail, how to use
this feature, and it sounds like a feasible way to implement
the libraries. The one disadvantage I see is, that the "package"
or "module" concept is not supported: each function has to be
in it's own source file, and it's not immediately clear, which
functions belong together and establish a library. Do you have
an idea how this could be accomplished? I suppose, that the FPATH
approach does not support subdirectories (i.e. one subdirectory
for each library).

 >>  o  How can name space conflicts be avoided?
 >>     (i.e. if the calling script has a function named "error",
 >>     an included library may define the function, too, causing
 >>     problems).
 >>

 > First,  by declaring functions with Korn syntax (function
 > keyword) and then using typeset,  which declares local
 > variables.

This works for local variables, but not for function names. If
the main script declares a function, that is re-declared in a
library module, a conflict occurs. Or is there a way to define
"local" functions?

 > Pass the variable names (vnames) of variables to be
 > set,  like dtksh does,  and use eval:

That's an excellent idea! Parameter passing using "call by name"
works, if the number of function return arguments is known by
the caller in advance.

This still leaves the problem, how multiple values (whose
number is not known in advance) can be returned. I think the
logical return value could be an array, but how can an array
be returned from a function?

 >>  o  How should library functions return a value?
 >>
 >>     Simple values or "scalar values" (i.e. a string or a number)
 >>     could just be printed to stdout, i.e.
 >>
 >>     welcomemsg=$(nntp_open $newsserver)
 >>
 >>     But how should a function i.e. return an array of strings?
 >>
 >>     set -A groupnames $(nntp_getgroups)
 >>
 >>     would not preserver whitespace characters.
 >>

 > The most efficient way is as shown above.

Well, as stated above the "call by name" way only works,
if the number of expected return values are known in advance.

 >>     [Perl: has comfortable array functions]
 >>
 >>     And how could a function return more than one value, with
 >>     a meaningful name?

 > Simply pass the vnames.  In ksh93,  a dot notation is used for
 > structured variables.  Also,  you have a name reference type variable
 > that eliminates the need,  and dangers,  of eval (never eval with
 > unknown input).  For instance,  this ksh93 function that turns
 > an array into a string:
[ksh93 example removed]

I agree that ksh93's "typeset -n" feature would be a very
convenient one for "call by name", but I would recommend not
to restrict the modules to ksh93, because it is not that far
used than ksh88 is.

 > A ksh88 version:

 >       function array_to_string
 >          {
 >          # Format: array_to_string vname_of_array vname_of_string
separator
 >          ((($# < 2) || ($# > 3))) && {
 >             print -u2 " Format: array_to_string arrayname stringname
[separator]"
 >             return 1
 >             }
 >          typeset array=$1 string=$2
 >          ((3==$#)) && [[ $3 = ? ]] && typeset IFS="${3}${IFS}"
 >          eval $string='"${array[*]}"'
 >          return 0
 >          }

Could you write an "string_to_array" function, that would preserve
all special characters from the string, i.e.

        '"this is" "a multiword" "string with a $"'

resulting in

        array[0]="this is"
        array[1]="a multiword"
        array[2]="string with a \$"

?

 >>     i.e. if a NNTP library function returns the number articles in
 >>     a group, the first and the last article number, it would be
 >>     very cryptic to assign the values to an array, i.e.
 >>
 >>     set -A ginfo $(nntp_getgroup comp.unix.shell)
 >>     artcount=${ginfo[0]}
           >>     firstart=${ginfo[1]}
 >>     lastart=${ginfo[2]}
 >>
 >>     [Perl: uses "hashes" or associative arrays, like "awk" has, i.e.
 >>     ginfo{"count"}, ginfo{"first"}, ginfo{"last"}
 >>     ]

 > ksh93 has associative arrays.

IMHO your "call by name" example is even better suited for
this problem.

[...]
 > As promised,  my function tutorial:

["FUN WITH FUNCTIONS (and aliases)" removed]

Excellent summary!

Heiner
--
 ___ _

\__ \  _/ -_) V / -_) ' \    SHELLdorado for Shell Script Programmers:
|___/\__\___|\_/\___|_||_|   http://www.oase-shareware.org/shell/

 
 
 

Korn Shell "Modules" - request for comments

Post by Dan Merc » Tue, 13 Jun 2000 04:00:00


In article <3944FF85.C6CBE...@odn.de>,

Heiner Steven <heiner.ste...@odn.de> writes:
> Dan Mercer <damer...@mmm.com> wrote:
> > Heiner Steven <heiner.ste...@odn.de> writes:
> [...]
> >>     Is it possible to write Korn shell library functions that
> >>     may be used as easily as perl modules?
> [...]
> >> In particular, I see the following open questions and problems
> >> regarding ksh libraries (kshlibs):

> >>  o  How can kshlibs be included?
> >>     Should they be "dotted in" (. libfuncs.ksh) or is
> >>     the "autoload" functionality more appropriate?
> >>     [Perl: "use" or "require"]

> > The FPATH is more useful,  since you only load what is necessary.
> > See below for a detailed explanation.

> Your excellent explanation describes in detail, how to use
> this feature, and it sounds like a feasible way to implement
> the libraries. The one disadvantage I see is, that the "package"
> or "module" concept is not supported: each function has to be
> in it's own source file, and it's not immediately clear, which
> functions belong together and establish a library. Do you have
> an idea how this could be accomplished? I suppose, that the FPATH
> approach does not support subdirectories (i.e. one subdirectory
> for each library).

FPATH can contain multiple libraries:

   FPATH=~/fun:~/fun/ksh93:~/fun/dtksh

In addition,  examine this section of the tutorial:

   The file can contain additional commands including multiple function
   definitions that will all be defined simultaneously.

For instance,  I have a dtksh function library that creates and
manages the DtComboBox.  All the functions are in one file,
DtComboBoxInitialize.  The first function defined in the file
is DtComboBoxInitialize:

   function DtComboBoxInitialize
      {
      [[ -o xtrace ]] && print -u2 "DtComboBoxInitialize entered"
      DtLoadWidget DtComboBox dtComboBoxWidgetClass
      }

As you can see,  by itself it doesn't do much.  But by invoking it,
it brings in all the functions defined in the file:

   $ grep ^fun DtComboBoxInitialize
   function DtComboBoxInitialize
   function DtCreateComboBox
   function DtComboBoxMenuPopup
   function DtComboBoxAddItem
   function DtComboBoxDeletePos
   function DtComboBoxClearText
   function DtComboBoxGetItems

> >>  o  How can name space conflicts be avoided?
> >>     (i.e. if the calling script has a function named "error",
> >>     an included library may define the function, too, causing
> >>     problems).

> > First,  by declaring functions with Korn syntax (function
> > keyword) and then using typeset,  which declares local
> > variables.

> This works for local variables, but not for function names. If
> the main script declares a function, that is re-declared in a
> library module, a conflict occurs. Or is there a way to define
> "local" functions?

I don't know of anyway to define local functions.  However,  you
can conditionally define functions:

   typeset +f funcname >/dev/null || function funcname {
      ...
      }

> > Pass the variable names (vnames) of variables to be
> > set,  like dtksh does,  and use eval:

> That's an excellent idea! Parameter passing using "call by name"
> works, if the number of function return arguments is known by
> the caller in advance.

> This still leaves the problem, how multiple values (whose
> number is not known in advance) can be returned. I think the
> logical return value could be an array, but how can an array
> be returned from a function?

Don't think of using functions by:

   x=$(funcname)

You might as well use a shell script for that.  Think instead of

   set_path PATH /usr/bin /usr/local/bin /usr/contrib/bin
   set_path CDPATH . ~ /usr/local/bin
   set_path MANPATH /usr/share/man /usr/local/man /usr/contrib/man

These are all scalars,  but it works as well for arrays

   array_from_string PATHARRAY PATH :

   function array_from_string {
      typeset vname=$1 string=$2
      ((3 == $#)) && typeset IFS="$3${IFS}"
      eval set -A $vname -- \$$string
      }

Since the name is not typeset in the function,  it has global scope.

- Show quoted text -

> >>  o  How should library functions return a value?

> >>     Simple values or "scalar values" (i.e. a string or a number)
> >>     could just be printed to stdout, i.e.

> >>     welcomemsg=$(nntp_open $newsserver)

> >>     But how should a function i.e. return an array of strings?

> >>     set -A groupnames $(nntp_getgroups)

> >>     would not preserver whitespace characters.

> > The most efficient way is as shown above.

> Well, as stated above the "call by name" way only works,
> if the number of expected return values are known in advance.

> >>     [Perl: has comfortable array functions]

> >>     And how could a function return more than one value, with
> >>     a meaningful name?

> > Simply pass the vnames.  In ksh93,  a dot notation is used for
> > structured variables.  Also,  you have a name reference type variable
> > that eliminates the need,  and dangers,  of eval (never eval with
> > unknown input).  For instance,  this ksh93 function that turns
> > an array into a string:
> [ksh93 example removed]

> I agree that ksh93's "typeset -n" feature would be a very
> convenient one for "call by name", but I would recommend not
> to restrict the modules to ksh93, because it is not that far
> used than ksh88 is.

> > A ksh88 version:

> >       function array_to_string
> >          {
> >          # Format: array_to_string vname_of_array vname_of_string
> separator
> >          ((($# < 2) || ($# > 3))) && {
> >             print -u2 " Format: array_to_string arrayname stringname
> [separator]"
> >             return 1
> >             }
> >          typeset array=$1 string=$2
> >          ((3==$#)) && [[ $3 = ? ]] && typeset IFS="${3}${IFS}"
> >          eval $string='"${array[*]}"'
> >          return 0
> >          }

> Could you write an "string_to_array" function, that would preserve
> all special characters from the string, i.e.

>         '"this is" "a multiword" "string with a $"'

I think you are mistaking the meaning of string to array.  It takes
a single string,  like the PATH,  and parses it into an array,  for
instance separating on the ":" character.

> resulting in

>         array[0]="this is"
>         array[1]="a multiword"
>         array[2]="string with a \$"

> ?

> >>     i.e. if a NNTP library function returns the number articles in
> >>     a group, the first and the last article number, it would be
> >>     very cryptic to assign the values to an array, i.e.

> >>     set -A ginfo $(nntp_getgroup comp.unix.shell)

If nntp_getgroup is a function,  you would call:

   nntp_getgroup ginfo comp.unix.shell

- Show quoted text -

> >>     artcount=${ginfo[0]}
>           >>     firstart=${ginfo[1]}
> >>     lastart=${ginfo[2]}

> >>     [Perl: uses "hashes" or associative arrays, like "awk" has, i.e.
> >>     ginfo{"count"}, ginfo{"first"}, ginfo{"last"}
> >>     ]

> > ksh93 has associative arrays.

> IMHO your "call by name" example is even better suited for
> this problem.

> [...]
> > As promised,  my function tutorial:

> ["FUN WITH FUNCTIONS (and aliases)" removed]

> Excellent summary!

> Heiner
> --
>  ___ _
> / __| |_ _____ _____ _ _     Heiner STEVEN <heiner.ste...@odn.de>
> \__ \  _/ -_) V / -_) ' \    SHELLdorado for Shell Script Programmers:
>|___/\__\___|\_/\___|_||_|   http://www.oase-shareware.org/shell/

Opinions expressed herein are my own and may not represent those of my employer.
 
 
 

Korn Shell "Modules" - request for comments

Post by Heiner Steve » Wed, 14 Jun 2000 04:00:00


[how should kshlib should be included? Suggestion: FPATH (autoload)]

 > > Your excellent explanation describes in detail, how to use
 > > this feature, and it sounds like a feasible way to implement
 > > the libraries. The one disadvantage I see is, that the "package"
 > > or "module" concept is not supported: each function has to be
 > > in it's own source file, and it's not immediately clear, which
 > > functions belong together and establish a library. Do you have
 > > an idea how this could be accomplished? I suppose, that the FPATH
 > > approach does not support subdirectories (i.e. one subdirectory
 > > for each library).
 >
 > FPATH can contain multiple libraries:
 >
 >    FPATH=~/fun:~/fun/ksh93:~/fun/dtksh

I see, but this way the FPATH variable would have to be
changed for each new library. It would be better, if the library
file could just be copied to some directory, and could immediately
be used.

Your next suggestion achives exactly this:

 > In addition,  examine this section of the tutorial:
 >
 >    The file can contain additional commands including multiple function
 >    definitions that will all be defined simultaneously.

This IMHO is the solution to the problem! Of course it requires
a kshlib user to call an initial function (having the name of
the library) to autoload a library, but this elegantly solves
another typical library programmer's problem: most libraries
need to do some initialization (i.e. to initialize variables,
configure the library to the current system, ...) *before* any
other function is called (in object oriented languages this would
be called the "constructor").

This way we have a "constructor": the name of the initial function
the library user specifies to "autoload" the whole library.

 > For instance,  I have a dtksh function library that creates and
 > manages the DtComboBox.  All the functions are in one file,
 > DtComboBoxInitialize.  The first function defined in the file
 > is DtComboBoxInitialize:
 >
 >    function DtComboBoxInitialize
 >       {
 >       [[ -o xtrace ]] && print -u2 "DtComboBoxInitialize entered"
 >       DtLoadWidget DtComboBox dtComboBoxWidgetClass
 >       }
 >
 > As you can see,  by itself it doesn't do much.  But by invoking it,
 > it brings in all the functions defined in the file:
 >
 >    $ grep ^fun DtComboBoxInitialize
 >    function DtComboBoxInitialize
 >    function DtCreateComboBox
 >    function DtComboBoxMenuPopup
 >    function DtComboBoxAddItem
 >    function DtComboBoxDeletePos
 >    function DtComboBoxClearText
 >    function DtComboBoxGetItems

["Name space conflicts" caused by identical function names within
user code and library code]

 > I don't know of anyway to define local functions.  However,  you
 > can conditionally define functions:
 >
 >    typeset +f funcname >/dev/null || function funcname {
 >       ...
 >       }

This is a good idea, but since the library functions could be
defined *before* a user function of the same name, a kshlib
user would have to check for the existance of a name. We
probably cannot burden the library user with this, but IMHO
the work around for the name space problem (reasonable unique
function prefixes) are acceptable.

 > >
 > > > Pass the variable names (vnames) of variables to be
 > > > set,  like dtksh does,  and use eval:
 > >
 > > That's an excellent idea! Parameter passing using "call by name"
 > > works, if the number of function return arguments is known by
 > > the caller in advance.
 > >
 > > This still leaves the problem, how multiple values (whose
 > > number is not known in advance) can be returned. I think the
 > > logical return value could be an array, but how can an array
 > > be returned from a function?
 >
 > Don't think of using functions by:
 >
 >    x=$(funcname)
 >
 > You might as well use a shell script for that.  Think instead of
 >
 >    set_path PATH /usr/bin /usr/local/bin /usr/contrib/bin
 >    set_path CDPATH . ~ /usr/local/bin
 >    set_path MANPATH /usr/share/man /usr/local/man /usr/contrib/man
 >
 > These are all scalars,  but it works as well for arrays
 >
 >    array_from_string PATHARRAY PATH :
 >
 >    function array_from_string {
 >       typeset vname=$1 string=$2
 >       ((3 == $#)) && typeset IFS="$3${IFS}"
 >       eval set -A $vname -- \$$string
 >       }

Point taken! I didn't realize that the "call by name" calling
syntax would work for arrary, too.

Well, this IMHO solves the most important problem of the
"kshlibs" idea: how a function can return multiple values. The
solution is (relatively) simple, at least for the user of the lib,
and efficient.

[ksh93's "typeset -n" feature could simplify "call by name"]

 > > > A ksh88 version:
 > >
 > > >       function array_to_string
 > > >          {
 > > >          # Format: array_to_string vname_of_array vname_of_string
 > > separator
 > > >          ((($# < 2) || ($# > 3))) && {
 > > >             print -u2 " Format: array_to_string arrayname stringname
 > > [separator]"
 > > >             return 1
 > > >             }
 > > >          typeset array=$1 string=$2
 > > >          ((3==$#)) && [[ $3 = ? ]] && typeset IFS="${3}${IFS}"
 > > >          eval $string='"${array[*]}"'
 > > >          return 0
 > > >          }
 > >
 > > Could you write an "string_to_array" function, that would preserve
 > > all special characters from the string, i.e.
 > >
 > >         '"this is" "a multiword" "string with a $"'
 > >
 >
 > I think you are mistaking the meaning of string to array.  It takes
 > a single string,  like the PATH,  and parses it into an array,  for
 > instance separating on the ":" character.

You're right, I'm not too used to "call by name" functions, yet.
But this will certainly change in the next time ;-)

[Further example removed]

Dan, thank you for your valuable comments!
--
 ___ _                          

\__ \  _/ -_) V / -_) ' \    SHELLdorado for Shell Script Programmers:
|___/\__\___|\_/\___|_||_|   http://www.oase-shareware.org/shell/

 
 
 

Korn Shell "Modules" - request for comments

Post by Heiner Steve » Thu, 15 Jun 2000 04:00:00


I think the discussion has brought to light many aspects of
Korn Shell Library ("kshlib") programming. With "kshlib" I mean
a shell script library (no "shared" or dynamically linked
library).

I could imagine "kshlibs" i.e. for the NNTP protocol (to get/post
news articles), CGI form data processing, or HTTP web page
retrieval.

In this article I will try to summarize the answers to my initial
questions.

Thanks to all people providing new aspects and insights, especially

        Durkin, Paul
        Francis, Erik Max
        Hiles, Brian
        Mercer, Dan
        Weisgerber, Christian

 > Is it possible to write Korn shell library functions that
 > may be used as easily as perl modules?

It is [with some restrictions]

 > How can kshlibs be included?

They could be "dotted in", but it is a good idea to use the
Korn Shell's "autoload" feature. This has the following
advantages:

 o  The path to the library file has not to be coded into
    a script. Instead the directories from the variable FPATH
    will be searched for the library

 o  A new kshlib can be added by just copying the library file
    into one of the FPATH directories

If an autoloaded file contains multiple functions, all functions
will be defined. This means that it's possible to have all
kshlib functions in one source file.

The kshlib file should contain a function named after the kshlib
file name. If the file name is i.e. "nntplib", there should be a
function called "nntplib" within the file. This function is an
initialization function, that can be used for kshlib internal
processing.

Since this function is the one used to initiate the autoload
(i.e. with "autoload nntplib; nntplib"), the initialization
function will always run *before* any other function of the
kshlib.

 > How can name space conflics be avoided?

This is a weak point: the kshlib programmer has to ensure,
that he selects "reasonably unique" names for his functions
and variables, because they must not interfere with functions
and variables a user of the library uses in his own script.

I suggest using a library prefix for each library function and
variable (i.e. "nntp_": "nntp_open()", "nntp_group()").
Functions and variables, that have library scope (and therefore
ideally should not be visible to the user) should have a name
with an initial underscore (i.e. "_nntp_fildescriptor").

A kshlib programmer may test, if a function already is defined
using

        typeset +f funcname >/dev/null || echo "not defined"

 > How should library functions return a value?

The return code of a library functions should be "success" or "no success"
values (i.e. "return 0" or "return 1").

If some variable values should be returned to the caller, the
function should use "call by name" calling syntax. In other words:
the caller of the function should specify *the name* of the
variable that should contain the return value.

Example (return one string):

    # Function definition in the kshlib file:
    function getline {
        (( $# == 1 )) || return 2
        typeset varname=$1 reply

        if read reply
        then
            eval $1='$reply'
            return 0
        fi
        return 1
    }

    After the call

        $ getline line

    the variable "line" will contain the result of the function.

This works for arrays, too:

Example (return an array):

    # Function definition in the kshlib file:
    function getdirlist {
        (( $# == 1 )) || return 2
        typeset arrayname=$1

        eval set -A $arrayname '$(ls)'
    }

    This function may be used i.e. like in the following line:

        $ getdirlist entries
        $ echo ${entries[*]}
        file1 file2 file3 file4

Respecting these conventions and guidelines (hopefully) will
help "kshlib" programmers to write versatile libraries. Users
of a "kshlib" then may profit by the experience and knowledge
of the "kshlib" programmers, and use high-quality,
well-tested Korn Shell Library Modules within their programs,
without having to care for the details of the library's
implementation.

Heiner
--
 ___ _                          

\__ \  _/ -_) V / -_) ' \    SHELLdorado for Shell Script Programmers:
|___/\__\___|\_/\___|_||_|   http://www.oase-shareware.org/shell/