[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