diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | include/lacweb.h | 14 | ||||
-rw-r--r-- | include/types.h | 3 | ||||
-rw-r--r-- | src/c/driver.c | 20 | ||||
-rw-r--r-- | src/c/lacweb.c | 105 | ||||
-rw-r--r-- | src/cjr_print.sml | 10 | ||||
-rw-r--r-- | src/tag.sml | 2 |
7 files changed, 127 insertions, 29 deletions
@@ -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("""); + lw_write_unsafe(ctx, """); 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))) |