annotate src/c/lacweb.c @ 152:67ab26888839

textarea
author Adam Chlipala <adamc@hcoop.net>
date Thu, 24 Jul 2008 10:41:53 -0400
parents f0d3402184d1
children 2be573fec9a6
rev   line source
adamc@117 1 #include <stdlib.h>
adamc@102 2 #include <stdio.h>
adamc@117 3 #include <string.h>
adamc@106 4 #include <ctype.h>
adamc@136 5 #include <assert.h>
adamc@102 6
adamc@102 7 #include "types.h"
adamc@102 8
adamc@102 9 lw_unit lw_unit_v = {};
adamc@102 10
adamc@117 11 struct lw_context {
adamc@117 12 char *page, *page_front, *page_back;
adamc@136 13 char *heap, *heap_front, *heap_back;
adamc@144 14 char **inputs;
adamc@117 15 };
adamc@117 16
adamc@144 17 extern int lw_inputs_len;
adamc@144 18
adamc@136 19 lw_context lw_init(size_t page_len, size_t heap_len) {
adamc@117 20 lw_context ctx = malloc(sizeof(struct lw_context));
adamc@136 21
adamc@117 22 ctx->page_front = ctx->page = malloc(page_len);
adamc@117 23 ctx->page_back = ctx->page_front + page_len;
adamc@136 24
adamc@136 25 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@136 26 ctx->heap_back = ctx->heap_front + heap_len;
adamc@136 27
adamc@144 28 ctx->inputs = calloc(lw_inputs_len, sizeof(char *));
adamc@144 29
adamc@117 30 return ctx;
adamc@106 31 }
adamc@106 32
adamc@117 33 void lw_free(lw_context ctx) {
adamc@117 34 free(ctx->page);
adamc@136 35 free(ctx->heap);
adamc@144 36 free(ctx->inputs);
adamc@136 37 free(ctx);
adamc@136 38 }
adamc@136 39
adamc@138 40 void lw_reset(lw_context ctx) {
adamc@138 41 ctx->page_front = ctx->page;
adamc@138 42 ctx->heap_front = ctx->heap;
adamc@144 43 memset(ctx->inputs, 0, lw_inputs_len * sizeof(char *));
adamc@144 44 }
adamc@144 45
adamc@144 46 int lw_input_num(char*);
adamc@144 47
adamc@144 48 void lw_set_input(lw_context ctx, char *name, char *value) {
adamc@144 49 int n = lw_input_num(name);
adamc@144 50
adamc@144 51 if (n < 0) {
adamc@144 52 printf("Bad input name");
adamc@144 53 exit(1);
adamc@144 54 }
adamc@144 55
adamc@144 56 assert(n < lw_inputs_len);
adamc@144 57 ctx->inputs[n] = value;
adamc@144 58
adamc@144 59 printf("[%d] %s = %s\n", n, name, value);
adamc@144 60 }
adamc@144 61
adamc@144 62 char *lw_get_input(lw_context ctx, int n) {
adamc@144 63 assert(n >= 0);
adamc@144 64 assert(n < lw_inputs_len);
adamc@144 65 printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@144 66 return ctx->inputs[n];
adamc@138 67 }
adamc@138 68
adamc@136 69 static void lw_check_heap(lw_context ctx, size_t extra) {
adamc@136 70 if (ctx->heap_back - ctx->heap_front < extra) {
adamc@136 71 size_t desired = ctx->heap_back - ctx->heap_front + extra, next;
adamc@136 72 char *new_heap;
adamc@136 73
adamc@136 74 for (next = ctx->heap_back - ctx->heap_front; next < desired; next *= 2);
adamc@136 75
adamc@136 76 new_heap = realloc(ctx->heap, next);
adamc@136 77
adamc@136 78 if (new_heap != ctx->heap) {
adamc@136 79 ctx->heap = new_heap;
adamc@136 80 puts("Couldn't get contiguous chunk");
adamc@136 81 exit(1);
adamc@136 82 }
adamc@136 83
adamc@136 84 ctx->heap_back = new_heap + next;
adamc@136 85 }
adamc@136 86 }
adamc@136 87
adamc@136 88 void *lw_malloc(lw_context ctx, size_t len) {
adamc@136 89 void *result;
adamc@136 90
adamc@136 91 lw_check_heap(ctx, len);
adamc@136 92
adamc@136 93 result = ctx->heap_front;
adamc@136 94 ctx->heap_front += len;
adamc@136 95 return result;
adamc@117 96 }
adamc@117 97
adamc@117 98 int lw_really_send(int sock, const void *buf, ssize_t len) {
adamc@117 99 while (len > 0) {
adamc@117 100 ssize_t n = send(sock, buf, len, 0);
adamc@117 101
adamc@117 102 if (n < 0)
adamc@117 103 return n;
adamc@117 104
adamc@117 105 buf += n;
adamc@117 106 len -= n;
adamc@117 107 }
adamc@117 108
adamc@117 109 return 0;
adamc@117 110 }
adamc@117 111
adamc@117 112 int lw_send(lw_context ctx, int sock) {
adamc@117 113 return lw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
adamc@117 114 }
adamc@117 115
adamc@117 116 static void lw_check(lw_context ctx, size_t extra) {
adamc@117 117 size_t desired = ctx->page_back - ctx->page_front + extra, next;
adamc@117 118 char *new_page;
adamc@117 119
adamc@117 120 for (next = ctx->page_back - ctx->page_front; next < desired; next *= 2);
adamc@117 121
adamc@117 122 new_page = realloc(ctx->page, next);
adamc@117 123 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@117 124 ctx->page_back = new_page + (ctx->page_back - ctx->page);
adamc@117 125 ctx->page = new_page;
adamc@117 126 }
adamc@117 127
adamc@117 128 static void lw_writec_unsafe(lw_context ctx, char c) {
adamc@117 129 *(ctx->page_front)++ = c;
adamc@117 130 }
adamc@117 131
adamc@117 132 void lw_writec(lw_context ctx, char c) {
adamc@117 133 lw_check(ctx, 1);
adamc@117 134 lw_writec_unsafe(ctx, c);
adamc@117 135 }
adamc@117 136
adamc@117 137 static void lw_write_unsafe(lw_context ctx, const char* s) {
adamc@117 138 int len = strlen(s);
adamc@117 139 memcpy(ctx->page_front, s, len);
adamc@117 140 ctx->page_front += len;
adamc@117 141 }
adamc@117 142
adamc@117 143 void lw_write(lw_context ctx, const char* s) {
adamc@117 144 lw_check(ctx, strlen(s));
adamc@117 145 lw_write_unsafe(ctx, s);
adamc@102 146 }
adamc@106 147
adamc@135 148
adamc@136 149 #define INTS_MAX 50
adamc@136 150 #define FLOATS_MAX 100
adamc@136 151
adamc@136 152 char *lw_Basis_attrifyInt(lw_context ctx, lw_Basis_int n) {
adamc@136 153 char *result;
adamc@136 154 int len;
adamc@136 155 lw_check_heap(ctx, INTS_MAX);
adamc@136 156 result = ctx->heap_front;
adamc@136 157 sprintf(result, "%d%n", n, &len);
adamc@137 158 ctx->heap_front += len+1;
adamc@136 159 return result;
adamc@106 160 }
adamc@106 161
adamc@136 162 char *lw_Basis_attrifyFloat(lw_context ctx, lw_Basis_float n) {
adamc@136 163 char *result;
adamc@136 164 int len;
adamc@137 165 lw_check_heap(ctx, FLOATS_MAX);
adamc@136 166 result = ctx->heap_front;
adamc@136 167 sprintf(result, "%g%n", n, &len);
adamc@137 168 ctx->heap_front += len+1;
adamc@136 169 return result;
adamc@106 170 }
adamc@106 171
adamc@136 172 char *lw_Basis_attrifyString(lw_context ctx, lw_Basis_string s) {
adamc@136 173 int len = strlen(s);
adamc@136 174 char *result, *p;
adamc@137 175 lw_check_heap(ctx, len * 6 + 1);
adamc@136 176
adamc@136 177 result = p = ctx->heap_front;
adamc@136 178
adamc@136 179 for (; *s; s++) {
adamc@136 180 char c = *s;
adamc@136 181
adamc@136 182 if (c == '"') {
adamc@136 183 strcpy(p, "&quot;");
adamc@136 184 p += 6;
adamc@136 185 } else if (c == '&') {
adamc@136 186 strcpy(p, "&amp;");
adamc@136 187 p += 5;
adamc@136 188 }
adamc@136 189 else if (isprint(c))
adamc@136 190 *p++ = c;
adamc@136 191 else {
adamc@136 192 int len2;
adamc@136 193 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 194 p += len2;
adamc@136 195 }
adamc@136 196 }
adamc@136 197
adamc@137 198 *p++ = 0;
adamc@136 199 ctx->heap_front = p;
adamc@136 200 return result;
adamc@106 201 }
adamc@106 202
adamc@117 203 static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
adamc@117 204 int len;
adamc@117 205
adamc@117 206 sprintf(ctx->page_front, "%d%n", n, &len);
adamc@117 207 ctx->page_front += len;
adamc@106 208 }
adamc@106 209
adamc@117 210 void lw_Basis_attrifyInt_w(lw_context ctx, lw_Basis_int n) {
adamc@117 211 lw_check(ctx, INTS_MAX);
adamc@117 212 lw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@106 213 }
adamc@106 214
adamc@117 215 void lw_Basis_attrifyFloat_w(lw_context ctx, lw_Basis_float n) {
adamc@117 216 int len;
adamc@117 217
adamc@117 218 lw_check(ctx, FLOATS_MAX);
adamc@117 219 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 220 ctx->page_front += len;
adamc@117 221 }
adamc@117 222
adamc@117 223 void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) {
adamc@117 224 lw_check(ctx, strlen(s) * 6);
adamc@117 225
adamc@106 226 for (; *s; s++) {
adamc@106 227 char c = *s;
adamc@106 228
adamc@106 229 if (c == '"')
adamc@117 230 lw_write_unsafe(ctx, "&quot;");
adamc@136 231 else if (c == '&')
adamc@136 232 lw_write_unsafe(ctx, "&amp;");
adamc@106 233 else if (isprint(c))
adamc@117 234 lw_writec_unsafe(ctx, c);
adamc@106 235 else {
adamc@117 236 lw_write_unsafe(ctx, "&#");
adamc@117 237 lw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@117 238 lw_writec_unsafe(ctx, ';');
adamc@106 239 }
adamc@106 240 }
adamc@106 241 }
adamc@120 242
adamc@120 243
adamc@137 244 char *lw_Basis_urlifyInt(lw_context ctx, lw_Basis_int n) {
adamc@137 245 int len;
adamc@137 246 char *r;
adamc@137 247
adamc@137 248 lw_check_heap(ctx, INTS_MAX);
adamc@137 249 r = ctx->heap_front;
adamc@137 250 sprintf(r, "%d%n", n, &len);
adamc@137 251 ctx->heap_front += len+1;
adamc@137 252 return r;
adamc@120 253 }
adamc@120 254
adamc@137 255 char *lw_Basis_urlifyFloat(lw_context ctx, lw_Basis_float n) {
adamc@137 256 int len;
adamc@137 257 char *r;
adamc@137 258
adamc@137 259 lw_check_heap(ctx, FLOATS_MAX);
adamc@137 260 r = ctx->heap_front;
adamc@137 261 sprintf(r, "%g%n", n, &len);
adamc@137 262 ctx->heap_front += len+1;
adamc@137 263 return r;
adamc@120 264 }
adamc@120 265
adamc@137 266 char *lw_Basis_urlifyString(lw_context ctx, lw_Basis_string s) {
adamc@137 267 char *r, *p;
adamc@137 268
adamc@137 269 lw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 270
adamc@137 271 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 272 char c = *s;
adamc@137 273
adamc@137 274 if (c == ' ')
adamc@137 275 *p++ = '+';
adamc@137 276 else if (isalnum(c))
adamc@137 277 *p++ = c;
adamc@137 278 else {
adamc@137 279 sprintf(p, "%%%02X", c);
adamc@137 280 p += 3;
adamc@137 281 }
adamc@137 282 }
adamc@137 283
adamc@137 284 *p++ = 0;
adamc@137 285 ctx->heap_front = p;
adamc@137 286 return r;
adamc@120 287 }
adamc@120 288
adamc@120 289 static void lw_Basis_urlifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
adamc@120 290 int len;
adamc@120 291
adamc@120 292 sprintf(ctx->page_front, "%d%n", n, &len);
adamc@120 293 ctx->page_front += len;
adamc@120 294 }
adamc@120 295
adamc@120 296 void lw_Basis_urlifyInt_w(lw_context ctx, lw_Basis_int n) {
adamc@120 297 lw_check(ctx, INTS_MAX);
adamc@120 298 lw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@120 299 }
adamc@120 300
adamc@120 301 void lw_Basis_urlifyFloat_w(lw_context ctx, lw_Basis_float n) {
adamc@120 302 int len;
adamc@120 303
adamc@120 304 lw_check(ctx, FLOATS_MAX);
adamc@120 305 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 306 ctx->page_front += len;
adamc@120 307 }
adamc@120 308
adamc@120 309 void lw_Basis_urlifyString_w(lw_context ctx, lw_Basis_string s) {
adamc@120 310 lw_check(ctx, strlen(s) * 3);
adamc@120 311
adamc@120 312 for (; *s; s++) {
adamc@120 313 char c = *s;
adamc@120 314
adamc@120 315 if (c == ' ')
adamc@120 316 lw_writec_unsafe(ctx, '+');
adamc@120 317 else if (isalnum(c))
adamc@120 318 lw_writec_unsafe(ctx, c);
adamc@120 319 else {
adamc@120 320 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 321 ctx->page_front += 3;
adamc@120 322 }
adamc@120 323 }
adamc@120 324 }
adamc@120 325
adamc@120 326
adamc@144 327 static char *lw_unurlify_advance(char *s) {
adamc@144 328 char *new_s = strchr(s, '/');
adamc@120 329
adamc@120 330 if (new_s)
adamc@120 331 *new_s++ = 0;
adamc@120 332 else
adamc@144 333 new_s = strchr(s, 0);
adamc@144 334
adamc@144 335 return new_s;
adamc@144 336 }
adamc@144 337
adamc@144 338 lw_Basis_int lw_unurlifyInt(char **s) {
adamc@144 339 char *new_s = lw_unurlify_advance(*s);
adamc@144 340 int r;
adamc@120 341
adamc@120 342 r = atoi(*s);
adamc@120 343 *s = new_s;
adamc@120 344 return r;
adamc@120 345 }
adamc@120 346
adamc@120 347 lw_Basis_float lw_unurlifyFloat(char **s) {
adamc@144 348 char *new_s = lw_unurlify_advance(*s);
adamc@120 349 int r;
adamc@120 350
adamc@120 351 r = atof(*s);
adamc@120 352 *s = new_s;
adamc@120 353 return r;
adamc@120 354 }
adamc@120 355
adamc@144 356 static lw_Basis_string lw_unurlifyString_to(char *r, char *s) {
adamc@144 357 char *s1, *s2;
adamc@144 358 int n;
adamc@136 359
adamc@144 360 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 361 char c = *s2;
adamc@136 362
adamc@136 363 switch (c) {
adamc@136 364 case '+':
adamc@136 365 *s1 = ' ';
adamc@136 366 break;
adamc@136 367 case '%':
adamc@144 368 assert(s2[1] != 0 && s2[2] != 0);
adamc@136 369 sscanf(s2+1, "%02X", &n);
adamc@136 370 *s1 = n;
adamc@136 371 s2 += 2;
adamc@136 372 break;
adamc@136 373 default:
adamc@136 374 *s1 = c;
adamc@136 375 }
adamc@136 376 }
adamc@136 377 *s1++ = 0;
adamc@144 378 return s1;
adamc@144 379 }
adamc@144 380
adamc@144 381 lw_Basis_string lw_unurlifyString(lw_context ctx, char **s) {
adamc@144 382 char *new_s = lw_unurlify_advance(*s);
adamc@144 383 char *r, *s1, *s2;
adamc@144 384 int len, n;
adamc@144 385
adamc@144 386 len = strlen(*s);
adamc@144 387 lw_check_heap(ctx, len + 1);
adamc@144 388
adamc@144 389 r = ctx->heap_front;
adamc@144 390 ctx->heap_front = lw_unurlifyString_to(ctx->heap_front, *s);
adamc@136 391 *s = new_s;
adamc@136 392 return r;
adamc@120 393 }
adamc@135 394
adamc@135 395
adamc@136 396 char *lw_Basis_htmlifyString(lw_context ctx, lw_Basis_string s) {
adamc@137 397 char *r, *s2;
adamc@137 398
adamc@137 399 lw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 400
adamc@137 401 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 402 char c = *s;
adamc@137 403
adamc@137 404 switch (c) {
adamc@137 405 case '<':
adamc@137 406 strcpy(s2, "&lt;");
adamc@137 407 s2 += 4;
adamc@137 408 break;
adamc@137 409 case '&':
adamc@137 410 strcpy(s2, "&amp;");
adamc@137 411 s2 += 5;
adamc@137 412 break;
adamc@137 413 default:
adamc@137 414 if (isprint(c))
adamc@137 415 *s2++ = c;
adamc@137 416 else {
adamc@137 417 int len2;
adamc@137 418 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 419 s2 += len2;
adamc@137 420 }
adamc@137 421 }
adamc@137 422 }
adamc@137 423
adamc@137 424 *s2++ = 0;
adamc@137 425 ctx->heap_front = s2;
adamc@137 426 return r;
adamc@135 427 }
adamc@135 428
adamc@135 429 void lw_Basis_htmlifyString_w(lw_context ctx, lw_Basis_string s) {
adamc@135 430 lw_check(ctx, strlen(s) * 5);
adamc@135 431
adamc@135 432 for (; *s; s++) {
adamc@135 433 char c = *s;
adamc@135 434
adamc@135 435 switch (c) {
adamc@135 436 case '<':
adamc@135 437 lw_write_unsafe(ctx, "&lt;");
adamc@135 438 break;
adamc@135 439 case '&':
adamc@135 440 lw_write_unsafe(ctx, "&amp;");
adamc@135 441 break;
adamc@135 442 default:
adamc@135 443 if (isprint(c))
adamc@135 444 lw_writec_unsafe(ctx, c);
adamc@135 445 else {
adamc@135 446 lw_write_unsafe(ctx, "&#");
adamc@135 447 lw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@135 448 lw_writec_unsafe(ctx, ';');
adamc@135 449 }
adamc@135 450 }
adamc@135 451 }
adamc@135 452 }