summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2008-07-17 14:18:57 -0400
committerGravatar Adam Chlipala <adamc@hcoop.net>2008-07-17 14:18:57 -0400
commit2ae89dd4180bb36e3f37ba5f1d92d59a029552c2 (patch)
tree640137276b8d1308ef2b4df28033b34199851dfe
parent2e00cd0bdfadfab33a3c802994c8c0e5cf565174 (diff)
Dynamic arena allocation
-rw-r--r--include/lacweb.h13
-rw-r--r--src/c/driver.c3
-rw-r--r--src/c/lacweb.c137
-rw-r--r--src/cjr_print.sml2
-rw-r--r--tests/cdataL.lac8
5 files changed, 142 insertions, 21 deletions
diff --git a/include/lacweb.h b/include/lacweb.h
index 4bd49769..7061731f 100644
--- a/include/lacweb.h
+++ b/include/lacweb.h
@@ -6,19 +6,20 @@ int lw_really_send(int sock, void *buf, ssize_t len);
extern lw_unit lw_unit_v;
-lw_context lw_init(int page_len);
+lw_context lw_init(size_t page_len, size_t heap_len);
void lw_free(lw_context);
+void *lw_malloc(lw_context, size_t);
int lw_send(lw_context, int sock);
void lw_write(lw_context, const char*);
-char *lw_Basis_htmlifyString(lw_Basis_string);
+char *lw_Basis_htmlifyString(lw_context, lw_Basis_string);
void lw_Basis_htmlifyString_w(lw_context, lw_Basis_string);
-char *lw_Basis_attrifyInt(lw_Basis_int);
-char *lw_Basis_attrifyFloat(lw_Basis_float);
-char *lw_Basis_attrifyString(lw_Basis_string);
+char *lw_Basis_attrifyInt(lw_context, lw_Basis_int);
+char *lw_Basis_attrifyFloat(lw_context, lw_Basis_float);
+char *lw_Basis_attrifyString(lw_context, lw_Basis_string);
void lw_Basis_attrifyInt_w(lw_context, lw_Basis_int);
void lw_Basis_attrifyFloat_w(lw_context, lw_Basis_float);
@@ -35,4 +36,4 @@ void lw_Basis_urlifyString_w(lw_context, lw_Basis_string);
lw_Basis_int lw_unurlifyInt(char **);
lw_Basis_float lw_unurlifyFloat(char **);
-lw_Basis_string lw_unurlifyString(char **);
+lw_Basis_string lw_unurlifyString(lw_context, char **);
diff --git a/src/c/driver.c b/src/c/driver.c
index 8f3ef70f..6fb3defe 100644
--- a/src/c/driver.c
+++ b/src/c/driver.c
@@ -72,7 +72,7 @@ static void worker(int sock) {
printf("Serving URI %s....\n", path);
- ctx = lw_init(1024);
+ ctx = lw_init(1024, 1024);
lw_write (ctx, "HTTP/1.1 200 OK\r\n");
lw_write(ctx, "Content-type: text/html\r\n\r\n");
lw_write(ctx, "<html>");
@@ -81,6 +81,7 @@ static void worker(int sock) {
lw_send(ctx, sock);
+ lw_free(ctx);
printf("Done with client.\n\n");
close(sock);
return;
diff --git a/src/c/lacweb.c b/src/c/lacweb.c
index bccadbdc..04564e43 100644
--- a/src/c/lacweb.c
+++ b/src/c/lacweb.c
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <assert.h>
#include "types.h"
@@ -9,17 +10,54 @@ lw_unit lw_unit_v = {};
struct lw_context {
char *page, *page_front, *page_back;
+ char *heap, *heap_front, *heap_back;
};
-lw_context lw_init(int page_len) {
+lw_context lw_init(size_t page_len, size_t heap_len) {
lw_context ctx = malloc(sizeof(struct lw_context));
+
ctx->page_front = ctx->page = malloc(page_len);
ctx->page_back = ctx->page_front + page_len;
+
+ ctx->heap_front = ctx->heap = malloc(heap_len);
+ ctx->heap_back = ctx->heap_front + heap_len;
+
return ctx;
}
void lw_free(lw_context ctx) {
free(ctx->page);
+ free(ctx->heap);
+ free(ctx);
+}
+
+static void lw_check_heap(lw_context ctx, size_t extra) {
+ if (ctx->heap_back - ctx->heap_front < extra) {
+ size_t desired = ctx->heap_back - ctx->heap_front + extra, next;
+ char *new_heap;
+
+ for (next = ctx->heap_back - ctx->heap_front; next < desired; next *= 2);
+
+ new_heap = realloc(ctx->heap, next);
+
+ if (new_heap != ctx->heap) {
+ ctx->heap = new_heap;
+ puts("Couldn't get contiguous chunk");
+ exit(1);
+ }
+
+ ctx->heap_back = new_heap + next;
+ }
+}
+
+void *lw_malloc(lw_context ctx, size_t len) {
+ void *result;
+
+ lw_check_heap(ctx, len);
+
+ result = ctx->heap_front;
+ ctx->heap_front += len;
+ return result;
}
int lw_really_send(int sock, const void *buf, ssize_t len) {
@@ -73,20 +111,58 @@ void lw_write(lw_context ctx, const char* s) {
}
-char *lw_Basis_attrifyInt(lw_Basis_int n) {
- return "0";
-}
+#define INTS_MAX 50
+#define FLOATS_MAX 100
-char *lw_Basis_attrifyFloat(lw_Basis_float n) {
- return "0.0";
+char *lw_Basis_attrifyInt(lw_context ctx, lw_Basis_int n) {
+ char *result;
+ int len;
+ lw_check_heap(ctx, INTS_MAX);
+ result = ctx->heap_front;
+ sprintf(result, "%d%n", n, &len);
+ ctx->heap_front += len;
+ return result;
}
-char *lw_Basis_attrifyString(lw_Basis_string s) {
- return "";
+char *lw_Basis_attrifyFloat(lw_context ctx, lw_Basis_float n) {
+ char *result;
+ int len;
+ lw_check_heap(ctx, INTS_MAX);
+ result = ctx->heap_front;
+ sprintf(result, "%g%n", n, &len);
+ ctx->heap_front += len;
+ return result;
}
-#define INTS_MAX 50
-#define FLOATS_MAX 100
+char *lw_Basis_attrifyString(lw_context ctx, lw_Basis_string s) {
+ int len = strlen(s);
+ char *result, *p;
+ lw_check_heap(ctx, len * 6);
+
+ result = p = ctx->heap_front;
+
+ for (; *s; s++) {
+ char c = *s;
+
+ if (c == '"') {
+ strcpy(p, "&quot;");
+ p += 6;
+ } else if (c == '&') {
+ strcpy(p, "&amp;");
+ p += 5;
+ }
+ else if (isprint(c))
+ *p++ = c;
+ else {
+ int len2;
+ sprintf(p, "&#%d;%n", c, &len2);
+ p += len2;
+ }
+ }
+
+ ctx->heap_front = p;
+ return result;
+}
static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
int len;
@@ -116,6 +192,8 @@ void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) {
if (c == '"')
lw_write_unsafe(ctx, "&quot;");
+ else if (c == '&')
+ lw_write_unsafe(ctx, "&amp;");
else if (isprint(c))
lw_writec_unsafe(ctx, c);
else {
@@ -205,12 +283,45 @@ lw_Basis_float lw_unurlifyFloat(char **s) {
return r;
}
-lw_Basis_string lw_unurlifyString(char **s) {
- return "";
+lw_Basis_string lw_unurlifyString(lw_context ctx, char **s) {
+ char *new_s = strchr(*s, '/');
+ char *r, *s1, *s2;
+ int len, n;
+
+ if (new_s)
+ *new_s++ = 0;
+ else
+ new_s = strchr(*s, 0);
+
+ len = strlen(*s);
+ lw_check_heap(ctx, len + 1);
+
+ r = ctx->heap_front;
+ for (s1 = r, s2 = *s; *s2; ++s1, ++s2) {
+ char c = *s2;
+
+ switch (c) {
+ case '+':
+ *s1 = ' ';
+ break;
+ case '%':
+ assert(s2 + 2 < new_s);
+ sscanf(s2+1, "%02X", &n);
+ *s1 = n;
+ s2 += 2;
+ break;
+ default:
+ *s1 = c;
+ }
+ }
+ *s1++ = 0;
+ ctx->heap_front = s1;
+ *s = new_s;
+ return r;
}
-char *lw_Basis_htmlifyString(lw_Basis_string s) {
+char *lw_Basis_htmlifyString(lw_context ctx, lw_Basis_string s) {
return "";
}
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index 68184acd..4cf3300d 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -212,7 +212,7 @@ fun unurlify (t, loc) =
case t of
TFfi ("Basis", "int") => string "lw_unurlifyInt(&request)"
| TFfi ("Basis", "float") => string "lw_unurlifyFloat(&request)"
- | TFfi ("Basis", "string") => string "lw_unurlifyString(&request)"
+ | TFfi ("Basis", "string") => string "lw_unurlifyString(ctx, &request)"
| TRecord 0 => string "lw_unit_v"
diff --git a/tests/cdataL.lac b/tests/cdataL.lac
new file mode 100644
index 00000000..3aa3bef6
--- /dev/null
+++ b/tests/cdataL.lac
@@ -0,0 +1,8 @@
+val subpage = fn s => <html><body>
+ <h1>{cdata s}</h1>
+</body></html>
+
+val main = fn () => <html><body>
+ <li> <a link={subpage "<Hi."}>Door #1</a></li>
+ <li> <a link={subpage "Bye."}>Door #2</a></li>
+</body></html>