<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.
</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/d24f1d50c27f86fa05aa0fac209b6468b07f4940">https://github.com/macports/macports-legacy-support/commit/d24f1d50c27f86fa05aa0fac209b6468b07f4940</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'> new d24f1d5 stdio.h: add open_memstream of (OS X < 10.13)
</span>d24f1d5 is described below
<span style='display:block; white-space:pre;color:#808000;'>commit d24f1d50c27f86fa05aa0fac209b6468b07f4940
</span>Author: Dennis Camera <dennis.camera@riiengineering.ch>
AuthorDate: Fri Jun 30 14:09:17 2023 +0200
<span style='display:block; white-space:pre;color:#404040;'> stdio.h: add open_memstream of (OS X < 10.13)
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> The implementation originates from https://piumarta.com/software/memstream/
</span>---
README.md | 9 +-
include/MacportsLegacySupport.h | 3 +
include/stdio.h | 9 ++
src/memstream.c | 180 ++++++++++++++++++++++++++++++++++++++++
test/test_open_memstream.c | 29 +++++++
5 files changed, 226 insertions(+), 4 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/README.md b/README.md
</span><span style='display:block; white-space:pre;color:#808080;'>index 28669fb..c271050 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/README.md
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/README.md
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -59,19 +59,20 @@ Wrapped headers and replaced functions are:
</span> <td>Adds declaration of <code>AI_NUMERICSERV</code></td>
<td>OSX10.5</td>
</tr>
<span style='display:block; white-space:pre;background:#ffe0e0;'>- <tr>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ <tr>
</span> <td rowspan="2"><code>pthread.h</code></td>
<td>Adds <code>PTHREAD_RWLOCK_INITIALIZER</code></td>
<td>OSX10.4</td>
</tr>
<span style='display:block; white-space:pre;background:#ffe0e0;'>- <tr>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ <tr>
</span> <td>Adds <code>pthread_setname_np</code> function</td>
<td>OSX10.5</td>
</tr>
<tr>
<td><code>stdio.h</code></td>
<span style='display:block; white-space:pre;background:#ffe0e0;'>- <td>Adds <code>dprintf</code>, <code>getline</code>, and <code>getdelim</code> functions</td>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- <td>OSX10.6</td>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ <td>Adds <code>dprintf</code>, <code>getline</code>, <code>getdelim</code>,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ and <code>open_memstream</code> functions</td>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ <td>OSX10.6, OSX10.12 (open_memstream)</td>
</span> </tr>
<tr>
<td rowspan="2"><code>stdlib.h</code></td>
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/include/MacportsLegacySupport.h b/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;color:#808080;'>index e38d319..98c58ea 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -151,6 +151,9 @@
</span> /* flsll */
#define __MP_LEGACY_SUPPORT_FLSLL__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1090)
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* open_memstream */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define __MP_LEGACY_SUPPORT_OPEN_MEMSTREAM__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* pthread_setname_np */
#define __MP_LEGACY_SUPPORT_PTHREAD_SETNAME_NP__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/include/stdio.h b/include/stdio.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 77a0b88..e3e3897 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/include/stdio.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/include/stdio.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -58,6 +58,15 @@ __MP__END_DECLS
</span>
#endif /* __MP_LEGACY_SUPPORT_GETLINE__ */
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* open_memstream */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __MP_LEGACY_SUPPORT_OPEN_MEMSTREAM__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__MP__BEGIN_DECLS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+FILE *open_memstream(char **ptr, size_t *sizeloc);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__MP__END_DECLS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MP_LEGACY_SUPPORT_OPEN_MEMSTREAM__ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* renameat */
#if __MP_LEGACY_SUPPORT_ATCALLS__
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/memstream.c b/src/memstream.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..f52b55d
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/memstream.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,180 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* memstream.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * This file is licensed under the MIT license by
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2013 Ian Piumarta.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Modifications for inclusion in macports-legacy-support
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2023 Dennis Camera.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ----------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OPEN_MEMSTREAM(3) BSD and Linux Library Functions OPEN_MEMSTREAM(3)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * SYNOPSIS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * FILE *open_memstream(char **bufp, size_t *sizep);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * DESCRIPTION
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * The open_memstream() function opens a stream for writing to a buffer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * The buffer is dynamically allocated (as with malloc(3)), and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * automatically grows as required. After closing the stream, the caller
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * should free(3) this buffer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * When the stream is closed (fclose(3)) or flushed (fflush(3)), the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * locations pointed to by bufp and sizep are updated to contain,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * respectively, a pointer to the buffer and the current size of the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * buffer. These values remain valid only as long as the caller performs
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * no further output on the stream. If further output is performed, then
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * the stream must again be flushed before trying to access these
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * variables.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * A null byte is maintained at the end of the buffer. This byte is not
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * included in the size value stored at sizep.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * The stream's file position can be changed with fseek(3) or fseeko(3).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Moving the file position past the end of the data already written fills
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * the intervening space with zeros.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * RETURN VALUE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Upon successful completion open_memstream() returns a FILE pointer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Otherwise, NULL is returned and errno is set to indicate the error.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * CONFORMING TO
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * POSIX.1-2008
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ----------------------------------------------------------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* MP support header */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "MacportsLegacySupport.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __MP_LEGACY_SUPPORT_OPEN_MEMSTREAM__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "stdio.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stddef.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <string.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <errno.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <assert.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define min(X, Y) (((X) < (Y)) ? (X) : (Y))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+struct memstream
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int position;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int size;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int capacity;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *contents;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char **ptr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t *sizeloc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if MEMSTREAM_DEBUG
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static void memstream_print(struct memstream *ms)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf("memstream %p {", ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf(" %i", ms->position);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf(" %i", ms->size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf(" %i", ms->capacity);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf(" %p", ms->contents);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf(" }\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# define memstream_info(ARGS) printf ARGS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# define memstream_print(ms)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# define memstream_info(ARGS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define memstream_check(MS) if (!(MS)->contents) { errno= ENOMEM; return -1; }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int memstream_grow(struct memstream *ms, int minsize)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int newcap= ms->capacity * 2; memstream_check(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ while (newcap <= minsize) newcap *= 2; memstream_info(("grow %p to %i\n", ms, newcap));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->contents= realloc(ms->contents, newcap);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!ms->contents) return -1; /* errno == ENOMEM */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memset(ms->contents + ms->capacity, 0, newcap - ms->capacity);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->capacity= newcap;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *ms->ptr= ms->contents; /* size has not changed */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int memstream_read(void *cookie, char *buf, int count)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct memstream *ms= (struct memstream *)cookie; memstream_check(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int n= min(ms->size - ms->position, count); memstream_info(("memstream_read %p %i\n", ms, count));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (n < 1) return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memcpy(buf, ms->contents, n);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->position += n; memstream_print(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return n;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int memstream_write(void *cookie, const char *buf, int count)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct memstream *ms= (struct memstream *)cookie; memstream_check(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ms->capacity <= ms->position + count)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (memstream_grow(ms, ms->position + count) < 0) /* errno == ENOMEM */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memcpy(ms->contents + ms->position, buf, count); memstream_info(("memstream_write %p %i\n", ms, count));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->position += count;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ms->size < ms->position) *ms->sizeloc= ms->size= ms->position; memstream_print(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(ms->size < ms->capacity);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(ms->contents[ms->size] == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return count;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static fpos_t memstream_seek(void *cookie, fpos_t offset, int whence)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct memstream *ms= (struct memstream *)cookie;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fpos_t pos= 0; memstream_check(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memstream_info(("memstream_seek %p %i %i\n", ms, (int)offset, whence));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ switch (whence) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case SEEK_SET: pos= offset; break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case SEEK_CUR: pos= ms->position + offset; break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case SEEK_END: pos= ms->size + offset; break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ default: errno= EINVAL; return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (pos >= ms->capacity) memstream_grow(ms, pos);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->position= pos;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ms->size < ms->position) *ms->sizeloc= ms->size= ms->position; memstream_print(ms); memstream_info(("=> %i\n", (int)pos));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(ms->size < ms->capacity && ms->contents[ms->size] == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return pos;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int memstream_close(void *cookie)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct memstream *ms= (struct memstream *)cookie; if (!ms->contents) { free(ms); errno= ENOMEM; return -1; }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->size= min(ms->size, ms->position);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *ms->ptr= ms->contents;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *ms->sizeloc= ms->size; assert(ms->size < ms->capacity);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->contents[ms->size]= 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+FILE *open_memstream(char **ptr, size_t *sizeloc)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ptr && sizeloc) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct memstream *ms= calloc(1, sizeof(struct memstream));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp= 0; if (!ms) return 0; /* errno == ENOMEM */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->position= ms->size= 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->capacity= 4096;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->contents= calloc(ms->capacity, 1); if (!ms->contents) { free(ms); return 0; } /* errno == ENOMEM */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->ptr= ptr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ms->sizeloc= sizeloc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memstream_print(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp= funopen(ms, memstream_read, memstream_write, memstream_seek, memstream_close);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!fp) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ms->contents);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ms);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 0; /* errno set by funopen */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *ptr= ms->contents;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *sizeloc= ms->size;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno= EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MP_LEGACY_SUPPORT_OPEN_MEMSTREAM__ */
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_open_memstream.c b/test/test_open_memstream.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..a35b024
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_open_memstream.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,29 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*#include "memstream.h"*/
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdio.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <assert.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int main()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *buffer = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t size = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp = open_memstream(&buffer, &size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (i = 0; i < 10240; ++i) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static char c = 42;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fflush(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(size == i);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fwrite(&c, 1, 1, fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(size == 10240);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(buffer);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = open_memstream(&buffer, &size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(fp, "This is a test of memstream, from main at %p.\n", main);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fputs(buffer, stdout);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(buffer);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span></pre><pre style='margin:0'>
</pre>