OSSP CVS Repository

ossp - Difference in ossp-pkg/var/var.c versions 1.85 and 1.86
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/var/var.c 1.85 -> 1.86

--- var.c        2002/03/07 09:14:05     1.85
+++ var.c        2002/03/07 12:11:09     1.86
@@ -104,6 +104,134 @@
 
 /*
 **
+**  ==== FORMATTING FUNCTIONS ====
+**
+*/
+
+/* minimal output-independent vprintf(3) variant which supports %{c,s,d,%} only */
+static int 
+var_mvxprintf(
+    int (*output)(void *ctx, const char *buffer, size_t 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 c;
+    int d;
+    int n;
+    int bytes;
+
+    if (format == NULL || ap == NULL)
+        return -1;
+    bytes = 0;
+    while (*format != '\0') {
+        if (*format == '%') {
+            c = *(format+1);
+            if (c == '%') {
+                /* expand "%%" */
+                cp = &c;
+                n = sizeof(char);
+            }
+            else if (c == 'c') {
+                /* expand "%c" */
+                c = (char)va_arg(ap, int);
+                cp = &c;
+                n = sizeof(char);
+            }
+            else if (c == 's') {
+                /* expand "%s" */
+                if ((cp = (char *)va_arg(ap, char *)) == NULL)
+                    cp = "(null)";
+                n = strlen(cp);
+            }
+            else if (c == 'd') {
+                /* expand "%d" */
+                d = (int)va_arg(ap, int);
+#ifdef HAVE_SNPRINTF
+                snprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */
+#else
+                sprintf(ibuf, "%d", d);                /* implicitly secure */
+#endif
+                cp = ibuf;
+                n = strlen(cp);
+            }
+            else {
+                /* any other "%X" */
+                cp = (char *)format;
+                n  = 2;
+            }
+            format += 2;
+        }
+        else {
+            /* plain text */
+            cp = (char *)format;
+            if ((format = strchr(cp, '%')) == NULL)
+                format = strchr(cp, '\0');
+            n = format - cp;
+        }
+        /* perform output operation */
+        if (output != NULL)
+            if ((n = output(ctx, cp, n)) == -1)
+                break;
+        bytes += n;
+    }
+    return bytes;
+}
+
+/* output callback function context for var_mvsnprintf() */
+typedef struct {
+    char *bufptr;
+    size_t buflen;
+} var_mvsnprintf_cb_t;
+
+/* output callback function for var_mvsnprintf() */
+static int 
+var_mvsnprintf_cb(
+    void *_ctx, 
+    const char *buffer, size_t bufsize)
+{
+    var_mvsnprintf_cb_t *ctx = (var_mvsnprintf_cb_t *)_ctx;
+
+    if (bufsize > ctx->buflen)
+        return -1;
+    memcpy(ctx->bufptr, buffer, bufsize);
+    ctx->bufptr += bufsize;
+    ctx->buflen -= bufsize;
+    return bufsize;
+}
+
+/* minimal vsnprintf(3) variant which supports %{c,s,d} only */
+static int 
+var_mvsnprintf(
+    char *buffer, size_t bufsize, 
+    const char *format, va_list ap)
+{
+    int n;
+    var_mvsnprintf_cb_t ctx;
+
+    if (format == NULL || ap == NULL)
+        return -1;
+    if (buffer != NULL && bufsize == 0)
+        return -1;
+    if (buffer == NULL) 
+        /* just determine output length */
+        n = var_mvxprintf(NULL, NULL, format, ap);
+    else {
+        /* perform real output */
+        ctx.bufptr = buffer;
+        ctx.buflen = bufsize;
+        n = var_mvxprintf(var_mvsnprintf_cb, &ctx, format, ap);
+        if (n != -1 && ctx.buflen == 0)
+            n = -1;
+        if (n != -1)
+            *(ctx.bufptr) = '\0';
+    }
+    return n;
+}
+
+/*
+**
 **  ==== PARSE CONTEXT FUNCTIONS ====
 **
 */
@@ -2476,6 +2604,71 @@
     return VAR_RC(rc);
 }
 
+/* format and expand a string */
+var_rc_t 
+var_formatv(
+    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;
+
+    /* 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);
+    nBuf = var_mvsnprintf(cpBuf, nBuf+1, fmt, ap);
+    if (nBuf == -1) {
+        free(cpBuf);
+        return VAR_RC(VAR_ERR_FORMATTING_FAILURE);
+    }
+
+    /* perform expansion */
+    if ((rc = var_expand(var, cpBuf, nBuf, dst_ptr, NULL, force_expand)) != VAR_OK) {
+        free(cpBuf);
+        return VAR_RC(rc);
+    }
+
+    /* cleanup */
+    free(cpBuf);
+
+    return VAR_OK;
+}
+
+/* format and expand a string */
+var_rc_t 
+var_format(
+    var_t *var, 
+    char **dst_ptr, int force_expand, 
+    const char *fmt, ...)
+{
+    var_rc_t rc;
+    va_list ap;
+
+    /* argument sanity checks */
+    if (var == NULL || dst_ptr == NULL || fmt == NULL)
+        return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+
+    va_start(ap, fmt);
+    rc = var_formatv(var, dst_ptr, force_expand, fmt, ap);
+    va_end(ap);
+
+    return VAR_RC(rc);
+}
+
 /* var_rc_t to string mapping table */
 static const char *var_errors[] = {
     "everything ok",                                           /* VAR_OK = 0 */
@@ -2522,7 +2715,8 @@
     "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 */
+    "undefined operation",                                     /* VAR_ERR_UNDEFINED_OPERATION */
+    "formatting failure"                                       /* VAR_ERR_FORMATTING_FAILURE */
 };
 
 /* transslate a return code into its corresponding descriptive text */

CVSTrac 2.0.1