head 1.39; access; symbols LMTP2NNTP_1_4_1:1.39 LMTP2NNTP_1_4_0:1.39 VAR_1_1_3:1.39 VAR_1_1_2:1.38 VAR_1_1_1:1.36 LMTP2NNTP_1_3_0:1.36 LMTP2NNTP_1_3b2:1.36 LMTP2NNTP_1_3b1:1.36 LMTP2NNTP_1_3a3:1.36 LMTP2NNTP_1_3a2:1.36 LMTP2NNTP_1_3a1:1.36 VAR_1_1_0:1.36 VAR_1_0_0:1.35 LMTP2NNTP_1_2_0:1.34 LMTP2NNTP_1_2b4:1.34 LMTP2NNTP_1_2b3:1.34 LMTP2NNTP_1_2b2:1.34 LMTP2NNTP_1_2b1:1.34 LMTP2NNTP_1_2a8:1.34 LMTP2NNTP_1_2a7:1.34 LMTP2NNTP_1_2a6:1.34 LMTP2NNTP_1_2a5:1.34 LMTP2NNTP_1_2a4:1.32 VAR_0_9_0:1.32 LMTP2NNTP_1_2a3:1.26 OSSP_RC_SPEC:1.18; locks; strict; comment @# @; 1.39 date 2005.01.20.20.29.06; author rse; state Exp; branches; next 1.38; 1.38 date 2004.10.29.20.41.18; author rse; state Exp; branches; next 1.37; 1.37 date 2004.10.29.20.40.18; author rse; state Exp; branches; next 1.36; 1.36 date 2004.04.04.08.07.34; author rse; state Exp; branches; next 1.35; 1.35 date 2003.02.14.21.17.07; author rse; state Exp; branches; next 1.34; 1.34 date 2002.05.27.15.29.17; author rse; state Exp; branches; next 1.33; 1.33 date 2002.05.23.09.13.20; author thl; state Exp; branches; next 1.32; 1.32 date 2002.03.08.12.55.52; author rse; state Exp; branches; next 1.31; 1.31 date 2002.03.07.12.39.30; author rse; state Exp; branches; next 1.30; 1.30 date 2002.03.07.12.19.46; author rse; state Exp; branches; next 1.29; 1.29 date 2002.03.07.12.11.09; author rse; state Exp; branches; next 1.28; 1.28 date 2002.03.07.09.14.05; author rse; state Exp; branches; next 1.27; 1.27 date 2002.03.06.10.18.19; author rse; state Exp; branches; next 1.26; 1.26 date 2002.03.04.12.01.53; author rse; state Exp; branches; next 1.25; 1.25 date 2002.03.04.11.53.27; author rse; state Exp; branches; next 1.24; 1.24 date 2002.02.28.14.58.07; author rse; state Exp; branches; next 1.23; 1.23 date 2002.02.28.11.40.46; author rse; state Exp; branches; next 1.22; 1.22 date 2002.02.28.08.48.44; author rse; state Exp; branches; next 1.21; 1.21 date 2002.02.28.08.08.16; author rse; state Exp; branches; next 1.20; 1.20 date 2002.02.27.13.44.16; author rse; state Exp; branches; next 1.19; 1.19 date 2002.02.27.11.55.26; author rse; state Exp; branches; next 1.18; 1.18 date 2002.01.02.17.12.18; author rse; state Exp; branches; next 1.17; 1.17 date 2001.12.17.12.57.46; author rse; state Exp; branches; next 1.16; 1.16 date 2001.12.17.10.29.43; author rse; state Exp; branches; next 1.15; 1.15 date 2001.12.16.23.40.16; author rse; state Exp; branches; next 1.14; 1.14 date 2001.12.12.17.18.55; author simons; state Exp; branches; next 1.13; 1.13 date 2001.12.12.16.51.20; author simons; state Exp; branches; next 1.12; 1.12 date 2001.12.12.14.34.18; author rse; state Exp; branches; next 1.11; 1.11 date 2001.12.08.16.02.15; author simons; state Exp; branches; next 1.10; 1.10 date 2001.12.04.13.37.55; author simons; state Exp; branches; next 1.9; 1.9 date 2001.12.03.10.51.27; author simons; state Exp; branches; next 1.8; 1.8 date 2001.11.20.15.46.35; author simons; state Exp; branches; next 1.7; 1.7 date 2001.11.20.13.08.17; author thl; state Exp; branches; next 1.6; 1.6 date 2001.11.20.12.22.42; author thl; state Exp; branches; next 1.5; 1.5 date 2001.11.19.16.15.32; author simons; state Exp; branches; next 1.4; 1.4 date 2001.11.19.15.38.47; author simons; state Exp; branches; next 1.3; 1.3 date 2001.11.16.15.44.17; author simons; state Exp; branches; next 1.2; 1.2 date 2001.11.13.12.47.59; author simons; state Exp; branches; next 1.1; 1.1 date 2001.11.13.12.36.48; author simons; state Exp; branches; next ; desc @@ 1.39 log @Bumped year in copyright messages for new year 2005 @ text @## ## OSSP var -- Variable Expansion ## Copyright (c) 2001-2005 Ralf S. Engelschall ## Copyright (c) 2001-2005 The OSSP Project (http://www.ossp.org/) ## Copyright (c) 2001-2005 Cable & Wireless (http://www.cw.com/) ## ## This file is part of OSSP var, an extensible data serialization ## library which can be found at http://www.ossp.org/pkg/lib/var/. ## ## Permission to use, copy, modify, and distribute this software for ## any purpose with or without fee is hereby granted, provided that ## the above copyright notice and this permission notice appear in all ## copies. ## ## THIS SOFTWARE IS PROVIDED `AS IS' AND ANY EXPRESSED OR IMPLIED ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ## SUCH DAMAGE. ## ## var.pod: Unix manual page source ## =pod =head1 NAME B -- Variable Expansion =head1 SYNOPSIS =over 2 =item Types: B, B, B, B, B, B. =item Functions: B, B, B, B, B, B, B, B. =item Variables: B. =back =head1 DESCRIPTION B is a flexible, full-featured and fast variable construct expansion library. It supports a configurable variable construct syntax very similar to the style found in many scripting languages (like C<@@>I, C<${>IC<}>, C<$(>IC<)>, etc.) and provides both simple scalar (C<${>IC<}>) and array (C<${>IC<[>IC<]}>) expansion, plus optionally one or more post-operations on the expanded value (C<${>IC<:>I[C<:>I...]]C<}>). The supported post-operations are length determination, case conversion, defaults, positive and negative alternatives, sub-strings, regular expression based substitutions, character translations, and padding. Additionally, a meta-construct plus arithmetic expressions for index and range calculations allow (even nested) iterations over array variable expansions (..C<[>..C<${>IC<[#+1]}>..C<]>..). The actual variable value lookup is performed through a callback function, so B can expand arbitrary values. =head1 SYNTAX CONSTRUCTS A string expanded through B can consist of arbitrary text characters plus one or more of the following special syntax constructs which are expanded by B. =over 4 =item C<\>I Character with the octal value I (I: C<0>,...,C<7>). =item C<\x>I, C<\x{>IC<}> Character with the hexadecimal value I or the characters denoted by grouped hexadecimal numbers I. (I, I: C<0>,...,C<9>,[C],...,[C]). =item C<\t>, C<\r>, C<\n> Tabulator (TAB), Carriage Return (CR) and Newline (NL) character. =item C<\\>, C<\>I Ordinary character C<\> and I. =item C<$>I, C<${>IC<}> Contents of scalar variable I. =item C<${>IC<[>IC<]>C<}> Contents of array variable I at position I. For I full arithmetic expressions are allowed. =item C<${>IC<:#}> Length of C<$>I. =item C<${>IC<:l}>, C<${>IC<:u}> C<$>I, converted to all lower-case or all upper-case. =item C<${>IC<:->IC<}> If C<$>I is not empty string and not undefined, then C<$>I, else I (Default Value). =item C<${>IC<:+>IC<}> If C<$>I is empty string, then empty string, else I (Positive Alternative). =item C<${>IC<:*>IC<}> If C<$>I is not empty string, then empty string, else I (Negative Alternative). =item C<${>IC<:o>IC<,>[I]C<}> Substring of C<$>I starting at position I with I characters. =item C<${>IC<:o>IC<->[I]C<}> Substring of C<$>I starting at position I and ending at position I (inclusive). =item C<${>IC<:s/>ICIC[C]C<}> C<$>I after replacing characters matching I with I. By default, case-sensitive regular expression matching is performed and only the first occurrence of I is replaced. Flag "C" switches to case insensitive matching; flag "C" switches to plain text pattern; flag "C" switches to replacements of all occurrences; flag "C" switches to multi-line matching (That is, change "C<^>" and "C<$>" from matching the start or end of the string to matching the start or end of any line). =item C<${>IC<:y/>ICIC C<$>I after replacing all characters found in the I character class by the corresponding character in the I character class. =item C<${>IC<:p/>ICIC{C,C,C}C<}> C<$>I after padding to I with I. Original contents of I is either left justified (flag "C"), centered (flag "C"), or right justified (flag "C"). =item C<${>IC<:%>I[C<(>IC<)>]C<}> C<$>I after passing it to an application-supplied function I. The optional argument I is passed to the function, too. By default no such functions are defined. =item C<[>IC<]>, C<[>IC<]>C<{>IC<,>IC<,>IC<}> Repeat expansion of I as long as at least one array variable does not expand to the empty string (first variant) or exactly (I-I)/I times (second variant). In both cases the character "C<#>" is expanded in I as the current loop index (C<0>,... for first variant and I,...,I with stepping I for second variant). The "C<#>" is usually used in the I of array variable lookups. For I, I and I, full arithmetic expressions are allowed. This loop construct can be nested, too. In this case an inner loop is fully repeated for each iteration of the outer loop. Additionally, arithmetic expressions are supported in both I, I, I and I parts of variable constructs in I. =back =head1 SYNTAX CONSTRUCTS (GRAMMAR) All the variable syntax constructs supported by B follow the same grammatical form. For completeness and reference reasons, the corresponding grammar is given in an extended BNF: input ::= ( TEXT | variable | INDEX_OPEN input INDEX_CLOSE (loop_limits)? )* variable ::= DELIM_INIT (name|expression) name ::= (NAME_CHARS)+ expression ::= DELIM_OPEN (name|variable)+ (INDEX_OPEN num_exp INDEX_CLOSE)? (':' command)* DELIM_CLOSE command ::= '-' (TEXT_EXP|variable)+ | '+' (TEXT_EXP|variable)+ | 'o' NUMBER ('-'|',') (NUMBER)? | '#' | '*' (TEXT_EXP|variable)+ | 's' '/' (TEXT_PATTERN)+ '/' (variable|TEXT_SUBST)* '/' ('m'|'g'|'i'|'t')* | 'y' '/' (variable|TEXT_SUBST)+ '/' (variable|TEXT_SUBST)* '/' | 'p' '/' NUMBER '/' (variable|TEXT_SUBST)* '/' ('r'|'l'|'c') | '%' (name|variable)+ ('(' (TEXT_ARGS)? ')')? | 'l' | 'u' num_exp ::= operand | operand ('+'|'-'|'*'|'/'|'%') num_exp operand ::= ('+'|'-')? NUMBER | INDEX_MARK | '(' num_exp ')' | variable loop_limits ::= DELIM_OPEN (num_exp)? ',' (num_exp)? (',' (num_exp)?)? DELIM_CLOSE NUMBER ::= ('0'|...|'9')+ TEXT_PATTERN::= (^('/'))+ TEXT_SUBST ::= (^(DELIM_INIT|'/'))+ TEXT_ARGS ::= (^(DELIM_INIT|')'))+ TEXT_EXP ::= (^(DELIM_INIT|DELIM_CLOSE|':'))+ TEXT ::= (^(DELIM_INIT|INDEX_OPEN|INDEX_CLOSE))+ DELIM_INIT ::= '$' DELIM_OPEN ::= '{' DELIM_CLOSE ::= '}' INDEX_OPEN ::= '[' INDEX_CLOSE ::= ']' INDEX_MARK ::= '#' NAME_CHARS ::= 'a'|...|'z'|'A'|...|'Z'|'0'|...|'9' Notice that the grammar definitions of DELIM_INIT, DELIM_OPEN, DELIM_CLOSE, INDEX_OPEN, INDEX_CLOSE, INDEX_MARK and NAME_CHARS correspond to the default syntax configuration only. They can be changed through the API (see B). =head1 APPLICATION PROGRAMMING INTERFACE (API) The following is a detailed description of the B B language Application Programming Interface (API): =head2 TYPES The B API consists of the following B data types: =over 4 =item B This is an exported enumerated integer type describing the return code of all API functions. On success, every API function returns C. On error, it returns C. For a list of all possible return codes see F. Their corresponding describing text can be determined with function B. =item B This is an opaque data type representing a variable expansion context. Only pointers to this abstract data type are used in the API. =item B This is an exported enumerated integer type describing configuration parameters for function B. Currently C for configuring the syntax via B, C for configuring the callback for value lookups via B, and C for configuring the callback for custom value operation functions via B are defined. =item B This is an exported structural data type describing the variable construct syntax. It is passed to B on C and consists of the following members (directly corresponding to the upper-case non-terminals in the grammar above): char escape; /* default: '\\' */ char delim_init; /* default: '$' */ char delim_open; /* default: '{' */ char delim_close; /* default: '}' */ char index_open; /* default: '[' */ char index_close; /* default: ']' */ char index_mark; /* default: '#' */ char *name_chars; /* default: "a-zA-Z0-9_" */ All members are single character constants, except for I which is a character class listing all valid characters. As an abbreviation the construct "IC<->I" is supported which means all characters from I to I (both included) in the underlying character set. =item B This is an exported function pointer type for variable value lookup functions. Such a callback function B has to be of the following prototype: var_rc_t *B(var_t *I, void *I, const char *I, size_t I, int I, const char **I, size_t *I, size_t *I); This function will be called by B internally whenever it has to resolve the contents of a variable. Its parameters are: =over 4 =item var_t *I This is the passed-through argument as passed to B as the first argument. This can be used in the callback function to distinguish the expansion context or to resolve return codes, etc. =item void *I This is the passed-through argument as passed to B on C as the forth argument. This can be used to provide an internal context to the callback function through B. =item const char *I This is a pointer to the name of the variable whose contents B wishes to resolve. Please note that the string is NOT necessarily terminated by a C ('C<\0>') character. If the callback function needs it C-terminated, it has to copy the string into an a temporary buffer of its own and C-terminate it there. =item size_t I This is the length of the variable name at I. =item int I This determines which entry of an array variable to lookup. If the variable specification that led to the execution of the lookup function did not contain an index, zero (C<0>) is provided by default as I. If I is less than zero, the callback should return the number of entries in the array variable. If I is greater or equal zero, it should return the specified particular entry. It is up to the callback to decide what to return for an index not equal to zero if the underlying variable is a scalar. =item const char **I This is a pointer to the location where the callback function should store the pointer to the resolved value of the variable. =item size_t *I This is a pointer to the location where the callback function should store the length of the resolved value of the variable. =item size_t *I This is a pointer to the location where the callback function should store the size of the buffer that has been allocated to hold the value of the resolved variable. If no buffer has been allocated by the callback at all, because the variable uses some other means of storing the contents -- as in the case of getenv(3), where the system provides the buffer for the string --, this should be set to zero (C<0>). In case a buffer size greater than zero is returned by the callback, B will make use of that buffer internally if possible. It will also free(3) the buffer when it is not needed anymore, so it is important that it was previously allocated with malloc(3) by the callback. =back The return code of the lookup function B is interpreted by B according to the following convention: C means success, that is, the contents of the variable has been resolved successfully and the I, I, and I variables have been filled with appropriate values. A return code C means that the resolving failed, such as a system error or lack of resources. In the latter two cases, the contents of I, I and I is assumed to be undefined. Hence, B will not free(3) any possibly allocated buffers, the callback must take care of this itself. If a callback returns the special C return code, the behavior of B depends on the setting of its I parameter. If I has been set, B will pass-through this error to the caller. If I has not been set, B will copy the expression that caused the lookup to fail verbatim into the output buffer so that an additional expanding pass may expand it later. If the callback returns an C, B will fail with this return code. If the cause for the error can not be denoted by an error code defined in F, callback implementors should use the error code C (which is currently defined to -64). It is guaranteed that no error code smaller than C is ever used by any B API function, so if the callback implementor wishes to distinguish between different reasons for failure, he subtract own callback return codes from this value, i.e., return (C - I) (I E= 0) from the callback function. =item B This is an exported function pointer type for variable value operation functions. Such a callback function B has to be of the following prototype: var_rc_t *B(var_t *I, void *I, const char *I, size_t I, const char *I, size_t I, const char *I, size_t I, const char **I, size_t *I, size_t *I); This function will be called by B internally whenever a custom operation is used. Its parameters are: =over 4 =item var_t *I This is the passed-through argument as passed to B as the first argument. This can be used in the callback function to distinguish the expansion context or to resolve return codes, etc. =item void *I This is the passed-through argument as passed to B on C as the forth argument. This can be used to provide an internal context to the callback function through B. =item const char *I This is a pointer to the name of the operation which B wishes to perform. Please note that the string is NOT necessarily terminated by a C ('C<\0>') character. If the callback function needs it C-terminated, it has to copy the string into an a temporary buffer of its own and C-terminate it there. =item size_t I This is the length of the variable name at I. =item const char *I This is a pointer to the optional argument string to the operation. If no argument string or an empty argument string was supplied this is C. =item size_t I This is the length of the I. =item const char *I This is a pointer to the value of the variable which the operation wants to adjust. =item size_t I This is the length of the I. =item const char **I This is a pointer to the location where the callback function should store the pointer to the adjusted value. =item size_t *I This is a pointer to the location where the callback function should store the length of the adjusted value of the variable. =item size_t *I This is a pointer to the location where the callback function should store the size of the buffer that has been allocated to hold the adjusted value of the variable. If no buffer has been allocated by the callback at all, because the variable uses some other means of storing the contents, this should be set to zero (C<0>). In case a buffer size greater than zero is returned by the callback, B will make use of that buffer internally if possible. It will also free(3) the buffer when it is not needed anymore, so it is important that it was previously allocated with malloc(3) by the callback. =back =back =head2 FUNCTIONS The B API consists of the following B functions: =over 4 =item var_rc_t B(var_t **I); Create a new variable expansion context and store it into I. =item var_rc_t B(var_t *I); Destroy the variable expansion context I. =item var_rc_t B(var_t *I, var_config_t I, ...); Configure the variable expansion context I. The variable argument list depends on the I identifier: =over 4 =item C, var_syntax_t *I This overrides the syntax configuration in I with the one provided in I. The complete structure contents is copied, so the caller is allowed to immediately destroy I after the B call. The default is the contents as shown above under the type description of B. =item C, var_cb_value_t I, void *I This overrides the value expansion in I. The default is C for I and I. At least C for I is not valid for proper operation of B, so the caller has to configure the callback before variable expansions can be successfully performed. =item C, var_cb_operation_t I, void *I This provides a custom value operation function for I. The default is C for I and I which means no custom operation is available. =back =item var_rc_t B(var_t *I, const char *I, size_t I, char *I, size_t I, int I); This expands escape sequences found in the input buffer I/I. The I/I point to a output buffer, into which the expanded data is copied if processing is successful. The size of this buffer must be at least I+1 characters. The reason is that B always adds a terminating C ('C<\0>') character at the end of the output buffer, so that you can use the result comfortably with other C library routines. The supplied I either has to point to a pre-allocated buffer or is allowed to point to I (because the unescaping operation is guaranteed to either keep the size or reduce the size of the input). The parameter I is a boolean flag that modifies the behavior of B. If is set to true (any value except zero), B will expand B escape sequences it sees, even those that it does not know about. This means that "C<\1>" will become "C<1>", even though "C<\1>" has no special meaning to B. If I is set to false (the value zero), such escape sequences will be copied verbatim to the output buffer. The quoted pairs supported by B are "C<\t>" (tabulator), "C<\r>" (carriage return), "C<\n>" (line feed), "C<\NNN>" (octal value), "C<\xNN>" (hexadecimal value), and "C<\x{NNMM..}>" (grouped hexadecimal values). =item var_rc_t B(var_t *I, const char *I, size_t I, char **I, size_t *I, int I); This is the heart of B. It expands all syntax constructs in I/I and stores them in an allocated buffer returned in I/I. The output buffer I/I is allocated by B using the system call malloc(3), thus it is the caller's responsibility to free(3) that buffer once it is no longer used anymore. The output buffer for convenience reasons is always C-terminated by B, but this C character is not counted for I. The I pointer can be specified as C if you are not interested in the output buffer length. The I flag determines how B deals with undefined variables (indicated by the callback function through the return code C). If it is set to true (any value except zero), B will fail with error code C whenever an undefined variable is encountered. That is, it just passes-through the return code of the callback function. If set to false (value zero), B will copy the expression it failed to expand verbatim 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 multi-pass expansion, you should set I to true in order to make sure no unexpanded variable constructs are left over in the buffer. If B fails with an error, I will point to I and I will contain the number of characters that have been consumed from I before the error occurred. In other words, if an error occurs, I/I point to the last parsing location in I/I before the error occurred. The only exceptions for this error semantics are: on C and C errors, I and I are undefined. =item var_rc_t B(var_t *I, char **I, int I, const char *I, va_list I); This is a high-level function on top of B which expands simple printf(3)-style constructs before expanding the complex variable constructs. So, this is something of a combination between sprintf(3) and B. It expands simple "C<%s>" (string, type "C"), "C<%d>" (integer number, type "C") and "C<%c>" (character, type "C") constructs in I. The values are taken from the variable argument vector I. After this expansion the result is passed through B by passing through the I, I and I arguments. The final result is a malloc(3)'ed buffer provided in I which the caller has to free(3) later. =item var_rc_t B(var_t *I, char **I, int I, const char *I, ...); This is just a wrapper around B which translates the variable argument list into C. =item var_rc_t B(var_t *I, var_rc_t I, char **I); This can be used to map any B return codes (as returned by all the B API functions) into a clear-text message describing the reason for failure in prose. Please note that errors coming from the callback, such as C and those based on it, cannot be mapped and will yield the message "C". =back =head2 VARIABLES The B API consists of the following B exported variables: =over 4 =item B This is just a pointer to the constant string "C". It is used as the first argument in B calls if B is built with B support. It then allows the application to determine whether a caught exception was thrown by B. See B below for more details. =back =head1 COMBINING UNESCAPING AND EXPANSION For maximum power and flexibility, you usually want to combine B and B. That is, you will want to use B to turn all escape sequences into their real representation before you call B for expanding variable constructs. This way the user can safely use specials like "C<\n>" or "C<\t>" throughout the template and achieve the desired effect. These escape sequences are particularly useful if search-and-replace or transpose actions are performed on variables before they are expanded. Be sure, though, to make the first B pass with the I flag set to false, or the routine will also expand escape sequences like "C<\1>", which might have a special meaning (regular expression back-references) in the B pass to follow. Once all known escape sequences are expanded, expand the variables with B. After that, you will want to have a second pass with B and the flag I set to true, to make sure all remaining escape sequences are expanded. Also, the B pass might have introduced now quoted pairs into the output text, which you need to expand to get the desired effect. =head1 EXCEPTION HANDLING B can be optionally built with support for exception handling via B (see http://www.ossp.org/pkg/lib/ex/). For this it has to be configured with the GNU Autoconf option C<--with-ex>. The difference then is that the B API functions throw exceptions instead of returning C return codes. The thrown exceptions can be identified as B exceptions by checking the exception attribute B. It is the B API symbol B for all B exceptions. The B attribute is always C. The B attribute is the B which forced the throwing of the exception. Exception throwing can be suppressed with B only. =head1 EXAMPLE (DEVELOPER) The following simple but complete program illustrates the full usage of B. It accepts a single argument on the command line and expands this in three steps (unescaping known escape sequences, expanding variable constructs, unescaping new and unknown escape sequences). The value lookup callback uses the process environment to resolve variables. #include #include #include #include "var.h" static var_rc_t lookup( var_t *var, void *ctx, const char *var_ptr, size_t var_len, int var_idx, const char **val_ptr, size_t *val_len, size_t *val_size) { char tmp[256]; if (var_idx != 0) return VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED; if (var_len > sizeof(tmp) - 1) return VAR_ERR_OUT_OF_MEMORY; memcpy(tmp, var_ptr, var_len); tmp[var_len] = '\0'; if ((*val_ptr = getenv(tmp)) == NULL) return VAR_ERR_UNDEFINED_VARIABLE; *val_len = strlen(*val_ptr); *val_size = 0; return VAR_OK; } static void die(const char *context, var_t *var, var_rc_t rc) { char *error; var_strerror(var, rc, &error); fprintf(stderr, "ERROR: %s: %s (%d)\n", context, error, rc); exit(1); } int main(int argc, char *argv[]) { var_t *var; var_rc_t rc; char *src_ptr; char *dst_ptr; size_t src_len; size_t dst_len; var_syntax_t syntax = { '\\', '$', '{', '}', '[', ']', '#', "a-zA-Z0-9_" }; /* command line handling */ if (argc != 2) die("command line", NULL, VAR_ERR_INVALID_ARGUMENT); src_ptr = argv[1]; src_len = strlen(src_ptr); fprintf(stdout, "input: \"%s\"\n", src_ptr); /* establish variable expansion context */ if ((rc = var_create(&var)) != VAR_OK) die("create context", NULL, rc); if ((rc = var_config(var, VAR_CONFIG_SYNTAX, &syntax)) != VAR_OK) die("configure syntax", var, rc); if ((rc = var_config(var, VAR_CONFIG_CB_VALUE, lookup, NULL)) != VAR_OK) die("configure callback", var, rc); /* unescape known escape sequences (in place) */ if ((rc = var_unescape(var, src_ptr, src_len, src_ptr, src_len+1, 0)) != VAR_OK) die("unescape known escape sequences", var, rc); src_len = strlen(src_ptr); fprintf(stdout, "unescaped: \"%s\"\n", src_ptr); /* expand variable constructs (force expansion) */ if ((rc = var_expand(var, src_ptr, src_len, &dst_ptr, &dst_len, 1)) != VAR_OK) { if (rc != VAR_ERR_INVALID_ARGUMENT && rc != VAR_ERR_OUT_OF_MEMORY) { fprintf(stdout, "parsing: \"%s\"\n", dst_ptr); fprintf(stdout, " %*s\n", dst_len, "^"); } die("variable expansion", var, rc); } fprintf(stdout, "expanded: \"%s\"\n", dst_ptr); /* unescape new and unknown escape sequences (in place) */ if ((rc = var_unescape(var, dst_ptr, dst_len, dst_ptr, dst_len+1, 1)) != VAR_OK) die("unescape new and unknown escape sequences", var, rc); fprintf(stdout, "output: \"%s\"\n", dst_ptr); free(dst_ptr); /* destroy variable expansion context */ if ((rc = var_destroy(var)) != VAR_OK) die("destroy context", var, rc); return 0; } Copy & paste the source code into a file F (or use the version already shipped with the B source distribution), compile it with $ cc `var-config --cflags` \ -o var_play var_play.c \ `var-config --ldflags --libs` and use it to play with the various B variable expansion possibilities. =head1 EXAMPLE (USER) The following are a few sample use cases of B variable expansions. They all assume the default syntax configuration and the following variable definitions: C<$foo=foo> (a scalar), C<$bar=Ebar1,bar2,bar3,E> (an array), C<$baz=Ebaz1,baz2,baz3,E> (another array), C<$quux=quux> (another scalar), C<$name=Efoo,bar,baz,quuxE> (another scalar) and C<$empty=""> (another scalar). Input Output ----------------------------- -------------- $foo foo ${foo} foo ${bar[0]} bar1 ${${name[1]}[0]} bar1 ${foo:u:y/O/U/:s/(.*)/<\1>/} ${foo:u:y/O/U/:s/(.*)/<\1>/} ${empty:-foo} foo ${foo:+yes}${foo:*no} yes ${empty:+yes}${empty:*no} no ${foo:p/6/./l} foo... ${foo:p/6/./r} ...foo [${bar[#]}${bar[#+1]:+,}] bar1,bar2,bar3 [${bar[#-1]:+,}${bar[#]}] bar1,bar2,bar3 [${bar[#]}]{2,1,3} bar2bar3 [${bar[#]}]{1,2,3} bar1bar3 [${foo[#]}[${bar[#]}]]{1,,2} foo1bar1bar2bar3foo2bar1bar2bar3 =head1 SEE ALSO pcre(3), regex(7), B (Value Access), B (Exception Handling). =head1 HISTORY B was initially written by Peter Simons Esimons@@crypt.toE in November 2001 under contract with the B sponsor B. Its API and internal code structure was revamped in February 2002 by Ralf S. Engelschall Erse@@engelschall.comE to fully conform to the B library standards. Before its initial public release, Ralf S. Engelschall in March 2002 finally added support for custom operations, the formatting functionality, optional multi-line matching, etc. =cut @ 1.38 log @more fixes @ text @d3 3 a5 3 ## Copyright (c) 2001-2004 Ralf S. Engelschall ## Copyright (c) 2001-2004 The OSSP Project (http://www.ossp.org/) ## Copyright (c) 2001-2004 Cable & Wireless (http://www.cw.com/) @ 1.37 log @Cleanup and extend the Unix manual page var(3) @ text @d79 6 a84 6 The supported post-operations are length determination, case conversion, defaults, positive and negative alternatives, sub-strings, regular expression based substitutions, character translations, and padding. Additionally, a meta-construct plus arithmetic expressions for index and range calculations allow (even nested) iterations over array variable expansions (..C<[>..C<${>IC<[#+1]}>..C<]>..). @ 1.36 log @adjust copyrights @ text @d110 1 a110 1 Tabulator, Carriage Return and Newline character. d136 1 a136 1 else I (default value). d141 1 a141 1 (positive alternative). d146 1 a146 1 (negative alternative). d162 1 a162 1 performed and only the first occurance of I is replaced. Flag d165 1 a165 1 occurances; flag "C" switches to multi-line matching (That is, change d192 1 a192 1 character "C<#>" is expanded in C as the current loop index d194 7 a200 6 I for second variant). I of array variable lookups. For I, I and I, full arithmetic expressions are allowed. This loop construct can be nested, too. In this case an inner loop is fully repeated for each iteration of the outer loop. Additionally, arithmetic expressions are supported in both I, I, I and I parts of variable constructs in I. d291 2 a292 2 code of all API functions. On success, every API functions returns C. On error, they return C. For a list of all d294 1 a294 1 can be determined with B. d304 5 a308 4 parameters for B. Currently C (for configuring the syntax via B) and C (for configuring the callback for value lookups via B) are defined. d562 10 a571 5 This overrides the syntax configuration in I with the one provided The default is C for I and I. At least C for I is not valid for proper operation of B, so the caller has to configure the callback before variable expansions can be successfully performed. d584 1 a584 1 supplied I either has to be point to a pre-allocated buffer or d586 1 a586 1 guarrantied to either keep the size or reduce the size of the input). d669 2 d675 6 d698 1 a698 1 Once, all known escape sequences are expanded, expand the variables d714 4 a717 4 checking the exception attribute C. It is the B API symbol C for all B exceptions. The C attribute is always C. The C attribute is the C which forced the throwing of the exception. d719 1 a719 1 Exception throwing can be suppressed with C only. d819 7 a825 5 Copy & paste the source code it into F (or use the version already shipped with the B source distribution), compile it with $ cc `var-config --cflags` -o var_play var_play.c `var-config --ldflags --libs` d861 1 a861 1 pcre(3), regex(7), B (Value Access). @ 1.35 log @final polishing for release 1.0.0 @ text @d3 3 a5 3 ## Copyright (c) 2001-2003 Ralf S. Engelschall ## Copyright (c) 2001-2003 The OSSP Project (http://www.ossp.org/) ## Copyright (c) 2001-2003 Cable & Wireless Deutschland (http://www.cw.com/de/) d7 1 a7 1 ## This file is part of OSSP VAR, an extensible data serialization d850 1 a850 1 B sponsor B. Its API and internal @ 1.34 log @backout now solved issue @ text @d3 3 a5 3 ## Copyright (c) 2001-2002 Ralf S. Engelschall ## Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/) ## Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.33 log @lib_var experts, please review @ text @a384 1 Returning an empty value requires this pointer to be non-NULL otherwise it is interpreted as not expandable. a408 5 *cppOut = NULL; returning NULL with size/out=0 means not expandable and keeps the current value *cppOut = (char *)mallocex(0); returning any freeable pointer with size/out=0 means empty value *pnOutsize = 0; *pnOut = 0; @ 1.32 log @polishing and copyright extension (add natural person) @ text @d385 1 d410 5 @ 1.31 log @more polishing @ text @d3 1 @ 1.30 log @Yeah, reduce the TODO list to zero items\! @ text @d79 1 a79 1 conversion, defaults, postive and negative alternatives, sub-strings, d292 1 a292 1 can be determined with var_strerror(). d302 1 a302 1 parameters for var_config(). Currently C (for d310 1 a310 1 construct syntax. It is passed to var_config() on C d339 1 a339 1 This function will be called by var_expand() internally whenever it has d346 1 a346 1 This is the passed-through argument as passed to var_expand() as the d352 1 a352 1 This is the passed-through argument as passed to var_config() on d355 1 a355 1 var_expand(). d359 2 a360 2 This is a pointer to the name of the variable which's contents var_expand() wishes to resolve. Please note that the string is NOT d402 1 a402 1 var_expand() will make use of that buffer internally if possible. It d410 1 a410 1 var_expand() according to the following convention: C means d417 1 a417 1 var_expand() will not free(3) any possibly allocated buffers, the d421 2 a422 2 code, the behaviour of var_expand() depends on the setting of its I parameter. If I has been set, var_expand() d424 2 a425 2 not been set, var_expand() will copy the expression that caused the lookup to fail verbatimly into the output buffer so that an additional d428 1 a428 1 If the callback returns an C, var_expand() will fail with d449 1 a449 1 This function will be called by var_expand() internally whenever a d456 1 a456 1 This is the passed-through argument as passed to var_expand() as the d462 1 a462 1 This is the passed-through argument as passed to var_config() on d465 1 a465 1 var_expand(). d469 1 a469 1 This is a pointer to the name of the operation which var_expand() wishes d519 1 a519 1 var_expand() will make use of that buffer internally if possible. It d553 1 a553 1 is allowed to immediately destroy I after the var_config() call. d561 1 a561 1 is not valid for proper operation of var_expand(), so the caller has to d573 1 a573 1 characters. The reason is that var_unescape() always adds a terminating d581 2 a582 2 of var_unescape(). If is set to true (any value except zero), var_unescape() will expand B escape sequences it sees, even those that d584 1 a584 1 even though "C<\1>" has no special meaning to var_unescape(). If I d586 1 a586 1 verbatimly to the output buffer. d588 1 a588 1 The quoted pairs supported by var_unescape() are "C<\t>" (tabulator), d599 1 a599 1 The output buffer I/I is allocated by var_expand() d602 2 a603 2 buffer for convinience reasons is always C-terminated by var_expand(), but this C character is not counted for I. d607 1 a607 1 The I flag determines how var_expand() deals with d610 1 a610 1 (any value except zero), var_expand() will fail with error code d613 2 a614 2 callback function. If set to false (value zero), var_expand() will copy the expression it failed to expand verbatimly into the output buffer, d616 1 a616 1 Generally, if you do not plan to use muli-pass expansion, you should set d620 1 a620 1 If var_expand() fails with an error, I will point to I d622 1 a622 1 consumed from I before the error occured. In other words, d624 1 a624 1 location in I/I before the error occured. The only d670 3 a672 3 var_unescape() and var_expand(). That is, you will want to use var_unescape() to turn all escape sequences into their real representation before you call var_expand() for expanding variable d677 1 a677 1 Be sure, though, to make the first var_unescape() pass with the I d680 1 a680 1 back-references) in the var_expand() pass to follow. d683 3 a685 3 with var_expand(). After that, you will want to have a second pass with var_unescape() and the flag I set to true, to make sure all remaining escape sequences are expanded. Also, the var_expand() pass d847 8 a854 4 B was written by Peter Simons Esimons@@crypt.toE in November 2001. Its API and internal code structure was revamped in February 2002 by Ralf S. Engelschall Erse@@engelschall.comE to fully conform to the B library standards. @ 1.29 log @New API functions var_format and var_formatv which provide a convinience interface to printf-style expansion and variable expansion. var_format is like a combination of snprintf(3) and var_expand(). Example: Assume the variable value context gives "bar" for ${ARRAY[7]}, then the call.. var_format(var, &tmp, 1, "foo${ARRAY[%d]}quux", 7);o ..results in tmp containing the malloc(3)'ed string "foobarquux". Thanks to Thomas L. for providing the hint to this functionality. @ text @d689 16 @ 1.28 log @Major bugfixing and enhancing of search & replace operation: - finally fix ${name:s/$/foo/} type substitutions (zero-length matching!) - add s/.../.../mg matching support (Perl-style multiline) - make non-multiline matching the default @ text @d56 2 d628 20 @ 1.27 log @Change semantics of ${name:-word} from "If $name is not empty string, then $name, else word" to: "If $name is not empty string and not undefined, then $name, else word". This provides a more intuitive usage of ${name:-word} because it allows the user to turn an undefined variable (as returned with VAR_ERR_UNDEFINED_VARIABLE by the callback) into a defined one. This is important because changing the callback to return undefined variables as empty variables is incorrect because it usually breaks the array loop construct. @ text @d162 3 a164 1 occurances. d228 1 a228 1 '/' ('g'|'i'|'t')* @ 1.26 log @Fix regex problem by no longer allowing variables in the pattern part of s/pattern/subst/. Because it is far more common that one needs '$' there instead of a variable. @ text @d132 2 a133 2 If C<$>I is not empty string, then C<$>I, else I (default value). @ 1.25 log @Add new important feature: user-supplied post-operation functions. This allows one to configure a var_cb_operation_t callback in the var_t context and allow it to implement functions triggered by ${name:%func[(arg)]}. This is especially intended for application-specific encoding and post-adjustment functions. @ text @d224 1 a224 1 | 's' '/' (variable|TEXT_SUBST)+ d252 1 @ 1.24 log @finish the API change Thomas started @ text @d46 2 a47 1 B. d176 5 d233 2 d252 2 a253 1 TEXT_SUBST ::= ^(DELIM_INIT|'/') d432 88 @ 1.23 log @more docs, less TODO @ text @d321 3 a323 3 var_rc_t *B(void *I, const char *I, size_t I, int I, const char **I, size_t *I, size_t *I); d330 6 d583 1 a583 1 void *ctx, @ 1.22 log @URL fixing and additional documents @ text @d185 4 d561 1 a561 1 =head1 EXAMPLE d667 29 @ 1.21 log @HEADS UPS: Mega-commit, revamping the whole library! - completely new API - completely new manual page @ text @d7 1 a7 1 ## library which can be found at http://www.ossp.org/pkg/var/. @ 1.20 log @style and text cleanups @ text @d38 1 a38 1 var_rc_t var_unescape(const char *src, size_t len, char *dst, int unescape_all); d40 1 a40 1 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); d42 5 a46 1 const char *var_strerror(var_rc_t rc); d48 1 a48 1 =head1 DESCRIPTION d50 6 a55 102 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); d57 1 a57 2 Don't be scared, the usage is way simpler than it looks at first glance. The parameters of var_expand() are: d59 1 a59 1 =over 4 d61 1 a61 1 =item const char *input d63 1 a63 95 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. The result buffer will be terminated by null byte, which is not included in the "result_len" counter. If var_expand() fails with an error, "result" will point to "input". The only exceptions are the VAR_ERR_INVALID_ARGUMENT VAR_ERR_OUT_OF_MEMORY errors, in which case "result" is undefined. =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 and VAR_ERR_OUT_OF_MEMORY --, "result_len" will contain the number of characters that have been consumed from "input" before the error occured. This argument can be NULL if the application is not interested in this information. =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 startindex; char endindex; char current_index; 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 */ '[', /* startindex */ ']', /* endindex */ '#', /* current_index */ '\\', /* 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. d65 2 a66 1 =back d68 22 a89 69 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 THE VAR_STRERROR FUNCTION In order to make life for application developers easier, the helper function var_strerror() has been provided, which can be used to map any of the error codes returned by the OSSP var library into a clear-text message describing the reason for failure. Please note that errors coming from the callback, such as VAR_ERR_CALLBACK and those based on it, cannot be mapped and will yield the message "unknown error". =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 The function var_expand() does not know how to look the contents of a variable up itself. Instead, it relies on a caller-supplied callback function, which adheres to the var_cb_t function interface: var_rc_t lookup(void *context, const char *varname, size_t name_len, int index, const char **data, size_t *data_len, size_t *buffer_size); This function will be called by var_expand() whenever it has to retrieve the contents of, say, the variable $name, using the following parameters: d93 1 a93 1 =item void *context d95 2 a96 4 The contents of context is passed through from the var_expand()'s "lookup_context" parameter to the callback. This parameter can be used by the programmer to provide internal data to the callback function through var_expand(). d98 1 a98 1 =item const char *varname d100 3 a102 20 This is a pointer to the name of the variable which's contents var_expand() wishes to retrieve. In our example of looking up $name, varname would point to the string "name". Please note that the string is NOT necessarily terminated by a '\0' character! If the callback function needs to pass the string to the standard C library string manipulation functions during the lookup, it will have to copy the string into a buffer of its own to ensure it is null-terminated. =item size_t name_len The "name_len" parameter contains the length of the variable name "varname" points to. =item int index The contents of this interger determines which entry of a variable array to look-up. If the variable specification that led to the execution of the lookup function did not contain an index, zero is provided per default. If "index" is negative, the callback must return the number of entries of the variable array. d104 1 a104 1 =item const char **data d106 1 a106 4 This is a pointer to the location where the callback function should store the pointer to the contents of the variable. =item size_t *data_len d108 1 a108 2 This is a pointer to the location where the callback function should store the length of the contents of the variable. d110 1 a110 13 =item size_t *buffer_size This is a pointer to the location where the callback function should store the size of the buffer that has been allocated to hold the contents of the looked-up variable. If no buffer has been allocated at all, because the variable uses some other means of storing the contents -- as in the case of getenv(3), where the system provides the buffer for the string --, this should be zero (0). In case a buffer size greater than zero is returned by the callback function, var_expand() will make use of that buffer internally if possible. If will also free(3) the buffer when it is not needed anymore. d112 1 a112 1 =back d114 1 a114 17 The return code of the lookup function is interpreted by var_expand() according to the following convention: VAR_OK means success, that is, the contents of the variable has been looked-up successfully and the "data", "data_len", and "buffer_size" locations have been filled with appropriate values. A return code VAR_ERR_XXX means that the lookup failed, such as a system error or lack of resources. In the latter two cases, the contents of "data", "data_len" and "buffer_size" is assumed to be undefined. Hence, var_expand() will not free(3) any possibly allocated buffers, the callback must take care of that itself. If a callback returns the special VAR_ERR_UNDEFINED_VARIABLE return code, the behaviour of var_expand() depends on the setting of the "force_expand" parameter. If force-expand mode has been set, var_expand() will fail with this error. If force-expand mode has not been set, var_expand() will copy the expression that caused the lookup to fail verbatimly into the output buffer so that an additional expanding pass may expand it later. d116 1 a116 40 If the callback returns an VAR_ERR_XXX, var_expand() will fail with the return code it got from the callback. If the cause for the error can not be denoted by an error code defined in var.h, callback implementors should use the error code VAR_ERR_CALLBACK, which is currently defined to -64. It is guaranteed that no error code smaller than VAR_ERR_CALLBACK is ever used by var_expand() or VAR_UNESCAPE(), so if the callback implementor wishes to distinguish between different reasons for failure, he can define his own set of errors typedef enum { LOOKUP_ERROR_ONE = -3, LOOKUP_ERROR_TWO = -2, LOOKUP_ERROR_THREE = -1, } lookup_error_t; and return, say, "(VAR_ERR_CALLBACK - LOOKUP_ERROR_TWO)". To illustrate the implementation of a proper callback, take a look at the following expamle that accesses the system environment via getenv(3) to lookup variables and to return them to var_expand(): var_rc_t env_lookup( void *context, const char *varname, size_t name_len, int idx, const char **data, size_t *data_len, size_t *buffer_size) { char tmp[256]; if (idx != 0) return VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED; if (name_len > sizeof(tmp) - 1) return VAR_ERR_CALLBACK; memcpy(tmp, varname, name_len); tmp[name_len] = '\0'; if ((*data = getenv(tmp)) == NULL) return VAR_ERR_UNDEFINED_VARIABLE; *data_len = strlen(*data); *buffer_size = 0; return VAR_OK; } d118 2 a119 1 =head1 SUPPORTED NAMED CHARACTERS d121 1 a121 1 The var_unescape() function knows the following constructs: d123 1 a123 1 =over 4 d125 1 a125 1 =item \t, \r, \n d127 1 a127 2 These expressions are replaced by the appropriate binary representation of a tab, a carrige return and a newline respectively. d129 1 a129 1 =item \abc d131 2 a132 6 This expression is replaced by the value of the octal number "abc". Valid digits of "a" are in the range of '0' to '3', for digits "b" and "c" in the range of '0' to '7'. Please note that an octal expression is recognized only if the backslash is followed by three digits! The expression "\1a7", for example, is interpreted as the quoted pair "\1" followed by the verbatim text "a7". d134 1 a134 1 =item \xAB d136 2 a137 3 This expression is replaced by the value of the hexadecimal number $AB. Both characters "A" and "B" must be in the range of '0' to '9', 'a' to 'f', or 'A' to 'F'. d139 1 a139 1 =item \x{...} d141 2 a142 4 This expression denotes a set of grouped hexadecimal numbers. The "..." part may consist of an arbitrary number of hexadecimal pairs, such as in "\x{}", "\x{ff}", or "\x{55ffab04}". The empty expression "\x{}" is a no-op; it will not produce any output. d144 1 a144 4 This construct may be useful to specify multi-byte characters (as in Unicode). Even though "\x{0102}" is effectively equivalent to "\x01\x02", the grouping of values may be useful in other contexts, even though var_unescape() or var_expand() make no direct use of it. d146 2 a147 1 =back d149 1 a149 1 =head1 SUPPORTED VARIABLE EXPRESSIONS d151 2 a152 22 Additionally to the ordinary variable expansion of $name or ${name}, var_expand() supports a number of operations that can be performed on the contents of "name" before it is copied to the output buffer. Such operations are always denoted by appending the a colon and a command character to the variable name, for expample: ${name:l} or ${name:s/foo/bar/}. You can specify multiple operations, which are executed from the left to the right, for expample: ${name:l:s/foo/bar/:u}. Also, you can nest variable expansion and command execution pretty much anywhere in the construct, for example: ${name:s/$foo/$bar/g}. In that context is probably useful to have a look at the formal expression grammar provided in section "EBNF GRAMMAR OF SUPPORTED EXPRESSIONS". Generally, all operations described below do not modify the contents of any variable -- var_expand() generally can't set variables, it will only read them. If the description says that an operation "replaces the contents of variable $foo", it is meant that rather than expanding the expression the the contents of $foo, it will expand to the modified string instead. The contents of $foo is left untouched in any case. d154 1 a154 1 =over 4 d156 6 a161 1 =item ${name:#} d163 1 a163 2 This operation will expand to the length of the contents of $name. If, for example, "$FOO" is "foobar", then "${FOO:#}" will result in "6". d165 3 a167 1 =item ${name:l} d169 1 a169 87 This operation will turn the contents of $name to all lower-case, using the system routine tolower(3), thereby possibly using the system's localization settings. =item ${name:u} This operation will turn the contents of $name to all upper-case, using the system routine toupper(3), thereby possibly using the system's localization settings. =item ${name:*} This operation will replace the contents of $name with the empty string ("") if $name is not empty. Otherwise, it will replace it by "word". =item ${name:-} This operation will replace the contents of $name with "word" if $name is empty. Otherwise, it will expand to the contents of $name. =item ${name:+} This operation will replace the contents of $name with "word" if $name is not empty. Otherwise, it will expand to the contents of $name. =item ${name:o-} This operation will cut the string starting at position "start" to ending position "end" out of the contents of $name and return that. Please note that the character at position "end" is included in the result; ${name:o3-4} for instance, will return a two-character string. Also, please note that start positions begin at zero (0)! If the "end" parameter is left out, as in ${name:o3-}, the operation will return the string starting at position 3 until the end. =item ${name:o,} This operation will cut the string starting at position "start" of length "length" out of the contents of $name and return that. ${name:o3,4} means, for instance, to return the next 4 characters starting at position 3 in the string. Please note that start positions begin at zero (0)! If "length" is left out, as in ${name:o3,}, the operation will return the string starting at position 3 until the end. =item ${name:s///[gti]} This operation will perform a search-and-replace operation on the contents of $name and return the result. The behavior of the search-and-replace is modified by the following flags parameter: If a 't' flag has been provided, a plain text search-and-replace is performed, otherwise, the default is to a regular expression search-and-replace as in the system utility sed(1). If the 'g' flag has been provided, the search-and-replace will replace all instances of "pattern" by "replace", otherwise, the default is to replace only the first instance. If the 'i' flag has been provided, the search-and-replace will take place case-insensitively, otherwise, the default is to distinguish character case. =item ${name:y///} This operation will translate all characters in the contents of $name that are found in the "ochars" class to the corresponding character in the "nchars" class, just like the system utility tr(1) does. Both "ochars" and "nchars" may contain character range specifications, for example "a-z0-9". A hyphon as the first or last character of the class specification is interpreted literally. Both the "ochars" and the "nchars" class must contain the same number of characters after all ranges are expanded, or var_expand() will abort with an error. If, for example, "$FOO" would contain "foobar", then "${FOO:y/a-z/A-Z/} would yield "FOOBAR". Another goodie is to use that operation to ROT13-encrypt or decrypt a string with the expression "${FOO:y/a-z/n-za-m/}". =item ${name:p///} This operation will pad the contents of $name with "string" according to the "align" parameter, so that the result is at least "width" characters long. Valid parameters for align are 'l' (left), 'r' (right), or 'c' (center). The "string" parameter may contain multiple characters, if you see any use for that. If, for example, "$FOO" is "foobar", then "${FOO:p/20/./c}" would yield ".......foobar......."; "${FOO:p/20/./l}" would yield "foobar.............."; and "${FOO:p/20/./r}" would yield "..............foobar"; d171 3 a173 1 =back a174 1 =head1 EBNF GRAMMAR OF SUPPORTED EXPRESSIONS d176 1 a176 1 input : ( TEXT | variable | START-INDEX input END-INDEX ( loop-limits )? )* d178 7 a184 1 loop-limits: START-DELIM (numexp)? ',' (numexp)? ( ',' (numexp)? )? END-DELIM d186 1 a186 1 variable : '$' (name|expression) d188 1 a188 1 expression : START-DELIM (name|variable)+ (START-INDEX num-exp END-INDEX)? (':' command)* END-DELIM d190 66 a255 1 name : (VARNAME)+ d257 1 a257 10 command : '-' (EXPTEXT|variable)+ | '+' (EXPTEXT|variable)+ | 'o' (NUMBER ('-'|',') (NUMBER)?) | '#' | '*' (EXPTEXT|variable)+ | 's' '/' (variable|SUBSTTEXT)+ '/' (variable|SUBSTTEXT)* '/' ('g'|'i'|'t')* | 'y' '/' (variable|SUBSTTEXT)+ '/' (variable|SUBSTTEXT)* '/' | 'p' '/' NUMBER '/' (variable|SUBSTTEXT)* '/' ('r'|'l'|'c') | 'l' | 'u' d259 2 a260 2 num-exp : operand | operand ('+'|'-'|'*'|'/'|'%') num-exp d262 1 a262 4 operand : ('+'|'-')? NUMBER | CURR-INDEX | '(' num-exp ')' | variable d264 1 a264 1 START-DELIM: '{' d266 1 a266 1 END-DELIM : '}' d268 1 a268 1 START-INDEX: '[' d270 50 a319 1 END-INDEX : ']' d321 2 a322 28 CURR-INDEX : '#' VARNAME : '[a-zA-Z0-9_]+' NUMBER : '[0-9]+' SUBSTTEXT : '[^$/]' EXPTEXT : '[^$}:]+' TEXT : '[^$[\]]+' Please note that the descriptions of START-DELIM, END-DELIM, VARNAME, SUBSTEXT, and EXPTEXT shown here assume that var_expand() has been called in the default configuration. In thruth, the contents of VARNAME corresponds directly to the setting of "namechars" in the var_config_t structure. Similarly, the dollar ('$') corresponds directly to the setting of "varinit", and the '{' and '}' characters to "startdelim" and "enddelim" respectively. =head1 CODES RETURNED BY THE LIBRARY Generally, all routines part of that library follow the convention that a return code of zero or greater denotes success and a return code of less than zero denotes failure. (This is slightly different for the callbacks, please see section "THE LOOKUP CALLBACK" for further details.) In order to distinguish the various causes of failure, the following set of defines is provided in var.h: d326 1 a326 1 =item VAR_OK d328 4 a331 1 No errors; everything went fine. d333 1 a333 1 =item VAR_ERR_INCOMPLETE_QUOTED_PAIR d335 20 a354 2 The configured escape character as the last character in the input buffer. d356 1 a356 1 =item VAR_ERR_INVALID_ARGUMENT d358 2 a359 2 Any of the provided arguments is invalid, for expample: the pointer to the input buffer is NULL. d361 1 a361 1 =item VAR_ERR_SUBMATCH_OUT_OF_RANGE d363 2 a364 4 During execution of a ${name:s/pattern/replace/flags} operation, a submatch has been referenced in the "replace" part, which's number is greater than the number of submatches encountered in the "pattern" part, for expample: ${name:s/foo(bar)/\2/}. d366 1 a366 1 =item VAR_ERR_UNKNOWN_QUOTED_PAIR_IN_REPLACE d368 3 a370 3 During execution of a ${name:s/pattern/replace/flags} operation, the parser encountered an unknown quoted pair in the "replace" part. Valid quoted pairs are "\\", "\0", "\1", ... , "\9" only. d372 10 a381 1 =item VAR_ERR_EMPTY_PADDING_FILL_STRING d383 1 a383 2 The "fill" part in an ${name:p/width/fill/pos/} expression was found to be empty. d385 18 a402 1 =item VAR_ERR_MISSING_PADDING_WIDTH d404 9 a412 2 The "width" part in an ${name:p/width/fill/pos/} expression was found to be empty. d414 1 a414 1 =item VAR_ERR_MALFORMATTED_PADDING d416 1 a416 2 Any of the "/" delimiters was missing while parsing a ${name:p/width/fill/pos/} expression. d418 1 a418 1 =item VAR_ERR_INCORRECT_TRANSPOSE_CLASS_SPEC d420 1 a420 4 While parsing a ${name:y/old-class/new-class/} expression, any of the character class specifications had a start-of-range character that was greater (in terms of ASCII encoding) than the end-of-range character, for expample: "[z-a]". d422 1 a422 1 =item VAR_ERR_EMPTY_TRANSPOSE_CLASS d424 1 a424 2 While parsing a ${name:y/old-class/new-class/} expression, any of the character class specifications was found to be empty. d426 1 a426 1 =item VAR_ERR_TRANSPOSE_CLASSES_MISMATCH d428 1 a428 3 While parsing a ${name:y/old-class/new-class/} expression, the number of characters found in the expanded "old-class" was different than the number of characters in new-class". d430 1 a430 1 =item VAR_ERR_MALFORMATTED_TRANSPOSE d432 2 a433 2 Any of the "/" delimiters was missing while parsing a ${name:y/old-class/new-class/} expression. d435 1 a435 1 =item VAR_ERR_OFFSET_LOGIC d437 1 a437 2 The "end" offset in a ${name:o,} expression is smaller than the "start" offset. d439 13 a451 1 =item VAR_ERR_OFFSET_OUT_OF_BOUNDS d453 1 a453 2 The "start" offset in a ${name:o,} expression is greater than the number of characters found in $name. d455 1 a455 1 =item VAR_ERR_RANGE_OUT_OF_BOUNDS d457 67 a523 3 The end-of-range in a ${name:o,} or ${name:o-} expression would be greater than the number of characters found in $name. d525 1 a525 1 =item VAR_ERR_INVALID_OFFSET_DELIMITER d527 1 a527 2 The two numbers in an offset operation are delimited by a character different from "," or "-". d529 1 a529 53 =item VAR_ERR_MISSING_START_OFFSET The "start" offset in a ${name:o,} or ${name:o-} expression was found to be empty. =item VAR_ERR_EMPTY_SEARCH_STRING The "pattern" part of a ${name:s/pattern/replace/flags} expression was found to be empty. =item VAR_ERR_MISSING_PARAMETER_IN_COMMAND In a ${name:+word}, ${name:-word}, or ${name:*word} expression, the "word" part was missing -- that means empty. =item VAR_ERR_INVALID_REGEX_IN_REPLACE While compiling the "pattern" part of a ${name:s/pattern/replace/flags} expression, regcomp(3) failed with an error. =item VAR_ERR_UNKNOWN_REPLACE_FLAG In a ${name:s/pattern/replace/flags} expression, a flag other that "t", "i", or "g" was found. =item VAR_ERR_MALFORMATTED_REPLACE Any of the "/" delimiters was missing while parsing a ${name:s/pattern/replace/flags} expression. =item VAR_ERR_UNKNOWN_COMMAND_CHAR In a ${name:} expression, "char" did not specify any of the supported operations. =item VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE At one point during parsing of the input buffer, an expression was found that was neither verbatim text nor a variable expression. This usually is the result of a inconsistent configuration of var_expand() via the var_config_t paramater. =item VAR_ERR_UNDEFINED_VARIABLE Looking up a variable's contents failed and var_expand() was running in "force expand" mode. =item VAR_ERR_INCOMPLETE_VARIABLE_SPEC The input buffer ended in the middle of a ${name} expression, or the configured variable initializer character was found to be the last character of the input buffer. d531 1 a531 53 =item VAR_ERR_OUT_OF_MEMORY var_expand() failed while malloc(3)ing internally needed buffers. =item VAR_ERR_INVALID_CONFIGURATION Any of the characters configured in the var_config_t structure as a special ("varinit", "startdelim", "enddelim", and "escape") was found to be a member of the "namechars" class. =item VAR_ERR_INCORRECT_CLASS_SPEC The character class specification "namechars" of the var_config_t structure provided to var_expand was syntactically incorrect, that is, the start-of-range was greater than end-of-range. (See also VAR_ERR_INCORRECT_TRANSPOSE_CLASS_SPEC.) =item VAR_ERR_INCOMPLETE_GROUPED_HEX var_unescape() encountered the end of the input buffer in the middle of a grouped-hex "\x{...}" expression. =item VAR_ERR_INCOMPLETE_OCTAL var_unescape() encountered the end of the input buffer in the middle of an octal "\000" expression. =item VAR_ERR_INVALID_OCTAL The second of third digit of an octal "\000" expression was found not be in the range of '0' to '7'. =item VAR_ERR_OCTAL_TOO_LARGE The value specified via an octal "\000" expression was larger than 0377. =item VAR_ERR_INVALID_HEX Any of the digits of a hex "\x00" expression was found not be in the range of '0' to '9' or 'a' to 'b'. =item VAR_ERR_INCOMPLETE_HEX var_unescape() encountered the end of the input buffer in the middle of a hex "\x00" expression. =item VAR_ERR_INCOMPLETE_NAMED_CHARACTER var_unescape() encountered the backslash ('\') as the last character of the input buffer. =item VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED d535 1 a535 1 =head1 SO ALSO d537 137 a673 1 regex(7) d676 1 @ 1.19 log @fix offset documentation @ text @d2 1 a2 1 ## VAR - OSSP variable expression library. d34 1 a34 1 var - OSSP variable expression library. @ 1.18 log @bump copyright year @ text @d541 1 a541 1 =item ${name:o,} d546 1 a546 1 result; ${name:o3,4} for instance, will return a two-character string. d548 2 a549 2 parameter is left out, as in ${name:o3,}, the operation will return the string starting at position 3 until the end. d551 1 a551 1 =item ${name:o-} d553 6 a558 6 This operation will cut the range of "start" to "end" out of the contents of $name and return that. ${name:o3-4} means, for instance, to return the next 4 charaters starting at position 3 in the string. Please note that start positions begin at zero (0)! If the "end" range is left out, as in ${name:o3-}, the operation will return the string starting at position 3 until the end. @ 1.17 log @allow result_len to be NULL @ text @d3 2 a4 2 ## Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ## Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.16 log @Finally adjust return code semantics of var_cb_t to use var_rc_t only. @ text @d183 2 a184 1 consumed from "input" before the error occured. @ 1.15 log @Implemented loops with explicit start, stop, and step values. @ text @d314 4 a317 4 int lookup(void *context, const char *varname, size_t name_len, int index, const char **data, size_t *data_len, size_t *buffer_size); d382 24 a405 32 accordin to the following convention: Any return code greater than zero means success, that is, the contents of the variable has been looked-up successfully and the "data", "data_len", and "buffer_size" locations have been filled with appropriate values. A return code of zero (0) means that the variable was undefined and its contents therefore could not be looked-up. A return code of less than zero means that the lookup failed for some other reason, such as a system error or lack of resources. In the latter two cases, the contents of "data", "data_len" and "buffer_size" is assumed to be undefined. Hence, var_expand() will not free(3) any possibly allocated buffers, the callback must take care of that itself. If a callback returns zero -- meaning the variable is undefined --, the behavior of var_expand() depends on the setting of the "force_expand" parameter. If force-expand mode has been set, var_expand() will fail with a VAR_ERR_UNDEFINED_VARIABLE error. If force-expand mode has not been set, var_expand() will copy the expression that caused the lookup to fail verbatimly into the output buffer so that an additional expanding pass may expand it later. If the callback returns an error -- meaning a return code less than zero --, var_expand() will fail with the return code it got from the callback. Callback implementors are encouraged to re-use the error codes defined in var.h whereever possible. An example of an error code a callback might want to reuse is VAR_ERR_OUT_OF_MEMORY. If the cause for the error can not be denoted by an error code defined in var.h, callback implementors should use the error code VAR_ERR_CALLBACK, which is currently defined to -64. It is guaranteed that no error code smaller than VAR_ERR_CALLBACK is ever used by var_expand() or VAR_UNESCAPE(), so if the callback implementor wishes to distinguish between different reasons for failure, he can define his own set of errors d419 3 a421 2 int env_lookup(void *context, const char *varname, size_t name_len, int index, d427 1 a427 1 if (index != 0) d429 1 a429 5 if (name_len > sizeof(tmp) - 1) { /* Callback can't expand variable names longer than sizeof(tmp) characters. */ a430 1 } d433 2 a434 3 *data = getenv(tmp); if (*data == NULL) return 0; d437 1 a437 1 return 1; @ 1.14 log @Guarantee that the buffer returned by var_expand() is terminated with a null byte. @ text @d619 3 a621 1 input : ( TEXT | variable | START-INDEX input END-INDEX )* @ 1.13 log @Implemented the looping construct. However, there are still some semantical issues that need to be clarified before the code is stable. @ text @d169 3 a171 1 responsibility to free(3) that buffer once it is not used anymore. d174 2 a175 2 The only exception is the VAR_ERR_INVALID_ARGUMENT error, in which case "result" is not modified. d181 3 a183 3 exception of VAR_ERR_INVALID_ARGUMENT --, "result_len" will contain the number of characters that have been consumed from "input" before the error occured. @ 1.12 log @fix comment @ text @d617 1 a617 1 input : (TEXT|variable)* d662 1 a662 1 TEXT : '[^$]+' @ 1.11 log @Added support for variables as operands in index specifications. @ text @d2 1 a2 1 ** VAR - OSSP variable expression library. @ 1.10 log @Updated the BNF grammar for the arithmetik parser. @ text @d642 1 @ 1.9 log @Extended the interface of var_cb_t to support variable arrays. To customize your already existing lookup functions quickly to the new interface, just add the "int index" parameter to the function's prototype and add the lines if (index != 0) return VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED; to the function itself. @ text @d621 1 a621 1 expression : START-DELIM (name|variable)+ (':' command)* END-DELIM d636 7 d646 6 @ 1.8 log @Changed semantics of the :o operation so that the specified end-offset is included in the result. Updated documentation and test cases appropriately. @ text @d204 3 d224 3 d313 1 a313 1 const char *varname, size_t name_len, d345 8 d426 1 a426 1 const char *varname, size_t name_len, d432 3 d860 2 @ 1.7 log @THLs review @ text @d534 1 a534 1 =item ${name:o-} d538 5 a542 7 Please note that the character at position "end" is not included in the result, "end - 1" is the last character position returned. ${name:o3,4}, for instance, will return the substring from position 3 to position 4 -- that is exactly one character. Also, please note that start positions begin at zero (0)! If the "end" parameter is left out, as in ${name:o3,}, the operation will return the string starting at position 3 until the end. d544 1 a544 4 //FIXME THL: I expect start-end *inclusive* //FIXME THL: I expect start,len len characters not len-1 =item ${name:o,} @ 1.6 log @THLs review @ text @d568 1 a568 1 the first instance. If the 't' flag has been provided, the @ 1.5 log @Added documentation for the var_strerror() call. @ text @a535 9 This operation will cut the range of "start" to "end" out of the contents of $name and return that. ${name:o3-4} means, for instance, to return the next 4 charaters starting at position 3 in the string. Please note that start positions begin at zero (0)! If the "end" range is left out, as in ${name:o3-}, the operation will return the string starting at position 3 until the end. =item ${name:o,} d545 12 @ 1.4 log @Added the missing part of the documentation. Everything is fully documented now. @ text @d42 2 d248 10 @ 1.3 log @Added all section of the man page, except for the PURPOSE section, which is till missing. @ text @d38 4 d44 243 a286 1 The purpose of VAR is ... @ 1.2 log @Added VAR_CALLBACK_ERROR to the list of return codes. @ text @d44 172 d218 23 d245 3 d250 4 d256 4 d262 4 d268 2 a269 1 =item ${name:?} d273 3 d278 7 d287 10 d299 12 d313 14 d329 11 d344 1 a344 1 input : (TEXT|variable)* d346 1 a346 1 variable : '$' (name|expression) d348 1 a348 1 expression : START-DELIM (name|variable)+ (':' command)* END-DELIM d350 1 a350 1 name : (VARNAME|SPECIAL1|SPECIAL2)+ d352 10 a361 10 command : '-' (EXPTEXT|variable)+ | '+' (EXPTEXT|variable)+ | 'o' (NUMBER ('-'|',') (NUMBER)?) | '#' | '*' (EXPTEXT|variable)+ | 's' '/' (variable|SUBSTTEXT)+ '/' (variable|SUBSTTEXT)* '/' ('g'|'i'|'t')* | 'y' '/' (variable|SUBSTTEXT)+ '/' (variable|SUBSTTEXT)* '/' | 'p' '/' NUMBER '/' (variable|SUBSTTEXT)* '/' ('r'|'l'|'c') | 'l' | 'u' d363 1 a363 1 START-DELIM: '{' d365 1 a365 1 END-DELIM : '}' d367 1 a367 1 VARNAME : '[a-zA-Z0-9_]+' d369 1 a369 1 SPECIAL1 : '[' d371 1 a371 1 SPECIAL2 : ']' d373 1 a373 1 NUMBER : '[0-9]+' d375 1 a375 1 SUBSTTEXT : '[^$/]' d377 7 a383 1 EXPTEXT : '[^$}:]+' d385 1 a385 1 TEXT : '[^$]+' d387 6 a392 1 =head1 CODES RETURNED BY THE LIBRARY d396 50 a445 1 =item VAR_CALLBACK_ERROR d447 2 a448 1 =item VAR_EMPTY_PADDING_FILL_STRING d450 1 a450 1 =item VAR_MISSING_PADDING_WIDTH d452 3 a454 1 =item VAR_MALFORMATTED_PADDING d456 1 a456 1 =item VAR_INCORRECT_TRANSPOSE_CLASS_SPEC d458 2 a459 1 =item VAR_EMPTY_TRANSPOSE_CLASS d461 1 a461 1 =item VAR_TRANSPOSE_CLASSES_MISMATCH d463 2 a464 1 =item VAR_MALFORMATTED_TRANSPOSE d466 1 a466 1 =item VAR_OFFSET_LOGIC_ERROR d468 2 a469 1 =item VAR_OFFSET_OUT_OF_BOUNDS d471 1 a471 1 =item VAR_RANGE_OUT_OF_BOUNDS d473 3 a475 1 =item VAR_INVALID_OFFSET_DELIMITER d477 1 a477 1 =item VAR_MISSING_START_OFFSET d479 2 a480 1 =item VAR_EMPTY_SEARCH_STRING d482 1 a482 1 =item VAR_MISSING_PARAMETER_IN_COMMAND d484 2 a485 1 =item VAR_INVALID_REGEX_IN_REPLACE d487 1 a487 1 =item VAR_UNKNOWN_REPLACE_FLAG d489 2 a490 1 =item VAR_MALFORMATTED_REPLACE d492 1 a492 1 =item VAR_UNKNOWN_COMMAND_CHAR d494 2 a495 1 =item VAR_INPUT_ISNT_TEXT_NOR_VARIABLE d497 1 a497 1 =item VAR_UNDEFINED_VARIABLE d499 3 a501 1 =item VAR_INCOMPLETE_VARIABLE_SPEC d503 1 a503 1 =item VAR_OUT_OF_MEMORY d505 2 a506 1 =item VAR_INVALID_CONFIGURATION d508 1 a508 1 =item VAR_INCORRECT_CLASS_SPEC d510 2 a511 1 =item VAR_INCOMPLETE_GROUPED_HEX d513 1 a513 1 =item VAR_INCOMPLETE_OCTAL d515 2 a516 1 =item VAR_INVALID_OCTAL d518 1 a518 1 =item VAR_OCTAL_TOO_LARGE d520 4 a523 1 =item VAR_INVALID_HEX d525 1 a525 1 =item VAR_INCOMPLETE_HEX d527 2 a528 1 =item VAR_INCOMPLETE_NAMED_CHARACTER d530 1 a530 1 =item VAR_INCOMPLETE_QUOTED_PAIR d532 55 a586 1 =item VAR_OK @ 1.1 log @Added skeleton version of the library's manual page. @ text @d42 1 d116 2 @