changeset 1881:a5b08bdfa450

New header file scheme to support FFI code in either of C or C++ [based on suggestion by Ron de Bruijn]
author Adam Chlipala <adam@chlipala.net>
date Fri, 11 Oct 2013 17:15:28 -0400
parents 0354df1b6849
children 77cde56d41b6
files doc/manual.tex include/urweb/types.h include/urweb/types_cpp.h include/urweb/urweb.h include/urweb/urweb_cpp.h
diffstat 5 files changed, 495 insertions(+), 479 deletions(-) [+]
line wrap: on
line diff
--- a/doc/manual.tex	Thu Oct 10 18:31:10 2013 -0400
+++ b/doc/manual.tex	Fri Oct 11 17:15:28 2013 -0400
@@ -139,13 +139,13 @@
 \item \texttt{alwaysInline PATH} requests that every call to the referenced function be inlined.  Section \ref{structure} explains how functions are assigned path strings.
 \item \texttt{benignEffectful Module.ident} registers an FFI function or transaction as having side effects.  The optimizer avoids removing, moving, or duplicating calls to such functions.  Every effectful FFI function must be registered, or the optimizer may make invalid transformations.  This version of the \texttt{effectful} directive registers that this function only has side effects that remain local to a single page generation.
 \item \texttt{clientOnly Module.ident} registers an FFI function or transaction that may only be run in client browsers.
-\item \texttt{clientToServer Module.ident} adds FFI type \texttt{Module.ident} to the list of types that are OK to marshal from clients to servers.  Values like XML trees and SQL queries are hard to marshal without introducing expensive validity checks, so it's easier to ensure that the server never trusts clients to send such values.  The file \texttt{include/urweb.h} shows examples of the C support functions that are required of any type that may be marshalled.  These include \texttt{attrify}, \texttt{urlify}, and \texttt{unurlify} functions.
+\item \texttt{clientToServer Module.ident} adds FFI type \texttt{Module.ident} to the list of types that are OK to marshal from clients to servers.  Values like XML trees and SQL queries are hard to marshal without introducing expensive validity checks, so it's easier to ensure that the server never trusts clients to send such values.  The file \texttt{include/urweb/urweb\_cpp.h} shows examples of the C support functions that are required of any type that may be marshalled.  These include \texttt{attrify}, \texttt{urlify}, and \texttt{unurlify} functions.
 \item \texttt{coreInline TREESIZE} sets how many nodes the AST of a function definition may have before the optimizer stops trying hard to inline calls to that function.  (This is one of two options for one of two intermediate languages within the compiler.)
 \item \texttt{database DBSTRING} sets the string to pass to libpq to open a database connection.
 \item \texttt{debug} saves some intermediate C files, which is mostly useful to help in debugging the compiler itself.
 \item \texttt{effectful Module.ident} registers an FFI function or transaction as having side effects.  The optimizer avoids removing, moving, or duplicating calls to such functions.  This is the default behavior for \texttt{transaction}-based types.
 \item \texttt{exe FILENAME} sets the filename to which to write the output executable.  The default for file \texttt{P.urp} is \texttt{P.exe}.  
-\item \texttt{ffi FILENAME} reads the file \texttt{FILENAME.urs} to determine the interface to a new FFI module.  The name of the module is calculated from \texttt{FILENAME} in the same way as for normal source files.  See the files \texttt{include/urweb.h} and \texttt{src/c/urweb.c} for examples of C headers and implementations for FFI modules.  In general, every type or value \texttt{Module.ident} becomes \texttt{uw\_Module\_ident} in C.
+\item \texttt{ffi FILENAME} reads the file \texttt{FILENAME.urs} to determine the interface to a new FFI module.  The name of the module is calculated from \texttt{FILENAME} in the same way as for normal source files.  See the files \texttt{include/urweb/urweb\_cpp.h} and \texttt{src/c/urweb.c} for examples of C headers and implementations for FFI modules.  In general, every type or value \texttt{Module.ident} becomes \texttt{uw\_Module\_ident} in C.
 \item \texttt{include FILENAME} adds \texttt{FILENAME} to the list of files to be \texttt{\#include}d in C sources.  This is most useful for interfacing with new FFI modules.
 \item \texttt{jsFunc Module.ident=name} gives the JavaScript name of an FFI value.
 \item \texttt{library FILENAME} parses \texttt{FILENAME.urp} and merges its contents with the rest of the current file's contents.  If \texttt{FILENAME.urp} doesn't exist, the compiler also tries \texttt{FILENAME/lib.urp}.
@@ -2394,16 +2394,18 @@
 
 \subsection{Writing C FFI Code}
 
+C source files connecting to the Ur/Web FFI should include \texttt{urweb.h}, and C++ source files should include \texttt{urweb\_cpp.h}.
+
 A server-side FFI type or value \texttt{Module.ident} must have a corresponding type or value definition \texttt{uw\_Module\_ident} in C code.  With the current Ur/Web version, it's not generally possible to work with Ur records or complex datatypes in C code, but most other kinds of types are fair game.
 
 \begin{itemize}
-  \item Primitive types defined in \texttt{Basis} are themselves using the standard FFI interface, so you may refer to them like \texttt{uw\_Basis\_t}.  See \texttt{include/types.h} for their definitions.
+  \item Primitive types defined in \texttt{Basis} are themselves using the standard FFI interface, so you may refer to them like \texttt{uw\_Basis\_t}.  See \texttt{include/urweb/types.h} for their definitions.
   \item Enumeration datatypes, which have only constructors that take no arguments, should be defined using C \texttt{enum}s.  The type is named as for any other type identifier, and each constructor \texttt{c} gets an enumeration constant named \texttt{uw\_Module\_c}.
   \item A datatype \texttt{dt} (such as \texttt{Basis.option}) that has one non-value-carrying constructor \texttt{NC} and one value-carrying constructor \texttt{C} gets special treatment.  Where \texttt{T} is the type of \texttt{C}'s argument, and where we represent \texttt{T} as \texttt{t} in C, we represent \texttt{NC} with \texttt{NULL}.  The representation of \texttt{C} depends on whether we're sure that we don't need to use \texttt{NULL} to represent \texttt{t} values; this condition holds only for strings and complex datatypes.  For such types, \texttt{C v} is represented with the C encoding of \texttt{v}, such that the translation of \texttt{dt} is \texttt{t}.  For other types, \texttt{C v} is represented with a pointer to the C encoding of v, such that the translation of \texttt{dt} is \texttt{t*}.
   \item Ur/Web involves many types of program syntax, such as for HTML and SQL code.  All of these types are implemented with normal C strings, and you may take advantage of that encoding to manipulate code as strings in C FFI code.  Be mindful that, in writing such code, it is your responsibility to maintain the appropriate code invariants, or you may reintroduce the code injection vulnerabilities that Ur/Web rules out.  The most convenient way to extend Ur/Web with functions that, e.g., use natively unsupported HTML tags is to generate the HTML code with the FFI.
 \end{itemize}
 
-The C FFI version of a Ur function with type \texttt{T1 -> ... -> TN -> R} or \texttt{T1 -> ... -> TN -> transaction R} has a C prototype like \texttt{R uw\_Module\_ident(uw\_context, T1, ..., TN)}.  Only functions with types of the second form may have side effects.  \texttt{uw\_context} is the type of state that persists across handling a client request.  Many functions that operate on contexts are prototyped in \texttt{include/urweb.h}.  Most should only be used internally by the compiler.  A few are useful in general FFI implementation:
+The C FFI version of a Ur function with type \texttt{T1 -> ... -> TN -> R} or \texttt{T1 -> ... -> TN -> transaction R} has a C prototype like \texttt{R uw\_Module\_ident(uw\_context, T1, ..., TN)}.  Only functions with types of the second form may have side effects.  \texttt{uw\_context} is the type of state that persists across handling a client request.  Many functions that operate on contexts are prototyped in \texttt{include/urweb/urweb\_cpp.h}.  Most should only be used internally by the compiler.  A few are useful in general FFI implementation:
 \begin{itemize}
   \item \begin{verbatim}
 void uw_error(uw_context, failure_kind, const char *fmt, ...);
--- a/include/urweb/types.h	Thu Oct 10 18:31:10 2013 -0400
+++ b/include/urweb/types.h	Fri Oct 11 17:15:28 2013 -0400
@@ -1,116 +1,9 @@
 #ifndef URWEB_TYPES_H
 #define URWEB_TYPES_H
 
-#include <time.h>
-#include <unistd.h>
-#include <stdint.h>
-
-typedef long long uw_Basis_int;
-typedef double uw_Basis_float;
-typedef char* uw_Basis_string;
-typedef char uw_Basis_char;
-typedef struct {
-  time_t seconds;
-  unsigned microseconds;
-} uw_Basis_time;
-typedef struct {
-  size_t size;
-  char *data;
-} uw_Basis_blob;
-
-typedef int uw_unit;
-typedef uw_unit uw_Basis_unit;
-
-typedef enum uw_Basis_bool { uw_Basis_False, uw_Basis_True } uw_Basis_bool;
+#include "types_cpp.h"
 
 typedef struct uw_context *uw_context;
-
-typedef uw_Basis_string uw_Basis_xhtml;
-typedef uw_Basis_string uw_Basis_page;
-typedef uw_Basis_string uw_Basis_xbody;
-typedef uw_Basis_string uw_Basis_css_class;
-
-typedef unsigned uw_Basis_client;
-typedef struct {
-  unsigned cli, chn;
-} uw_Basis_channel;
-
-typedef struct {
-  int context;
-  unsigned long long source;
-} uw_Basis_source;
-
-typedef struct uw_Basis_file {
-  uw_Basis_string name, type;
-  uw_Basis_blob data;
-} uw_Basis_file;
-
-typedef struct uw_Basis_postBody {
-  uw_Basis_string type, data;
-  size_t len;
-} uw_Basis_postBody;
-
-typedef uw_Basis_string uw_Basis_queryString;
-
-typedef struct {
-  uw_Basis_string name, value, remaining;
-} uw_Basis_postField;
-
-typedef enum { SUCCESS, FATAL, BOUNDED_RETRY, UNLIMITED_RETRY, RETURN_INDIRECTLY } failure_kind;
-
-typedef enum { SERVED, KEEP_OPEN, FAILED } request_result;
-
 typedef struct input *uw_input;
 
-#define INTS_MAX 50
-#define FLOATS_MAX 100
-#define TIMES_MAX 100
-
-typedef void (*uw_callback)(void *);
-typedef void (*uw_callback_with_retry)(void *, int will_retry);
-typedef void (*uw_logger)(void*, const char *fmt, ...);
-
-typedef struct {
-  void (*callback)(uw_context);
-  unsigned int period;
-} uw_periodic;
-
-typedef struct {
-  int inputs_len, timeout;
-  char *url_prefix;
-
-  void (*client_init)();
-  void (*initializer)(uw_context);
-  void (*expunger)(uw_context, uw_Basis_client);
-
-  void (*db_init)(uw_context);
-  int (*db_begin)(uw_context);
-  int (*db_commit)(uw_context);
-  int (*db_rollback)(uw_context);
-  void (*db_close)(uw_context);
-
-  void (*handle)(uw_context, char *);
-
-  int (*input_num)(const char*);
-  uw_Basis_string (*cookie_sig)(uw_context);
-  int (*check_url)(const char *);
-  int (*check_mime)(const char *);
-  int (*check_requestHeader)(const char *);
-  int (*check_responseHeader)(const char *);
-  int (*check_envVar)(const char *);
-
-  void (*on_error)(uw_context, char *);
-
-  uw_periodic *periodics; // 0-terminated array
-
-  uw_Basis_string time_format;
-} uw_app;
-
-#define ERROR_BUF_LEN 1024
-
-typedef struct {
-  size_t max;
-  char *start, *front, *back;
-} uw_buffer;
-
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/urweb/types_cpp.h	Fri Oct 11 17:15:28 2013 -0400
@@ -0,0 +1,114 @@
+#ifndef URWEB_TYPES_CPP_H
+#define URWEB_TYPES_CPP_H
+
+#include <time.h>
+#include <unistd.h>
+#include <stdint.h>
+
+typedef long long uw_Basis_int;
+typedef double uw_Basis_float;
+typedef char* uw_Basis_string;
+typedef char uw_Basis_char;
+typedef struct {
+  time_t seconds;
+  unsigned microseconds;
+} uw_Basis_time;
+typedef struct {
+  size_t size;
+  char *data;
+} uw_Basis_blob;
+
+typedef int uw_unit;
+typedef uw_unit uw_Basis_unit;
+
+typedef enum uw_Basis_bool { uw_Basis_False, uw_Basis_True } uw_Basis_bool;
+
+typedef uw_Basis_string uw_Basis_xhtml;
+typedef uw_Basis_string uw_Basis_page;
+typedef uw_Basis_string uw_Basis_xbody;
+typedef uw_Basis_string uw_Basis_css_class;
+
+typedef unsigned uw_Basis_client;
+typedef struct {
+  unsigned cli, chn;
+} uw_Basis_channel;
+
+typedef struct {
+  int context;
+  unsigned long long source;
+} uw_Basis_source;
+
+typedef struct uw_Basis_file {
+  uw_Basis_string name, type;
+  uw_Basis_blob data;
+} uw_Basis_file;
+
+typedef struct uw_Basis_postBody {
+  uw_Basis_string type, data;
+  size_t len;
+} uw_Basis_postBody;
+
+typedef uw_Basis_string uw_Basis_queryString;
+
+typedef struct {
+  uw_Basis_string name, value, remaining;
+} uw_Basis_postField;
+
+typedef enum { SUCCESS, FATAL, BOUNDED_RETRY, UNLIMITED_RETRY, RETURN_INDIRECTLY } failure_kind;
+
+typedef enum { SERVED, KEEP_OPEN, FAILED } request_result;
+
+#define INTS_MAX 50
+#define FLOATS_MAX 100
+#define TIMES_MAX 100
+
+typedef void (*uw_callback)(void *);
+typedef void (*uw_callback_with_retry)(void *, int will_retry);
+typedef void (*uw_logger)(void*, const char *fmt, ...);
+
+struct uw_context;
+
+typedef struct {
+  void (*callback)(struct uw_context *);
+  unsigned int period;
+} uw_periodic;
+
+typedef struct {
+  int inputs_len, timeout;
+  char *url_prefix;
+
+  void (*client_init)();
+  void (*initializer)(struct uw_context *);
+  void (*expunger)(struct uw_context *, uw_Basis_client);
+
+  void (*db_init)(struct uw_context *);
+  int (*db_begin)(struct uw_context *);
+  int (*db_commit)(struct uw_context *);
+  int (*db_rollback)(struct uw_context *);
+  void (*db_close)(struct uw_context *);
+
+  void (*handle)(struct uw_context *, char *);
+
+  int (*input_num)(const char*);
+  uw_Basis_string (*cookie_sig)(struct uw_context *);
+  int (*check_url)(const char *);
+  int (*check_mime)(const char *);
+  int (*check_requestHeader)(const char *);
+  int (*check_responseHeader)(const char *);
+  int (*check_envVar)(const char *);
+
+  void (*on_error)(struct uw_context *, char *);
+
+  uw_periodic *periodics; // 0-terminated array
+
+  uw_Basis_string time_format;
+} uw_app;
+
+#define ERROR_BUF_LEN 1024
+
+typedef struct {
+  size_t max;
+  char *start, *front, *back;
+} uw_buffer;
+
+#endif
--- a/include/urweb/urweb.h	Thu Oct 10 18:31:10 2013 -0400
+++ b/include/urweb/urweb.h	Fri Oct 11 17:15:28 2013 -0400
@@ -1,373 +1,7 @@
 #ifndef URWEB_H
 #define URWEB_H
 
-#include <sys/types.h>
-
 #include "types.h"
-
-int uw_really_send(int sock, const void *buf, ssize_t len);
-int uw_really_write(int fd, const void *buf, size_t len);
-
-extern uw_unit uw_unit_v;
-
-void uw_global_init(void);
-void uw_app_init(uw_app*);
-
-void uw_client_connect(unsigned id, int pass, int sock,
-                       int (*send)(int sockfd, const void *buf, size_t len),
-                       int (*close)(int fd),
-                       void *logger_data, uw_logger log_error);
-void uw_prune_clients(uw_context);
-failure_kind uw_initialize(uw_context);
-
-uw_context uw_init(int id, void *logger_data, uw_logger log_debug);
-void uw_close(uw_context);
-int uw_set_app(uw_context, uw_app*);
-uw_app *uw_get_app(uw_context);
-void uw_set_db(uw_context, void*);
-void *uw_get_db(uw_context);
-void uw_free(uw_context);
-void uw_reset(uw_context);
-void uw_reset_keep_request(uw_context);
-void uw_reset_keep_error_message(uw_context);
-char *uw_get_url_prefix(uw_context);
-
-failure_kind uw_begin_init(uw_context);
-void uw_set_on_success(char *);
-void uw_set_headers(uw_context, char *(*get_header)(void *, const char *), void *get_header_data);
-void uw_set_env(uw_context, char *(*get_env)(void *, const char *), void *get_env_data);
-failure_kind uw_begin(uw_context, char *path);
-failure_kind uw_begin_onError(uw_context, char *msg);
-void uw_login(uw_context);
-void uw_commit(uw_context);
-int uw_rollback(uw_context, int will_retry);
-
-__attribute__((noreturn)) void uw_error(uw_context, failure_kind, const char *fmt, ...);
-char *uw_error_message(uw_context);
-void uw_set_error_message(uw_context, const char *fmt, ...);
-uw_Basis_string uw_dup_and_clear_error_message(uw_context);
-int uw_has_error(uw_context);
-void uw_push_cleanup(uw_context, void (*func)(void *), void *arg);
-void uw_pop_cleanup(uw_context);
-
-void *uw_malloc(uw_context, size_t);
-void uw_begin_region(uw_context);
-void uw_end_region(uw_context);
-void uw_memstats(uw_context);
-
-int uw_send(uw_context, int sock);
-int uw_print(uw_context, int fd);
-int uw_output(uw_context ctx, int (*output)(void *data, const char *buf, size_t len), void *data);
-
-int uw_set_input(uw_context, const char *name, char *value);
-int uw_set_file_input(uw_context, char *name, uw_Basis_file);
-
-char *uw_get_input(uw_context, int name);
-char *uw_get_optional_input(uw_context, int name);
-uw_Basis_file uw_get_file_input(uw_context, int name);
-void uw_enter_subform(uw_context, int name);
-void uw_leave_subform(uw_context);
-int uw_enter_subforms(uw_context, int name);
-int uw_next_entry(uw_context);
-
-void uw_write(uw_context, const char*);
-
-uw_Basis_source uw_Basis_new_client_source(uw_context, uw_Basis_string);
-uw_unit uw_Basis_set_client_source(uw_context, uw_Basis_source, uw_Basis_string);
-
-void uw_set_script_header(uw_context, const char*);
-char *uw_Basis_get_settings(uw_context, uw_unit);
-char *uw_get_real_script(uw_context);
-
-uw_Basis_string uw_Basis_maybe_onload(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_maybe_onunload(uw_context, uw_Basis_string);
-
-void uw_set_needs_push(uw_context, int);
-void uw_set_needs_sig(uw_context, int);
-
-char *uw_Basis_htmlifyInt(uw_context, uw_Basis_int);
-char *uw_Basis_htmlifyFloat(uw_context, uw_Basis_float);
-char *uw_Basis_htmlifyString(uw_context, uw_Basis_string);
-char *uw_Basis_htmlifyBool(uw_context, uw_Basis_bool);
-char *uw_Basis_htmlifyTime(uw_context, uw_Basis_time);
-char *uw_Basis_htmlifySpecialChar(uw_context, unsigned char);
-char *uw_Basis_htmlifySource(uw_context, uw_Basis_source);
-
-uw_unit uw_Basis_htmlifyInt_w(uw_context, uw_Basis_int);
-uw_unit uw_Basis_htmlifyFloat_w(uw_context, uw_Basis_float);
-uw_unit uw_Basis_htmlifyString_w(uw_context, uw_Basis_string);
-uw_unit uw_Basis_htmlifyBool_w(uw_context, uw_Basis_bool);
-uw_unit uw_Basis_htmlifyTime_w(uw_context, uw_Basis_time);
-uw_unit uw_Basis_htmlifySpecialChar_w(uw_context, unsigned char);
-uw_unit uw_Basis_htmlifySource_w(uw_context, uw_Basis_source);
-
-char *uw_Basis_attrifyInt(uw_context, uw_Basis_int);
-char *uw_Basis_attrifyFloat(uw_context, uw_Basis_float);
-char *uw_Basis_attrifyString(uw_context, uw_Basis_string);
-char *uw_Basis_attrifyChar(uw_context, uw_Basis_char);
-char *uw_Basis_attrifyTime(uw_context, uw_Basis_time);
-char *uw_Basis_attrifyChannel(uw_context, uw_Basis_channel);
-char *uw_Basis_attrifyClient(uw_context, uw_Basis_client);
-char *uw_Basis_attrifyCss_class(uw_context, uw_Basis_css_class);
-
-uw_unit uw_Basis_attrifyInt_w(uw_context, uw_Basis_int);
-uw_unit uw_Basis_attrifyFloat_w(uw_context, uw_Basis_float);
-uw_unit uw_Basis_attrifyString_w(uw_context, uw_Basis_string);
-uw_unit uw_Basis_attrifyChar_w(uw_context, uw_Basis_char);
-
-char *uw_Basis_urlifyInt(uw_context, uw_Basis_int);
-char *uw_Basis_urlifyFloat(uw_context, uw_Basis_float);
-char *uw_Basis_urlifyString(uw_context, uw_Basis_string);
-char *uw_Basis_urlifyBool(uw_context, uw_Basis_bool);
-char *uw_Basis_urlifyTime(uw_context, uw_Basis_time);
-char *uw_Basis_urlifyChannel(uw_context, uw_Basis_channel);
-char *uw_Basis_urlifySource(uw_context, uw_Basis_source);
-
-uw_unit uw_Basis_urlifyInt_w(uw_context, uw_Basis_int);
-uw_unit uw_Basis_urlifyFloat_w(uw_context, uw_Basis_float);
-uw_unit uw_Basis_urlifyString_w(uw_context, uw_Basis_string);
-uw_unit uw_Basis_urlifyBool_w(uw_context, uw_Basis_bool);
-uw_unit uw_Basis_urlifyTime_w(uw_context, uw_Basis_time);
-uw_unit uw_Basis_urlifyChannel_w(uw_context, uw_Basis_channel);
-uw_unit uw_Basis_urlifySource_w(uw_context, uw_Basis_source);
-
-uw_Basis_unit uw_Basis_unurlifyUnit(uw_context ctx, char **s);
-uw_Basis_int uw_Basis_unurlifyInt(uw_context, char **);
-uw_Basis_float uw_Basis_unurlifyFloat(uw_context, char **);
-uw_Basis_string uw_Basis_unurlifyString(uw_context, char **);
-uw_Basis_string uw_Basis_unurlifyString_fromClient(uw_context, char **);
-uw_Basis_bool uw_Basis_unurlifyBool(uw_context, char **);
-uw_Basis_time uw_Basis_unurlifyTime(uw_context, char **);
-
-uw_Basis_int uw_Basis_strlen(uw_context, const char *);
-uw_Basis_bool uw_Basis_strlenGe(uw_context, uw_Basis_string, uw_Basis_int);
-uw_Basis_char uw_Basis_strsub(uw_context, const char *, uw_Basis_int);
-uw_Basis_string uw_Basis_strsuffix(uw_context, const char *, uw_Basis_int);
-uw_Basis_string uw_Basis_strcat(uw_context, const char *, const char *);
-uw_Basis_string uw_Basis_mstrcat(uw_context ctx, ...);
-uw_Basis_int *uw_Basis_strindex(uw_context, const char *, uw_Basis_char);
-uw_Basis_int *uw_Basis_strsindex(uw_context, const char *, const char *needle);
-uw_Basis_string uw_Basis_strchr(uw_context, const char *, uw_Basis_char);
-uw_Basis_int uw_Basis_strcspn(uw_context, const char *, const char *);
-uw_Basis_string uw_Basis_substring(uw_context, const char *, uw_Basis_int, uw_Basis_int);
-uw_Basis_string uw_Basis_str1(uw_context, uw_Basis_char);
-
-uw_Basis_string uw_strdup(uw_context, const char *);
-uw_Basis_string uw_maybe_strdup(uw_context, const char *);
-char *uw_memdup(uw_context, const char *, size_t);
-
-uw_Basis_string uw_Basis_sqlifyInt(uw_context, uw_Basis_int);
-uw_Basis_string uw_Basis_sqlifyFloat(uw_context, uw_Basis_float);
-uw_Basis_string uw_Basis_sqlifyString(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_sqlifyChar(uw_context, uw_Basis_char);
-uw_Basis_string uw_Basis_sqlifyBool(uw_context, uw_Basis_bool);
-uw_Basis_string uw_Basis_sqlifyTime(uw_context, uw_Basis_time);
-uw_Basis_string uw_Basis_sqlifyBlob(uw_context, uw_Basis_blob);
-uw_Basis_string uw_Basis_sqlifyChannel(uw_context, uw_Basis_channel);
-uw_Basis_string uw_Basis_sqlifyClient(uw_context, uw_Basis_client);
-
-uw_Basis_string uw_Basis_sqlifyIntN(uw_context, uw_Basis_int*);
-uw_Basis_string uw_Basis_sqlifyFloatN(uw_context, uw_Basis_float*);
-uw_Basis_string uw_Basis_sqlifyStringN(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_sqlifyBoolN(uw_context, uw_Basis_bool*);
-uw_Basis_string uw_Basis_sqlifyTimeN(uw_context, uw_Basis_time*);
-
-char *uw_Basis_ensqlBool(uw_Basis_bool);
-char *uw_Basis_ensqlTime(uw_context ctx, uw_Basis_time);
-
-char *uw_Basis_jsifyString(uw_context, uw_Basis_string);
-char *uw_Basis_jsifyChar(uw_context, uw_Basis_char);
-char *uw_Basis_jsifyChannel(uw_context, uw_Basis_channel);
-char *uw_Basis_jsifyTime(uw_context, uw_Basis_time);
-
-uw_Basis_string uw_Basis_intToString(uw_context, uw_Basis_int);
-uw_Basis_string uw_Basis_floatToString(uw_context, uw_Basis_float);
-uw_Basis_string uw_Basis_charToString(uw_context, uw_Basis_char);
-uw_Basis_string uw_Basis_boolToString(uw_context, uw_Basis_bool);
-uw_Basis_string uw_Basis_timeToString(uw_context, uw_Basis_time);
-
-uw_Basis_int *uw_Basis_stringToInt(uw_context, uw_Basis_string);
-uw_Basis_float *uw_Basis_stringToFloat(uw_context, uw_Basis_string);
-uw_Basis_char *uw_Basis_stringToChar(uw_context, uw_Basis_string);
-uw_Basis_bool *uw_Basis_stringToBool(uw_context, uw_Basis_string);
-uw_Basis_time *uw_Basis_stringToTime(uw_context, const char *);
-
-uw_Basis_int uw_Basis_stringToInt_error(uw_context, uw_Basis_string);
-uw_Basis_float uw_Basis_stringToFloat_error(uw_context, uw_Basis_string);
-uw_Basis_char uw_Basis_stringToChar_error(uw_context, uw_Basis_string);
-uw_Basis_bool uw_Basis_stringToBool_error(uw_context, uw_Basis_string);
-uw_Basis_time uw_Basis_stringToTime_error(uw_context, const char *);
-uw_Basis_blob uw_Basis_stringToBlob_error(uw_context, uw_Basis_string, size_t);
-uw_Basis_channel uw_Basis_stringToChannel_error(uw_context, uw_Basis_string);
-uw_Basis_client uw_Basis_stringToClient_error(uw_context, uw_Basis_string);
-
-uw_Basis_time uw_Basis_unsqlTime(uw_context, uw_Basis_string);
-
-uw_Basis_string uw_Basis_requestHeader(uw_context, uw_Basis_string);
-
-void uw_write_header(uw_context, uw_Basis_string);
-void uw_clear_headers(uw_context);
-
-uw_Basis_string uw_Basis_get_cookie(uw_context, uw_Basis_string c);
-uw_unit uw_Basis_set_cookie(uw_context, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v, uw_Basis_time *expires, uw_Basis_bool secure);
-uw_unit uw_Basis_clear_cookie(uw_context, uw_Basis_string prefix, uw_Basis_string c);
-
-uw_Basis_channel uw_Basis_new_channel(uw_context, uw_unit);
-uw_unit uw_Basis_send(uw_context, uw_Basis_channel, uw_Basis_string);
-
-uw_Basis_client uw_Basis_self(uw_context);
-
-uw_Basis_string uw_Basis_bless(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_blessMime(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_blessRequestHeader(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_blessResponseHeader(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_blessEnvVar(uw_context, uw_Basis_string);
-
-uw_Basis_string uw_Basis_checkUrl(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_checkMime(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_checkRequestHeader(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_checkResponseHeader(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_checkEnvVar(uw_context, uw_Basis_string);
-
-uw_Basis_string uw_Basis_getHeader(uw_context, uw_Basis_string name);
-uw_unit uw_Basis_setHeader(uw_context, uw_Basis_string name, uw_Basis_string value);
-uw_Basis_string uw_Basis_getenv(uw_context, uw_Basis_string name);
-
-uw_Basis_string uw_unnull(uw_Basis_string);
-uw_Basis_string uw_Basis_makeSigString(uw_context, uw_Basis_string);
-int uw_streq(uw_Basis_string, uw_Basis_string);
-uw_Basis_string uw_Basis_sigString(uw_context, uw_unit);
-
-uw_Basis_string uw_Basis_fileName(uw_context, uw_Basis_file);
-uw_Basis_string uw_Basis_fileMimeType(uw_context, uw_Basis_file);
-uw_Basis_blob uw_Basis_fileData(uw_context, uw_Basis_file);
-uw_Basis_int uw_Basis_blobSize(uw_context, uw_Basis_blob);
-uw_Basis_blob uw_Basis_textBlob(uw_context, uw_Basis_string);
-
-uw_Basis_string uw_Basis_postType(uw_context, uw_Basis_postBody);
-uw_Basis_string uw_Basis_postData(uw_context, uw_Basis_postBody);
-void uw_noPostBody(uw_context);
-void uw_postBody(uw_context, uw_Basis_postBody);
-int uw_hasPostBody(uw_context);
-uw_Basis_postBody uw_getPostBody(uw_context);
-
-void uw_mayReturnIndirectly(uw_context);
-__attribute__((noreturn)) void uw_return_blob(uw_context, uw_Basis_blob, uw_Basis_string mimeType);
-__attribute__((noreturn)) void uw_redirect(uw_context, uw_Basis_string url);
-
-uw_Basis_time uw_Basis_now(uw_context);
-uw_Basis_time uw_Basis_addSeconds(uw_context, uw_Basis_time, uw_Basis_int);
-uw_Basis_int uw_Basis_diffInSeconds(uw_context, uw_Basis_time, uw_Basis_time);
-uw_Basis_int uw_Basis_toSeconds(uw_context, uw_Basis_time);
-uw_Basis_int uw_Basis_diffInMilliseconds(uw_context, uw_Basis_time, uw_Basis_time);
-uw_Basis_int uw_Basis_toMilliseconds(uw_context, uw_Basis_time);
-extern const uw_Basis_time uw_Basis_minTime;
-
-void uw_register_transactional(uw_context, void *data, uw_callback commit, uw_callback rollback, uw_callback_with_retry free);
-
-void uw_check_heap(uw_context, size_t extra);
-char *uw_heap_front(uw_context);
-void uw_set_heap_front(uw_context, char*);
-
-uw_Basis_string uw_Basis_unAs(uw_context, uw_Basis_string);
-
-extern char *uw_sqlfmtInt;
-extern char *uw_sqlfmtFloat;
-extern int uw_Estrings, uw_sql_type_annotations;
-extern char *uw_sqlsuffixString;
-extern char *uw_sqlsuffixChar;
-extern char *uw_sqlsuffixBlob;
-extern char *uw_sqlfmtUint4;
-
-void *uw_get_global(uw_context, char *name);
-void uw_set_global(uw_context, char *name, void *data, uw_callback free);
-
-uw_Basis_bool uw_Basis_isalnum(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isalpha(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isblank(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_iscntrl(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isdigit(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isgraph(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_islower(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isprint(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_ispunct(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isspace(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isupper(uw_context, uw_Basis_char);
-uw_Basis_bool uw_Basis_isxdigit(uw_context, uw_Basis_char);
-uw_Basis_char uw_Basis_tolower(uw_context, uw_Basis_char);
-uw_Basis_char uw_Basis_toupper(uw_context, uw_Basis_char);
-
-uw_Basis_int uw_Basis_ord(uw_context, uw_Basis_char);
-uw_Basis_char uw_Basis_chr(uw_context, uw_Basis_int);
-
-uw_Basis_string uw_Basis_currentUrl(uw_context);
-void uw_set_currentUrl(uw_context, char *);
-
-extern size_t uw_messages_max, uw_clients_max, uw_headers_max, uw_page_max, uw_heap_max, uw_script_max;
-extern size_t uw_inputs_max, uw_cleanup_max, uw_subinputs_max, uw_deltas_max, uw_transactionals_max, uw_globals_max;
-
-extern size_t uw_database_max;
-
-extern int uw_time;
-
-void uw_set_deadline(uw_context, int);
-void uw_check_deadline(uw_context);
-
-uw_Basis_unit uw_Basis_debug(uw_context, uw_Basis_string);
-uw_Basis_int uw_Basis_naughtyDebug(uw_context, uw_Basis_string);
-
-void uw_set_client_data(uw_context, void *);
-
-uw_Basis_int uw_Basis_rand(uw_context);
-
-extern int uw_time_max, uw_supports_direct_status, uw_min_heap;
-
-failure_kind uw_runCallback(uw_context, void (*callback)(uw_context));
-
-uw_Basis_string uw_Basis_timef(uw_context, const char *fmt, uw_Basis_time);
-uw_Basis_time uw_Basis_stringToTimef(uw_context, const char *fmt, uw_Basis_string);
-uw_Basis_time uw_Basis_stringToTimef_error(uw_context, const char *fmt, uw_Basis_string);
-
-uw_Basis_string uw_Basis_crypt(uw_context, uw_Basis_string key, uw_Basis_string salt);
-
-uw_Basis_bool uw_Basis_eq_time(uw_context, uw_Basis_time, uw_Basis_time);
-uw_Basis_bool uw_Basis_lt_time(uw_context, uw_Basis_time, uw_Basis_time);
-uw_Basis_bool uw_Basis_le_time(uw_context, uw_Basis_time, uw_Basis_time);
-
-void uw_buffer_init(size_t max, uw_buffer *, size_t initial);
-void uw_buffer_free(uw_buffer *);
-void uw_buffer_reset(uw_buffer *);
-int uw_buffer_check(uw_buffer *, size_t extra);
-size_t uw_buffer_used(uw_buffer *);
-size_t uw_buffer_avail(uw_buffer *);
-int uw_buffer_append(uw_buffer *, const char *, size_t);
-
-void uw_setQueryString(uw_context, uw_Basis_string);
-uw_Basis_string uw_queryString(uw_context);
-
-uw_Basis_time *uw_Basis_readUtc(uw_context, uw_Basis_string);
-
-void uw_isPost(uw_context);
-uw_Basis_bool uw_Basis_currentUrlHasPost(uw_context);
-uw_Basis_bool uw_Basis_currentUrlHasQueryString(uw_context);
-
-uw_Basis_string uw_Basis_fresh(uw_context);
-
-uw_Basis_float uw_Basis_floatFromInt(uw_context, uw_Basis_int);
-uw_Basis_int uw_Basis_ceil(uw_context, uw_Basis_float);
-uw_Basis_int uw_Basis_trunc(uw_context, uw_Basis_float);
-uw_Basis_int uw_Basis_round(uw_context, uw_Basis_float);
-
-uw_Basis_string uw_Basis_atom(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_css_url(uw_context, uw_Basis_string);
-uw_Basis_string uw_Basis_property(uw_context, uw_Basis_string);
-
-void uw_begin_initializing(uw_context);
-void uw_end_initializing(uw_context);
-
-uw_Basis_string uw_Basis_fieldName(uw_context, uw_Basis_postField);
-uw_Basis_string uw_Basis_fieldValue(uw_context, uw_Basis_postField);
-uw_Basis_string uw_Basis_remainingFields(uw_context, uw_Basis_postField);
-uw_Basis_postField *uw_Basis_firstFormField(uw_context, uw_Basis_string);
+#include "urweb_cpp.h"
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/urweb/urweb_cpp.h	Fri Oct 11 17:15:28 2013 -0400
@@ -0,0 +1,373 @@
+#ifndef URWEB_CPP_H
+#define URWEB_CPP_H
+
+#include <sys/types.h>
+
+#include "types_cpp.h"
+
+int uw_really_send(int sock, const void *buf, ssize_t len);
+int uw_really_write(int fd, const void *buf, size_t len);
+
+extern uw_unit uw_unit_v;
+
+void uw_global_init(void);
+void uw_app_init(uw_app*);
+
+void uw_client_connect(unsigned id, int pass, int sock,
+                       int (*send)(int sockfd, const void *buf, size_t len),
+                       int (*close)(int fd),
+                       void *logger_data, uw_logger log_error);
+void uw_prune_clients(struct uw_context *);
+failure_kind uw_initialize(struct uw_context *);
+
+struct uw_context * uw_init(int id, void *logger_data, uw_logger log_debug);
+void uw_close(struct uw_context *);
+int uw_set_app(struct uw_context *, uw_app*);
+uw_app *uw_get_app(struct uw_context *);
+void uw_set_db(struct uw_context *, void*);
+void *uw_get_db(struct uw_context *);
+void uw_free(struct uw_context *);
+void uw_reset(struct uw_context *);
+void uw_reset_keep_request(struct uw_context *);
+void uw_reset_keep_error_message(struct uw_context *);
+char *uw_get_url_prefix(struct uw_context *);
+
+failure_kind uw_begin_init(struct uw_context *);
+void uw_set_on_success(char *);
+void uw_set_headers(struct uw_context *, char *(*get_header)(void *, const char *), void *get_header_data);
+void uw_set_env(struct uw_context *, char *(*get_env)(void *, const char *), void *get_env_data);
+failure_kind uw_begin(struct uw_context *, char *path);
+failure_kind uw_begin_onError(struct uw_context *, char *msg);
+void uw_login(struct uw_context *);
+void uw_commit(struct uw_context *);
+int uw_rollback(struct uw_context *, int will_retry);
+
+__attribute__((noreturn)) void uw_error(struct uw_context *, failure_kind, const char *fmt, ...);
+char *uw_error_message(struct uw_context *);
+void uw_set_error_message(struct uw_context *, const char *fmt, ...);
+uw_Basis_string uw_dup_and_clear_error_message(struct uw_context *);
+int uw_has_error(struct uw_context *);
+void uw_push_cleanup(struct uw_context *, void (*func)(void *), void *arg);
+void uw_pop_cleanup(struct uw_context *);
+
+void *uw_malloc(struct uw_context *, size_t);
+void uw_begin_region(struct uw_context *);
+void uw_end_region(struct uw_context *);
+void uw_memstats(struct uw_context *);
+
+int uw_send(struct uw_context *, int sock);
+int uw_print(struct uw_context *, int fd);
+int uw_output(struct uw_context * ctx, int (*output)(void *data, const char *buf, size_t len), void *data);
+
+int uw_set_input(struct uw_context *, const char *name, char *value);
+int uw_set_file_input(struct uw_context *, char *name, uw_Basis_file);
+
+char *uw_get_input(struct uw_context *, int name);
+char *uw_get_optional_input(struct uw_context *, int name);
+uw_Basis_file uw_get_file_input(struct uw_context *, int name);
+void uw_enter_subform(struct uw_context *, int name);
+void uw_leave_subform(struct uw_context *);
+int uw_enter_subforms(struct uw_context *, int name);
+int uw_next_entry(struct uw_context *);
+
+void uw_write(struct uw_context *, const char*);
+
+uw_Basis_source uw_Basis_new_client_source(struct uw_context *, uw_Basis_string);
+uw_unit uw_Basis_set_client_source(struct uw_context *, uw_Basis_source, uw_Basis_string);
+
+void uw_set_script_header(struct uw_context *, const char*);
+char *uw_Basis_get_settings(struct uw_context *, uw_unit);
+char *uw_get_real_script(struct uw_context *);
+
+uw_Basis_string uw_Basis_maybe_onload(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_maybe_onunload(struct uw_context *, uw_Basis_string);
+
+void uw_set_needs_push(struct uw_context *, int);
+void uw_set_needs_sig(struct uw_context *, int);
+
+char *uw_Basis_htmlifyInt(struct uw_context *, uw_Basis_int);
+char *uw_Basis_htmlifyFloat(struct uw_context *, uw_Basis_float);
+char *uw_Basis_htmlifyString(struct uw_context *, uw_Basis_string);
+char *uw_Basis_htmlifyBool(struct uw_context *, uw_Basis_bool);
+char *uw_Basis_htmlifyTime(struct uw_context *, uw_Basis_time);
+char *uw_Basis_htmlifySpecialChar(struct uw_context *, unsigned char);
+char *uw_Basis_htmlifySource(struct uw_context *, uw_Basis_source);
+
+uw_unit uw_Basis_htmlifyInt_w(struct uw_context *, uw_Basis_int);
+uw_unit uw_Basis_htmlifyFloat_w(struct uw_context *, uw_Basis_float);
+uw_unit uw_Basis_htmlifyString_w(struct uw_context *, uw_Basis_string);
+uw_unit uw_Basis_htmlifyBool_w(struct uw_context *, uw_Basis_bool);
+uw_unit uw_Basis_htmlifyTime_w(struct uw_context *, uw_Basis_time);
+uw_unit uw_Basis_htmlifySpecialChar_w(struct uw_context *, unsigned char);
+uw_unit uw_Basis_htmlifySource_w(struct uw_context *, uw_Basis_source);
+
+char *uw_Basis_attrifyInt(struct uw_context *, uw_Basis_int);
+char *uw_Basis_attrifyFloat(struct uw_context *, uw_Basis_float);
+char *uw_Basis_attrifyString(struct uw_context *, uw_Basis_string);
+char *uw_Basis_attrifyChar(struct uw_context *, uw_Basis_char);
+char *uw_Basis_attrifyTime(struct uw_context *, uw_Basis_time);
+char *uw_Basis_attrifyChannel(struct uw_context *, uw_Basis_channel);
+char *uw_Basis_attrifyClient(struct uw_context *, uw_Basis_client);
+char *uw_Basis_attrifyCss_class(struct uw_context *, uw_Basis_css_class);
+
+uw_unit uw_Basis_attrifyInt_w(struct uw_context *, uw_Basis_int);
+uw_unit uw_Basis_attrifyFloat_w(struct uw_context *, uw_Basis_float);
+uw_unit uw_Basis_attrifyString_w(struct uw_context *, uw_Basis_string);
+uw_unit uw_Basis_attrifyChar_w(struct uw_context *, uw_Basis_char);
+
+char *uw_Basis_urlifyInt(struct uw_context *, uw_Basis_int);
+char *uw_Basis_urlifyFloat(struct uw_context *, uw_Basis_float);
+char *uw_Basis_urlifyString(struct uw_context *, uw_Basis_string);
+char *uw_Basis_urlifyBool(struct uw_context *, uw_Basis_bool);
+char *uw_Basis_urlifyTime(struct uw_context *, uw_Basis_time);
+char *uw_Basis_urlifyChannel(struct uw_context *, uw_Basis_channel);
+char *uw_Basis_urlifySource(struct uw_context *, uw_Basis_source);
+
+uw_unit uw_Basis_urlifyInt_w(struct uw_context *, uw_Basis_int);
+uw_unit uw_Basis_urlifyFloat_w(struct uw_context *, uw_Basis_float);
+uw_unit uw_Basis_urlifyString_w(struct uw_context *, uw_Basis_string);
+uw_unit uw_Basis_urlifyBool_w(struct uw_context *, uw_Basis_bool);
+uw_unit uw_Basis_urlifyTime_w(struct uw_context *, uw_Basis_time);
+uw_unit uw_Basis_urlifyChannel_w(struct uw_context *, uw_Basis_channel);
+uw_unit uw_Basis_urlifySource_w(struct uw_context *, uw_Basis_source);
+
+uw_Basis_unit uw_Basis_unurlifyUnit(struct uw_context * ctx, char **s);
+uw_Basis_int uw_Basis_unurlifyInt(struct uw_context *, char **);
+uw_Basis_float uw_Basis_unurlifyFloat(struct uw_context *, char **);
+uw_Basis_string uw_Basis_unurlifyString(struct uw_context *, char **);
+uw_Basis_string uw_Basis_unurlifyString_fromClient(struct uw_context *, char **);
+uw_Basis_bool uw_Basis_unurlifyBool(struct uw_context *, char **);
+uw_Basis_time uw_Basis_unurlifyTime(struct uw_context *, char **);
+
+uw_Basis_int uw_Basis_strlen(struct uw_context *, const char *);
+uw_Basis_bool uw_Basis_strlenGe(struct uw_context *, uw_Basis_string, uw_Basis_int);
+uw_Basis_char uw_Basis_strsub(struct uw_context *, const char *, uw_Basis_int);
+uw_Basis_string uw_Basis_strsuffix(struct uw_context *, const char *, uw_Basis_int);
+uw_Basis_string uw_Basis_strcat(struct uw_context *, const char *, const char *);
+uw_Basis_string uw_Basis_mstrcat(struct uw_context * ctx, ...);
+uw_Basis_int *uw_Basis_strindex(struct uw_context *, const char *, uw_Basis_char);
+uw_Basis_int *uw_Basis_strsindex(struct uw_context *, const char *, const char *needle);
+uw_Basis_string uw_Basis_strchr(struct uw_context *, const char *, uw_Basis_char);
+uw_Basis_int uw_Basis_strcspn(struct uw_context *, const char *, const char *);
+uw_Basis_string uw_Basis_substring(struct uw_context *, const char *, uw_Basis_int, uw_Basis_int);
+uw_Basis_string uw_Basis_str1(struct uw_context *, uw_Basis_char);
+
+uw_Basis_string uw_strdup(struct uw_context *, const char *);
+uw_Basis_string uw_maybe_strdup(struct uw_context *, const char *);
+char *uw_memdup(struct uw_context *, const char *, size_t);
+
+uw_Basis_string uw_Basis_sqlifyInt(struct uw_context *, uw_Basis_int);
+uw_Basis_string uw_Basis_sqlifyFloat(struct uw_context *, uw_Basis_float);
+uw_Basis_string uw_Basis_sqlifyString(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_sqlifyChar(struct uw_context *, uw_Basis_char);
+uw_Basis_string uw_Basis_sqlifyBool(struct uw_context *, uw_Basis_bool);
+uw_Basis_string uw_Basis_sqlifyTime(struct uw_context *, uw_Basis_time);
+uw_Basis_string uw_Basis_sqlifyBlob(struct uw_context *, uw_Basis_blob);
+uw_Basis_string uw_Basis_sqlifyChannel(struct uw_context *, uw_Basis_channel);
+uw_Basis_string uw_Basis_sqlifyClient(struct uw_context *, uw_Basis_client);
+
+uw_Basis_string uw_Basis_sqlifyIntN(struct uw_context *, uw_Basis_int*);
+uw_Basis_string uw_Basis_sqlifyFloatN(struct uw_context *, uw_Basis_float*);
+uw_Basis_string uw_Basis_sqlifyStringN(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_sqlifyBoolN(struct uw_context *, uw_Basis_bool*);
+uw_Basis_string uw_Basis_sqlifyTimeN(struct uw_context *, uw_Basis_time*);
+
+char *uw_Basis_ensqlBool(uw_Basis_bool);
+char *uw_Basis_ensqlTime(struct uw_context * ctx, uw_Basis_time);
+
+char *uw_Basis_jsifyString(struct uw_context *, uw_Basis_string);
+char *uw_Basis_jsifyChar(struct uw_context *, uw_Basis_char);
+char *uw_Basis_jsifyChannel(struct uw_context *, uw_Basis_channel);
+char *uw_Basis_jsifyTime(struct uw_context *, uw_Basis_time);
+
+uw_Basis_string uw_Basis_intToString(struct uw_context *, uw_Basis_int);
+uw_Basis_string uw_Basis_floatToString(struct uw_context *, uw_Basis_float);
+uw_Basis_string uw_Basis_charToString(struct uw_context *, uw_Basis_char);
+uw_Basis_string uw_Basis_boolToString(struct uw_context *, uw_Basis_bool);
+uw_Basis_string uw_Basis_timeToString(struct uw_context *, uw_Basis_time);
+
+uw_Basis_int *uw_Basis_stringToInt(struct uw_context *, uw_Basis_string);
+uw_Basis_float *uw_Basis_stringToFloat(struct uw_context *, uw_Basis_string);
+uw_Basis_char *uw_Basis_stringToChar(struct uw_context *, uw_Basis_string);
+uw_Basis_bool *uw_Basis_stringToBool(struct uw_context *, uw_Basis_string);
+uw_Basis_time *uw_Basis_stringToTime(struct uw_context *, const char *);
+
+uw_Basis_int uw_Basis_stringToInt_error(struct uw_context *, uw_Basis_string);
+uw_Basis_float uw_Basis_stringToFloat_error(struct uw_context *, uw_Basis_string);
+uw_Basis_char uw_Basis_stringToChar_error(struct uw_context *, uw_Basis_string);
+uw_Basis_bool uw_Basis_stringToBool_error(struct uw_context *, uw_Basis_string);
+uw_Basis_time uw_Basis_stringToTime_error(struct uw_context *, const char *);
+uw_Basis_blob uw_Basis_stringToBlob_error(struct uw_context *, uw_Basis_string, size_t);
+uw_Basis_channel uw_Basis_stringToChannel_error(struct uw_context *, uw_Basis_string);
+uw_Basis_client uw_Basis_stringToClient_error(struct uw_context *, uw_Basis_string);
+
+uw_Basis_time uw_Basis_unsqlTime(struct uw_context *, uw_Basis_string);
+
+uw_Basis_string uw_Basis_requestHeader(struct uw_context *, uw_Basis_string);
+
+void uw_write_header(struct uw_context *, uw_Basis_string);
+void uw_clear_headers(struct uw_context *);
+
+uw_Basis_string uw_Basis_get_cookie(struct uw_context *, uw_Basis_string c);
+uw_unit uw_Basis_set_cookie(struct uw_context *, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v, uw_Basis_time *expires, uw_Basis_bool secure);
+uw_unit uw_Basis_clear_cookie(struct uw_context *, uw_Basis_string prefix, uw_Basis_string c);
+
+uw_Basis_channel uw_Basis_new_channel(struct uw_context *, uw_unit);
+uw_unit uw_Basis_send(struct uw_context *, uw_Basis_channel, uw_Basis_string);
+
+uw_Basis_client uw_Basis_self(struct uw_context *);
+
+uw_Basis_string uw_Basis_bless(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_blessMime(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_blessRequestHeader(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_blessResponseHeader(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_blessEnvVar(struct uw_context *, uw_Basis_string);
+
+uw_Basis_string uw_Basis_checkUrl(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_checkMime(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_checkRequestHeader(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_checkResponseHeader(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_checkEnvVar(struct uw_context *, uw_Basis_string);
+
+uw_Basis_string uw_Basis_getHeader(struct uw_context *, uw_Basis_string name);
+uw_unit uw_Basis_setHeader(struct uw_context *, uw_Basis_string name, uw_Basis_string value);
+uw_Basis_string uw_Basis_getenv(struct uw_context *, uw_Basis_string name);
+
+uw_Basis_string uw_unnull(uw_Basis_string);
+uw_Basis_string uw_Basis_makeSigString(struct uw_context *, uw_Basis_string);
+int uw_streq(uw_Basis_string, uw_Basis_string);
+uw_Basis_string uw_Basis_sigString(struct uw_context *, uw_unit);
+
+uw_Basis_string uw_Basis_fileName(struct uw_context *, uw_Basis_file);
+uw_Basis_string uw_Basis_fileMimeType(struct uw_context *, uw_Basis_file);
+uw_Basis_blob uw_Basis_fileData(struct uw_context *, uw_Basis_file);
+uw_Basis_int uw_Basis_blobSize(struct uw_context *, uw_Basis_blob);
+uw_Basis_blob uw_Basis_textBlob(struct uw_context *, uw_Basis_string);
+
+uw_Basis_string uw_Basis_postType(struct uw_context *, uw_Basis_postBody);
+uw_Basis_string uw_Basis_postData(struct uw_context *, uw_Basis_postBody);
+void uw_noPostBody(struct uw_context *);
+void uw_postBody(struct uw_context *, uw_Basis_postBody);
+int uw_hasPostBody(struct uw_context *);
+uw_Basis_postBody uw_getPostBody(struct uw_context *);
+
+void uw_mayReturnIndirectly(struct uw_context *);
+__attribute__((noreturn)) void uw_return_blob(struct uw_context *, uw_Basis_blob, uw_Basis_string mimeType);
+__attribute__((noreturn)) void uw_redirect(struct uw_context *, uw_Basis_string url);
+
+uw_Basis_time uw_Basis_now(struct uw_context *);
+uw_Basis_time uw_Basis_addSeconds(struct uw_context *, uw_Basis_time, uw_Basis_int);
+uw_Basis_int uw_Basis_diffInSeconds(struct uw_context *, uw_Basis_time, uw_Basis_time);
+uw_Basis_int uw_Basis_toSeconds(struct uw_context *, uw_Basis_time);
+uw_Basis_int uw_Basis_diffInMilliseconds(struct uw_context *, uw_Basis_time, uw_Basis_time);
+uw_Basis_int uw_Basis_toMilliseconds(struct uw_context *, uw_Basis_time);
+extern const uw_Basis_time uw_Basis_minTime;
+
+void uw_register_transactional(struct uw_context *, void *data, uw_callback commit, uw_callback rollback, uw_callback_with_retry free);
+
+void uw_check_heap(struct uw_context *, size_t extra);
+char *uw_heap_front(struct uw_context *);
+void uw_set_heap_front(struct uw_context *, char*);
+
+uw_Basis_string uw_Basis_unAs(struct uw_context *, uw_Basis_string);
+
+extern char *uw_sqlfmtInt;
+extern char *uw_sqlfmtFloat;
+extern int uw_Estrings, uw_sql_type_annotations;
+extern char *uw_sqlsuffixString;
+extern char *uw_sqlsuffixChar;
+extern char *uw_sqlsuffixBlob;
+extern char *uw_sqlfmtUint4;
+
+void *uw_get_global(struct uw_context *, char *name);
+void uw_set_global(struct uw_context *, char *name, void *data, uw_callback free);
+
+uw_Basis_bool uw_Basis_isalnum(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isalpha(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isblank(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_iscntrl(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isdigit(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isgraph(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_islower(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isprint(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_ispunct(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isspace(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isupper(struct uw_context *, uw_Basis_char);
+uw_Basis_bool uw_Basis_isxdigit(struct uw_context *, uw_Basis_char);
+uw_Basis_char uw_Basis_tolower(struct uw_context *, uw_Basis_char);
+uw_Basis_char uw_Basis_toupper(struct uw_context *, uw_Basis_char);
+
+uw_Basis_int uw_Basis_ord(struct uw_context *, uw_Basis_char);
+uw_Basis_char uw_Basis_chr(struct uw_context *, uw_Basis_int);
+
+uw_Basis_string uw_Basis_currentUrl(struct uw_context *);
+void uw_set_currentUrl(struct uw_context *, char *);
+
+extern size_t uw_messages_max, uw_clients_max, uw_headers_max, uw_page_max, uw_heap_max, uw_script_max;
+extern size_t uw_inputs_max, uw_cleanup_max, uw_subinputs_max, uw_deltas_max, uw_transactionals_max, uw_globals_max;
+
+extern size_t uw_database_max;
+
+extern int uw_time;
+
+void uw_set_deadline(struct uw_context *, int);
+void uw_check_deadline(struct uw_context *);
+
+uw_Basis_unit uw_Basis_debug(struct uw_context *, uw_Basis_string);
+uw_Basis_int uw_Basis_naughtyDebug(struct uw_context *, uw_Basis_string);
+
+void uw_set_client_data(struct uw_context *, void *);
+
+uw_Basis_int uw_Basis_rand(struct uw_context *);
+
+extern int uw_time_max, uw_supports_direct_status, uw_min_heap;
+
+failure_kind uw_runCallback(struct uw_context *, void (*callback)(struct uw_context *));
+
+uw_Basis_string uw_Basis_timef(struct uw_context *, const char *fmt, uw_Basis_time);
+uw_Basis_time uw_Basis_stringToTimef(struct uw_context *, const char *fmt, uw_Basis_string);
+uw_Basis_time uw_Basis_stringToTimef_error(struct uw_context *, const char *fmt, uw_Basis_string);
+
+uw_Basis_string uw_Basis_crypt(struct uw_context *, uw_Basis_string key, uw_Basis_string salt);
+
+uw_Basis_bool uw_Basis_eq_time(struct uw_context *, uw_Basis_time, uw_Basis_time);
+uw_Basis_bool uw_Basis_lt_time(struct uw_context *, uw_Basis_time, uw_Basis_time);
+uw_Basis_bool uw_Basis_le_time(struct uw_context *, uw_Basis_time, uw_Basis_time);
+
+void uw_buffer_init(size_t max, uw_buffer *, size_t initial);
+void uw_buffer_free(uw_buffer *);
+void uw_buffer_reset(uw_buffer *);
+int uw_buffer_check(uw_buffer *, size_t extra);
+size_t uw_buffer_used(uw_buffer *);
+size_t uw_buffer_avail(uw_buffer *);
+int uw_buffer_append(uw_buffer *, const char *, size_t);
+
+void uw_setQueryString(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_queryString(struct uw_context *);
+
+uw_Basis_time *uw_Basis_readUtc(struct uw_context *, uw_Basis_string);
+
+void uw_isPost(struct uw_context *);
+uw_Basis_bool uw_Basis_currentUrlHasPost(struct uw_context *);
+uw_Basis_bool uw_Basis_currentUrlHasQueryString(struct uw_context *);
+
+uw_Basis_string uw_Basis_fresh(struct uw_context *);
+
+uw_Basis_float uw_Basis_floatFromInt(struct uw_context *, uw_Basis_int);
+uw_Basis_int uw_Basis_ceil(struct uw_context *, uw_Basis_float);
+uw_Basis_int uw_Basis_trunc(struct uw_context *, uw_Basis_float);
+uw_Basis_int uw_Basis_round(struct uw_context *, uw_Basis_float);
+
+uw_Basis_string uw_Basis_atom(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_css_url(struct uw_context *, uw_Basis_string);
+uw_Basis_string uw_Basis_property(struct uw_context *, uw_Basis_string);
+
+void uw_begin_initializing(struct uw_context *);
+void uw_end_initializing(struct uw_context *);
+
+uw_Basis_string uw_Basis_fieldName(struct uw_context *, uw_Basis_postField);
+uw_Basis_string uw_Basis_fieldValue(struct uw_context *, uw_Basis_postField);
+uw_Basis_string uw_Basis_remainingFields(struct uw_context *, uw_Basis_postField);
+uw_Basis_postField *uw_Basis_firstFormField(struct uw_context *, uw_Basis_string);
+
+#endif