]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/var.c
kes If doing a mount, look for a slot, and if specified pass it to
[bacula/bacula] / bacula / src / lib / var.c
index 87d043a2860fafa42b0075fdca2a41fff5fd2f6c..14289b19a8edece5f81d4415241a08e9abc6ad04 100644 (file)
@@ -18,7 +18,7 @@
  *  Adapted by Kern Sibbald to Bacula June 2003
  */
 /*
-   Copyright (C) 2000-2003 Kern Sibbald and John Walker
+   Copyright (C) 2000-2004 Kern Sibbald and John Walker
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
 
  */
 
-
 #include "bacula.h"
 #if defined(HAVE_PCREPOSIX)
 #  include <pcreposix.h>
+#elif defined(HAVE_WIN32)
+#  include "bregex.h"
 #else
 #  include <regex.h>
 #endif
@@ -107,51 +108,51 @@ static const var_syntax_t var_syntax_default = {
 */
 
 /* minimal output-independent vprintf(3) variant which supports %{c,s,d,%} only */
-static int 
+static int
 var_mvxprintf(
-    int (*output)(void *ctx, const char *buffer, int bufsize), void *ctx, 
+    int (*output)(void *ctx, const char *buffer, int bufsize), void *ctx,
     const char *format, va_list ap)
 {
     /* sufficient integer buffer: <available-bits> x log_10(2) + safety */
-    char ibuf[((sizeof(int)*8)/3)+10]; 
-    char *cp;
+    char ibuf[((sizeof(int)*8)/3)+10];
+    const char *cp;
     char c;
     int d;
     int n;
     int bytes;
 
-    if (format == NULL || ap == NULL)
+    if (format == NULL)
        return -1;
     bytes = 0;
     while (*format != '\0') {
-        if (*format == '%') {
+       if (*format == '%') {
            c = *(format+1);
-            if (c == '%') {
-                /* expand "%%" */
+           if (c == '%') {
+               /* expand "%%" */
                cp = &c;
                n = sizeof(char);
            }
-            else if (c == 'c') {
-                /* expand "%c" */
+           else if (c == 'c') {
+               /* expand "%c" */
                c = (char)va_arg(ap, int);
                cp = &c;
                n = sizeof(char);
            }
-            else if (c == 's') {
-                /* expand "%s" */
+           else if (c == 's') {
+               /* expand "%s" */
                if ((cp = (char *)va_arg(ap, char *)) == NULL)
-                    cp = "(null)";
+                   cp = "(null)";
                n = strlen(cp);
            }
-            else if (c == 'd') {
-                /* expand "%d" */
+           else if (c == 'd') {
+               /* expand "%d" */
                d = (int)va_arg(ap, int);
-                bsnprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */
+               bsnprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */
                cp = ibuf;
                n = strlen(cp);
            }
            else {
-                /* any other "%X" */
+               /* any other "%X" */
                cp = (char *)format;
                n  = 2;
            }
@@ -160,8 +161,8 @@ var_mvxprintf(
        else {
            /* plain text */
            cp = (char *)format;
-            if ((format = strchr(cp, '%')) == NULL)
-                format = strchr(cp, '\0');
+           if ((format = strchr(cp, '%')) == NULL)
+               format = strchr(cp, '\0');
            n = format - cp;
        }
        /* perform output operation */
@@ -180,9 +181,9 @@ typedef struct {
 } var_mvsnprintf_cb_t;
 
 /* output callback function for var_mvsnprintf() */
-static int 
+static int
 var_mvsnprintf_cb(
-    void *_ctx, 
+    void *_ctx,
     const char *buffer, int bufsize)
 {
     var_mvsnprintf_cb_t *ctx = (var_mvsnprintf_cb_t *)_ctx;
@@ -196,19 +197,19 @@ var_mvsnprintf_cb(
 }
 
 /* minimal vsnprintf(3) variant which supports %{c,s,d} only */
-static int 
+static int
 var_mvsnprintf(
-    char *buffer, int bufsize, 
+    char *buffer, int bufsize,
     const char *format, va_list ap)
 {
     int n;
     var_mvsnprintf_cb_t ctx;
 
-    if (format == NULL || ap == NULL)
+    if (format == NULL)
        return -1;
     if (buffer != NULL && bufsize == 0)
        return -1;
-    if (buffer == NULL) 
+    if (buffer == NULL)
        /* just determine output length */
        n = var_mvxprintf(NULL, NULL, format, ap);
     else {
@@ -219,7 +220,7 @@ var_mvsnprintf(
        if (n != -1 && ctx.buflen == 0)
            n = -1;
        if (n != -1)
-            *(ctx.bufptr) = '\0';
+           *(ctx.bufptr) = '\0';
     }
     return n;
 }
@@ -264,7 +265,7 @@ typedef struct {
     int buffer_size;
 } tokenbuf_t;
 
-static void 
+static void
 tokenbuf_init(
     tokenbuf_t *buf)
 {
@@ -274,7 +275,7 @@ tokenbuf_init(
     return;
 }
 
-static int 
+static int
 tokenbuf_isundef(
     tokenbuf_t *buf)
 {
@@ -283,7 +284,7 @@ tokenbuf_isundef(
     return 0;
 }
 
-static int 
+static int
 tokenbuf_isempty(
     tokenbuf_t *buf)
 {
@@ -292,7 +293,7 @@ tokenbuf_isempty(
     return 0;
 }
 
-static void 
+static void
 tokenbuf_set(
     tokenbuf_t *buf, const char *begin, const char *end, int buffer_size)
 {
@@ -302,7 +303,7 @@ tokenbuf_set(
     return;
 }
 
-static void 
+static void
 tokenbuf_move(
     tokenbuf_t *src, tokenbuf_t *dst)
 {
@@ -313,7 +314,7 @@ tokenbuf_move(
     return;
 }
 
-static int 
+static int
 tokenbuf_assign(
     tokenbuf_t *buf, const char *data, int len)
 {
@@ -329,7 +330,7 @@ tokenbuf_assign(
     return 1;
 }
 
-static int 
+static int
 tokenbuf_append(
     tokenbuf_t *output, const char *data, int len)
 {
@@ -386,14 +387,14 @@ tokenbuf_append(
     return 1;
 }
 
-static int 
+static int
 tokenbuf_merge(
     tokenbuf_t *output, tokenbuf_t *input)
 {
     return tokenbuf_append(output, input->begin, input->end - input->begin);
 }
 
-static void 
+static void
 tokenbuf_free(
     tokenbuf_t *buf)
 {
@@ -410,7 +411,7 @@ tokenbuf_free(
 **
 */
 
-static void 
+static void
 expand_range(char a, char b, char_class_t chrclass)
 {
     do {
@@ -419,7 +420,7 @@ expand_range(char a, char b, char_class_t chrclass)
     return;
 }
 
-static var_rc_t 
+static var_rc_t
 expand_character_class(const char *desc, char_class_t chrclass)
 {
     int i;
@@ -430,7 +431,7 @@ expand_character_class(const char *desc, char_class_t chrclass)
 
     /* walk through class description and set appropriate entries in array */
     while (*desc != EOS) {
-        if (desc[1] == '-' && desc[2] != EOS) {
+       if (desc[1] == '-' && desc[2] != EOS) {
            if (desc[0] > desc[2])
                return VAR_ERR_INCORRECT_CLASS_SPEC;
            expand_range(desc[0], desc[2], chrclass);
@@ -449,9 +450,9 @@ expand_character_class(const char *desc, char_class_t chrclass)
 **
 */
 
-static int 
+static int
 expand_isoct(
-    char c)
+    int c)
 {
     if (c >= '0' && c <= '7')
        return 1;
@@ -459,16 +460,16 @@ expand_isoct(
        return 0;
 }
 
-static var_rc_t 
+static var_rc_t
 expand_octal(
     const char **src, char **dst, const char *end)
 {
-    unsigned char c;
+    int c;
 
     if (end - *src < 3)
        return VAR_ERR_INCOMPLETE_OCTAL;
-    if (   !expand_isoct(**src) 
-       || !expand_isoct((*src)[1]) 
+    if (   !expand_isoct(**src)
+       || !expand_isoct((*src)[1])
        || !expand_isoct((*src)[2]))
        return VAR_ERR_INVALID_OCTAL;
 
@@ -489,52 +490,52 @@ expand_octal(
     return VAR_OK;
 }
 
-static int 
+static int
 expand_ishex(
-    char c)
+    int c)
 {
     if ((c >= '0' && c <= '9') ||
-        (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+       (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
        return 1;
     else
        return 0;
 }
 
-static var_rc_t 
+static var_rc_t
 expand_simple_hex(
     const char **src, char **dst, const char *end)
 {
-    unsigned char c = 0;
+    int c = 0;
 
     if (end - *src < 2)
        return VAR_ERR_INCOMPLETE_HEX;
-    if (   !expand_ishex(**src) 
+    if (   !expand_ishex(**src)
        || !expand_ishex((*src)[1]))
        return VAR_ERR_INVALID_HEX;
 
     if (**src >= '0' && **src <= '9')
-        c = **src - '0';
-    else if (c >= 'a' && c <= 'f')
-        c = **src - 'a' + 10;
-    else if (c >= 'A' && c <= 'F')
-        c = **src - 'A' + 10;
+       c = **src - '0';
+    else if (**src >= 'a' && **src <= 'f')
+       c = **src - 'a' + 10;
+    else if (**src >= 'A' && **src <= 'F')
+       c = **src - 'A' + 10;
 
     c = c << 4;
     (*src)++;
 
     if (**src >= '0' && **src <= '9')
-        c += **src - '0';
+       c += **src - '0';
     else if (**src >= 'a' && **src <= 'f')
-        c += **src - 'a' + 10;
+       c += **src - 'a' + 10;
     else if (**src >= 'A' && **src <= 'F')
-        c += **src - 'A' + 10;
+       c += **src - 'A' + 10;
 
-    **dst = (char) c;
+    **dst = (char)c;
     (*dst)++;
     return VAR_OK;
 }
 
-static var_rc_t 
+static var_rc_t
 expand_grouped_hex(
     const char **src, char **dst, const char *end)
 {
@@ -551,7 +552,7 @@ expand_grouped_hex(
     return VAR_OK;
 }
 
-static var_rc_t 
+static var_rc_t
 expand_hex(
     const char **src, char **dst, const char *end)
 {
@@ -564,7 +565,7 @@ expand_hex(
        return expand_simple_hex(src, dst, end);
 }
 
-/* 
+/*
 **
 **  ==== RECURSIVE-DESCEND VARIABLE EXPANSION PARSER ====
 **
@@ -576,7 +577,7 @@ static int parse_numexp (var_t *var, var_parse_t *ctx, const char *begin, const
 static int parse_name  (var_t *var, var_parse_t *ctx, const char *begin, const char *end);
 
 /* parse pattern text */
-static int 
+static int
 parse_pattern(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end)
@@ -595,7 +596,7 @@ parse_pattern(
 }
 
 /* parse substitution text */
-static int 
+static int
 parse_substext(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end)
@@ -614,7 +615,7 @@ parse_substext(
 }
 
 /* parse expression text */
-static int 
+static int
 parse_exptext(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end)
@@ -625,7 +626,7 @@ parse_exptext(
     for (p = begin;    p != end
                    && *p != var->syntax.delim_init
                    && *p != var->syntax.delim_close
-                    && *p != ':'; p++) {
+                   && *p != ':'; p++) {
        if (*p == var->syntax.escape) {
            if (p + 1 == end)
                return VAR_ERR_INCOMPLETE_QUOTED_PAIR;
@@ -636,7 +637,7 @@ parse_exptext(
 }
 
 /* parse opertion argument text */
-static int 
+static int
 parse_opargtext(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end)
@@ -654,7 +655,7 @@ parse_opargtext(
     return (p - begin);
 }
 
-static int 
+static int
 parse_opargtext_or_variable(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -702,7 +703,7 @@ error_return:
 }
 
 /* parse expression or variable */
-static int 
+static int
 parse_exptext_or_variable(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -735,8 +736,7 @@ parse_exptext_or_variable(
            goto error_return;
        if (rc > 0) {
            p += rc;
-           if (!tokenbuf_append
-               (result, tmp.begin, tmp.end - tmp.begin)) {
+           if (!tokenbuf_merge(result, &tmp)) {
                rc = VAR_ERR_OUT_OF_MEMORY;
                goto error_return;
            }
@@ -754,7 +754,7 @@ error_return:
 }
 
 /* parse substitution text or variable */
-static int 
+static int
 parse_substext_or_variable(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -787,8 +787,7 @@ parse_substext_or_variable(
            goto error_return;
        if (rc > 0) {
            p += rc;
-           if (!tokenbuf_append
-               (result, tmp.begin, tmp.end - tmp.begin)) {
+           if (!tokenbuf_merge(result, &tmp)) {
                rc = VAR_ERR_OUT_OF_MEMORY;
                goto error_return;
            }
@@ -806,17 +805,17 @@ error_return:
 }
 
 /* parse class description */
-static int 
+static int
 parse_class_description(
     var_t *var, var_parse_t *ctx,
     tokenbuf_t *src, tokenbuf_t *dst)
 {
     unsigned char c, d;
-    const char *p; 
+    const char *p;
 
     p = src->begin;
     while (p != src->end) {
-        if ((src->end - p) >= 3 && p[1] == '-') {
+       if ((src->end - p) >= 3 && p[1] == '-') {
            if (*p > p[2])
                return VAR_ERR_INCORRECT_TRANSPOSE_CLASS_SPEC;
            for (c = *p, d = p[2]; c <= d; ++c) {
@@ -834,12 +833,12 @@ parse_class_description(
 }
 
 /* parse regex replace part */
-static int 
+static int
 parse_regex_replace(
     var_t *var, var_parse_t *ctx,
-    const char *data, 
+    const char *data,
     tokenbuf_t *orig,
-    regmatch_t *pmatch, 
+    regmatch_t *pmatch,
     tokenbuf_t *expanded)
 {
     const char *p;
@@ -849,13 +848,13 @@ parse_regex_replace(
     tokenbuf_init(expanded);
 
     while (p != orig->end) {
-        if (*p == '\\') {
+       if (*p == '\\') {
            if (orig->end - p <= 1) {
                tokenbuf_free(expanded);
                return VAR_ERR_INCOMPLETE_QUOTED_PAIR;
            }
            p++;
-            if (*p == '\\') {
+           if (*p == '\\') {
                if (!tokenbuf_append(expanded, p, 1)) {
                    tokenbuf_free(expanded);
                    return VAR_ERR_OUT_OF_MEMORY;
@@ -867,7 +866,7 @@ parse_regex_replace(
                tokenbuf_free(expanded);
                return VAR_ERR_UNKNOWN_QUOTED_PAIR_IN_REPLACE;
            }
-            i = (*p - '0');
+           i = (*p - '0');
            p++;
            if (pmatch[i].rm_so == -1 || pmatch[i].rm_eo == -1) {
                tokenbuf_free(expanded);
@@ -891,10 +890,10 @@ parse_regex_replace(
 }
 
 /* operation: transpose */
-static int 
+static int
 op_transpose(
     var_t *var, var_parse_t *ctx,
-    tokenbuf_t *data, 
+    tokenbuf_t *data,
     tokenbuf_t *search,
     tokenbuf_t *replace)
 {
@@ -946,12 +945,12 @@ error_return:
 }
 
 /* operation: search & replace */
-static int 
+static int
 op_search_and_replace(
     var_t *var, var_parse_t *ctx,
-    tokenbuf_t *data, 
+    tokenbuf_t *data,
     tokenbuf_t *search,
-    tokenbuf_t *replace, 
+    tokenbuf_t *replace,
     tokenbuf_t *flags)
 {
     tokenbuf_t tmp;
@@ -967,16 +966,16 @@ op_search_and_replace(
 
     for (p = flags->begin; p != flags->end; p++) {
        switch (tolower(*p)) {
-            case 'm':
+           case 'm':
                multiline = 1;
                break;
-            case 'i':
+           case 'i':
                case_insensitive = 1;
                break;
-            case 'g':
+           case 'g':
                global = 1;
                break;
-            case 't':
+           case 't':
                no_regex = 1;
                break;
            default:
@@ -1032,7 +1031,7 @@ op_search_and_replace(
        }
 
        /* compile the pattern. */
-       rc = regcomp(&preg, tmp.begin, 
+       rc = regcomp(&preg, tmp.begin,
                     (  REG_EXTENDED
                      | (multiline ? REG_NEWLINE : 0)
                      | (case_insensitive ? REG_ICASE : 0)));
@@ -1043,9 +1042,9 @@ op_search_and_replace(
        }
 
        /* match the pattern and create the result string in the tmp buffer */
-        tokenbuf_append(&tmp, "", 0);
+       tokenbuf_append(&tmp, "", 0);
        for (p = mydata.begin; p < mydata.end; ) {
-            if (p == mydata.begin || p[-1] == '\n')
+           if (p == mydata.begin || p[-1] == '\n')
                regexec_flag = 0;
            else
                regexec_flag = REG_NOTBOL;
@@ -1055,8 +1054,8 @@ op_search_and_replace(
                tokenbuf_append(&tmp, p, mydata.end - p);
                break;
            }
-           else if (   multiline 
-                    && (p + pmatch[0].rm_so) == mydata.end 
+           else if (   multiline
+                    && (p + pmatch[0].rm_so) == mydata.end
                     && (pmatch[0].rm_eo - pmatch[0].rm_so) == 0) {
                /* special case: found empty pattern (usually /^/ or /$/ only)
                   in multi-line at end of data (after the last newline) */
@@ -1080,7 +1079,7 @@ op_search_and_replace(
                    return rc;
                }
                /* append replace string */
-               if (!tokenbuf_append(&tmp, myreplace.begin, myreplace.end - myreplace.begin)) {
+               if (!tokenbuf_merge(&tmp, &myreplace)) {
                    regfree(&preg);
                    tokenbuf_free(&tmp);
                    tokenbuf_free(&mydata);
@@ -1105,7 +1104,7 @@ op_search_and_replace(
                    }
                    p++;
                }
-               /* append prolog string and stop processing if we 
+               /* append prolog string and stop processing if we
                   do not perform the search & replace globally */
                if (!global) {
                    if (!tokenbuf_append(&tmp, p, mydata.end - p)) {
@@ -1128,12 +1127,12 @@ op_search_and_replace(
 }
 
 /* operation: offset substring */
-static int 
+static int
 op_offset(
     var_t *var, var_parse_t *ctx,
-    tokenbuf_t *data, 
+    tokenbuf_t *data,
     int num1,
-    int num2, 
+    int num2,
     int isrange)
 {
     tokenbuf_t res;
@@ -1170,11 +1169,11 @@ op_offset(
 }
 
 /* operation: padding */
-static int 
+static int
 op_padding(
     var_t *var, var_parse_t *ctx,
-    tokenbuf_t *data, 
-    int width, 
+    tokenbuf_t *data,
+    int width,
     tokenbuf_t *fill,
     char position)
 {
@@ -1204,7 +1203,7 @@ op_padding(
        if (i > 0) {
            i = i / (fill->end - fill->begin);
            while (i > 0) {
-               if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) {
+               if (!tokenbuf_merge(&result, fill)) {
                    tokenbuf_free(&result);
                    return VAR_ERR_OUT_OF_MEMORY;
                }
@@ -1215,7 +1214,7 @@ op_padding(
                tokenbuf_free(&result);
                return VAR_ERR_OUT_OF_MEMORY;
            }
-           if (!tokenbuf_append(&result, data->begin, data->end - data->begin)) {
+           if (!tokenbuf_merge(&result, data)) {
                tokenbuf_free(&result);
                return VAR_ERR_OUT_OF_MEMORY;
            }
@@ -1230,7 +1229,7 @@ op_padding(
            /* create the prefix */
            i = i / (fill->end - fill->begin);
            while (i > 0) {
-               if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) {
+               if (!tokenbuf_merge(&result, fill)) {
                    tokenbuf_free(&result);
                    return VAR_ERR_OUT_OF_MEMORY;
                }
@@ -1243,7 +1242,7 @@ op_padding(
                return VAR_ERR_OUT_OF_MEMORY;
            }
            /* append the actual data string */
-           if (!tokenbuf_append(&result, data->begin, data->end - data->begin)) {
+           if (!tokenbuf_merge(&result, data)) {
                tokenbuf_free(&result);
                return VAR_ERR_OUT_OF_MEMORY;
            }
@@ -1251,7 +1250,7 @@ op_padding(
            i = width - (result.end - result.begin);
            i = i / (fill->end - fill->begin);
            while (i > 0) {
-               if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) {
+               if (!tokenbuf_merge(&result, fill)) {
                    tokenbuf_free(&result);
                    return VAR_ERR_OUT_OF_MEMORY;
                }
@@ -1271,7 +1270,7 @@ op_padding(
 }
 
 /* parse an integer number ("123") */
-static int 
+static int
 parse_integer(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -1284,7 +1283,7 @@ parse_integer(
     num = 0;
     while (isdigit(*p) && p != end) {
        num *= 10;
-        num += (*p - '0');
+       num += (*p - '0');
        p++;
     }
     if (result != NULL)
@@ -1293,7 +1292,7 @@ parse_integer(
 }
 
 /* parse an operation (":x...") */
-static int 
+static int
 parse_operation(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -1321,7 +1320,7 @@ parse_operation(
 
     /* dispatch through the first operation character */
     switch (tolower(*p)) {
-        case 'l': {
+       case 'l': {
            /* turn value to lowercase. */
            if (data->begin != NULL) {
                /* if the buffer does not live in an allocated buffer,
@@ -1339,7 +1338,7 @@ parse_operation(
            p++;
            break;
        }
-        case 'u': {
+       case 'u': {
            /* turn value to uppercase. */
            if (data->begin != NULL) {
                /* if the buffer does not live in an allocated buffer,
@@ -1357,7 +1356,7 @@ parse_operation(
            p++;
            break;
        }
-        case 'o': {
+       case 'o': {
            /* cut out substring of value. */
            p++;
            rc = parse_integer(var, ctx, p, end, &num1);
@@ -1368,10 +1367,10 @@ parse_operation(
            else if (rc < 0)
                goto error_return;
            p += rc;
-            if (*p == ',') {
+           if (*p == ',') {
                isrange = 0;
                p++;
-            } else if (*p == '-') {
+           } else if (*p == '-') {
                isrange = 1;
                p++;
            } else {
@@ -1387,11 +1386,11 @@ parse_operation(
            }
            break;
        }
-        case '#': {
+       case '#': {
            /* determine length of the value */
            if (data->begin != NULL) {
                char buf[((sizeof(int)*8)/3)+10]; /* sufficient size: <#bits> x log_10(2) + safety */
-                sprintf(buf, "%d", (int)(data->end - data->begin));
+               sprintf(buf, "%d", (int)(data->end - data->begin));
                tokenbuf_free(data);
                if (!tokenbuf_assign(data, buf, strlen(buf))) {
                    rc = VAR_ERR_OUT_OF_MEMORY;
@@ -1401,7 +1400,7 @@ parse_operation(
            p++;
            break;
        }
-        case '-': {
+       case '-': {
            /* substitute parameter if data is empty */
            p++;
            rc = parse_exptext_or_variable(var, ctx, p, end, &tmptokbuf);
@@ -1420,7 +1419,7 @@ parse_operation(
            }
            break;
        }
-        case '*': {
+       case '*': {
            /* substitute empty string if data is not empty, parameter otherwise. */
            p++;
            rc = parse_exptext_or_variable(var, ctx, p, end, &tmptokbuf);
@@ -1437,13 +1436,13 @@ parse_operation(
                    tokenbuf_move(&tmptokbuf, data);
                } else {
                    tokenbuf_free(data);
-                    data->begin = data->end = "";
+                   data->begin = data->end = "";
                    data->buffer_size = 0;
                }
            }
            break;
        }
-        case '+': {
+       case '+': {
            /* substitute parameter if data is not empty. */
            p++;
            rc = parse_exptext_or_variable(var, ctx, p, end, &tmptokbuf);
@@ -1460,10 +1459,10 @@ parse_operation(
            }
            break;
        }
-        case 's': {
+       case 's': {
            /* search and replace. */
            p++;
-            if (*p != '/')
+           if (*p != '/')
                return VAR_ERR_MALFORMATTED_REPLACE;
            p++;
            rc = parse_pattern(var, ctx, p, end);
@@ -1471,7 +1470,7 @@ parse_operation(
                goto error_return;
            tokenbuf_set(&search, p, p + rc, 0);
            p += rc;
-            if (*p != '/') {
+           if (*p != '/') {
                rc = VAR_ERR_MALFORMATTED_REPLACE;
                goto error_return;
            }
@@ -1480,7 +1479,7 @@ parse_operation(
            if (rc < 0)
                goto error_return;
            p += rc;
-            if (*p != '/') {
+           if (*p != '/') {
                rc = VAR_ERR_MALFORMATTED_REPLACE;
                goto error_return;
            }
@@ -1497,17 +1496,17 @@ parse_operation(
            }
            break;
        }
-        case 'y': {
+       case 'y': {
            /* transpose characters from class A to class B. */
            p++;
-            if (*p != '/')
+           if (*p != '/')
                return VAR_ERR_MALFORMATTED_TRANSPOSE;
            p++;
            rc = parse_substext_or_variable(var, ctx, p, end, &search);
            if (rc < 0)
                goto error_return;
            p += rc;
-            if (*p != '/') {
+           if (*p != '/') {
                rc = VAR_ERR_MALFORMATTED_TRANSPOSE;
                goto error_return;
            }
@@ -1516,7 +1515,7 @@ parse_operation(
            if (rc < 0)
                goto error_return;
            p += rc;
-            if (*p != '/') {
+           if (*p != '/') {
                rc = VAR_ERR_MALFORMATTED_TRANSPOSE;
                goto error_return;
            } else
@@ -1528,10 +1527,10 @@ parse_operation(
            }
            break;
        }
-        case 'p': {
+       case 'p': {
            /* padding. */
            p++;
-            if (*p != '/')
+           if (*p != '/')
                return VAR_ERR_MALFORMATTED_PADDING;
            p++;
            rc = parse_integer(var, ctx, p, end, &num1);
@@ -1540,7 +1539,7 @@ parse_operation(
                goto error_return;
            }
            p += rc;
-            if (*p != '/') {
+           if (*p != '/') {
                rc = VAR_ERR_MALFORMATTED_PADDING;
                goto error_return;
            }
@@ -1549,12 +1548,12 @@ parse_operation(
            if (rc < 0)
                goto error_return;
            p += rc;
-            if (*p != '/') {
+           if (*p != '/') {
                rc = VAR_ERR_MALFORMATTED_PADDING;
                goto error_return;
            }
            p++;
-            if (*p != 'l' && *p != 'c' && *p != 'r') {
+           if (*p != 'l' && *p != 'c' && *p != 'r') {
                rc = VAR_ERR_MALFORMATTED_PADDING;
                goto error_return;
            }
@@ -1566,7 +1565,7 @@ parse_operation(
            }
            break;
        }
-        case '%': {
+       case '%': {
            /* operation callback function */
            const char *op_ptr;
            int op_len;
@@ -1575,7 +1574,7 @@ parse_operation(
            const char *val_ptr;
            int val_len;
            const char *out_ptr;
-           int out_len; 
+           int out_len;
            int out_size;
            tokenbuf_t args;
 
@@ -1586,7 +1585,7 @@ parse_operation(
            op_ptr = p;
            op_len = rc;
            p += rc;
-            if (*p == '(') {
+           if (*p == '(') {
                p++;
                tokenbuf_init(&args);
                rc = parse_opargtext_or_variable(var, ctx, p, end, &args);
@@ -1595,7 +1594,7 @@ parse_operation(
                p += rc;
                arg_ptr = args.begin;
                arg_len = args.end - args.begin;
-                if (*p != ')') {
+               if (*p != ')') {
                    rc = VAR_ERR_MALFORMED_OPERATION_ARGUMENTS;
                    goto error_return;
                }
@@ -1615,11 +1614,16 @@ parse_operation(
                                              arg_ptr, arg_len,
                                              val_ptr, val_len,
                                              &out_ptr, &out_len, &out_size);
-               if (rc < 0)
+               if (rc < 0) {
+                   if (arg_ptr != NULL)
+                       free((void *)arg_ptr);
                    goto error_return;
+               }
                tokenbuf_free(data);
                tokenbuf_set(data, out_ptr, out_ptr+out_len, out_size);
            }
+           if (arg_ptr != NULL)
+              free((void *)arg_ptr);
            break;
        }
        default:
@@ -1648,10 +1652,10 @@ error_return:
 }
 
 /* parse numerical expression operand */
-static int 
+static int
 parse_numexp_operand(
     var_t *var, var_parse_t *ctx,
-    const char *begin, const char *end, 
+    const char *begin, const char *end,
     int *result, int *failed)
 {
     const char *p;
@@ -1675,7 +1679,7 @@ parse_numexp_operand(
        if (p == end)
            return VAR_ERR_INCOMPLETE_INDEX_SPEC;
        /* parse closing parenthesis */
-        if (*p != ')')
+       if (*p != ')')
            return VAR_ERR_UNCLOSED_BRACKET_IN_INDEX;
        p++;
     }
@@ -1711,7 +1715,7 @@ parse_numexp_operand(
        }
     }
     /* parse relative index mark ("#") */
-    else if (  var->syntax.index_mark != EOS 
+    else if (  var->syntax.index_mark != EOS
             && *p == var->syntax.index_mark) {
        p++;
        *result = ctx->index_this;
@@ -1752,10 +1756,10 @@ parse_numexp_operand(
 }
 
 /* parse numerical expression ("x+y") */
-static int 
+static int
 parse_numexp(
     var_t *var, var_parse_t *ctx,
-    const char *begin, const char *end, 
+    const char *begin, const char *end,
     int *result, int *failed)
 {
     const char *p;
@@ -1776,28 +1780,28 @@ parse_numexp(
 
     /* parse numerical operator */
     while (p != end) {
-        if (*p == '+' || *p == '-') {
+       if (*p == '+' || *p == '-') {
            op = *p++;
            /* recursively parse right operand (light binding) */
            rc = parse_numexp(var, ctx, p, end, &right, failed);
            if (rc < 0)
                return rc;
            p += rc;
-            if (op == '+')
+           if (op == '+')
                *result = (*result + right);
            else
                *result = (*result - right);
        }
-        else if (*p == '*' || *p == '/' || *p == '%') {
+       else if (*p == '*' || *p == '/' || *p == '%') {
            op = *p++;
            /* recursively parse right operand (string binding) */
            rc = parse_numexp_operand(var, ctx, p, end, &right, failed);
            if (rc < 0)
                return rc;
            p += rc;
-            if (op == '*')
+           if (op == '*')
                *result = (*result * right);
-            else if (op == '/') {
+           else if (op == '/') {
                if (right == 0) {
                    if (*failed)
                        *result = 0;
@@ -1807,7 +1811,7 @@ parse_numexp(
                else
                    *result = (*result / right);
            }
-            else if (op == '%') {
+           else if (op == '%') {
                if (right == 0) {
                    if (*failed)
                        *result = 0;
@@ -1827,7 +1831,7 @@ parse_numexp(
 }
 
 /* parse variable name ("abc") */
-static int 
+static int
 parse_name(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end)
@@ -1841,7 +1845,7 @@ parse_name(
 }
 
 /* lookup a variable value through the callback function */
-static int 
+static int
 lookup_value(
     var_t *var, var_parse_t *ctx,
     const char *var_ptr, int  var_len, int var_inc, int var_idx,
@@ -1852,13 +1856,13 @@ lookup_value(
 
     /* pass through to original callback */
     rc = (*var->cb_value_fct)(var, var->cb_value_ctx,
-                             var_ptr, var_len, var_inc, var_idx, 
+                             var_ptr, var_len, var_inc, var_idx,
                              val_ptr, val_len, val_size);
 
     /* convert undefined variable into empty variable if relative
        lookups are counted. This is the case inside an active loop
        construct if no limits are given. There the parse_input()
-       has to proceed until all variables have undefined values. 
+       has to proceed until all variables have undefined values.
        This trick here allows it to determine this case. */
     if (ctx->rel_lookup_flag && rc == VAR_ERR_UNDEFINED_VARIABLE) {
        ctx->rel_lookup_cnt--;
@@ -1873,7 +1877,7 @@ lookup_value(
 }
 
 /* parse complex variable construct ("${name...}") */
-static int 
+static int
 parse_variable_complex(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -1885,7 +1889,7 @@ parse_variable_complex(
     int failed = 0;
     int rc;
     int idx = 0;
-    int inc;   
+    int inc;
     tokenbuf_t name;
     tokenbuf_t tmp;
 
@@ -1932,7 +1936,7 @@ parse_variable_complex(
        tokenbuf_free(&tmp);          /* KES 11/9/2003 */
     } while (rc > 0);
 
-    /* we must have the complete expanded variable name now, 
+    /* we must have the complete expanded variable name now,
        so make sure we really do. */
     if (name.begin == name.end) {
        if (ctx->force_expand) {
@@ -1941,7 +1945,7 @@ parse_variable_complex(
        }
        else {
            /* If no force_expand is requested, we have to back-off.
-               We're not sure whether our approach here is 100% correct,
+              We're not sure whether our approach here is 100% correct,
               because it _could_ have side-effects according to Peter
               Simons, but as far as we know and tried it, it is
               correct. But be warned -- RSE */
@@ -2005,7 +2009,7 @@ goahead:
        tokenbuf_free(&tmp);
        tokenbuf_init(&tmp);
        p--;
-        while (p != end && *p == ':') {
+       while (p != end && *p == ':') {
            p++;
            if (!failed)
                rc = parse_operation(var, ctx, p, end, result);
@@ -2052,7 +2056,7 @@ error_return:
 }
 
 /* parse variable construct ("$name" or "${name...}") */
-static int 
+static int
 parse_variable(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -2075,13 +2079,13 @@ parse_variable(
     if (p == end)
        return VAR_ERR_INCOMPLETE_VARIABLE_SPEC;
 
-    /* parse a simple variable name. 
+    /* parse a simple variable name.
        (if this fails, we're try to parse a complex variable construct) */
     rc = parse_name(var, ctx, p, end);
     if (rc < 0)
        return rc;
     if (rc > 0) {
-        inc = (p[rc] == '+');
+       inc = (p[rc] == '+');
        rc2 = lookup_value(var, ctx, p, rc, inc, 0, &data, &len, &buffer_size);
        if (rc2 == VAR_ERR_UNDEFINED_VARIABLE && !ctx->force_expand) {
            tokenbuf_set(result, begin, begin + 1 + rc, 0);
@@ -2101,7 +2105,7 @@ parse_variable(
 }
 
 /* parse loop construct limits ("[...]{b,s,e}") */
-static var_rc_t 
+static var_rc_t
 parse_looplimits(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -2198,14 +2202,14 @@ parse_looplimits(
 }
 
 /* parse plain text */
-static int 
+static int
 parse_text(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end)
 {
     const char *p;
 
-    /* parse until delim_init (variable construct) 
+    /* parse until delim_init (variable construct)
        or index_open (loop construct) is found */
     for (p = begin; p != end; p++) {
        if (*p == var->syntax.escape) {
@@ -2216,7 +2220,7 @@ parse_text(
        else if (*p == var->syntax.delim_init)
            break;
        else if (   var->syntax.index_open != EOS
-                && (   *p == var->syntax.index_open 
+                && (   *p == var->syntax.index_open
                     || *p == var->syntax.index_close))
            break;
     }
@@ -2224,7 +2228,7 @@ parse_text(
 }
 
 /* expand input in general */
-static var_rc_t 
+static var_rc_t
 parse_input(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
@@ -2245,8 +2249,8 @@ parse_input(
 
     do {
        /* try to parse a loop construct */
-       if (   p != end 
-           && var->syntax.index_open != EOS 
+       if (   p != end
+           && var->syntax.index_open != EOS
            && *p == var->syntax.index_open) {
            p++;
 
@@ -2266,24 +2270,24 @@ parse_input(
               or there is a stop limit known and it is still not reached */
            re_loop:
            for (i = start;
-                (   (   open_stop 
-                     && (   loop_limit_length < 0 
-                         || rel_lookup_cnt > ctx->rel_lookup_cnt)) 
-                 || (   !open_stop 
+                (   (   open_stop
+                     && (   loop_limit_length < 0
+                         || rel_lookup_cnt > ctx->rel_lookup_cnt))
+                 || (   !open_stop
                      && i <= stop)                                );
                 i += step) {
 
                /* remember current output end for restoring */
                output_backup = (output->end - output->begin);
 
-               /* open temporary context for recursion */ 
+               /* open temporary context for recursion */
                ctx = var_parse_push(ctx, &myctx);
                ctx->force_expand    = 1;
                ctx->rel_lookup_flag = 1;
                ctx->index_this      = i;
 
                /* recursive parse input through ourself */
-               rc = parse_input(var, ctx, p, end, 
+               rc = parse_input(var, ctx, p, end,
                                 output, recursion_level+1);
 
                /* retrieve info and close temporary context */
@@ -2302,7 +2306,7 @@ parse_input(
 
                /* try to parse loop construct limit specification */
                if (loop_limit_length < 0) {
-                   rc2 = parse_looplimits(var, ctx, p+rc+1, end, 
+                   rc2 = parse_looplimits(var, ctx, p+rc+1, end,
                                           &start, &step, &stop, &open_stop);
                    if (rc2 < 0)
                        goto error_return;
@@ -2355,7 +2359,7 @@ parse_input(
            tokenbuf_free(&result);
            p += rc;
            continue;
-       }    
+       }
        tokenbuf_free(&result);
        if (rc < 0)
            goto error_return;
@@ -2385,14 +2389,14 @@ parse_input(
     return (var_rc_t)rc;
 }
 
-/* 
+/*
 **
 **  ==== APPLICATION PROGRAMMING INTERFACE (API) ====
 **
 */
 
 /* create variable expansion context */
-var_rc_t 
+var_rc_t
 var_create(
     var_t **pvar)
 {
@@ -2409,7 +2413,7 @@ var_create(
 }
 
 /* destroy variable expansion context */
-var_rc_t 
+var_rc_t
 var_destroy(
     var_t *var)
 {
@@ -2420,10 +2424,10 @@ var_destroy(
 }
 
 /* configure variable expansion context */
-var_rc_t 
+var_rc_t
 var_config(
-    var_t *var, 
-    var_config_t mode, 
+    var_t *var,
+    var_config_t mode,
     ...)
 {
     va_list ap;
@@ -2448,7 +2452,7 @@ var_config(
            var->syntax.name_chars  = NULL; /* unused internally */
            if ((rc = expand_character_class(s->name_chars, var->syntax_nameclass)) != VAR_OK)
                return VAR_RC(rc);
-           if (   var->syntax_nameclass[(int)var->syntax.delim_init] 
+           if (   var->syntax_nameclass[(int)var->syntax.delim_init]
                || var->syntax_nameclass[(int)var->syntax.delim_open]
                || var->syntax_nameclass[(int)var->syntax.delim_close]
                || var->syntax_nameclass[(int)var->syntax.escape])
@@ -2481,11 +2485,11 @@ var_config(
 }
 
 /* perform unescape operation on a buffer */
-var_rc_t 
+var_rc_t
 var_unescape(
-    var_t *var, 
-    const char *src, int srclen, 
-    char *dst, int dstlen, 
+    var_t *var,
+    const char *src, int srclen,
+    char *dst, int dstlen,
     int all)
 {
     const char *end;
@@ -2495,34 +2499,34 @@ var_unescape(
        return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
     end = src + srclen;
     while (src < end) {
-        if (*src == '\\') {
+       if (*src == '\\') {
            if (++src == end)
                return VAR_RC(VAR_ERR_INCOMPLETE_NAMED_CHARACTER);
            switch (*src) {
-                case '\\':
+               case '\\':
                    if (!all) {
-                        *dst++ = '\\';
+                       *dst++ = '\\';
                    }
-                    *dst++ = '\\';
+                   *dst++ = '\\';
                    break;
-                case 'n':
-                    *dst++ = '\n';
+               case 'n':
+                   *dst++ = '\n';
                    break;
-                case 't':
-                    *dst++ = '\t';
+               case 't':
+                   *dst++ = '\t';
                    break;
-                case 'r':
-                    *dst++ = '\r';
+               case 'r':
+                   *dst++ = '\r';
                    break;
-                case 'x':
+               case 'x':
                    ++src;
                    if ((rc = expand_hex(&src, &dst, end)) != VAR_OK)
                        return VAR_RC(rc);
                    break;
-                case '0': case '1': case '2': case '3': case '4':
-                case '5': case '6': case '7': case '8': case '9':
-                   if (   end - src >= 3 
-                       && isdigit((int)src[1]) 
+               case '0': case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                   if (   end - src >= 3
+                       && isdigit((int)src[1])
                        && isdigit((int)src[2])) {
                        if ((rc = expand_octal(&src, &dst, end)) != 0)
                            return VAR_RC(rc);
@@ -2530,7 +2534,7 @@ var_unescape(
                    }
                default:
                    if (!all) {
-                        *dst++ = '\\';
+                       *dst++ = '\\';
                    }
                    *dst++ = *src;
            }
@@ -2543,11 +2547,11 @@ var_unescape(
 }
 
 /* perform expand operation on a buffer */
-var_rc_t 
+var_rc_t
 var_expand(
-    var_t *var, 
-    const char *src_ptr, int src_len, 
-    char **dst_ptr, int *dst_len, 
+    var_t *var,
+    const char *src_ptr, int src_len,
+    char **dst_ptr, int *dst_len,
     int force_expand)
 {
     var_parse_t ctx;
@@ -2571,9 +2575,9 @@ var_expand(
 
     /* post-processing */
     if (rc >= 0) {
-       /* always EOS-terminate output for convinience reasons 
+       /* always EOS-terminate output for convinience reasons
           but do not count the EOS-terminator in the length */
-        if (!tokenbuf_append(&output, "\0", 1)) {
+       if (!tokenbuf_append(&output, "\0", 1)) {
            tokenbuf_free(&output);
            return VAR_RC(VAR_ERR_OUT_OF_MEMORY);
        }
@@ -2595,28 +2599,20 @@ var_expand(
 }
 
 /* format and expand a string */
-var_rc_t 
+var_rc_t
 var_formatv(
-    var_t *var, 
-    char **dst_ptr, int force_expand, 
+    var_t *var,
+    char **dst_ptr, int force_expand,
     const char *fmt, va_list ap)
 {
     var_rc_t rc;
-    va_list apbak;
     char *cpBuf;
-    int nBuf;
+    int nBuf = 5000;
 
     /* argument sanity checks */
     if (var == NULL || dst_ptr == NULL || fmt == NULL)
        return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
 
-    /* determine formatting buffer length */
-    apbak = ap;
-    nBuf = var_mvsnprintf(NULL, 0, fmt, ap);
-    ap = apbak;
-    if (nBuf == -1)
-       return VAR_RC(VAR_ERR_FORMATTING_FAILURE);
-
     /* perform formatting */
     if ((cpBuf = (char *)malloc(nBuf+1)) == NULL)
        return VAR_RC(VAR_ERR_OUT_OF_MEMORY);
@@ -2639,10 +2635,10 @@ var_formatv(
 }
 
 /* format and expand a string */
-var_rc_t 
+var_rc_t
 var_format(
-    var_t *var, 
-    char **dst_ptr, int force_expand, 
+    var_t *var,
+    char **dst_ptr, int force_expand,
     const char *fmt, ...)
 {
     var_rc_t rc;
@@ -2661,61 +2657,61 @@ var_format(
 
 /* var_rc_t to string mapping table */
 static const char *var_errors[] = {
-    "everything ok",                                           /* VAR_OK = 0 */
-    "incomplete named character",                              /* VAR_ERR_INCOMPLETE_NAMED_CHARACTER */
-    "incomplete hexadecimal value",                            /* VAR_ERR_INCOMPLETE_HEX */
-    "invalid hexadecimal value",                               /* VAR_ERR_INVALID_HEX */
-    "octal value too large",                                   /* VAR_ERR_OCTAL_TOO_LARGE */
-    "invalid octal value",                                     /* VAR_ERR_INVALID_OCTAL */
-    "incomplete octal value",                                  /* VAR_ERR_INCOMPLETE_OCTAL */
-    "incomplete grouped hexadecimal value",                    /* VAR_ERR_INCOMPLETE_GROUPED_HEX */
-    "incorrect character class specification",                 /* VAR_ERR_INCORRECT_CLASS_SPEC */
-    "invalid expansion configuration",                         /* VAR_ERR_INVALID_CONFIGURATION */
-    "out of memory",                                           /* VAR_ERR_OUT_OF_MEMORY */
-    "incomplete variable specification",                       /* VAR_ERR_INCOMPLETE_VARIABLE_SPEC */
-    "undefined variable",                                      /* VAR_ERR_UNDEFINED_VARIABLE */
-    "input is neither text nor variable",                      /* VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE */
-    "unknown command character in variable",                   /* VAR_ERR_UNKNOWN_COMMAND_CHAR */
-    "malformatted search and replace operation",               /* VAR_ERR_MALFORMATTED_REPLACE */
-    "unknown flag in search and replace operation",            /* VAR_ERR_UNKNOWN_REPLACE_FLAG */
-    "invalid regex in search and replace operation",           /* VAR_ERR_INVALID_REGEX_IN_REPLACE */
-    "missing parameter in command",                            /* VAR_ERR_MISSING_PARAMETER_IN_COMMAND */
-    "empty search string in search and replace operation",     /* VAR_ERR_EMPTY_SEARCH_STRING */
-    "start offset missing in cut operation",                   /* VAR_ERR_MISSING_START_OFFSET */
-    "offsets in cut operation delimited by unknown character", /* VAR_ERR_INVALID_OFFSET_DELIMITER */
-    "range out of bounds in cut operation",                    /* VAR_ERR_RANGE_OUT_OF_BOUNDS */
-    "offset out of bounds in cut operation",                   /* VAR_ERR_OFFSET_OUT_OF_BOUNDS */
-    "logic error in cut operation",                            /* VAR_ERR_OFFSET_LOGIC */
-    "malformatted transpose operation",                        /* VAR_ERR_MALFORMATTED_TRANSPOSE */
-    "source and target class mismatch in transpose operation", /* VAR_ERR_TRANSPOSE_CLASSES_MISMATCH */
-    "empty character class in transpose operation",            /* VAR_ERR_EMPTY_TRANSPOSE_CLASS */
-    "incorrect character class in transpose operation",        /* VAR_ERR_INCORRECT_TRANSPOSE_CLASS_SPEC */
-    "malformatted padding operation",                          /* VAR_ERR_MALFORMATTED_PADDING */
-    "width parameter missing in padding operation",            /* VAR_ERR_MISSING_PADDING_WIDTH */
-    "fill string missing in padding operation",                /* VAR_ERR_EMPTY_PADDING_FILL_STRING */
-    "unknown quoted pair in search and replace operation",     /* VAR_ERR_UNKNOWN_QUOTED_PAIR_IN_REPLACE */
-    "sub-matching reference out of range",                     /* VAR_ERR_SUBMATCH_OUT_OF_RANGE */
-    "invalid argument",                                        /* VAR_ERR_INVALID_ARGUMENT */
-    "incomplete quoted pair",                                  /* VAR_ERR_INCOMPLETE_QUOTED_PAIR */
-    "lookup function does not support variable arrays",        /* VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED */
-    "index of array variable contains an invalid character",   /* VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC */
-    "index of array variable is incomplete",                   /* VAR_ERR_INCOMPLETE_INDEX_SPEC */
-    "bracket expression in array variable's index not closed", /* VAR_ERR_UNCLOSED_BRACKET_IN_INDEX */
-    "division by zero error in index specification",           /* VAR_ERR_DIVISION_BY_ZERO_IN_INDEX */
-    "unterminated loop construct",                             /* VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT */
-    "invalid character in loop limits",                        /* VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS */
-    "malformed operation argument list",                       /* VAR_ERR_MALFORMED_OPERATION_ARGUMENTS */
-    "undefined operation",                                     /* VAR_ERR_UNDEFINED_OPERATION */
-    "formatting failure"                                       /* VAR_ERR_FORMATTING_FAILURE */
+    _("everything ok"),                                           /* VAR_OK = 0 */
+    _("incomplete named character"),                              /* VAR_ERR_INCOMPLETE_NAMED_CHARACTER */
+    _("incomplete hexadecimal value"),                            /* VAR_ERR_INCOMPLETE_HEX */
+    _("invalid hexadecimal value"),                               /* VAR_ERR_INVALID_HEX */
+    _("octal value too large"),                                   /* VAR_ERR_OCTAL_TOO_LARGE */
+    _("invalid octal value"),                                     /* VAR_ERR_INVALID_OCTAL */
+    _("incomplete octal value"),                                  /* VAR_ERR_INCOMPLETE_OCTAL */
+    _("incomplete grouped hexadecimal value"),                    /* VAR_ERR_INCOMPLETE_GROUPED_HEX */
+    _("incorrect character class specification"),                 /* VAR_ERR_INCORRECT_CLASS_SPEC */
+    _("invalid expansion configuration"),                         /* VAR_ERR_INVALID_CONFIGURATION */
+    _("out of memory"),                                           /* VAR_ERR_OUT_OF_MEMORY */
+    _("incomplete variable specification"),                       /* VAR_ERR_INCOMPLETE_VARIABLE_SPEC */
+    _("undefined variable"),                                      /* VAR_ERR_UNDEFINED_VARIABLE */
+    _("input is neither text nor variable"),                      /* VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE */
+    _("unknown command character in variable"),                   /* VAR_ERR_UNKNOWN_COMMAND_CHAR */
+    _("malformatted search and replace operation"),               /* VAR_ERR_MALFORMATTED_REPLACE */
+    _("unknown flag in search and replace operation"),            /* VAR_ERR_UNKNOWN_REPLACE_FLAG */
+    _("invalid regex in search and replace operation"),           /* VAR_ERR_INVALID_REGEX_IN_REPLACE */
+    _("missing parameter in command"),                            /* VAR_ERR_MISSING_PARAMETER_IN_COMMAND */
+    _("empty search string in search and replace operation"),     /* VAR_ERR_EMPTY_SEARCH_STRING */
+    _("start offset missing in cut operation"),                   /* VAR_ERR_MISSING_START_OFFSET */
+    _("offsets in cut operation delimited by unknown character"), /* VAR_ERR_INVALID_OFFSET_DELIMITER */
+    _("range out of bounds in cut operation"),                    /* VAR_ERR_RANGE_OUT_OF_BOUNDS */
+    _("offset out of bounds in cut operation"),                   /* VAR_ERR_OFFSET_OUT_OF_BOUNDS */
+    _("logic error in cut operation"),                            /* VAR_ERR_OFFSET_LOGIC */
+    _("malformatted transpose operation"),                        /* VAR_ERR_MALFORMATTED_TRANSPOSE */
+    _("source and target class mismatch in transpose operation"), /* VAR_ERR_TRANSPOSE_CLASSES_MISMATCH */
+    _("empty character class in transpose operation"),            /* VAR_ERR_EMPTY_TRANSPOSE_CLASS */
+    _("incorrect character class in transpose operation"),        /* VAR_ERR_INCORRECT_TRANSPOSE_CLASS_SPEC */
+    _("malformatted padding operation"),                          /* VAR_ERR_MALFORMATTED_PADDING */
+    _("width parameter missing in padding operation"),            /* VAR_ERR_MISSING_PADDING_WIDTH */
+    _("fill string missing in padding operation"),                /* VAR_ERR_EMPTY_PADDING_FILL_STRING */
+    _("unknown quoted pair in search and replace operation"),     /* VAR_ERR_UNKNOWN_QUOTED_PAIR_IN_REPLACE */
+    _("sub-matching reference out of range"),                     /* VAR_ERR_SUBMATCH_OUT_OF_RANGE */
+    _("invalid argument"),                                        /* VAR_ERR_INVALID_ARGUMENT */
+    _("incomplete quoted pair"),                                  /* VAR_ERR_INCOMPLETE_QUOTED_PAIR */
+    _("lookup function does not support variable arrays"),        /* VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED */
+    _("index of array variable contains an invalid character"),   /* VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC */
+    _("index of array variable is incomplete"),                   /* VAR_ERR_INCOMPLETE_INDEX_SPEC */
+    _("bracket expression in array variable's index not closed"), /* VAR_ERR_UNCLOSED_BRACKET_IN_INDEX */
+    _("division by zero error in index specification"),           /* VAR_ERR_DIVISION_BY_ZERO_IN_INDEX */
+    _("unterminated loop construct"),                             /* VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT */
+    _("invalid character in loop limits"),                        /* VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS */
+    _("malformed operation argument list"),                       /* VAR_ERR_MALFORMED_OPERATION_ARGUMENTS */
+    _("undefined operation"),                                     /* VAR_ERR_UNDEFINED_OPERATION */
+    _("formatting failure")                                       /* VAR_ERR_FORMATTING_FAILURE */
 };
 
 /* translate a return code into its corresponding descriptive text */
-char *var_strerror(var_t *var, var_rc_t rc)
+const char *var_strerror(var_t *var, var_rc_t rc)
 {
-    char *str;
+    const char *str;
     rc = (var_rc_t)(0 - rc);
     if (rc < 0 || rc >= (int)sizeof(var_errors) / (int)sizeof(char *)) {
-        str = "unknown error";
+       str = _("unknown error");
     } else {
        str = (char *)var_errors[rc];
     }