annotate src/c/lacweb.c @ 184:98c29e3986d3

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