Index: ossp-pkg/var/var.pod RCS File: /v/ossp/cvs/ossp-pkg/var/var.pod,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/var/var.pod,v' 2>/dev/null --- var.pod 2001/11/16 15:44:17 1.3 +++ var.pod 2001/11/19 15:38:47 1.4 @@ -35,9 +35,255 @@ =head1 SYNOPSIS +var_rc_t var_unescape(const char *src, size_t len, char *dst, int unescape_all); + +var_rc_t var_expand(const char *input, size_t input_len, char **result, size_t *result_len, var_cb_t lookup, void *lookup_context, const var_config_t *config, int force_expand); + =head1 DESCRIPTION -The purpose of VAR is ... +The routines included in this library, var_unescape() and +var_expand(), enable application developers to make use of variable +expansion in an arbitrary text buffer. Assume, for instance, your +application provided the data items + + HOST = peti.example.org + OSTYPE = FreeBSD + HOME = /home/my-application + +and you had obtained the following message from the user via means of +a configuration file, the system environment, or the command line: + + My-application starting up with the following configuration: + + HOST = $HOST + OSTYPE = $OSTYPE + HOME = $HOME + +Then you could use var_expand() to replace the variables in that +message by their actual contents. + +The good thing about this kind of approach is that you separate the +actual information in a message from the message's layout, language, +or content encoding. If the user doesn't like messages as long the one +above, he'd simply provide the template + + my-application: $HOST ($OSTYPE), $HOME + +to get the result, he's interested in. Maybe all he's interested in +is: + + my-application's home is $HOME + +To take things one step further, OSSP var provides the user -- the +person providing the template file, that is -- with powerful +mechanisms to modify the presentation of the variable's contents. For +example, the expression ${HOME:l} would yield the contents of the +variable HOME converted to all lower-case. Or, to show on even more +powerful construct: The expression ${HOME:y/ \t/__/} would turn all +blanks or tabs in the contents of HOME to underscores, before +inserting it into the output text. + +Similarly, the function var_unescape() will expand "quoted pairs", +thus allowing the user to speficy non-printable characters is a +template, such as the carrige return ('\r'), the newline ('\n'), or -- +as seen above -- the tab ('\t'). + +Using these two routines in combination, gives the application +developer the power to have the user custumize the application's +messages as he or she sees fit at virtually no extra cost; +incorporating a template mechanism into your own applications with +OSSP var is extremely simple. + +=head1 THE VAR_UNESCAPE FUNCTION + +The purpose of var_unescape() is to expand any quoted pairs found in +the input buffer. Its prototype is: + + var_rc_t var_unescape(const char *src, size_t len, + char *dst, int unescape_all); + +The first parameter, "src", is a pointer to the input buffer, which +should be processed. Unlike most C library functions, var_unescape() +does not expect the buffer to be terminated by a null byte ('\0'), +instead, it expects the length of the buffer's contents as parameter +"len". The third parameter, "dst" is a pointer to a buffer, into which +the expanded buffer is copied if processing is successful. The size of +this buffer must be at least len+1 characters. The reason the result +buffer has to be one byte longer than the input buffer is that +var_unescape() always adds a terminating null byte at the end of the +output buffer, so that you can use the result comfortably with other C +library routines. + +The last parameter, "unescape_all", is flag that modifies the behavior +of var_unescape(). If is set to TRUE (any value except zero, that is), +var_unescape() will expand B quoted pair it sees, even those that +it does not know about. Hence, a "\1" will become a "1", even though +"\1" has no special meaning to var_unescape(). If "unescape_all" is +set to FALSE (zero), such quoted pairs will be copied verbatimly to +the output buffer. + +The quoted pairs supported by var_unescape() are '\t', '\r', '\n', +'\abc' (octal), '\xAB' (hexadecimal), and '\x{...}' (grouped +hexadecimal). Please refer to section "SUPPORTED NAMED CHARACTERS" for +a more comprehensive description of these quoted pairs. + +If var_unescape() encounters any syntax errors, it will return an +error code denoting exactly what kind of error occured; please refer +to section "CODES RETURNED BY THE LIBRARY" for a complete list of +possible return codes. If no error occured, VAR_OK is returned. + +=head1 THE VAR_EXPAND FUNCTION + +The second function of OSSP var is var_expand(), the routine that will +expand any variables found in a text buffer to their actual contents. +Its prototype is: + + var_rc_t var_expand(const char *input, size_t input_len, + char **result, size_t *result_len, + var_cb_t lookup, void *lookup_context, + const var_config_t *config, + int force_expand); + +Don't be scared, the usage is way simpler than it looks at first +glance. The parameters of var_expand() are: + +=over 4 + +=item const char *input + +A pointer to the text buffer containing the variable expressions to be +expanded. Unlike in most other C library functions, this text buffer +need not be terminated by a null byte. + +=item size_t input_len + +The length of the text buffer's contents. + +=item char **result + +A pointer to a character pointer in which the location of the expanded +text buffer will be stored. The result buffer will be allocated by +var_expand() using the system call malloc(3), thus it is the caller's +responsibility to free(3) that buffer once it is not used anymore. + +If var_expand() fails with an error, "result" will point to "input". +The only exception is the VAR_ERR_INVALID_ARGUMENT error, in which +case "result" is not modified. + +=item size_t *result_len + +A pointer to the location in which the length of the expanded text +buffer will be stored. If var_expand() fails with an error -- with the +exception of VAR_ERR_INVALID_ARGUMENT --, "result_len" will contain +the number of characters that have been consumed from "input" before +the error occured. + +=item var_cb_t lookup + +A pointer to the function used to perform the actual variable lookup. +Please refer to section "THE LOOKUP CALLBACK" for a comprehensive +description. + +=item void *lookup_context + +An arbitrary value passed through to "lookup" every time it is called. +Please refer to section "THE LOOKUP CALLBACK" for a comprehensive +description. + +=item const var_config_t *config + +The configuration of var_expand(). The var_config_t structure is +defined as follows: + + typedef struct { + char varinit; + char startdelim; + char enddelim; + char escape; + char *namechars; + } var_config_t; + +Using this structure, you can modify the parser to use different +tokens to find variable constructs. If "config" is NULL, the default +configuration will be used, which you can access through the +declaration + + extern const var_config_t var_config_default; + +in var.h. The default configuration for var_init looks like this: + + const var_config_t var_config_default = { + '$', /* varinit */ + '{', /* startdelim */ + '}', /* enddelim */ + '\\', /* escape */ + "a-zA-Z0-9_" /* namechars */ + }; + +Please note that the setting of var_config_t.escape is actually a +single backslash; the quote above has been taken from the C source +code, which is why the backslash had to be escaped with another +backslash for the C pre-processor. + +=item int force_expand + +This flag determines how var_expand() deals with undefined variables. +If it is set to TRUE (any value but zero), var_expand() will fail with +error code VAR_ERR_UNDEFINED_VARIABLE whenever an undefined variable +is encountered. If set to FALSE (zero), var_expand() will copy the +expression it failed to expand verbatimly into the output buffer, in +order to enable you to go over the buffer with an additional pass. + +Generally, if you do not plan to use muli-pass expansion, you should +set "force_expand" to TRUE in order to make sure no unexpanded +variables are left over in the buffer. + +=back + +var_expand() returns VAR_OK if everything went fine, and one of the +error codes described in section "CODES RETURNED BY THE LIBRARY" if +the function call failed. + +=head1 COMBINING VAR_UNESCAPE AND VAR_EXPAND + +For maximum power and flexibility, you will want to use both routines +provided by this library in combination. That is, you will want to use +var_unescape() to turn all quoted pairs into their real +representation, before you call var_expand(), because then the user +can safely use specials like "\n" or "\t" throughout the template and +achieve the desired effect. These quoted pairs are particularly useful +if search-and-replace or transpose actions are performed on variables +before they're expanded. Be sure, though, to make the first +var_unescape() pass with "expand_all" set to FALSE, or the routine +will also expand quoted pairs like "\1", which might have a special +meaning in the var_expand() pass to follow. + +Once, all known quoted pairs are expanded, expand the variables with +var_expand(). After that, you will want to have a second pass with +var_unescape() and "expand_all" set to TRUE, to make sure all +remaining quoted pairs are expanded. Also, the var_expand() pass might +have introduced now quoted pairs into the output text, which you need +to expand to get the desired effect. + +Take a look at this code snipped, to see how to combine var_unescape() +und var_expand() properly: + + var_rc_t rc; + char* result; + size_t result_len; + + if ((rc = var_unescape(input, strlen(input), output, 0)) != VAR_OK || + (rc = var_expand(output, strlen(output), + &result, &result_len, + &lookup, NULL, + NULL, 1)) != VAR_OK || + (rc = var_unescape(input, strlen(input), output, 1)) != VAR_OK) + { + printf("Expanding the template failed with error %d.\n", rc); + exit(1); + } + [...] + free(result); =head1 THE LOOKUP CALLBACK