summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--include/lacweb.h14
-rw-r--r--include/types.h3
-rw-r--r--src/c/driver.c20
-rw-r--r--src/c/lacweb.c105
-rw-r--r--src/cjr_print.sml10
-rw-r--r--src/tag.sml2
7 files changed, 127 insertions, 29 deletions
diff --git a/Makefile b/Makefile
index c6d66184..ace1e702 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ clib/lacweb.o: src/c/lacweb.c
gcc -O3 -I include -c src/c/lacweb.c -o clib/lacweb.o
clib/driver.o: src/c/driver.c
- gcc -O3 -c src/c/driver.c -o clib/driver.o
+ gcc -O3 -I include -c src/c/driver.c -o clib/driver.o
src/lacweb.cm: src/prefix.cm src/sources
cat src/prefix.cm src/sources \
diff --git a/include/lacweb.h b/include/lacweb.h
index 983f979a..891b059d 100644
--- a/include/lacweb.h
+++ b/include/lacweb.h
@@ -1,9 +1,21 @@
+#include <sys/types.h>
+
#include "types.h"
+int lw_really_send(int sock, void *buf, ssize_t len);
+
extern lw_unit lw_unit_v;
-void lw_write(const char*);
+lw_context lw_init(int page_len);
+void lw_free(lw_context);
+int lw_send(lw_context, int sock);
+
+void lw_write(lw_context, const char*);
char *lw_Basis_attrifyInt(lw_Basis_int);
char *lw_Basis_attrifyFloat(lw_Basis_float);
char *lw_Basis_attrifyString(lw_Basis_string);
+
+void lw_Basis_attrifyInt_w(lw_context, lw_Basis_int);
+void lw_Basis_attrifyFloat_w(lw_context, lw_Basis_float);
+void lw_Basis_attrifyString_w(lw_context, lw_Basis_string);
diff --git a/include/types.h b/include/types.h
index 28a8ea80..2dfaad84 100644
--- a/include/types.h
+++ b/include/types.h
@@ -6,3 +6,6 @@ struct __lws_0 {
};
typedef struct __lws_0 lw_unit;
+
+typedef struct lw_context *lw_context;
+
diff --git a/src/c/driver.c b/src/c/driver.c
index 16b2dad5..8f3ef70f 100644
--- a/src/c/driver.c
+++ b/src/c/driver.c
@@ -5,11 +5,13 @@
#include <sys/socket.h>
#include <netinet/in.h>
+#include "lacweb.h"
+
int lw_port = 8080;
int lw_backlog = 10;
int lw_bufsize = 1024;
-void lw_handle(char*);
+void lw_handle(lw_context, char*);
static void worker(int sock) {
char buf[lw_bufsize+1], *back = buf, *s;
@@ -36,10 +38,11 @@ static void worker(int sock) {
if (s = strstr(buf, "\r\n\r\n")) {
char *cmd, *path;
+ lw_context ctx;
*s = 0;
- if (!(s = strstr(buf, "\n"))) {
+ if (!(s = strstr(buf, "\r\n"))) {
fprintf(stderr, "No newline in buf\n");
close(sock);
return;
@@ -68,10 +71,15 @@ static void worker(int sock) {
}
printf("Serving URI %s....\n", path);
- puts("Content-type: text/html\n\n");
- puts("<html>");
- lw_handle(path);
- puts("</html>");
+
+ ctx = lw_init(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>");
+ lw_handle(ctx, path);
+ lw_write(ctx, "</html>");
+
+ lw_send(ctx, sock);
printf("Done with client.\n\n");
close(sock);
diff --git a/src/c/lacweb.c b/src/c/lacweb.c
index 10ccd6a0..ef8e7184 100644
--- a/src/c/lacweb.c
+++ b/src/c/lacweb.c
@@ -1,16 +1,75 @@
+#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <ctype.h>
#include "types.h"
lw_unit lw_unit_v = {};
-void lw_writec(char c) {
- fputc(c, stdout);
+struct lw_context {
+ char *page, *page_front, *page_back;
+};
+
+lw_context lw_init(int page_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;
+ return ctx;
+}
+
+void lw_free(lw_context ctx) {
+ free(ctx->page);
+}
+
+int lw_really_send(int sock, const void *buf, ssize_t len) {
+ while (len > 0) {
+ ssize_t n = send(sock, buf, len, 0);
+
+ if (n < 0)
+ return n;
+
+ buf += n;
+ len -= n;
+ }
+
+ return 0;
}
-void lw_write(const char* s) {
- fputs(s, stdout);
+int lw_send(lw_context ctx, int sock) {
+ return lw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
+}
+
+static void lw_check(lw_context ctx, size_t extra) {
+ size_t desired = ctx->page_back - ctx->page_front + extra, next;
+ char *new_page;
+
+ for (next = ctx->page_back - ctx->page_front; next < desired; next *= 2);
+
+ new_page = realloc(ctx->page, next);
+ ctx->page_front = new_page + (ctx->page_front - ctx->page);
+ ctx->page_back = new_page + (ctx->page_back - ctx->page);
+ ctx->page = new_page;
+}
+
+static void lw_writec_unsafe(lw_context ctx, char c) {
+ *(ctx->page_front)++ = c;
+}
+
+void lw_writec(lw_context ctx, char c) {
+ lw_check(ctx, 1);
+ lw_writec_unsafe(ctx, c);
+}
+
+static void lw_write_unsafe(lw_context ctx, const char* s) {
+ int len = strlen(s);
+ memcpy(ctx->page_front, s, len);
+ ctx->page_front += len;
+}
+
+void lw_write(lw_context ctx, const char* s) {
+ lw_check(ctx, strlen(s));
+ lw_write_unsafe(ctx, s);
}
char *lw_Basis_attrifyInt(lw_Basis_int n) {
@@ -25,27 +84,43 @@ char *lw_Basis_attrifyString(lw_Basis_string s) {
return "";
}
-char *lw_Basis_attrifyInt_w(lw_Basis_int n) {
- printf("%d", n);
+#define INTS_MAX 50
+#define FLOATS_MAX 100
+
+static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
+ int len;
+
+ sprintf(ctx->page_front, "%d%n", n, &len);
+ ctx->page_front += len;
+}
+
+void lw_Basis_attrifyInt_w(lw_context ctx, lw_Basis_int n) {
+ lw_check(ctx, INTS_MAX);
+ lw_Basis_attrifyInt_w_unsafe(ctx, n);
}
-char *lw_Basis_attrifyFloat_w(lw_Basis_float n) {
- printf("%g", n);
+void lw_Basis_attrifyFloat_w(lw_context ctx, lw_Basis_float n) {
+ int len;
+
+ lw_check(ctx, FLOATS_MAX);
+ sprintf(ctx->page_front, "%g%n", n, &len);
+ ctx->page_front += len;
}
-char *lw_Basis_attrifyString_w(lw_Basis_string s) {
+void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) {
+ lw_check(ctx, strlen(s) * 6);
+
for (; *s; s++) {
char c = *s;
if (c == '"')
- lw_write("&quot;");
+ lw_write_unsafe(ctx, "&quot;");
else if (isprint(c))
- lw_writec(c);
+ lw_writec_unsafe(ctx, c);
else {
- lw_write("&#");
- lw_Basis_attrifyInt_w(c);
- lw_writec(';');
+ lw_write_unsafe(ctx, "&#");
+ lw_Basis_attrifyInt_w_unsafe(ctx, c);
+ lw_writec_unsafe(ctx, ';');
}
}
- lw_write(s);
}
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index 19df046f..980be593 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -80,7 +80,7 @@ fun p_exp' par env (e, _) =
string m,
string "_",
string x,
- string "(",
+ string "(ctx, ",
p_list (p_exp env) es,
string ")"]
| EApp (e1, e2) => parenIf par (box [p_exp' true env e1,
@@ -111,7 +111,7 @@ fun p_exp' par env (e, _) =
string ".",
string x]
- | EWrite e => box [string "(lw_write(",
+ | EWrite e => box [string "(lw_write(ctx, ",
p_exp env e,
string "), lw_unit_v)"]
@@ -158,7 +158,7 @@ fun p_decl env ((d, _) : decl) =
p_typ env ran,
space,
string ("__lwn_" ^ fx ^ "_" ^ Int.toString n),
- string "(",
+ string "(lw_context ctx, ",
p_typ env dom,
space,
p_rel env' 0,
@@ -179,7 +179,7 @@ fun p_page env (s, n) =
string "\")) {",
newline,
p_enamed env n,
- string "(lw_unit_v);",
+ string "(ctx, lw_unit_v);",
newline,
string "}",
newline]
@@ -197,7 +197,7 @@ fun p_file env (ds, ps) =
newline,
p_list_sep newline (fn x => x) pds,
newline,
- string "void lw_handle(char *request) {",
+ string "void lw_handle(lw_context ctx, char *request) {",
newline,
p_list_sep newline (fn x => x) pds',
newline,
diff --git a/src/tag.sml b/src/tag.sml
index ebccc26d..9004a55b 100644
--- a/src/tag.sml
+++ b/src/tag.sml
@@ -100,7 +100,7 @@ fun exp env (e, s) =
val e = (EClosure (cn, args), loc)
val t = (CFfi ("Basis", "string"), loc)
in
- ((x, e, t),
+ (((CName "href", loc), e, t),
(count, tags, byTag, newTags))
end
| _ => ((x, e, t), (count, tags, byTag, newTags)))