[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [trunnel/master] Teach trunnel to emit its C files, and store them as data.



commit 821423c0ac52ff438e1f8f81bc41e8d7c69f6b67
Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date:   Thu Sep 25 13:14:18 2014 -0400

    Teach trunnel to emit its C files, and store them as data.
---
 .gitignore                      |    2 +
 MANIFEST.in                     |    3 -
 c/trunnel.c                     |  242 -------------------------------
 include/trunnel-impl.h          |  306 ---------------------------------------
 include/trunnel.h               |   60 --------
 lib/trunnel/Boilerplate.py      |   63 ++++++++
 lib/trunnel/CodeGen.py          |    4 +-
 lib/trunnel/__main__.py         |   25 +++-
 lib/trunnel/data/trunnel-impl.h |  306 +++++++++++++++++++++++++++++++++++++++
 lib/trunnel/data/trunnel.c      |  242 +++++++++++++++++++++++++++++++
 lib/trunnel/data/trunnel.h      |   60 ++++++++
 setup.py                        |    3 +-
 test/Makefile                   |   15 +-
 test/run_tests.sh               |   11 +-
 14 files changed, 716 insertions(+), 626 deletions(-)

diff --git a/.gitignore b/.gitignore
index f944487..0efb950 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,8 @@ tests.log
 
 /test/valid/*.[ch]
 /test/ctest
+/test/include
+
 /doc/*.[ch]
 /doc/trunnel.html
 /doc/trunnel.txt
diff --git a/MANIFEST.in b/MANIFEST.in
index e9ebebe..4d96c8f 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,9 +2,6 @@ include README
 include LICENSE
 include test.sh
 
-include c/*.c
-include include/*.h
-
 include examples/*.trunnel
 
 include doc/*.md
diff --git a/c/trunnel.c b/c/trunnel.c
deleted file mode 100644
index 4bc28e3..0000000
--- a/c/trunnel.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/* trunnel.c -- Helper functions to implement trunnel.
- *
- * Copyright 2014, The Tor Project, Inc.
- * See license at the end of this file for copying information.
- *
- * See trunnel-impl.h for documentation of these functions.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "trunnel-impl.h"
-
-#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
-	__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#  define IS_LITTLE_ENDIAN 1
-#elif defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) &&     \
-	BYTE_ORDER == __ORDER_LITTLE_ENDIAN
-#  define IS_LITTLE_ENDIAN 1
-#elif defined(_WIN32)
-#  define IS_LITTLE_ENDIAN 1
-#elif defined(__APPLE__)
-#  include <libkern/OSByteOrder.h>
-#  define BSWAP64(x) OSSwapLittleToHostInt64(x)
-#elif defined(sun) || defined(__sun)
-#  include <sys/byteorder.h>
-#  ifndef _BIG_ENDIAN
-#    define IS_LITTLE_ENDIAN
-#  endif
-#else
-# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#  include <sys/endian.h>
-# else
-#  include <endian.h>
-# endif
-#  if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
-	__BYTE_ORDER == __LITTLE_ENDIAN
-#    define IS_LITTLE_ENDIAN
-#  endif
-#endif
-
-#ifdef _WIN32
-uint16_t
-trunnel_htons(uint16_t s)
-{
-  return (s << 8) | (s >> 8);
-}
-uint16_t
-trunnel_ntohs(uint16_t s)
-{
-  return (s << 8) | (s >> 8);
-}
-uint32_t
-trunnel_htonl(uint32_t s)
-{
-  return (s << 24) |
-         ((s << 8)&0xff0000) |
-         ((s >> 8)&0xff00) |
-         (s >> 24);
-}
-uint32_t
-trunnel_ntohl(uint32_t s)
-{
-  return (s << 24) |
-         ((s << 8)&0xff0000) |
-         ((s >> 8)&0xff00) |
-         (s >> 24);
-}
-#endif
-
-uint64_t
-trunnel_htonll(uint64_t a)
-{
-#ifdef IS_LITTLE_ENDIAN
-  return trunnel_htonl(a>>32) | (((uint64_t)trunnel_htonl(a))<<32);
-#else
-  return a;
-#endif
-}
-
-uint64_t
-trunnel_ntohll(uint64_t a)
-{
-  return trunnel_htonll(a);
-}
-
-#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
-/** Used for debugging and running tricky test cases: Makes the nth
- * memoryation allocation call from now fail.
- */
-int trunnel_provoke_alloc_failure = 0;
-#endif
-
-void *
-trunnel_dynarray_expand(size_t *allocated_p, void *ptr,
-                        size_t howmanymore, size_t eltsize)
-{
-  size_t newsize = howmanymore + *allocated_p;
-  void *newarray = NULL;
-  if (newsize < 8)
-    newsize = 8;
-  if (newsize < *allocated_p * 2)
-    newsize = *allocated_p * 2;
-  if (newsize <= *allocated_p || newsize < howmanymore)
-    return NULL;
-  newarray = trunnel_reallocarray(ptr, newsize, eltsize);
-  if (newarray == NULL)
-    return NULL;
-
-  *allocated_p = newsize;
-  return newarray;
-}
-
-#ifndef trunnel_reallocarray
-void *
-trunnel_reallocarray(void *a, size_t x, size_t y)
-{
-#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
-   if (trunnel_provoke_alloc_failure) {
-     if (--trunnel_provoke_alloc_failure == 0)
-       return NULL;
-   }
-#endif
-   if (x > SIZE_MAX / y)
-     return NULL;
-   return trunnel_realloc(a, x * y);
-}
-#endif
-
-const char *
-trunnel_string_getstr(trunnel_string_t *str)
-{
-  trunnel_assert(str->allocated_ >= str->n_);
-  if (str->allocated_ == str->n_) {
-    TRUNNEL_DYNARRAY_EXPAND(char, str, 1, {});
-  }
-  str->elts_[str->n_] = 0;
-  return str->elts_;
-trunnel_alloc_failed:
-  return NULL;
-}
-
-int
-trunnel_string_setstr0(trunnel_string_t *str, const char *val, size_t len,
-                       uint8_t *errcode_ptr)
-{
-  if (len == SIZE_MAX)
-    goto trunnel_alloc_failed;
-  if (str->allocated_ <= len) {
-    TRUNNEL_DYNARRAY_EXPAND(char, str, len + 1 - str->allocated_, {});
-  }
-  memcpy(str->elts_, val, len);
-  str->n_ = len;
-  str->elts_[len] = 0;
-  return 0;
-trunnel_alloc_failed:
-  *errcode_ptr = 1;
-  return -1;
-}
-
-int
-trunnel_string_setlen(trunnel_string_t *str, size_t newlen,
-                      uint8_t *errcode_ptr)
-{
-  if (newlen == SIZE_MAX)
-    goto trunnel_alloc_failed;
-  if (str->allocated_ < newlen + 1) {
-    TRUNNEL_DYNARRAY_EXPAND(char, str, newlen + 1 - str->allocated_, {});
-  }
-  if (str->n_ < newlen) {
-    memset(& (str->elts_[str->n_]), 0, (newlen - str->n_));
-  }
-  str->n_ = newlen;
-  str->elts_[newlen] = 0;
-  return 0;
-
- trunnel_alloc_failed:
-  *errcode_ptr = 1;
-  return -1;
-}
-
-void *
-trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p,
-                        void *ptr, size_t newlen,
-                        size_t eltsize, trunnel_free_fn_t free_fn,
-                        uint8_t *errcode_ptr)
-{
-  if (*allocated_p < newlen) {
-    void *newptr = trunnel_dynarray_expand(allocated_p, ptr,
-                                           newlen - *allocated_p, eltsize);
-    if (newptr == NULL)
-      goto trunnel_alloc_failed;
-    ptr = newptr;
-  }
-  if (free_fn && *len_p > newlen) {
-    size_t i;
-    void **elts = (void **) ptr;
-    for (i = newlen; i < *len_p; ++i) {
-      free_fn(elts[i]);
-      elts[i] = NULL;
-    }
-  }
-  if (*len_p < newlen) {
-    memset( ((char*)ptr) + (eltsize * *len_p), 0, (newlen - *len_p) * eltsize);
-  }
-  *len_p = newlen;
-  return ptr;
- trunnel_alloc_failed:
-  *errcode_ptr = 1;
-  return NULL;
-}
-
-/*
-Copyright 2014  The Tor Project, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-
-    * Neither the names of the copyright owners nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/include/trunnel-impl.h b/include/trunnel-impl.h
deleted file mode 100644
index 4dd710f..0000000
--- a/include/trunnel-impl.h
+++ /dev/null
@@ -1,306 +0,0 @@
-/* trunnel-impl.h -- Implementation helpers for trunnel, included by
- * generated trunnel files
- *
- * Copyright 2014, The Tor Project, Inc.
- * See license at the end of this file for copying information.
- */
-
-#ifndef TRUNNEL_IMPL_H_INCLUDED_
-#define TRUNNEL_IMPL_H_INCLUDED_
-#include "trunnel.h"
-#include <assert.h>
-#include <string.h>
-#ifdef TRUNNEL_LOCAL_H
-#include "trunnel-local.h"
-#endif
-
-#ifdef _MSC_VER
-#define uint8_t unsigned char
-#define uint16_t unsigned short
-#define uint32_t unsigned int
-#define uint64_t unsigned __int64
-#define inline __inline
-#else
-#include <stdint.h>
-#endif
-
-#ifdef _WIN32
-uint32_t trunnel_htonl(uint32_t a);
-uint32_t trunnel_ntohl(uint32_t a);
-uint16_t trunnel_htons(uint16_t a);
-uint16_t trunnel_ntohs(uint16_t a);
-#else
-#include <arpa/inet.h>
-#define trunnel_htonl(x) htonl(x)
-#define trunnel_htons(x) htons(x)
-#define trunnel_ntohl(x) ntohl(x)
-#define trunnel_ntohs(x) ntohs(x)
-#endif
-uint64_t trunnel_htonll(uint64_t a);
-uint64_t trunnel_ntohll(uint64_t a);
-
-#ifndef trunnel_assert
-#define trunnel_assert(x) assert(x)
-#endif
-
-static inline void
-trunnel_set_uint64(void *p, uint64_t v) {
-  memcpy(p, &v, 8);
-}
-static inline void
-trunnel_set_uint32(void *p, uint32_t v) {
-  memcpy(p, &v, 4);
-}
-static inline void
-trunnel_set_uint16(void *p, uint16_t v) {
-  memcpy(p, &v, 2);
-}
-static inline void
-trunnel_set_uint8(void *p, uint8_t v) {
-  memcpy(p, &v, 1);
-}
-
-static inline uint64_t
-trunnel_get_uint64(const void *p) {
-  uint64_t x;
-  memcpy(&x, p, 8);
-  return x;
-}
-static inline uint32_t
-trunnel_get_uint32(const void *p) {
-  uint32_t x;
-  memcpy(&x, p, 4);
-  return x;
-}
-static inline uint16_t
-trunnel_get_uint16(const void *p) {
-  uint16_t x;
-  memcpy(&x, p, 2);
-  return x;
-}
-static inline uint8_t
-trunnel_get_uint8(const void *p) {
-  return *(const uint8_t*)p;
-}
-
-
-#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
-extern int trunnel_provoke_alloc_failure;
-
-static inline void *
-trunnel_malloc(size_t n)
-{
-   if (trunnel_provoke_alloc_failure) {
-     if (--trunnel_provoke_alloc_failure == 0)
-       return NULL;
-   }
-   return malloc(n);
-}
-static inline void *
-trunnel_calloc(size_t a, size_t b)
-{
-   if (trunnel_provoke_alloc_failure) {
-     if (--trunnel_provoke_alloc_failure == 0)
-       return NULL;
-   }
-   return calloc(a,b);
-}
-static inline char *
-trunnel_strdup(const char *s)
-{
-   if (trunnel_provoke_alloc_failure) {
-     if (--trunnel_provoke_alloc_failure == 0)
-       return NULL;
-   }
-   return strdup(s);
-}
-#else
-#ifndef trunnel_malloc
-#define trunnel_malloc(x) (malloc((x)))
-#endif
-#ifndef trunnel_calloc
-#define trunnel_calloc(a,b) (calloc((a),(b)))
-#endif
-#ifndef trunnel_strdup
-#define trunnel_strdup(s) (strdup((s)))
-#endif
-#endif
-
-#ifndef trunnel_realloc
-#define trunnel_realloc(a,b) realloc((a),(b))
-#endif
-
-#ifndef trunnel_free_
-#define trunnel_free_(x) (free(x))
-#endif
-#define trunnel_free(x) ((x) ? (trunnel_free_(x),0) : (0))
-
-#ifndef trunnel_abort
-#define trunnel_abort() abort()
-#endif
-
-#ifndef trunnel_memwipe
-#define trunnel_memwipe(mem, len) ((void)0)
-#define trunnel_wipestr(s) ((void)0)
-#else
-#define trunnel_wipestr(s) do {                 \
-    if (s)                                      \
-      trunnel_memwipe(s, strlen(s));            \
-  } while (0)
-#endif
-
-/* ====== dynamic arrays ======== */
-
-#ifdef NDEBUG
-#define TRUNNEL_DYNARRAY_GET(da, n)             \
-  ((da)->elts_[(n)])
-#else
-/** Return the 'n'th element of 'da'. */
-#define TRUNNEL_DYNARRAY_GET(da, n)             \
-  (((n) >= (da)->n_ ? (trunnel_abort(),0) : 0), (da)->elts_[(n)])
-#endif
-
-/** Change the 'n'th element of 'da' to 'v'. */
-#define TRUNNEL_DYNARRAY_SET(da, n, v) do {                    \
-    trunnel_assert((n) < (da)->n_);                            \
-    (da)->elts_[(n)] = (v);                                    \
-  } while (0)
-
-/** Expand the dynamic array 'da' of 'elttype' so that it can hold at least
- * 'howmanymore' elements than its current capacity. Always tries to increase
- * the length of the array. On failure, run the code in 'on_fail' and goto
- * trunnel_alloc_failed. */
-#define TRUNNEL_DYNARRAY_EXPAND(elttype, da, howmanymore, on_fail) do { \
-    elttype *newarray;                                               \
-    newarray = trunnel_dynarray_expand(&(da)->allocated_,            \
-                                       (da)->elts_, (howmanymore),   \
-                                       sizeof(elttype));             \
-    if (newarray == NULL) {                                          \
-      on_fail;                                                       \
-      goto trunnel_alloc_failed;                                     \
-    }                                                                \
-    (da)->elts_ = newarray;                                          \
-  } while (0)
-
-/** Add 'v' to the end of the dynamic array 'da' of 'elttype', expanding it if
- * necessary.  code in 'on_fail' and goto trunnel_alloc_failed. */
-#define TRUNNEL_DYNARRAY_ADD(elttype, da, v, on_fail) do { \
-      if ((da)->n_ == (da)->allocated_) {                  \
-        TRUNNEL_DYNARRAY_EXPAND(elttype, da, 1, on_fail);  \
-      }                                                    \
-      (da)->elts_[(da)->n_++] = (v);                       \
-    } while (0)
-
-/** Return the number of elements in 'da'. */
-#define TRUNNEL_DYNARRAY_LEN(da) ((da)->n_)
-
-/** Remove all storage held by 'da' and set it to be empty.  Does not free
- * storage held by the elements themselves. */
-#define TRUNNEL_DYNARRAY_CLEAR(da) do {           \
-    trunnel_free((da)->elts_);                    \
-    (da)->elts_ = NULL;                           \
-    (da)->n_ = (da)->allocated_ = 0;              \
-  } while (0)
-
-/** Remove all storage held by 'da' and set it to be empty.  Does not free
- * storage held by the elements themselves. */
-#define TRUNNEL_DYNARRAY_WIPE(da) do {                                  \
-    trunnel_memwipe((da)->elts_, (da)->allocated_ * sizeof((da)->elts_[0])); \
-  } while (0)
-
-/** Helper: wraps or implements an OpenBSD-style reallocarray.  Behaves
- * as realloc(a, x*y), but verifies that no overflow will occur in the
- * multiplication. Returns NULL on failure. */
-#ifndef trunnel_reallocarray
-void *trunnel_reallocarray(void *a, size_t x, size_t y);
-#endif
-
-/** Helper to expand a dynamic array. Behaves as TRUNNEL_DYNARRAY_EXPAND(),
- * taking the array of elements in 'ptr', a pointer to thethe current number
- * of allocated elements in allocated_p, the minimum numbeer of elements to
- * add in 'howmanymore', and the size of a single element in 'eltsize'.
- *
- * On success, adjust *allocated_p, and return the new value for the array of
- * elements.  On failure, adjust nothing and return NULL.
- */
-void *trunnel_dynarray_expand(size_t *allocated_p, void *ptr,
-                              size_t howmanymore, size_t eltsize);
-
-/** Type for a function to free members of a dynarray of pointers. */
-typedef void (*trunnel_free_fn_t)(void *);
-
-/**
- * Helper to change the length of a dynamic array. Takes pointers to the
- * current allocated and n fields of the array in 'allocated_p' and 'len_p',
- * and the current array of elements in 'ptr'; takes the length of a single
- * element in 'eltsize'.  Changes the length to 'newlen'.  If 'newlen' is
- * greater than the current length, pads the new elements with 0.  If newlen
- * is less than the current length, and free_fn is non-NULL, treat the
- * array as an array of void *, and invoke free_fn() on each removed element.
- *
- * On success, adjust *allocated_p and *len_p, and return the new value for
- * the array of elements.  On failure, adjust nothing, set *errcode_ptr to 1,
- * and return NULL.
- */
-void *trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p,
-                              void *ptr, size_t newlen,
-                              size_t eltsize, trunnel_free_fn_t free_fn,
-                              uint8_t *errcode_ptr);
-
-/**
- * Helper: return a pointer to the value of 'str' as a NUL-terminated string.
- * Might have to reallocate the storage for 'str' in order to fit in the final
- * NUL character.  On allocation failure, return NULL.
- */
-const char *trunnel_string_getstr(trunnel_string_t *str);
-
-/**
- * Helper: change the contents of 'str' to hold the 'len'-byte string in
- * 'inp'.  Adjusts the storage to have a terminating NUL that doesn't count
- * towards the length of the string.  On success, return 0.  On failure, set
- * *errcode_ptr to 1 and return -1.
- */
-int trunnel_string_setstr0(trunnel_string_t *str, const char *inp, size_t len,
-                           uint8_t *errcode_ptr);
-
-/**
- * As trunnel_dynarray_setlen, but adjusts a string rather than a dynamic
- * array, and ensures that the new string is NUL-terminated.
- */
-int trunnel_string_setlen(trunnel_string_t *str, size_t newlen,
-                           uint8_t *errcode_ptr);
-
-#endif
-
-
-/*
-Copyright 2014  The Tor Project, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-
-    * Neither the names of the copyright owners nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/include/trunnel.h b/include/trunnel.h
deleted file mode 100644
index 0a78e6c..0000000
--- a/include/trunnel.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* trunnel.h -- Public declarations for trunnel, to be included
- * in trunnel header files.
-
- * Copyright 2014, The Tor Project, Inc.
- * See license at the end of this file for copying information.
- */
-
-#ifndef TRUNNEL_H_INCLUDED_
-#define TRUNNEL_H_INCLUDED_
-
-#include <sys/types.h>
-
-/** Macro to declare a variable-length dynamically allocated array.  Trunnel
- * uses these to store all variable-length arrays. */
-#define TRUNNEL_DYNARRAY_HEAD(name, elttype)       \
-  struct name {                                    \
-    size_t n_;                                     \
-    size_t allocated_;                             \
-    elttype *elts_;                                \
-  }
-
-/** Initializer for a dynamic array of a given element type. */
-#define TRUNNEL_DYNARRAY_INIT(elttype) { 0, 0, (elttype*)NULL }
-
-/** Typedef used for storing variable-length arrays of char. */
-typedef TRUNNEL_DYNARRAY_HEAD(trunnel_string_st, char) trunnel_string_t;
-
-#endif
-
-/*
-Copyright 2014  The Tor Project, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-
-    * Neither the names of the copyright owners nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/lib/trunnel/Boilerplate.py b/lib/trunnel/Boilerplate.py
new file mode 100644
index 0000000..221d09e
--- /dev/null
+++ b/lib/trunnel/Boilerplate.py
@@ -0,0 +1,63 @@
+# CodeGen.py -- code generator for trunnel.
+#
+# Copyright 2014, The Tor Project, Inc.
+# See license at the end of this file for copying information.
+
+import os
+import trunnel
+
+FILES = [ "trunnel.c", "trunnel.h", "trunnel-impl.h" ]
+
+def emit(target_dir=None):
+    if target_dir == None:
+        target_dir = '.'
+    directory = os.path.split(__file__)[0]
+    if not os.path.exists(target_dir):
+        os.makedirs(target_dir)
+    for f in FILES:
+        emitfile(f,
+                 os.path.join(directory, "data", f),
+                 os.path.join(target_dir, f))
+
+def emitfile(fname, in_fname, out_fname):
+    settings = {
+        'fname' : 'fname',
+        'version' : trunnel.__version__
+        }
+    with open(in_fname, 'r') as inp, open(out_fname, 'w') as out:
+        out.write("/* %(fname)s -- copied from Trunnel v%(version)s\n"
+                  " * https://gitweb.torproject.org/trunnel.git\n";
+                  " */\n")
+        out.write(inp.read())
+
+__license__ = """
+Copyright 2014  The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+    * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""
diff --git a/lib/trunnel/CodeGen.py b/lib/trunnel/CodeGen.py
index 90178fc..cb779c9 100644
--- a/lib/trunnel/CodeGen.py
+++ b/lib/trunnel/CodeGen.py
@@ -2749,7 +2749,7 @@ MODULE_BOILERPLATE = """\
 """
 
 
-def generate_code(input_fname, extra_options=[]):
+def generate_code(input_fname, extra_options=[], target_dir=None):
     """Read a trunnel file from 'input_fname' and write the result to
        appropriate output files.  If 'extra_options' is set, add those
        options as though they had been specified in the file with
@@ -2758,6 +2758,8 @@ def generate_code(input_fname, extra_options=[]):
     basename = input_fname
     if basename.endswith(".trunnel"):
         basename = basename[:-len(".trunnel")]
+    if target_dir != None:
+        basename = os.path.join(target_dir, os.path.split(basename)[1])
 
     c_fname = basename + ".c"
     h_fname = basename + ".h"
diff --git a/lib/trunnel/__main__.py b/lib/trunnel/__main__.py
index 68ed405..99b7fd4 100644
--- a/lib/trunnel/__main__.py
+++ b/lib/trunnel/__main__.py
@@ -5,23 +5,36 @@
 
 if __name__ == '__main__':
     import sys
+    import trunnel.Boilerplate
     import trunnel.CodeGen
     import getopt
 
-    opts, args = getopt.gnu_getopt(sys.argv[1:], "O:", ["option="])
-
-    if len(args) < 1:
-        sys.stderr.write("Syntax: python -m trunnel.Main <fname>\n")
-        sys.exit(1)
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "O:",
+                                   ["option=","write-c-files","target-dir="])
 
     more_options = []
+    target_dir = None
+    write_c_files = None
 
     for (k, v) in opts:
         if k in ('-O', '--option'):
             more_options.append(v)
+        elif k == '--write-c-files':
+            write_c_files = True
+        elif k == '--target-dir':
+            target_dir = v
+
+    if len(args) < 1 and not write_c_files:
+        sys.stderr.write("Syntax: python -m trunnel <fname>\n")
+        sys.exit(1)
 
     for filename in args:
-        trunnel.CodeGen.generate_code(filename, more_options)
+        trunnel.CodeGen.generate_code(filename, more_options,
+                                      target_dir=target_dir)
+
+    if write_c_files:
+        trunnel.Boilerplate.emit(target_dir=target_dir)
+
 
 __license__ = """
 Copyright 2014  The Tor Project, Inc.
diff --git a/lib/trunnel/data/trunnel-impl.h b/lib/trunnel/data/trunnel-impl.h
new file mode 100644
index 0000000..4dd710f
--- /dev/null
+++ b/lib/trunnel/data/trunnel-impl.h
@@ -0,0 +1,306 @@
+/* trunnel-impl.h -- Implementation helpers for trunnel, included by
+ * generated trunnel files
+ *
+ * Copyright 2014, The Tor Project, Inc.
+ * See license at the end of this file for copying information.
+ */
+
+#ifndef TRUNNEL_IMPL_H_INCLUDED_
+#define TRUNNEL_IMPL_H_INCLUDED_
+#include "trunnel.h"
+#include <assert.h>
+#include <string.h>
+#ifdef TRUNNEL_LOCAL_H
+#include "trunnel-local.h"
+#endif
+
+#ifdef _MSC_VER
+#define uint8_t unsigned char
+#define uint16_t unsigned short
+#define uint32_t unsigned int
+#define uint64_t unsigned __int64
+#define inline __inline
+#else
+#include <stdint.h>
+#endif
+
+#ifdef _WIN32
+uint32_t trunnel_htonl(uint32_t a);
+uint32_t trunnel_ntohl(uint32_t a);
+uint16_t trunnel_htons(uint16_t a);
+uint16_t trunnel_ntohs(uint16_t a);
+#else
+#include <arpa/inet.h>
+#define trunnel_htonl(x) htonl(x)
+#define trunnel_htons(x) htons(x)
+#define trunnel_ntohl(x) ntohl(x)
+#define trunnel_ntohs(x) ntohs(x)
+#endif
+uint64_t trunnel_htonll(uint64_t a);
+uint64_t trunnel_ntohll(uint64_t a);
+
+#ifndef trunnel_assert
+#define trunnel_assert(x) assert(x)
+#endif
+
+static inline void
+trunnel_set_uint64(void *p, uint64_t v) {
+  memcpy(p, &v, 8);
+}
+static inline void
+trunnel_set_uint32(void *p, uint32_t v) {
+  memcpy(p, &v, 4);
+}
+static inline void
+trunnel_set_uint16(void *p, uint16_t v) {
+  memcpy(p, &v, 2);
+}
+static inline void
+trunnel_set_uint8(void *p, uint8_t v) {
+  memcpy(p, &v, 1);
+}
+
+static inline uint64_t
+trunnel_get_uint64(const void *p) {
+  uint64_t x;
+  memcpy(&x, p, 8);
+  return x;
+}
+static inline uint32_t
+trunnel_get_uint32(const void *p) {
+  uint32_t x;
+  memcpy(&x, p, 4);
+  return x;
+}
+static inline uint16_t
+trunnel_get_uint16(const void *p) {
+  uint16_t x;
+  memcpy(&x, p, 2);
+  return x;
+}
+static inline uint8_t
+trunnel_get_uint8(const void *p) {
+  return *(const uint8_t*)p;
+}
+
+
+#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
+extern int trunnel_provoke_alloc_failure;
+
+static inline void *
+trunnel_malloc(size_t n)
+{
+   if (trunnel_provoke_alloc_failure) {
+     if (--trunnel_provoke_alloc_failure == 0)
+       return NULL;
+   }
+   return malloc(n);
+}
+static inline void *
+trunnel_calloc(size_t a, size_t b)
+{
+   if (trunnel_provoke_alloc_failure) {
+     if (--trunnel_provoke_alloc_failure == 0)
+       return NULL;
+   }
+   return calloc(a,b);
+}
+static inline char *
+trunnel_strdup(const char *s)
+{
+   if (trunnel_provoke_alloc_failure) {
+     if (--trunnel_provoke_alloc_failure == 0)
+       return NULL;
+   }
+   return strdup(s);
+}
+#else
+#ifndef trunnel_malloc
+#define trunnel_malloc(x) (malloc((x)))
+#endif
+#ifndef trunnel_calloc
+#define trunnel_calloc(a,b) (calloc((a),(b)))
+#endif
+#ifndef trunnel_strdup
+#define trunnel_strdup(s) (strdup((s)))
+#endif
+#endif
+
+#ifndef trunnel_realloc
+#define trunnel_realloc(a,b) realloc((a),(b))
+#endif
+
+#ifndef trunnel_free_
+#define trunnel_free_(x) (free(x))
+#endif
+#define trunnel_free(x) ((x) ? (trunnel_free_(x),0) : (0))
+
+#ifndef trunnel_abort
+#define trunnel_abort() abort()
+#endif
+
+#ifndef trunnel_memwipe
+#define trunnel_memwipe(mem, len) ((void)0)
+#define trunnel_wipestr(s) ((void)0)
+#else
+#define trunnel_wipestr(s) do {                 \
+    if (s)                                      \
+      trunnel_memwipe(s, strlen(s));            \
+  } while (0)
+#endif
+
+/* ====== dynamic arrays ======== */
+
+#ifdef NDEBUG
+#define TRUNNEL_DYNARRAY_GET(da, n)             \
+  ((da)->elts_[(n)])
+#else
+/** Return the 'n'th element of 'da'. */
+#define TRUNNEL_DYNARRAY_GET(da, n)             \
+  (((n) >= (da)->n_ ? (trunnel_abort(),0) : 0), (da)->elts_[(n)])
+#endif
+
+/** Change the 'n'th element of 'da' to 'v'. */
+#define TRUNNEL_DYNARRAY_SET(da, n, v) do {                    \
+    trunnel_assert((n) < (da)->n_);                            \
+    (da)->elts_[(n)] = (v);                                    \
+  } while (0)
+
+/** Expand the dynamic array 'da' of 'elttype' so that it can hold at least
+ * 'howmanymore' elements than its current capacity. Always tries to increase
+ * the length of the array. On failure, run the code in 'on_fail' and goto
+ * trunnel_alloc_failed. */
+#define TRUNNEL_DYNARRAY_EXPAND(elttype, da, howmanymore, on_fail) do { \
+    elttype *newarray;                                               \
+    newarray = trunnel_dynarray_expand(&(da)->allocated_,            \
+                                       (da)->elts_, (howmanymore),   \
+                                       sizeof(elttype));             \
+    if (newarray == NULL) {                                          \
+      on_fail;                                                       \
+      goto trunnel_alloc_failed;                                     \
+    }                                                                \
+    (da)->elts_ = newarray;                                          \
+  } while (0)
+
+/** Add 'v' to the end of the dynamic array 'da' of 'elttype', expanding it if
+ * necessary.  code in 'on_fail' and goto trunnel_alloc_failed. */
+#define TRUNNEL_DYNARRAY_ADD(elttype, da, v, on_fail) do { \
+      if ((da)->n_ == (da)->allocated_) {                  \
+        TRUNNEL_DYNARRAY_EXPAND(elttype, da, 1, on_fail);  \
+      }                                                    \
+      (da)->elts_[(da)->n_++] = (v);                       \
+    } while (0)
+
+/** Return the number of elements in 'da'. */
+#define TRUNNEL_DYNARRAY_LEN(da) ((da)->n_)
+
+/** Remove all storage held by 'da' and set it to be empty.  Does not free
+ * storage held by the elements themselves. */
+#define TRUNNEL_DYNARRAY_CLEAR(da) do {           \
+    trunnel_free((da)->elts_);                    \
+    (da)->elts_ = NULL;                           \
+    (da)->n_ = (da)->allocated_ = 0;              \
+  } while (0)
+
+/** Remove all storage held by 'da' and set it to be empty.  Does not free
+ * storage held by the elements themselves. */
+#define TRUNNEL_DYNARRAY_WIPE(da) do {                                  \
+    trunnel_memwipe((da)->elts_, (da)->allocated_ * sizeof((da)->elts_[0])); \
+  } while (0)
+
+/** Helper: wraps or implements an OpenBSD-style reallocarray.  Behaves
+ * as realloc(a, x*y), but verifies that no overflow will occur in the
+ * multiplication. Returns NULL on failure. */
+#ifndef trunnel_reallocarray
+void *trunnel_reallocarray(void *a, size_t x, size_t y);
+#endif
+
+/** Helper to expand a dynamic array. Behaves as TRUNNEL_DYNARRAY_EXPAND(),
+ * taking the array of elements in 'ptr', a pointer to thethe current number
+ * of allocated elements in allocated_p, the minimum numbeer of elements to
+ * add in 'howmanymore', and the size of a single element in 'eltsize'.
+ *
+ * On success, adjust *allocated_p, and return the new value for the array of
+ * elements.  On failure, adjust nothing and return NULL.
+ */
+void *trunnel_dynarray_expand(size_t *allocated_p, void *ptr,
+                              size_t howmanymore, size_t eltsize);
+
+/** Type for a function to free members of a dynarray of pointers. */
+typedef void (*trunnel_free_fn_t)(void *);
+
+/**
+ * Helper to change the length of a dynamic array. Takes pointers to the
+ * current allocated and n fields of the array in 'allocated_p' and 'len_p',
+ * and the current array of elements in 'ptr'; takes the length of a single
+ * element in 'eltsize'.  Changes the length to 'newlen'.  If 'newlen' is
+ * greater than the current length, pads the new elements with 0.  If newlen
+ * is less than the current length, and free_fn is non-NULL, treat the
+ * array as an array of void *, and invoke free_fn() on each removed element.
+ *
+ * On success, adjust *allocated_p and *len_p, and return the new value for
+ * the array of elements.  On failure, adjust nothing, set *errcode_ptr to 1,
+ * and return NULL.
+ */
+void *trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p,
+                              void *ptr, size_t newlen,
+                              size_t eltsize, trunnel_free_fn_t free_fn,
+                              uint8_t *errcode_ptr);
+
+/**
+ * Helper: return a pointer to the value of 'str' as a NUL-terminated string.
+ * Might have to reallocate the storage for 'str' in order to fit in the final
+ * NUL character.  On allocation failure, return NULL.
+ */
+const char *trunnel_string_getstr(trunnel_string_t *str);
+
+/**
+ * Helper: change the contents of 'str' to hold the 'len'-byte string in
+ * 'inp'.  Adjusts the storage to have a terminating NUL that doesn't count
+ * towards the length of the string.  On success, return 0.  On failure, set
+ * *errcode_ptr to 1 and return -1.
+ */
+int trunnel_string_setstr0(trunnel_string_t *str, const char *inp, size_t len,
+                           uint8_t *errcode_ptr);
+
+/**
+ * As trunnel_dynarray_setlen, but adjusts a string rather than a dynamic
+ * array, and ensures that the new string is NUL-terminated.
+ */
+int trunnel_string_setlen(trunnel_string_t *str, size_t newlen,
+                           uint8_t *errcode_ptr);
+
+#endif
+
+
+/*
+Copyright 2014  The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+    * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/lib/trunnel/data/trunnel.c b/lib/trunnel/data/trunnel.c
new file mode 100644
index 0000000..4bc28e3
--- /dev/null
+++ b/lib/trunnel/data/trunnel.c
@@ -0,0 +1,242 @@
+/* trunnel.c -- Helper functions to implement trunnel.
+ *
+ * Copyright 2014, The Tor Project, Inc.
+ * See license at the end of this file for copying information.
+ *
+ * See trunnel-impl.h for documentation of these functions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "trunnel-impl.h"
+
+#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
+	__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define IS_LITTLE_ENDIAN 1
+#elif defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) &&     \
+	BYTE_ORDER == __ORDER_LITTLE_ENDIAN
+#  define IS_LITTLE_ENDIAN 1
+#elif defined(_WIN32)
+#  define IS_LITTLE_ENDIAN 1
+#elif defined(__APPLE__)
+#  include <libkern/OSByteOrder.h>
+#  define BSWAP64(x) OSSwapLittleToHostInt64(x)
+#elif defined(sun) || defined(__sun)
+#  include <sys/byteorder.h>
+#  ifndef _BIG_ENDIAN
+#    define IS_LITTLE_ENDIAN
+#  endif
+#else
+# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#  include <sys/endian.h>
+# else
+#  include <endian.h>
+# endif
+#  if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+	__BYTE_ORDER == __LITTLE_ENDIAN
+#    define IS_LITTLE_ENDIAN
+#  endif
+#endif
+
+#ifdef _WIN32
+uint16_t
+trunnel_htons(uint16_t s)
+{
+  return (s << 8) | (s >> 8);
+}
+uint16_t
+trunnel_ntohs(uint16_t s)
+{
+  return (s << 8) | (s >> 8);
+}
+uint32_t
+trunnel_htonl(uint32_t s)
+{
+  return (s << 24) |
+         ((s << 8)&0xff0000) |
+         ((s >> 8)&0xff00) |
+         (s >> 24);
+}
+uint32_t
+trunnel_ntohl(uint32_t s)
+{
+  return (s << 24) |
+         ((s << 8)&0xff0000) |
+         ((s >> 8)&0xff00) |
+         (s >> 24);
+}
+#endif
+
+uint64_t
+trunnel_htonll(uint64_t a)
+{
+#ifdef IS_LITTLE_ENDIAN
+  return trunnel_htonl(a>>32) | (((uint64_t)trunnel_htonl(a))<<32);
+#else
+  return a;
+#endif
+}
+
+uint64_t
+trunnel_ntohll(uint64_t a)
+{
+  return trunnel_htonll(a);
+}
+
+#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
+/** Used for debugging and running tricky test cases: Makes the nth
+ * memoryation allocation call from now fail.
+ */
+int trunnel_provoke_alloc_failure = 0;
+#endif
+
+void *
+trunnel_dynarray_expand(size_t *allocated_p, void *ptr,
+                        size_t howmanymore, size_t eltsize)
+{
+  size_t newsize = howmanymore + *allocated_p;
+  void *newarray = NULL;
+  if (newsize < 8)
+    newsize = 8;
+  if (newsize < *allocated_p * 2)
+    newsize = *allocated_p * 2;
+  if (newsize <= *allocated_p || newsize < howmanymore)
+    return NULL;
+  newarray = trunnel_reallocarray(ptr, newsize, eltsize);
+  if (newarray == NULL)
+    return NULL;
+
+  *allocated_p = newsize;
+  return newarray;
+}
+
+#ifndef trunnel_reallocarray
+void *
+trunnel_reallocarray(void *a, size_t x, size_t y)
+{
+#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
+   if (trunnel_provoke_alloc_failure) {
+     if (--trunnel_provoke_alloc_failure == 0)
+       return NULL;
+   }
+#endif
+   if (x > SIZE_MAX / y)
+     return NULL;
+   return trunnel_realloc(a, x * y);
+}
+#endif
+
+const char *
+trunnel_string_getstr(trunnel_string_t *str)
+{
+  trunnel_assert(str->allocated_ >= str->n_);
+  if (str->allocated_ == str->n_) {
+    TRUNNEL_DYNARRAY_EXPAND(char, str, 1, {});
+  }
+  str->elts_[str->n_] = 0;
+  return str->elts_;
+trunnel_alloc_failed:
+  return NULL;
+}
+
+int
+trunnel_string_setstr0(trunnel_string_t *str, const char *val, size_t len,
+                       uint8_t *errcode_ptr)
+{
+  if (len == SIZE_MAX)
+    goto trunnel_alloc_failed;
+  if (str->allocated_ <= len) {
+    TRUNNEL_DYNARRAY_EXPAND(char, str, len + 1 - str->allocated_, {});
+  }
+  memcpy(str->elts_, val, len);
+  str->n_ = len;
+  str->elts_[len] = 0;
+  return 0;
+trunnel_alloc_failed:
+  *errcode_ptr = 1;
+  return -1;
+}
+
+int
+trunnel_string_setlen(trunnel_string_t *str, size_t newlen,
+                      uint8_t *errcode_ptr)
+{
+  if (newlen == SIZE_MAX)
+    goto trunnel_alloc_failed;
+  if (str->allocated_ < newlen + 1) {
+    TRUNNEL_DYNARRAY_EXPAND(char, str, newlen + 1 - str->allocated_, {});
+  }
+  if (str->n_ < newlen) {
+    memset(& (str->elts_[str->n_]), 0, (newlen - str->n_));
+  }
+  str->n_ = newlen;
+  str->elts_[newlen] = 0;
+  return 0;
+
+ trunnel_alloc_failed:
+  *errcode_ptr = 1;
+  return -1;
+}
+
+void *
+trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p,
+                        void *ptr, size_t newlen,
+                        size_t eltsize, trunnel_free_fn_t free_fn,
+                        uint8_t *errcode_ptr)
+{
+  if (*allocated_p < newlen) {
+    void *newptr = trunnel_dynarray_expand(allocated_p, ptr,
+                                           newlen - *allocated_p, eltsize);
+    if (newptr == NULL)
+      goto trunnel_alloc_failed;
+    ptr = newptr;
+  }
+  if (free_fn && *len_p > newlen) {
+    size_t i;
+    void **elts = (void **) ptr;
+    for (i = newlen; i < *len_p; ++i) {
+      free_fn(elts[i]);
+      elts[i] = NULL;
+    }
+  }
+  if (*len_p < newlen) {
+    memset( ((char*)ptr) + (eltsize * *len_p), 0, (newlen - *len_p) * eltsize);
+  }
+  *len_p = newlen;
+  return ptr;
+ trunnel_alloc_failed:
+  *errcode_ptr = 1;
+  return NULL;
+}
+
+/*
+Copyright 2014  The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+    * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/lib/trunnel/data/trunnel.h b/lib/trunnel/data/trunnel.h
new file mode 100644
index 0000000..0a78e6c
--- /dev/null
+++ b/lib/trunnel/data/trunnel.h
@@ -0,0 +1,60 @@
+/* trunnel.h -- Public declarations for trunnel, to be included
+ * in trunnel header files.
+
+ * Copyright 2014, The Tor Project, Inc.
+ * See license at the end of this file for copying information.
+ */
+
+#ifndef TRUNNEL_H_INCLUDED_
+#define TRUNNEL_H_INCLUDED_
+
+#include <sys/types.h>
+
+/** Macro to declare a variable-length dynamically allocated array.  Trunnel
+ * uses these to store all variable-length arrays. */
+#define TRUNNEL_DYNARRAY_HEAD(name, elttype)       \
+  struct name {                                    \
+    size_t n_;                                     \
+    size_t allocated_;                             \
+    elttype *elts_;                                \
+  }
+
+/** Initializer for a dynamic array of a given element type. */
+#define TRUNNEL_DYNARRAY_INIT(elttype) { 0, 0, (elttype*)NULL }
+
+/** Typedef used for storing variable-length arrays of char. */
+typedef TRUNNEL_DYNARRAY_HEAD(trunnel_string_st, char) trunnel_string_t;
+
+#endif
+
+/*
+Copyright 2014  The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+    * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/setup.py b/setup.py
index 6d10939..99012c6 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,8 @@ setup(name='Trunnel',
       author='Nick Mathewson',
       author_email='nickm@xxxxxxxxxxxxxx',
       url='https://gitweb.torproject.org/trunnel.git/',
-      package_dir={'': 'lib'},
       packages=['trunnel'],
+      package_dir={'': 'lib'},
+      package_data={'trunnel' : ['data/*.c', 'data/*.h']},
       license='3-clause BSD'
       )
diff --git a/test/Makefile b/test/Makefile
index 8bca859..ba70e8d 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -7,7 +7,7 @@
 MORE_CFLAGS=-fno-inline --coverage
 
 CC=gcc
-CFLAGS=-g -O0 -fstack-protector-all -Wstack-protector -fwrapv --param ssp-buffer-size=1 -fPIE -fasynchronous-unwind-tables -Wall -fno-strict-aliasing -Wno-deprecated-declarations -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition -Waddress -Wmissing-noreturn -Wstrict-overflow=1 -I . -I ../include -DTRUNNEL_DEBUG_FAILING_ALLOC -DTRUNNEL_CHECK_ENCODED_LEN $(MORE_CFLAGS)
+CFLAGS=-g -O0 -fstack-protector-all -Wstack-protector -fwrapv --param ssp-buffer-size=1 -fPIE -fasynchronous-unwind-tables -Wall -fno-strict-aliasing -Wno-deprecated-declarations -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition -Waddress -Wmissing-noreturn -Wstrict-overflow=1 -I . -I ./include -DTRUNNEL_DEBUG_FAILING_ALLOC -DTRUNNEL_CHECK_ENCODED_LEN $(MORE_CFLAGS)
 #OTHER_FLAGS= -Qunused-arguments -Wshorten-64-to-32
 
 TEST_OBJS = \
@@ -33,13 +33,18 @@ TEST_OBJS = \
     c/test_remainder_repeats.o \
     c/test_util.o
 
+BOILERPLATE_FILES=\
+    ./include/trunnel.c \
+    ./include/trunnel.h \
+    ./include/trunnel-impl.h \
+
 OBJS=tinytest/tinytest.o \
     valid/simple.o \
     valid/derived.o \
     valid/opaque.o \
     valid/leftover.o \
     valid/contexts.o \
-    ../c/trunnel.o \
+    ./include/trunnel.o \
     $(TEST_OBJS)
 
 all: ctest
@@ -54,7 +59,7 @@ reset-gcov:
 	rm -f */*.gcda ../*/*.gcda
 
 distclean: clean
-	rm -f valid/*.[ch]
+	rm -f valid/*.[ch] include/*.[ch]
 
 test: ctest
 	./ctest
@@ -65,6 +70,7 @@ valid/opaque.o: valid/opaque.h valid/opaque.h
 valid/leftover.o: valid/leftover.h valid/leftover.c
 valid/contexts.o: valid/contexts.h
 $(TEST_OBJS) : tinytest/tinytest.h tinytest/tinytest_macros.h valid/simple.h valid/derived.h
+$(OBJS) : include/trunnel.h include/trunnel-impl.h
 tinytest/tinytest.o: tinytest/tinytest.h tinytest/tinytest_macros.h
 
 valid/simple.c valid/simple.h: valid/simple.trunnel ../lib/trunnel/*py
@@ -82,4 +88,5 @@ valid/leftover.c valid/leftover.h: valid/leftover.trunnel ../lib/trunnel/*py
 valid/contexts.c valid/contexts.h: valid/contexts.trunnel ../lib/trunnel/*py
 	PYTHONPATH=../lib:${PYTHONPATH} python -m trunnel valid/contexts.trunnel
 
-
+$(BOILERPLATE_FILES): ../lib/trunnel/*py ../lib/trunnel/data/*.[ch]
+	PYTHONPATH=../lib:${PYTHONPATH} python -m trunnel --target-dir=./include --write-c-files
diff --git a/test/run_tests.sh b/test/run_tests.sh
index 176cfa7..c66b604 100755
--- a/test/run_tests.sh
+++ b/test/run_tests.sh
@@ -8,12 +8,13 @@
 # Copyright 2014 The Tor Project, Inc.
 # See LICENSE file for copying information.
 
-export PYTHONPATH=../lib:${PYTHONPATH}
+export PYTHONPATH=`dirname $0`/../lib:${PYTHONPATH}
 GRAMMAR=`dirname $0`/../lib/trunnel/Grammar.py
 CODEGEN=`dirname $0`/../lib/trunnel/CodeGen.py
 TRUNNEL=`dirname $0`/../lib/trunnel/__main__.py
+BOILERPLATE=`dirname $0`/../lib/trunnel/Boilerplate.py
 CC=gcc
-CFLAGS="-g -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all -Wstack-protector -fwrapv --param ssp-buffer-size=1 -fPIE -fasynchronous-unwind-tables -Wall -fno-strict-aliasing -Wno-deprecated-declarations -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition -Waddress -Wmissing-noreturn -Wstrict-overflow=1 -I `dirname $0`/../include"
+CFLAGS="-g -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all -Wstack-protector -fwrapv --param ssp-buffer-size=1 -fPIE -fasynchronous-unwind-tables -Wall -fno-strict-aliasing -Wno-deprecated-declarations -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition -Waddress -Wmissing-noreturn -Wstrict-overflow=1 -I `dirname $0`/include/"
 X=" -Wshorten-64-to-32  -Qunused-arguments"
 
 PYTHON=python
@@ -37,6 +38,8 @@ for fn in `dirname $0`/failing/*.trunnel; do
   $RUN $TRUNNEL $fn 2>>tests.log && echo "SHOULD HAVE FAILED: $fn"
 done
 
+$RUN $TRUNNEL --target-dir=`dirname $0`/include --write-c-files
+
 # Try valid tests.
 for fn in `dirname $0`/valid/*.trunnel; do
   echo >>tests.log "==== $fn"
@@ -49,7 +52,9 @@ echo >>tests.log "==== MakeGrammar"
 $RUN $GRAMMAR > grammar.tmp 2>>tests.log || echo "FAILED: grammar"
 rm -f grammar.tmp
 
-$COVERAGE report $TRUNNEL $GRAMMAR $CODEGEN
+$COVERAGE report $TRUNNEL $GRAMMAR $CODEGEN $BOILERPLATE
 $COVERAGE annotate $TRUNNEL
 $COVERAGE annotate $GRAMMAR
 $COVERAGE annotate $CODEGEN
+$COVERAGE annotate $BOILERPLATE
+

_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits