xref: /titanic_44/usr/src/lib/libshell/common/nval.3 (revision 4b22b9337f359bfd063322244f5336cc7c6ffcfa)
.fp 5 CW
NVAL 3 "12 Feb 2003"

NAME

nval - the \f5ksh name/value library

SYNOPSIS
#include <nval.h>
libshell.a -lshell
"DATA TYPES"
Namval_t;
Namfun_t;
Namarr_t;
Namdisc_t;
Namval_t *nv_open(const char *name, Dt_t *dict, int flags);
Namval_t *nv_create(const char *name, Dt_t *dict, int flags, Namfun_t *fp);
void nv_close(Namval_t *np);
"GETTING AND SETTING VALUES"
char *nv_getval(Namval_t *np);
Sfdouble_t nv_getnum(Namval_t *np);
char *nv_name(Namval_t *np);
void nv_putval(Namval_t *np, const char *val, int flags);
void nv_unset(Namval_t *np);
int nv_clone(Namval_t *src, Namval_t *dest, int flags);
"ATTRIBUTES AND SIZE"
int nv_isnull(Namval_t *np);
int nv_setsize(Namval_t *np, int size);
int nv_size(Namval_t *np);
unsigned nv_isattr(Namval_t *np, unsigned flags);
unsigned nv_onattr(Namval_t *np, unsigned flags);
unsigned nv_offattr(Namval_t *np, unsigned flags);
void nv_newattr(Namval_t *np, unsigned flags, int size);
"ARRAY HANDLING"
unsigned nv_isarray(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);
Namval_t *nv_opensub(Namval_t *np);
void nv_setvec(Namval_t *np, int append, int argc, char *argv[]);
char *nv_getsub(Namval_t *np);
int nv_nextsub(Namval_t *np);
int nv_aindex(Namval_t *np);
"DISCIPLINES"
Namfun_t *nv_disc(Namval_t *np, Namfun_t *fp, int flags);
Namfun_t *nv_hasdisc(Namval_t *np, const Namdisc_t *dp);
char *nv_getv(Namval_t *np, Namfun_t *fp);
Sfdouble_t 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);
char *nv_adddisc(Namval_t *np, const char **names);
const Namdisc_t *nv_discfun(int which);
"MISCELLANEOUS FUNCTIONS"
int nv_scan(Dt_t *dict, void(*fn)(Namval_t*,void*), void *data, int mask, int flags);
Dt_t nv_dict(Namval_t *np);
void nv_setvtree(Namval_t *np);
void nv_setref(Namval_t *np, Dt_t *dp, int flags);
Namval_t *nv_lastdict(void);

DESCRIPTION

Nval is a library of functions for interacting with name-value pairs as used in \f5ksh. It is built on top the container dictionary type library facility in \f5libcdt. (See cdt(3)). Each name-value pair is represented by a type named \f5Namval_t. A \f5Namval_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 \f5nv_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 dict defines the dictionary to search. A \f5NULL value causes the shell global variable dictionary to be searched.

The flags argument consists of the bitwise-or of zero or more of the attributes listed later and zero or more of the following:

\f5NV_VARNAME: An invalid variable name causes an error.
\f5NV_IDENTIFIER: A variable name that is not an identifier causes an error.
\f5NV_ASSIGN: The name argument can contain an assignment.
\f5NV_NOARRAY: The name argument cannot contain a subscript.
\f5NV_NOREF: Do not follow references when finding the name-value pair.
\f5NV_NOADD: The name-value pair will not be added if it doesn't exist. Instead, a \f5NULL pointer will be returned.
\f5NV_NOSCOPE: Only the top level scope is used.
\f5NV_NOFAIL: Just return \f5NULL when an error occurs. By default an error message is displayed and the current command is aborted.

If a name-value pair by this name does not already exist, it is created unless flags contains the \f5NV_NOADD flag. If \f5NV_VARNAME, \f5NV_IDENTIFIER and \f5NV_ASSIGN are all not specified, then no validity check is performed on the name argument and no further processing is performed. Otherwise, if \f5NV_ASSIGN is specified, then the characters up to the first \f5= or \f5+= are used to find the name-value pair, and the characters after the \f5= are used to define the value that will be assigned to this name-value pair. If name does not contain an \f5=, 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 \f5NV_NOREF flag, if the name-value pair give by name has the \f5NV_REF attribute, it will be replaced by the variable whose name is the value of this name-value pair. If \f5NV_ASSIGN is set in the flags argument, the name variable can contain an \f5= 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.

It is possible for an application to create additional dictionaries with the cdt library and associate them with name-value pairs. The \f5nv_dict() function returns the dictionary associated with the specified name-value pair, or if no dictionary was specified, \f5NULL is returned. The \f5nv_lastdict() function returns a pointer the the name-value pair that contains the last dictionary searched on the previous \f5nv_open().

The \f5nv_close() indicates that the pointer returned by \f5nv_open() or \f5nv_opensub() will not be referenced again. If the name-value pair is unset, and not referenced elsewhere, the name-value pair may be freed.

The \f5nv_name() function returns the name of the given name-value pair np. The \f5nv_setsize() 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. If size is greater than or equal to zero, the current size is changed to this value. The \f5nv_size() function is equivalent to \f5nv_setsize() with the second argument negative.

The \f5nv_getval() function returns the value of the given name-value pair as a string. A \f5NULL return value indicates that the name-value pair is unset. The \f5nv_getnum() function returns the value of the given name-value pair as a double precision number using the \f5Sfio library (See Sfio(3)) type \f5Sfdouble_t. For name-value pairs without the \f5NV_INTEGER attribute, the string value is evaluated as an arithmetic expression to arrive at a numerical value.

The \f5nv_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 \f5NV_LONG, \f5NV_SHORT, \f5NV_DOUBLE, \f5NV_INTEGER, \f5NV_RDONLY, \f5NV_REF, \f5NV_BINARY, and \f5NV_NOFREE. The presence of \f5NV_RDONLY allows the assignment to occur even if the name-value pair has the \f5NV_RDONLY attribute. The presence of \f5NV_INTEGER indicates that the value argument is actually a pointer to a numerical type. By default this type is \f5long, but can be modified with \f5NV_LONG, \f5NV_SHORT, and \f5NV_DOUBLE to represent \f5long long, \f5short, \f5double, \f5long double, and \f5float. The presence of \f5NV_REF indicates that the value argument is actually a pointer to a name-value pair and \f5np should become a reference to this name-value pair. If \f5NV_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 \f5nv_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:

\f5NV_EXPORT: The export attribute.
\f5NV_RDONLY: The readonly attribute.
\f5NV_LTOU: Lower case characters are converted to upper case characters.
\f5NV_UTOL: Upper case characters are converted to lower case characters.
\f5NV_RJUST: Right justify and blank fill. This attribute has an associated size that defines the string length of the value.
\f5NV_LJUST: Left justify and blank fill. This attribute has an associated size that defines the string length of the value.
\f5NV_ZFILL: Without \f5NV_LJUST, right justifies and fills with leading zeros. With \f5NV_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.
\f5NV_TAGGED: Indicates the tagged attribute.
\f5NV_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.
\f5NV_DOUBLE: Used in conjunction with \f5NV_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.
\f5NV_EXPNOTE: Used in conjunction with \f5NV_INTEGER and \f5NV_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.
\f5NV_BINARY: The name-value pair contains a buffer of binary data and \f5nv_size() is the number of bytes for this data. By default the value will be represented by the base64 encoding of the buffer. The \f5NV_LJUST flag may also be specified and causes the buffer size to be fixed and data either truncated or filled with \f50 bytes.
\f5NV_REF: The name-value pair is a name reference variable.
\f5NV_NODISC: All discipline functions are ignored when performing assignments and lookups.

The \f5nv_isattr() function can test whether or not any of the attributes given by flags is set. The \f5nv_onattr() and \f5nv_offattr() functions turn attributes on or off respectively. Only attributes that do not affect the value can be set in this way. The \f5nv_newattr() function can be used to change the attributes and size of the given name-value pair which may result in the value being changed to conform to the new attributes and size. The size argument is needed for attributes that require an additional argument such as justifies variables. Changing the attribute may require changing the value to agree with the new attributes. For an array variable, the values for each of the subscripts will be changed.

The \f5nv_isarray() function returns a non-zero value if the specified name-value pair is an array.

The \f5nv_scan() function is used to walk through all name-value pairs in the dictionary given by dict. If the \f5flags variable contains the \f5NV_NOSCOPE flag, then only the top scope will be examined. The remaining flags will be used in conjunction with mask to further restrict the walk. If mask is non-zero, only the nodes for which \f5nv_isattr(node\f5,mask\f5) is equal to flags will be visited. If fn is non-zero, then this function will be executed for each name-value pair in the walk. The arguments to fn will be a pointer to the name-value pair and the data pointer passed to \f5nv_scan(). The number of elements visited will be returned.

The \f5nv_clone() function is used make a copy of the contents of name-value pair src to another name-value pair dest.

Disciplines provide a way to intercept the lookup and assignment operations, to manage the creation of sub-variables, and to extend the operations permitted on a name-value pair. A discipline consists of a set of one or more 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 \f5Namfun_t and \f5Namdisc_t. The \f5Namdisc_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:

 \f5size_t dsize;
 \f5void (*putval)(Namval_t*,const char*,int,Namfun_t*);
 \f5char *(*getval)(Namval_t*,Namfun_t*);
 \f5double (*getnum)(Namval_t*,Namfun_t*);
 \f5char *(*setdisc)(Namval_t*,const char*,Namval_t*,Namfun_t*);
 \f5Namval_t *(*createf)(Namval_t*,const char*,Namfun_t*);
 \f5Namfun_t *(*clonef)(Namval_t*,Namval_t*,int,Namfun_t*);
 \f5char *(*namef)(Namval_t*,Namfun_t*);
 \f5Namval_t *(*nextf)(Namval_t*,Dt_t*,Namfun_t*);
 \f5Namval_t *(*typef)(Namval_t*,Namfun_t*);
The \f5Namfun_t type contains a member named \f5disc which points to a \f5Namdisc_t structure. To create a discipline with additional user data, define a structure with an instance of \f5Namfun_t as the first element. An application must initialize the \f5Namfun_t portion of the structure to zero and then set the disc field to point to the \f5Namdisc_t structure. The \f5dsize field of the \f5Namdisc_t structure must be the size of this structure. A value of 0, indicates that there are no additional fields and is equivalent to \f5sizeof(Namfun_t). If different instances of this structure uses different sizes, then the \f5size field in the \f5Namfun_t can must be set to this size and overrides the value in the \f5Namdisc_t structure.

When a variable is referenced by calling the \f5nv_getval() function, and the \f5NV_NODISC attribute is not set, the \f5getval() discipline function is called with a pointer to the name-value pair, np, and a pointer to the discipline, fp. Inside the \f5getval() function, the \f5nv_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 \f5getnum() discipline is called whenever a numerical value is needed for the name-value pair np and the \f5NV_NODISC attribute is not set, The \f5nv_getn() function can be called from within the \f5getnum() discipline to get the value that would have resulted if there were no \f5getnum() discipline.

The \f5putval\f5() discipline function is used to override the assignment of values to a name-value pair. It is called whenever a value is assigned with \f5nv_putval() and the \f5NV_NODISC attribute is not set, or when a name-value pair is unset with \f5nv_unset(). When a name-value pair is unset, \f5putval\f5() is called with value set to \f5NULL. The \f5nv_putv() function is used within the \f5putval() to perform the assignment or unset that would have occurred if the discipline had not been installed.

The \f5createf() discipline function is called from \f5nv_open() or \f5nv_create() when the name-value pair preceding a \s+2.\s-2 is found. This function is passed the name-value pointer plus the remaining string and the current flags argument. The \f5createf() 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 \f5nv_open(). The \f5nv_create() function may be called within the \f5createf() discipline function to perform the action that would have occurred by an earlier \f5nv_open() function.

The \f5setdisc() discipline function is used to extend the set of available shell level discipline functions associated with a name-value pair by allowing builtins or functions whose name is of the form varname\f5.action to be defined. By default, each name-value pair can have a \f5get, \f5set, and \f5unset discipline associated with it. Whenever a builtin or function whose name is of the form varname\f5.action is defined or is unset, and action is not \f5get, \f5set, or \f5unset, the setdisc\f5() function is invoked with the same argument format as \f5nv_setdisc\f5(). The argument f points to the name-value pair associated with the function being defined, or \f5NULL 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 \f5nv_setdisc(np\f5,a\f5,f\f5,fp\f5) so that it can be searched for in previously stacked disciplines. Otherwise, the setdisc\f5() function should save the function name-value pair pointer, and return a non-\f5NULL 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 \f5NULL, then f points to an action name instead of a name-value pair pointer. The setdisc\f5() must return the name of the action that follows the action name given by f. If f is also \f5NULL, 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.

The \f5nv_adddisc() function is a higher level function that adds a setdisc discipline to the name-value pair that allows shell level disciplines to be created for each of the name specified in \f5names.

The \f5nv_discfun() function can be used to get a pointer to discipline functions that are provided by the library. Currently, the only one that is provided is the ones used to implement \f5nv_adddisc() which can be returned with an argument of \f5NV_DCADD.

The \f5clonef() discipline function is called by \f5nv_clone() when making a copy of the \f5Namfun_t discipline to the new node. The first argument is the original node, the second argument is the new node, and the third argument is the flags that were passed down to \f5nv_clone(). It must return a new instance of the \f5Namfun_t* \f5fp. If omitted, then memory whose size is determinated by the \f5size field of \f5fp, if non-zero, or \f5fp->disc, will be allocated and copied from \f5fp.

The \f5namef() discipline function returns the name for this name-value pair.

The \f5nextf() is used for walking through the list of sub-variables associated with this name-value pair. If the dictionary argument is \f5NULL, it must return the first sub-variable. Otherwise, it must return the next sub-variable, or \f5NULL if there are no more variables.

A discipline is installed or removed with the \f5nv_disc() function. The following flags can be specified:

\f5NV_FIRST: If fp is non-\f5NULL, the discipline is moved to the top of the stack or pushed onto the top of the stack of disciplines associated with the given name-value pair np if not already present. Otherwise, the top of the discipline stack is returned.
\f5NV_LAST: If fp is non-\f5NULL, the discipline is moved to the bottom of the stack or pushed onto the bottom of the stack of disciplines associated with the given name-value pair np if not already present. Otherwise, the bottom of the discipline stack is returned.
\f5NV_POP: If fp is non-\f5NULL and it is on the stack, it is removed and fp is returned. If fp is non-\f5NULL and is not on the stack, \f5NULL is returned. Otherwise, the the top discipline is popped and returned.
\f5NV_CLONE: If fp is non-\f5NULL and it is on the stack, it is replace by a copy created by \f5malloc(3). The \f5nofree field is set to \f50. The new discipline is returned. Otherwise, \f5NULL is returned.
\f50: If fp is non-\f5NULL then it is equivalent to \f5NV_FIRST. Otherwise, it is equivalent to \f5NV_POP.

The \f5nv_hasdisc() function can be used to tell whether a discipline whose discipline functions are those defined in dp. A pointer to this discipline is returned.

The \f5nv_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 \f5nv_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 \f5nv_associative() implements the default associative array semantics that are used with \f5typeset -A. The function fun will be called with third argument as follows:

\f5NV_AINIT: This will be called at initialization. The function you supply must return a pointer to a structure that contains the type \f5Namarr_t as the first element. All other calls receive this value as an argument.
\f5NV_AFREE: This will be called after all elements of the name-value pair have been deleted and the array is to be freed.
\f5NV_ADELETE: The current element should be deleted.
\f5NV_ANEXT: This means that the array subscript should be advanced to the next subscript. A \f5NULL return indicates that there are no more subscripts.
\f5NV_ANAME: The name of the current subscript must be returned.
\f5NV_ACURRENT: Returns a pointer to a name-value pair corresponding to the current subscript, or \f5NULL if this array type doesn't create represent each element as a name-value pair.

If np refers to an array, the \f5nv_getsub() returns a pointer to the name of the current subscript. Otherwise, \f5nv_getsub() returns \f5NULL.

The \f5nv_opensub() function returns a pointer to the name-value pair corresponding to the current subscript in an associative array. Note that the \f5nv_close() function should be called when the pointer is no longer needed.

The \f5nv_putsub() function is used to set the subscript for the next reference to \f5np. If the \f5name argument is not \f5NULL, it defines the value of the next subscript. The \f5mode argument can contain one or more of the following flags:

\f5ARRAY_ADD: Add the subscript if not found. Otherwise, \f5nv_putsub() returns \f5NULL if the given subscript is not found.
\f5ARRAY_SCAN: Begin a walk through the subscripts starting at the subscript given by \f5name. If \f5name is \f5NULL the walk is started from the beginning.
\f5ARRAY_UNDEF: This causes any current scan to terminate and leaves the subscript in an undefined state.

If \f5ARRAY_ADD is not given and the subscript does not exist, a \f5NULL value is returned.

The \f5nv_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 \f5nv_setref() function makes the name-value pair \f5np into a reference to the variable whose name is given by the value of \f5np. The \f5nv_open() open function is called with this name, the dictionary given by \f5dp, and the \f5flags argument. A \f5NULL value causes the shell global variable dictionary to be searched.

The \f5nv_setvtree() function makes the name-value pair \f5np into a tree structured variable so that \f5nv_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.

SEE ALSO
cdt(3) shell(3)
AUTHOR
David G. Korn (dgk@research.att.com).