[augeas-devel] [PATCH 2 of 7] Work around lack of open_memstream on non-GNU systems

David Lutterkort dlutter at redhat.com
Thu May 29 23:56:44 UTC 2008


4 files changed, 108 insertions(+), 32 deletions(-)
configure.ac   |    1 
src/builtin.c  |   28 ++++++++----------
src/internal.c |   84 ++++++++++++++++++++++++++++++++++++++++++++------------
src/internal.h |   27 ++++++++++++++++++


# HG changeset patch
# User David Lutterkort <dlutter at redhat.com>
# Date 1212104441 25200
# Node ID 15f4b0a2233f3be09f47f5e7993ce8b950bb6956
# Parent  60d5b5f6f78ec966fcfc14fe0bdda60cd69c4a4a
Work around lack of open_memstream on non-GNU systems

Since open_memstream is only available with glibc, wrap its use and fall
back to writing to a tempfile on other platforms.

diff -r 60d5b5f6f78e -r 15f4b0a2233f configure.ac
--- a/configure.ac	Thu May 29 16:39:23 2008 -0700
+++ b/configure.ac	Thu May 29 16:40:41 2008 -0700
@@ -15,6 +15,7 @@ AC_SUBST(AUGEAS_CFLAGS)
 AC_SUBST(AUGEAS_CFLAGS)
 
 AUGEAS_CHECK_READLINE
+AC_CHECK_FUNCS([open_memstream])
 
 AC_OUTPUT(Makefile
           src/Makefile
diff -r 60d5b5f6f78e -r 15f4b0a2233f src/builtin.c
--- a/src/builtin.c	Thu May 29 16:39:23 2008 -0700
+++ b/src/builtin.c	Thu May 29 16:40:41 2008 -0700
@@ -24,6 +24,7 @@
 #include <stdarg.h>
 
 #include "syntax.h"
+#include "memory.h"
 
 #define UNIMPL_BODY(name)                       \
     {                                           \
@@ -96,14 +97,13 @@ static struct value *make_exn_lns_error(
 }
 
 static void exn_print_tree(struct value *exn, struct tree *tree) {
-    FILE *stream;
-    char *buf;
-    size_t size;
+    struct memstream ms;
 
-    stream = open_memstream(&buf, &size);
-    print_tree(tree, stream, "/*", 1);
-    fclose (stream);
-    exn_printf_line(exn, "%s", buf);
+    init_memstream(&ms);
+    print_tree(tree, ms.stream, "/*", 1);
+    close_memstream(&ms);
+    exn_printf_line(exn, "%s", ms.buf);
+    FREE(ms.buf);
 }
 
 /* V_LENS -> V_STRING -> V_TREE */
@@ -139,23 +139,21 @@ static struct value *lens_put(struct inf
     assert(tree->tag == V_TREE);
     assert(str->tag == V_STRING);
 
-    FILE *stream;
-    char *buf;
-    size_t size;
+    struct memstream ms;
     struct value *v;
     struct lns_error *err;
 
-    stream = open_memstream(&buf, &size);
-    lns_put(stream, l->lens, tree->tree, str->string->str, &err);
-    fclose (stream);
+    init_memstream(&ms);
+    lns_put(ms.stream, l->lens, tree->tree, str->string->str, &err);
+    close_memstream(&ms);
 
     if (err == NULL) {
         v = make_value(V_STRING, ref(info));
-        v->string = make_string(buf);
+        v->string = make_string(ms.buf);
     } else {
         v = make_exn_lns_error(info, err, str->string->str);
         free_lns_error(err);
-        free(buf);
+        FREE(ms.buf);
     }
     return v;
 }
diff -r 60d5b5f6f78e -r 15f4b0a2233f src/internal.c
--- a/src/internal.c	Thu May 29 16:39:23 2008 -0700
+++ b/src/internal.c	Thu May 29 16:40:41 2008 -0700
@@ -227,27 +227,77 @@ int print_chars(FILE *out, const char *t
 }
 
 char *format_pos(const char *text, int pos) {
-    char *buf;
-    size_t size;
-    FILE *stream = open_memstream(&buf, &size);
-    print_pos(stream, text, pos);
-    fclose(stream);
+    static const int window = 28;
+    char *buf = NULL, *left = NULL, *right = NULL;
+    int before = pos;
+    int llen, rlen;
+    int r;
+
+    if (before > window)
+        before = window;
+    left = escape(text + pos - before, before);
+    if (left == NULL)
+        goto done;
+    right = escape(text + pos, window);
+    if (right == NULL)
+        goto done;
+
+    llen = strlen(left);
+    rlen = strlen(right);
+    if (llen < window && rlen < window) {
+        r = asprintf(&buf, "%*s%s|=|%s%-*s\n", window - llen, "<", left,
+                     right, window - rlen, ">");
+    } else if (strlen(left) < window) {
+        r = asprintf(&buf, "%*s%s|=|%s>\n", window - llen, "<", left, right);
+    } else if (strlen(right) < window) {
+        r = asprintf(&buf, "<%s|=|%s%-*s\n", left, right, window - rlen, ">");
+    } else {
+        r = asprintf(&buf, "<%s|=|%s>\n", left, right);
+    }
+    if (r < 0) {
+        buf = NULL;
+    }
+
+ done:
+    free(left);
+    free(right);
     return buf;
 }
 
 void print_pos(FILE *out, const char *text, int pos) {
-    static const int window = 28;
-    int before = pos;
-    int total;
-    if (before > window)
-        before = window;
-    total = print_chars(NULL, text + pos - before, before);
-    if (total < window)
-        fprintf(out, "%*s", window - total, "<");
-    print_chars(out, text + pos - before, before);
-    fprintf(out, "|=|");
-    total = print_chars(out, text + pos, window);
-    fprintf(out, "%*s\n", window - total, ">");
+    char *format = format_pos(text, pos);
+
+    if (format != NULL) {
+        fputs(format, out);
+        FREE(format);
+    }
+}
+
+int init_memstream(struct memstream *ms) {
+    MEMZERO(ms, 1);
+#if HAVE_OPEN_MEMSTREAM
+    ms->stream = open_memstream(&(ms->buf), &(ms->size));
+    return ms->stream == NULL ? -1 : 0;
+#else
+    ms->stream = tmpfile();
+    if (ms->stream == NULL) {
+        return -1;
+    }
+    return 0;
+#endif
+}
+
+int close_memstream(struct memstream *ms) {
+#if !HAVE_OPEN_MEMSTREAM
+    rewind(ms->stream);
+    ms->buf = fread_file_lim(ms->stream, MAX_READ_LEN, &(ms->size));
+#endif
+    if (fclose(ms->stream) == EOF) {
+        FREE(ms->buf);
+        ms->size = 0;
+        return -1;
+    }
+    return 0;
 }
 
 
diff -r 60d5b5f6f78e -r 15f4b0a2233f src/internal.h
--- a/src/internal.h	Thu May 29 16:39:23 2008 -0700
+++ b/src/internal.h	Thu May 29 16:40:41 2008 -0700
@@ -256,6 +256,33 @@ int print_tree(const struct tree *tree, 
                int pr_hidden);
 int tree_equal(const struct tree *t1, const struct tree *t2);
 
+/* Wrappers to simulate OPEN_MEMSTREAM where that's not available. The
+ * STREAM member is opened by INIT_MEMSTREAM and closed by
+ * CLOSE_MEMSTREAM. The BUF is allocated automatically, but can not be used
+ * until after CLOSE_MEMSTREAM has been called. It is the callers
+ * responsibility to free up BUF.
+ */
+struct memstream {
+    FILE   *stream;
+    char   *buf;
+    size_t size;
+};
+
+/* Initialize a memstream. On systems that have OPEN_MEMSTREAM, it is used
+ * to open MS->STREAM. On systems without OPEN_MEMSTREAM, MS->STREAM is
+ * backed by a temporary file.
+ *
+ * MS must be allocated in advance; INIT_MEMSTREAM initializes it.
+ */
+int init_memstream(struct memstream *ms);
+
+/* Close a memstream. After calling this, MS->STREAM can not be used
+ * anymore and a string representing whatever was written to it is
+ * available in MS->BUF. The caller must free MS->BUF.
+ *
+ * The caller must free the MEMSTREAM structure.
+ */
+int close_memstream(struct memstream *ms);
 #endif
 
 




More information about the augeas-devel mailing list