NVAL(3)

NAME

nval - a ksh name/value library

SYNOPSIS

#include	<nval.h>
Namval_t 	*nv_open(const char *name, Hashtab_t *table, int flags);
void	nv_close(Namval_t *np);
Hashtab_t	*nv_getscope(int index);
char	*nv_getval(Namval_t *np);
double	nv_getnum(Namval_t *np);
unsigned	nv_isattr(Namval_t *np, unsigned flags);
char	*nv_name(Namval_t *np);
void	nv_newattr(Namval_t *np, unsigned flags, int size);
void	nv_putval(Namval_t *np, const char *val, int flags);
int	nv_size(Namval_t *np);
Namfun_t	*nv_stack(Namval_t *np, Namfun_t *fp);
int	nv_scan(Hashtab_t *table, void(*fn)(Namval_t*,int,int));
void	nv_unset(Namval_t *np);
Namarr_t	*nv_setarray(Namval_t *np,void*(*fun)(Namval_t*,const char*,int));
Namval_t	*nv_putsub(Namval_t *np, char *name, long mode);
char	*nv_getsub(Namval_t *np);
int	nv_nextsub(Namval_t *np);
int	nv_aindex(Namval_t *np);
void	nv_setref(Namval_t *np);
void	nv_setvtree(Namval_t *np);
char	*nv_getv(Namval_t *np, Namfun_t *fp);
double	nv_getn(Namval_t *np, Namfun_t *fp);
void	nv_putv(Namval_t *np, const char *val, int flags, Namfun_t *fp);
char	*nv_setdisc(Namval_t *np, const char *a, Namval_t *f, Namfun_t *fp);
Namval_t	*nv_create(Namval_t *np, const char *name, Namfun_t *fp);

DESCRIPTION

Nval is a library of functions for interacting with name-value pairs as used in ksh. It is built on top an the extensible hashing library facility in libast. (See hash(3)). Each name-value pair is represented by a type named Namval_t. A Namval_t contains the name, value and attributes of a variable. Some attributes can have an associated number that represents the field width, arithmetic base, or precision. Additionally, each name-value pair can be associated with one or more processing disciplines that affect its behavior.

The function nv_open() returns a pointer to a name-value pair corresponding to the given name. It can also assign a value and give attributes to a name-value pair. The argument table defines the table to search. A NULL value causes the shell variable table to be searched. It is possible for an application to create additional tables with the hash library. In addition, the nv_getscope() function returns a ponter to the hash table for the scope corresponding to index, or NULL if no such table exists. A value of 0 for index indicates the global scope. A positive index indicates the number of levels back on the function call stack to find the scope. The flags argument consists of the bitwise-or of zero or more of the attributes listed later and zero or more of the following:

    NV_VARNAME: An invalid variable name causes an error.

    NV_IDENTIFIER: A variable name that is not an identifier causes an error.

    NV_ASSIGN: The name argument can contain an assignment.

    NV_NOARRAY: The name argument cannot contain a subscript.

    NV_NOREF: Do not follow references when finding the name-value pair.

    NV_NOADD: The name-value pair will not be added if it doesn't exist. Instead, a NULL pointer will be returned.

    NV_NOSCOPE: Only the top level scope is used.

If a name-value pair by this name does not already exist, it is created unless flags contains the NV_NOADD flag. If neither NV_VARNAME nor NV_IDENTIFIER is specified, and NV_NOASSIGN is specified, then no validity check is performed on the name argument and no further processing is performed. Otherwise, if NV_NOASSIGN is not specified, then the characters up to the first = are used to find the name-value pair, and the characters after the = are used to define the value that will be assigned to this name-value pair. If name does not contain an =, than no assignment will be made. If the first identifier in name is a reference and is not preceded by a ., it will be replaced by the value of the reference to find the name of a variable. Unless flags contains the NV_NOREF flag, if the name-value pair give by name has the NV_REF attribute, it will be replaced by the variable whose name is the value of this name-value pair. Unless prohibited by the NV_NOASSIGN flags argument, the name variable can contain an = and a value that will be assigned to the name-value pair. Any attributes appearing in the flags argument will be applied to the name-value pair after any value is assigned.

The nv_close() indicates that the pointer returned by nv_open() will not be referenced again. If the name-value pair is unset, and not referenced elsewhere, the name-value pair may be freed.

The nv_name() function returns the name of the given name-value pair np. The nv_size() function returns the size of the field for justified variables, the arithmetic base for integer variables, and the precision or number of places after the decimal point for floating point variables. The nv_getval() function returns the value of the given name-value pair as a string. A NULL return value indicates that the name-value pair is unset. The nv_getnum() function returns the value of the given name-value pair as a double precision number. For name-value pairs without the NV_INTEGER attribute, the string value is evaluated as an arithmetic expression to arrive at a numerical value.

The nv_putval() function is used to assign a value to the name-value pair np. The flags argument consists zero or more of the bitwise-or of NV_INTEGER, NV_RDONLY, NV_REF, and NV_NOFREE. The presence of NV_RDONLY allows the assignment to occur even if the name-value pair has the NV_RDONLY attribute. The presence of NV_INTEGER indicates that the value argument is actually a pointer to a double precision number containing the value for this name-value pair. The presence of NV_REF indicates that the value argument is actually a pointer to a name-value pair and np should become a reference to this name-value pair. If NV_NOFREE is specified, value itself becomes the value of the name-value pair np. Otherwise, a copy of the value is stored as the value for np.

The nv_unset() function clears out the value and attributes of the given name-value function but does not free the name-value pair.

The following attributes can be associated with a name-value pair:

    NV_EXPORT: The export attribute.

    NV_RDONLY: The readonly attribute.

    NV_LTOU: Lower case characters are converted to upper case characters.

    NV_UTOL: Upper case characters are converted to lower case characters.

    NV_RJUST: Right justify and blank fill. This attribute has an associated size that defines the string length of the value.

    NV_LJUST: Left justify and blank fill. This attribute has an associated size that defines the string length of the value.

    NV_ZFILL: Without NV_LJUST, right justifies and fills with leading zeros. With NV_LJUST, left justify and strip leading zeros. Left justify and blank fill. This attribute has an associated size that defines the string length of the value.

    NV_TAGGED: Indicates the tagged attribute.

    NV_INTEGER: Causes value to be represented by a number. This attribute has an associated number that defines the arithmetic base to be used when the value is expanded as a string.

    NV_DOUBLE: Used in conjunction with NV_INTEGER to cause value to be stored as a double precision floating point number. This attribute has an associated number that defines the number of places after the decimal point to be used when the value is expanded as a string.

    NV_EXPNOTE: Used in conjunction with NV_INTEGER and NV_DOUBLE to cause the value to be represented in scientific notation when expanded as a string. This attribute has an associated number that defines the the precision of the mantissa.

    NV_REF: The name-value pair is a name reference variable.

The nv_isattr() function can test whether or not any of the attributes given by flags is set. The attribute NV_ARRAY can be used to test whether or not the given name-value pair is an array. The nv_newattr() function can be used to change the attributes of the given name-value pair. The size argument is needed for attributes that require an additional argument. Changing the attribute may require changing the value to agree with the new attributes. For an array variable, each of the values will be changed.

The nv_scan() function is used to walk through all name-value pairs in the table given by table. If fn is non-zero, then this function will be executed for each name-value pair in the table. The number of elements in the table will be returned.

Disciplines provide a way to intercept the lookup and assignment operations and to extend the operations permitted on a name-value pair. A discipline consists of a set of functions and related data that are used to override and extend the operations on a name-value pair. A discipline is defined by the types Namfun_t and Namdisc_t. The Namdisc_t is not modified by any of these functions and can therefore be shared by several name-value pairs. It contains following public fields in the order listed:
      size_t		dsize;
      void		(*putval)(Namval_t*,const char*,int,Namfun_t*);
      char		*(*getval)(Namval_t*,Namfun_t*);
      double		(*getnum)(Namval_t*,Namfun_t*);
      char		*(*setdisc)(Namval_t*,const char*,Namval_t*,Namfun_t*);
      Namval_t	*(*create)(Namval_t*,const char*,Namfun_t*);
The Namfun_t type contains a member named disc which points to a Namdisc_t structure. To create a discipline with additional user data, define a structure with an instance of Namfun_t as the first element. The dsize field of the Namdisc_t structure must be the size of this structure. A value of 0, indicates that there are no additional fields and is equivalent to sizeof(Namfun_t).

When a variable is referenced by calling the nv_getval() function, the getval() discipline function is called with a pointer to the name-value pair, np, and a pointer to the discipline, fp. Inside the getval() function, the nv_getv() function can be called to get the value of the name-value pair that would have resulted if the discipline were not used. The getnum() discipline is called whenever a numerical value is needed for the name-value pair np. The nv_getn() function can be called from within the getnum() discipline to get the value that would have resulted if there were no getnum() discipline.

The putval() discipline function is used to override the assignment of values to a name-value pair. It is called whenever a value is assigned with nv_putval() or unset with nv_unset(). When a name-value pair is unset, putval() is called with value set to NULL. The nv_putv() function is used within the putval() to perform the assignment or unset that would have occurred if the discipline had not been installed.

The create() discipline function is called from nv_open() when the name-value pair for name containing a . doesn't exist, unless NV_NOADD was specified. This function is passed the name-value pointer of the longest parent name-value pair that exists, plus the remaining string. The create() discipline function must return the created name-value pair, otherwise the default action will be taken. If the name-value pair that is returned, is the same as the one given, then the the behavior will be the same as if an invalid name had been given to nv_open(). The nv_create() function may be called within the create() discipline function to perform the action that would have occurred by an earlier discipline.

The setdisc() discipline function is used to extend the set of available shell level discipline functions associated with a name-value pair by allowing functions whose name is of the form varname.action to be defined. By default, each name-value pair can have a get, set, and unset discipline associated with it. Whenever a function whose name is of the form varname.action is defined or is unset, and action is not get, set, or unset, the setdisc() function is invoked with the same argument format as nv_setdisc(). The argument f points to the name-value pair associated with the function being defined, or NULL if the function is being unset. If the given action a is not known by this discipline, it should return the value returned by calling nv_setdisc(np,a,f,fp) so that it can be searched for in previously stacked disciplines. Otherwise, the setdisc() function should save the function name-value pair pointer, and return a non-NULL value. The name-value pointer to the function can be used to invoke the function at an application defined point. If the action a is NULL, then f points to an action name instead of a name-value pair pointer. The setdisc() must return the name of the action that follows the action name given by f. If f is also NULL, the name of the first action must be returned. This allows an application to get the list of valid discipline action names allowed by a given name-value pair.

A discipline is installed or removed with the nv_stack() function. If fp is non-NULL, the discipline is pushed onto the stack of disciplines associated with the given name-value pair np. Otherwise, the most recently pushed discipline is popped and returned.

The nv_aindex() function returns the current index for the indexed array given by the name-value pair pointer np. The return value is negative if np refers to an associative array.

The nv_setarray() function is used to create an associative array from a name-value pair node. The function fun defines the semantics of the associative array. Using fun equal to nv_associative() implements the default associative array semantics that are used with typeset -A. The function fun will be called with third argument as follows:

    NV_AINIT: This will be called at initialization. The function you supply must return a pointer to a structure that contains the type Namarr_t as the first element. All other calls receive this value as an argument.

    NV_AFREE: This will be called after all elements of the name-value pair have been deleted and the array is to be freed.

    NV_ADELETE: The current element should be deleted.

    NV_ANEXT: This means that the array subscript should be advanced to the next subscript. A NULL return indicates that there are no more subscripts.

    NV_ANAME: The name of the current subscript must be returned.

If np refers to an array, the nv_getsub() returns a pointer to the name of the current subscript. Otherwise, nv_getsub() returns NULL.

The nv_putsub() function is used to set the subscript for the next reference to np. If the name argument is not NULL, it defines the value of the next subscript. The mode argument can contain one or more of the following flags:

    ARRAY_ADD: Add the subscript if not found. Otherwise, nv_putsub() returns NULL if the given subscript is not found.

    ARRAY_SCAN: Begin a walk through the subscripts starting at the subscript given by name if given. Otherwise, the walk is started from the beginning.

    ARRAY_UNDEF: This causes any current scan to terminate and leaves the subscript in an undefined state.

If ARRAY_ADD is not given and the subscript does not exist, a NULL value is returned.

The nv_nextsub() function is used to advance to the next subscript. It returns 0 if there are no more subscripts or if called when not in a scan.

The nv_setref() function makes the name-value pair np into a reference to the variable whose name is given by the value of np.

The nv_setvtree() function makes the name-value pair np into a tree structured variable so that nv_getval() will return a string containing all the names and values of children nodes in a format that can be used in a shell compound assignment.

AUTHOR David G. Korn (dgk@research.att.com).