annotate src/c/urweb.c @ 572:57018f21cd5c

Handling singnal bind
author Adam Chlipala <adamc@hcoop.net>
date Sun, 21 Dec 2008 12:30:57 -0500
parents a152905c3c3b
children ac947e2f29ff
rev   line source
adamc@436 1 #define _XOPEN_SOURCE
adamc@436 2
adamc@117 3 #include <stdlib.h>
adamc@102 4 #include <stdio.h>
adamc@117 5 #include <string.h>
adamc@457 6 #include <strings.h>
adamc@106 7 #include <ctype.h>
adamc@167 8 #include <setjmp.h>
adamc@167 9 #include <stdarg.h>
adamc@102 10
adamc@102 11 #include "types.h"
adamc@102 12
adamc@311 13 uw_unit uw_unit_v = {};
adamc@102 14
adamc@167 15 #define ERROR_BUF_LEN 1024
adamc@167 16
adamc@323 17 typedef struct regions {
adamc@323 18 struct regions *next;
adamc@323 19 } regions;
adamc@323 20
adamc@425 21 typedef struct {
adamc@425 22 void (*func)(void*);
adamc@425 23 void *arg;
adamc@425 24 } cleanup;
adamc@425 25
adamc@311 26 struct uw_context {
adamc@458 27 char *headers, *headers_end;
adamc@457 28
adamc@462 29 char *outHeaders, *outHeaders_front, *outHeaders_back;
adamc@117 30 char *page, *page_front, *page_back;
adamc@136 31 char *heap, *heap_front, *heap_back;
adamc@144 32 char **inputs;
adamc@167 33
adamc@562 34 char *script, *script_front, *script_back;
adamc@565 35 int source_count;
adamc@562 36
adamc@272 37 void *db;
adamc@272 38
adamc@167 39 jmp_buf jmp_buf;
adamc@167 40
adamc@323 41 regions *regions;
adamc@323 42
adamc@425 43 cleanup *cleanup, *cleanup_front, *cleanup_back;
adamc@425 44
adamc@167 45 char error_message[ERROR_BUF_LEN];
adamc@117 46 };
adamc@117 47
adamc@311 48 extern int uw_inputs_len;
adamc@144 49
adamc@562 50 uw_context uw_init(size_t outHeaders_len, size_t script_len, size_t page_len, size_t heap_len) {
adamc@311 51 uw_context ctx = malloc(sizeof(struct uw_context));
adamc@136 52
adamc@458 53 ctx->headers = ctx->headers_end = NULL;
adamc@457 54
adamc@462 55 ctx->outHeaders_front = ctx->outHeaders = malloc(outHeaders_len);
adamc@462 56 ctx->outHeaders_back = ctx->outHeaders_front + outHeaders_len;
adamc@462 57
adamc@462 58 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@462 59
adamc@117 60 ctx->page_front = ctx->page = malloc(page_len);
adamc@117 61 ctx->page_back = ctx->page_front + page_len;
adamc@136 62
adamc@136 63 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@136 64 ctx->heap_back = ctx->heap_front + heap_len;
adamc@136 65
adamc@311 66 ctx->inputs = calloc(uw_inputs_len, sizeof(char *));
adamc@144 67
adamc@272 68 ctx->db = NULL;
adamc@272 69
adamc@323 70 ctx->regions = NULL;
adamc@323 71
adamc@425 72 ctx->cleanup_front = ctx->cleanup_back = ctx->cleanup = malloc(0);
adamc@425 73
adamc@167 74 ctx->error_message[0] = 0;
adamc@167 75
adamc@562 76 ctx->script_front = ctx->script = malloc(script_len);
adamc@562 77 ctx->script_back = ctx->script_front + script_len;
adamc@565 78 ctx->source_count = 0;
adamc@562 79
adamc@117 80 return ctx;
adamc@106 81 }
adamc@106 82
adamc@311 83 void uw_set_db(uw_context ctx, void *db) {
adamc@272 84 ctx->db = db;
adamc@272 85 }
adamc@272 86
adamc@311 87 void *uw_get_db(uw_context ctx) {
adamc@272 88 return ctx->db;
adamc@272 89 }
adamc@272 90
adamc@311 91 void uw_free(uw_context ctx) {
adamc@462 92 free(ctx->outHeaders);
adamc@562 93 free(ctx->script);
adamc@117 94 free(ctx->page);
adamc@136 95 free(ctx->heap);
adamc@144 96 free(ctx->inputs);
adamc@425 97 free(ctx->cleanup);
adamc@136 98 free(ctx);
adamc@136 99 }
adamc@136 100
adamc@562 101 void uw_reset_keep_error_message(uw_context ctx) {
adamc@462 102 ctx->outHeaders_front = ctx->outHeaders;
adamc@562 103 ctx->script_front = ctx->script;
adamc@138 104 ctx->page_front = ctx->page;
adamc@138 105 ctx->heap_front = ctx->heap;
adamc@323 106 ctx->regions = NULL;
adamc@425 107 ctx->cleanup_front = ctx->cleanup;
adamc@565 108 ctx->source_count = 0;
adamc@167 109 }
adamc@167 110
adamc@562 111 void uw_reset_keep_request(uw_context ctx) {
adamc@562 112 uw_reset_keep_error_message(ctx);
adamc@562 113 ctx->error_message[0] = 0;
adamc@167 114 }
adamc@167 115
adamc@311 116 void uw_reset(uw_context ctx) {
adamc@311 117 uw_reset_keep_request(ctx);
adamc@311 118 memset(ctx->inputs, 0, uw_inputs_len * sizeof(char *));
adamc@144 119 }
adamc@144 120
adamc@311 121 void uw_db_init(uw_context);
adamc@311 122 void uw_handle(uw_context, char *);
adamc@167 123
adamc@311 124 failure_kind uw_begin_init(uw_context ctx) {
adamc@272 125 int r = setjmp(ctx->jmp_buf);
adamc@272 126
adamc@272 127 if (r == 0)
adamc@311 128 uw_db_init(ctx);
adamc@272 129
adamc@272 130 return r;
adamc@272 131 }
adamc@272 132
adamc@458 133 void uw_set_headers(uw_context ctx, char *headers) {
adamc@458 134 char *s = headers, *s2;
adamc@458 135 ctx->headers = headers;
adamc@458 136
adamc@458 137 while (s2 = strchr(s, '\r')) {
adamc@458 138 s = s2;
adamc@458 139
adamc@458 140 if (s[1] == 0)
adamc@458 141 break;
adamc@458 142
adamc@458 143 *s = 0;
adamc@458 144 s += 2;
adamc@458 145 }
adamc@458 146
adamc@458 147 ctx->headers_end = s;
adamc@458 148 }
adamc@458 149
adamc@458 150 failure_kind uw_begin(uw_context ctx, char *path) {
adamc@190 151 int r = setjmp(ctx->jmp_buf);
adamc@190 152
adamc@190 153 if (r == 0)
adamc@311 154 uw_handle(ctx, path);
adamc@167 155
adamc@190 156 return r;
adamc@167 157 }
adamc@167 158
adamc@311 159 __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) {
adamc@425 160 cleanup *cl;
adamc@425 161
adamc@167 162 va_list ap;
adamc@167 163 va_start(ap, fmt);
adamc@167 164
adamc@167 165 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
adamc@167 166
adamc@425 167 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
adamc@425 168 cl->func(cl->arg);
adamc@425 169
adamc@425 170 ctx->cleanup_front = ctx->cleanup;
adamc@425 171
adamc@190 172 longjmp(ctx->jmp_buf, fk);
adamc@167 173 }
adamc@167 174
adamc@425 175 void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) {
adamc@425 176 if (ctx->cleanup_front >= ctx->cleanup_back) {
adamc@425 177 int len = ctx->cleanup_back - ctx->cleanup, newLen;
adamc@425 178 if (len == 0)
adamc@425 179 newLen = 1;
adamc@425 180 else
adamc@428 181 newLen = len * 2;
adamc@470 182 ctx->cleanup = realloc(ctx->cleanup, newLen * sizeof(cleanup));
adamc@425 183 ctx->cleanup_front = ctx->cleanup + len;
adamc@425 184 ctx->cleanup_back = ctx->cleanup + newLen;
adamc@425 185 }
adamc@425 186
adamc@425 187 ctx->cleanup_front->func = func;
adamc@425 188 ctx->cleanup_front->arg = arg;
adamc@425 189 ++ctx->cleanup_front;
adamc@425 190 }
adamc@425 191
adamc@425 192 void uw_pop_cleanup(uw_context ctx) {
adamc@425 193 if (ctx->cleanup_front == ctx->cleanup)
adamc@425 194 uw_error(ctx, FATAL, "Attempt to pop from empty cleanup action stack");
adamc@425 195
adamc@425 196 --ctx->cleanup_front;
adamc@425 197 ctx->cleanup_front->func(ctx->cleanup_front->arg);
adamc@425 198 }
adamc@425 199
adamc@311 200 char *uw_error_message(uw_context ctx) {
adamc@167 201 return ctx->error_message;
adamc@167 202 }
adamc@167 203
adamc@311 204 int uw_input_num(char*);
adamc@144 205
adamc@311 206 void uw_set_input(uw_context ctx, char *name, char *value) {
adamc@311 207 int n = uw_input_num(name);
adamc@144 208
adamc@169 209 if (n < 0)
adamc@311 210 uw_error(ctx, FATAL, "Bad input name %s", name);
adamc@144 211
adamc@311 212 if (n >= uw_inputs_len)
adamc@311 213 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n);
adamc@169 214
adamc@144 215 ctx->inputs[n] = value;
adamc@144 216
adamc@282 217 //printf("[%d] %s = %s\n", n, name, value);
adamc@144 218 }
adamc@144 219
adamc@311 220 char *uw_get_input(uw_context ctx, int n) {
adamc@169 221 if (n < 0)
adamc@311 222 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 223 if (n >= uw_inputs_len)
adamc@311 224 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@282 225 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@144 226 return ctx->inputs[n];
adamc@138 227 }
adamc@138 228
adamc@311 229 char *uw_get_optional_input(uw_context ctx, int n) {
adamc@190 230 if (n < 0)
adamc@311 231 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 232 if (n >= uw_inputs_len)
adamc@311 233 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@426 234 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@190 235 return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]);
adamc@190 236 }
adamc@190 237
adamc@311 238 static void uw_check_heap(uw_context ctx, size_t extra) {
adamc@136 239 if (ctx->heap_back - ctx->heap_front < extra) {
adamc@321 240 size_t desired = ctx->heap_front - ctx->heap + extra, next;
adamc@136 241 char *new_heap;
adamc@136 242
adamc@317 243 next = ctx->heap_back - ctx->heap;
adamc@317 244 if (next == 0)
adamc@317 245 next = 1;
adamc@317 246 for (; next < desired; next *= 2);
adamc@136 247
adamc@136 248 new_heap = realloc(ctx->heap, next);
adamc@321 249 ctx->heap_front = new_heap + (ctx->heap_front - ctx->heap);
adamc@169 250 ctx->heap_back = new_heap + next;
adamc@136 251
adamc@136 252 if (new_heap != ctx->heap) {
adamc@136 253 ctx->heap = new_heap;
adamc@311 254 uw_error(ctx, UNLIMITED_RETRY, "Couldn't allocate new heap chunk contiguously");
adamc@136 255 }
adamc@136 256
adamc@169 257 ctx->heap = new_heap;
adamc@136 258 }
adamc@136 259 }
adamc@136 260
adamc@311 261 void *uw_malloc(uw_context ctx, size_t len) {
adamc@136 262 void *result;
adamc@136 263
adamc@311 264 uw_check_heap(ctx, len);
adamc@136 265
adamc@136 266 result = ctx->heap_front;
adamc@136 267 ctx->heap_front += len;
adamc@136 268 return result;
adamc@117 269 }
adamc@117 270
adamc@323 271 void uw_begin_region(uw_context ctx) {
adamc@323 272 regions *r = (regions *) ctx->heap_front;
adamc@323 273
adamc@323 274 uw_check_heap(ctx, sizeof(regions));
adamc@323 275
adamc@323 276 ctx->heap_front += sizeof(regions);
adamc@323 277
adamc@323 278 r->next = ctx->regions;
adamc@323 279 ctx->regions = r;
adamc@323 280 }
adamc@323 281
adamc@323 282 void uw_end_region(uw_context ctx) {
adamc@323 283 regions *r = ctx->regions;
adamc@323 284
adamc@323 285 if (r == NULL)
adamc@323 286 uw_error(ctx, FATAL, "Region stack underflow");
adamc@323 287
adamc@323 288 ctx->heap_front = (char *) r;
adamc@323 289 ctx->regions = r->next;
adamc@323 290 }
adamc@323 291
adamc@324 292 void uw_memstats(uw_context ctx) {
adamc@462 293 printf("Headers: %d/%d\n", ctx->outHeaders_front - ctx->outHeaders, ctx->outHeaders_back - ctx->outHeaders);
adamc@562 294 printf("Script: %d/%d\n", ctx->script_front - ctx->script, ctx->script_back - ctx->script);
adamc@324 295 printf("Page: %d/%d\n", ctx->page_front - ctx->page, ctx->page_back - ctx->page);
adamc@324 296 printf("Heap: %d/%d\n", ctx->heap_front - ctx->heap, ctx->heap_back - ctx->heap);
adamc@324 297 }
adamc@324 298
adamc@436 299 int uw_really_send(int sock, const void *buf, size_t len) {
adamc@117 300 while (len > 0) {
adamc@436 301 size_t n = send(sock, buf, len, 0);
adamc@117 302
adamc@117 303 if (n < 0)
adamc@117 304 return n;
adamc@117 305
adamc@117 306 buf += n;
adamc@117 307 len -= n;
adamc@117 308 }
adamc@117 309
adamc@117 310 return 0;
adamc@117 311 }
adamc@117 312
adamc@311 313 int uw_send(uw_context ctx, int sock) {
adamc@462 314 int n = uw_really_send(sock, ctx->outHeaders, ctx->outHeaders_front - ctx->outHeaders);
adamc@462 315
adamc@462 316 if (n < 0)
adamc@462 317 return n;
adamc@462 318
adamc@462 319 n = uw_really_send(sock, "\r\n", 2);
adamc@462 320
adamc@462 321 if (n < 0)
adamc@462 322 return n;
adamc@462 323
adamc@464 324 return uw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
adamc@462 325 }
adamc@462 326
adamc@462 327 static void uw_check_headers(uw_context ctx, size_t extra) {
adamc@462 328 size_t desired = ctx->outHeaders_front - ctx->outHeaders + extra, next;
adamc@462 329 char *new_outHeaders;
adamc@462 330
adamc@462 331 next = ctx->outHeaders_back - ctx->outHeaders;
adamc@462 332 if (next < desired) {
adamc@462 333 if (next == 0)
adamc@462 334 next = 1;
adamc@462 335 for (; next < desired; next *= 2);
adamc@462 336
adamc@462 337 new_outHeaders = realloc(ctx->outHeaders, next);
adamc@462 338 ctx->outHeaders_front = new_outHeaders + (ctx->outHeaders_front - ctx->outHeaders);
adamc@462 339 ctx->outHeaders_back = new_outHeaders + next;
adamc@462 340 ctx->outHeaders = new_outHeaders;
adamc@462 341 }
adamc@462 342 }
adamc@462 343
adamc@462 344 void uw_write_header(uw_context ctx, uw_Basis_string s) {
adamc@462 345 int len = strlen(s);
adamc@462 346
adamc@462 347 uw_check_headers(ctx, len + 1);
adamc@462 348 strcpy(ctx->outHeaders_front, s);
adamc@462 349 ctx->outHeaders_front += len;
adamc@562 350 }
adamc@562 351
adamc@562 352 static void uw_check_script(uw_context ctx, size_t extra) {
adamc@562 353 size_t desired = ctx->script_front - ctx->script + extra, next;
adamc@562 354 char *new_script;
adamc@562 355
adamc@562 356 next = ctx->script_back - ctx->script;
adamc@562 357 if (next < desired) {
adamc@562 358 if (next == 0)
adamc@562 359 next = 1;
adamc@562 360 for (; next < desired; next *= 2);
adamc@562 361
adamc@562 362 new_script = realloc(ctx->script, next);
adamc@562 363 ctx->script_front = new_script + (ctx->script_front - ctx->script);
adamc@562 364 ctx->script_back = new_script + next;
adamc@562 365 ctx->script = new_script;
adamc@562 366 }
adamc@562 367 }
adamc@562 368
adamc@562 369 void uw_write_script(uw_context ctx, uw_Basis_string s) {
adamc@562 370 int len = strlen(s);
adamc@562 371
adamc@562 372 uw_check_script(ctx, len + 1);
adamc@562 373 strcpy(ctx->script_front, s);
adamc@562 374 ctx->script_front += len;
adamc@562 375 }
adamc@562 376
adamc@565 377 char *uw_Basis_get_script(uw_context ctx, uw_unit u) {
adamc@565 378 if (ctx->script_front == ctx->script) {
adamc@565 379 char *r = uw_malloc(ctx, 1);
adamc@565 380 r[0] = 0;
adamc@565 381 return r;
adamc@565 382 } else {
adamc@565 383 char *r = uw_malloc(ctx, 41 + (ctx->script_front - ctx->script));
adamc@565 384
adamc@565 385 sprintf(r, "<script type=\"text/javascript\">%s</script>", ctx->script);
adamc@565 386 return r;
adamc@565 387 }
adamc@565 388 }
adamc@565 389
adamc@565 390 int uw_Basis_new_client_source(uw_context ctx, uw_unit u) {
adamc@562 391 size_t len;
adamc@562 392
adamc@562 393 uw_check_script(ctx, 8 + INTS_MAX);
adamc@565 394 sprintf(ctx->script_front, "var e%d=0\n%n", ctx->source_count, &len);
adamc@562 395 ctx->script_front += len;
adamc@562 396
adamc@565 397 return ctx->source_count++;
adamc@117 398 }
adamc@117 399
adamc@311 400 static void uw_check(uw_context ctx, size_t extra) {
adamc@321 401 size_t desired = ctx->page_front - ctx->page + extra, next;
adamc@117 402 char *new_page;
adamc@117 403
adamc@317 404 next = ctx->page_back - ctx->page;
adamc@428 405 if (next < desired) {
adamc@428 406 if (next == 0)
adamc@428 407 next = 1;
adamc@428 408 for (; next < desired; next *= 2);
adamc@117 409
adamc@428 410 new_page = realloc(ctx->page, next);
adamc@428 411 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@428 412 ctx->page_back = new_page + next;
adamc@428 413 ctx->page = new_page;
adamc@428 414 }
adamc@117 415 }
adamc@117 416
adamc@311 417 static void uw_writec_unsafe(uw_context ctx, char c) {
adamc@117 418 *(ctx->page_front)++ = c;
adamc@117 419 }
adamc@117 420
adamc@311 421 void uw_writec(uw_context ctx, char c) {
adamc@311 422 uw_check(ctx, 1);
adamc@311 423 uw_writec_unsafe(ctx, c);
adamc@117 424 }
adamc@117 425
adamc@311 426 static void uw_write_unsafe(uw_context ctx, const char* s) {
adamc@117 427 int len = strlen(s);
adamc@117 428 memcpy(ctx->page_front, s, len);
adamc@117 429 ctx->page_front += len;
adamc@117 430 }
adamc@117 431
adamc@311 432 void uw_write(uw_context ctx, const char* s) {
adamc@311 433 uw_check(ctx, strlen(s) + 1);
adamc@311 434 uw_write_unsafe(ctx, s);
adamc@183 435 *ctx->page_front = 0;
adamc@102 436 }
adamc@106 437
adamc@135 438
adamc@311 439 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
adamc@136 440 char *result;
adamc@136 441 int len;
adamc@311 442 uw_check_heap(ctx, INTS_MAX);
adamc@136 443 result = ctx->heap_front;
adamc@276 444 sprintf(result, "%lld%n", n, &len);
adamc@137 445 ctx->heap_front += len+1;
adamc@136 446 return result;
adamc@106 447 }
adamc@106 448
adamc@311 449 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@136 450 char *result;
adamc@136 451 int len;
adamc@311 452 uw_check_heap(ctx, FLOATS_MAX);
adamc@136 453 result = ctx->heap_front;
adamc@136 454 sprintf(result, "%g%n", n, &len);
adamc@137 455 ctx->heap_front += len+1;
adamc@136 456 return result;
adamc@106 457 }
adamc@106 458
adamc@311 459 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
adamc@136 460 int len = strlen(s);
adamc@136 461 char *result, *p;
adamc@311 462 uw_check_heap(ctx, len * 6 + 1);
adamc@136 463
adamc@136 464 result = p = ctx->heap_front;
adamc@136 465
adamc@136 466 for (; *s; s++) {
adamc@136 467 char c = *s;
adamc@136 468
adamc@136 469 if (c == '"') {
adamc@136 470 strcpy(p, "&quot;");
adamc@136 471 p += 6;
adamc@136 472 } else if (c == '&') {
adamc@136 473 strcpy(p, "&amp;");
adamc@136 474 p += 5;
adamc@136 475 }
adamc@136 476 else if (isprint(c))
adamc@136 477 *p++ = c;
adamc@136 478 else {
adamc@136 479 int len2;
adamc@136 480 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 481 p += len2;
adamc@136 482 }
adamc@136 483 }
adamc@136 484
adamc@137 485 *p++ = 0;
adamc@136 486 ctx->heap_front = p;
adamc@136 487 return result;
adamc@106 488 }
adamc@106 489
adamc@311 490 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@117 491 int len;
adamc@117 492
adamc@276 493 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@117 494 ctx->page_front += len;
adamc@106 495 }
adamc@106 496
adamc@428 497 uw_unit uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 498 uw_check(ctx, INTS_MAX);
adamc@311 499 uw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@428 500
adamc@428 501 return uw_unit_v;
adamc@106 502 }
adamc@106 503
adamc@428 504 uw_unit uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@117 505 int len;
adamc@117 506
adamc@311 507 uw_check(ctx, FLOATS_MAX);
adamc@117 508 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 509 ctx->page_front += len;
adamc@428 510
adamc@428 511 return uw_unit_v;
adamc@117 512 }
adamc@117 513
adamc@428 514 uw_unit uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 515 uw_check(ctx, strlen(s) * 6);
adamc@117 516
adamc@106 517 for (; *s; s++) {
adamc@106 518 char c = *s;
adamc@106 519
adamc@106 520 if (c == '"')
adamc@311 521 uw_write_unsafe(ctx, "&quot;");
adamc@136 522 else if (c == '&')
adamc@311 523 uw_write_unsafe(ctx, "&amp;");
adamc@106 524 else if (isprint(c))
adamc@311 525 uw_writec_unsafe(ctx, c);
adamc@106 526 else {
adamc@311 527 uw_write_unsafe(ctx, "&#");
adamc@311 528 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 529 uw_writec_unsafe(ctx, ';');
adamc@106 530 }
adamc@106 531 }
adamc@428 532
adamc@428 533 return uw_unit_v;
adamc@106 534 }
adamc@120 535
adamc@120 536
adamc@311 537 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@137 538 int len;
adamc@137 539 char *r;
adamc@137 540
adamc@311 541 uw_check_heap(ctx, INTS_MAX);
adamc@137 542 r = ctx->heap_front;
adamc@276 543 sprintf(r, "%lld%n", n, &len);
adamc@137 544 ctx->heap_front += len+1;
adamc@137 545 return r;
adamc@120 546 }
adamc@120 547
adamc@311 548 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@137 549 int len;
adamc@137 550 char *r;
adamc@137 551
adamc@311 552 uw_check_heap(ctx, FLOATS_MAX);
adamc@137 553 r = ctx->heap_front;
adamc@137 554 sprintf(r, "%g%n", n, &len);
adamc@137 555 ctx->heap_front += len+1;
adamc@137 556 return r;
adamc@120 557 }
adamc@120 558
adamc@311 559 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 560 char *r, *p;
adamc@137 561
adamc@311 562 uw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 563
adamc@137 564 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 565 char c = *s;
adamc@137 566
adamc@137 567 if (c == ' ')
adamc@137 568 *p++ = '+';
adamc@137 569 else if (isalnum(c))
adamc@137 570 *p++ = c;
adamc@137 571 else {
adamc@137 572 sprintf(p, "%%%02X", c);
adamc@137 573 p += 3;
adamc@137 574 }
adamc@137 575 }
adamc@137 576
adamc@137 577 *p++ = 0;
adamc@137 578 ctx->heap_front = p;
adamc@137 579 return r;
adamc@120 580 }
adamc@120 581
adamc@311 582 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 583 if (b == uw_Basis_False)
adamc@186 584 return "0";
adamc@186 585 else
adamc@186 586 return "1";
adamc@186 587 }
adamc@186 588
adamc@311 589 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@120 590 int len;
adamc@120 591
adamc@276 592 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@120 593 ctx->page_front += len;
adamc@120 594 }
adamc@120 595
adamc@428 596 uw_unit uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 597 uw_check(ctx, INTS_MAX);
adamc@311 598 uw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@428 599
adamc@428 600 return uw_unit_v;
adamc@120 601 }
adamc@120 602
adamc@428 603 uw_unit uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@120 604 int len;
adamc@120 605
adamc@311 606 uw_check(ctx, FLOATS_MAX);
adamc@120 607 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 608 ctx->page_front += len;
adamc@428 609
adamc@428 610 return uw_unit_v;
adamc@120 611 }
adamc@120 612
adamc@488 613 uw_Basis_string uw_Basis_urlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@488 614 return uw_Basis_urlifyInt(ctx, t);
adamc@488 615 }
adamc@488 616
adamc@428 617 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 618 uw_check(ctx, strlen(s) * 3);
adamc@120 619
adamc@120 620 for (; *s; s++) {
adamc@120 621 char c = *s;
adamc@120 622
adamc@120 623 if (c == ' ')
adamc@311 624 uw_writec_unsafe(ctx, '+');
adamc@120 625 else if (isalnum(c))
adamc@311 626 uw_writec_unsafe(ctx, c);
adamc@120 627 else {
adamc@120 628 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 629 ctx->page_front += 3;
adamc@120 630 }
adamc@120 631 }
adamc@428 632
adamc@428 633 return uw_unit_v;
adamc@120 634 }
adamc@120 635
adamc@428 636 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 637 if (b == uw_Basis_False)
adamc@311 638 uw_writec(ctx, '0');
adamc@186 639 else
adamc@311 640 uw_writec(ctx, '1');
adamc@428 641
adamc@428 642 return uw_unit_v;
adamc@186 643 }
adamc@186 644
adamc@120 645
adamc@311 646 static char *uw_unurlify_advance(char *s) {
adamc@144 647 char *new_s = strchr(s, '/');
adamc@120 648
adamc@120 649 if (new_s)
adamc@120 650 *new_s++ = 0;
adamc@120 651 else
adamc@144 652 new_s = strchr(s, 0);
adamc@144 653
adamc@144 654 return new_s;
adamc@144 655 }
adamc@144 656
adamc@311 657 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 658 char *new_s = uw_unurlify_advance(*s);
adamc@311 659 uw_Basis_int r;
adamc@120 660
adamc@276 661 r = atoll(*s);
adamc@120 662 *s = new_s;
adamc@120 663 return r;
adamc@120 664 }
adamc@120 665
adamc@311 666 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 667 char *new_s = uw_unurlify_advance(*s);
adamc@311 668 uw_Basis_float r;
adamc@120 669
adamc@120 670 r = atof(*s);
adamc@120 671 *s = new_s;
adamc@120 672 return r;
adamc@120 673 }
adamc@120 674
adamc@488 675 uw_Basis_time uw_Basis_unurlifyTime(uw_context ctx, char **s) {
adamc@488 676 return uw_Basis_unurlifyInt(ctx, s);
adamc@488 677 }
adamc@488 678
adamc@311 679 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 680 char *s1, *s2;
adamc@144 681 int n;
adamc@136 682
adamc@144 683 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 684 char c = *s2;
adamc@136 685
adamc@136 686 switch (c) {
adamc@136 687 case '+':
adamc@136 688 *s1 = ' ';
adamc@136 689 break;
adamc@136 690 case '%':
adamc@169 691 if (s2[1] == 0)
adamc@311 692 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 693 if (s2[2] == 0)
adamc@311 694 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 695 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 696 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 697 *s1 = n;
adamc@136 698 s2 += 2;
adamc@136 699 break;
adamc@136 700 default:
adamc@136 701 *s1 = c;
adamc@136 702 }
adamc@136 703 }
adamc@136 704 *s1++ = 0;
adamc@144 705 return s1;
adamc@144 706 }
adamc@144 707
adamc@311 708 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 709 char *new_s = uw_unurlify_advance(*s);
adamc@311 710 uw_Basis_bool r;
adamc@186 711
adamc@186 712 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 713 r = uw_Basis_False;
adamc@186 714 else
adamc@311 715 r = uw_Basis_True;
adamc@186 716
adamc@186 717 *s = new_s;
adamc@186 718 return r;
adamc@186 719 }
adamc@186 720
adamc@311 721 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 722 char *new_s = uw_unurlify_advance(*s);
adamc@144 723 char *r, *s1, *s2;
adamc@144 724 int len, n;
adamc@144 725
adamc@200 726 len = strlen(*s);
adamc@311 727 uw_check_heap(ctx, len + 1);
adamc@144 728
adamc@144 729 r = ctx->heap_front;
adamc@311 730 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 731 *s = new_s;
adamc@136 732 return r;
adamc@120 733 }
adamc@135 734
adamc@135 735
adamc@311 736 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 737 int len;
adamc@286 738 char *r;
adamc@286 739
adamc@311 740 uw_check_heap(ctx, INTS_MAX);
adamc@286 741 r = ctx->heap_front;
adamc@286 742 sprintf(r, "%lld%n", n, &len);
adamc@286 743 ctx->heap_front += len+1;
adamc@286 744 return r;
adamc@286 745 }
adamc@286 746
adamc@428 747 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 748 int len;
adamc@286 749
adamc@311 750 uw_check(ctx, INTS_MAX);
adamc@286 751 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 752 ctx->page_front += len;
adamc@428 753
adamc@428 754 return uw_unit_v;
adamc@286 755 }
adamc@286 756
adamc@311 757 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 758 int len;
adamc@286 759 char *r;
adamc@286 760
adamc@311 761 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 762 r = ctx->heap_front;
adamc@286 763 sprintf(r, "%g%n", n, &len);
adamc@286 764 ctx->heap_front += len+1;
adamc@286 765 return r;
adamc@286 766 }
adamc@286 767
adamc@428 768 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 769 int len;
adamc@286 770
adamc@311 771 uw_check(ctx, FLOATS_MAX);
adamc@286 772 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 773 ctx->page_front += len;
adamc@428 774
adamc@428 775 return uw_unit_v;
adamc@286 776 }
adamc@286 777
adamc@311 778 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 779 char *r, *s2;
adamc@137 780
adamc@311 781 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 782
adamc@137 783 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 784 char c = *s;
adamc@137 785
adamc@137 786 switch (c) {
adamc@137 787 case '<':
adamc@137 788 strcpy(s2, "&lt;");
adamc@137 789 s2 += 4;
adamc@137 790 break;
adamc@137 791 case '&':
adamc@137 792 strcpy(s2, "&amp;");
adamc@137 793 s2 += 5;
adamc@137 794 break;
adamc@137 795 default:
adamc@137 796 if (isprint(c))
adamc@137 797 *s2++ = c;
adamc@137 798 else {
adamc@137 799 int len2;
adamc@137 800 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 801 s2 += len2;
adamc@137 802 }
adamc@137 803 }
adamc@137 804 }
adamc@137 805
adamc@137 806 *s2++ = 0;
adamc@137 807 ctx->heap_front = s2;
adamc@137 808 return r;
adamc@135 809 }
adamc@135 810
adamc@428 811 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 812 uw_check(ctx, strlen(s) * 6);
adamc@135 813
adamc@135 814 for (; *s; s++) {
adamc@135 815 char c = *s;
adamc@135 816
adamc@135 817 switch (c) {
adamc@135 818 case '<':
adamc@311 819 uw_write_unsafe(ctx, "&lt;");
adamc@135 820 break;
adamc@135 821 case '&':
adamc@311 822 uw_write_unsafe(ctx, "&amp;");
adamc@135 823 break;
adamc@135 824 default:
adamc@135 825 if (isprint(c))
adamc@311 826 uw_writec_unsafe(ctx, c);
adamc@135 827 else {
adamc@311 828 uw_write_unsafe(ctx, "&#");
adamc@311 829 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 830 uw_writec_unsafe(ctx, ';');
adamc@135 831 }
adamc@135 832 }
adamc@135 833 }
adamc@428 834
adamc@428 835 return uw_unit_v;
adamc@135 836 }
adamc@180 837
adamc@311 838 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 839 if (b == uw_Basis_False)
adamc@286 840 return "False";
adamc@286 841 else
adamc@286 842 return "True";
adamc@286 843 }
adamc@286 844
adamc@428 845 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 846 if (b == uw_Basis_False) {
adamc@311 847 uw_check(ctx, 6);
adamc@286 848 strcpy(ctx->page_front, "False");
adamc@286 849 ctx->page_front += 5;
adamc@286 850 } else {
adamc@311 851 uw_check(ctx, 5);
adamc@286 852 strcpy(ctx->page_front, "True");
adamc@286 853 ctx->page_front += 4;
adamc@286 854 }
adamc@428 855
adamc@428 856 return uw_unit_v;
adamc@286 857 }
adamc@286 858
adamc@436 859 #define TIME_FMT "%x %X"
adamc@438 860 #define TIME_FMT_PG "%Y-%m-%d %T"
adamc@436 861
adamc@436 862 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@436 863 size_t len;
adamc@436 864 char *r;
adamc@436 865 struct tm stm;
adamc@436 866
adamc@436 867 if (localtime_r(&t, &stm)) {
adamc@436 868 uw_check_heap(ctx, TIMES_MAX);
adamc@436 869 r = ctx->heap_front;
adamc@436 870 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 871 ctx->heap_front += len+1;
adamc@436 872 return r;
adamc@436 873 } else
adamc@436 874 return "<i>Invalid time</i>";
adamc@436 875 }
adamc@436 876
adamc@436 877 uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
adamc@436 878 size_t len;
adamc@436 879 char *r;
adamc@436 880 struct tm stm;
adamc@436 881
adamc@436 882 if (localtime_r(&t, &stm)) {
adamc@436 883 uw_check(ctx, TIMES_MAX);
adamc@436 884 r = ctx->page_front;
adamc@436 885 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 886 ctx->page_front += len;
adamc@436 887 } else {
adamc@436 888 uw_check(ctx, 20);
adamc@436 889 strcpy(ctx->page_front, "<i>Invalid time</i>");
adamc@436 890 ctx->page_front += 19;
adamc@436 891 }
adamc@436 892
adamc@436 893 return uw_unit_v;
adamc@436 894 }
adamc@436 895
adamc@311 896 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 897 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 898 char *s;
adamc@180 899
adamc@311 900 uw_check_heap(ctx, len);
adamc@180 901
adamc@180 902 s = ctx->heap_front;
adamc@180 903
adamc@180 904 strcpy(s, s1);
adamc@180 905 strcat(s, s2);
adamc@180 906 ctx->heap_front += len;
adamc@180 907
adamc@180 908 return s;
adamc@180 909 }
adamc@278 910
adamc@311 911 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 912 int len = strlen(s1) + 1;
adamc@278 913 char *s;
adamc@278 914
adamc@311 915 uw_check_heap(ctx, len);
adamc@278 916
adamc@278 917 s = ctx->heap_front;
adamc@278 918
adamc@278 919 strcpy(s, s1);
adamc@278 920 ctx->heap_front += len;
adamc@278 921
adamc@278 922 return s;
adamc@278 923 }
adamc@280 924
adamc@493 925 uw_Basis_string uw_Basis_maybe_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@493 926 if (s1)
adamc@493 927 return uw_Basis_strdup(ctx, s1);
adamc@493 928 else
adamc@493 929 return NULL;
adamc@493 930 }
adamc@493 931
adamc@280 932
adamc@311 933 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 934 int len;
adamc@281 935 char *r;
adamc@281 936
adamc@311 937 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 938 r = ctx->heap_front;
adamc@281 939 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 940 ctx->heap_front += len+1;
adamc@281 941 return r;
adamc@281 942 }
adamc@281 943
adamc@467 944 char *uw_Basis_sqlifyIntN(uw_context ctx, uw_Basis_int *n) {
adamc@467 945 if (n == NULL)
adamc@467 946 return "NULL";
adamc@467 947 else
adamc@467 948 return uw_Basis_sqlifyInt(ctx, *n);
adamc@467 949 }
adamc@467 950
adamc@311 951 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 952 int len;
adamc@281 953 char *r;
adamc@281 954
adamc@311 955 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 956 r = ctx->heap_front;
adamc@281 957 sprintf(r, "%g::float8%n", n, &len);
adamc@281 958 ctx->heap_front += len+1;
adamc@281 959 return r;
adamc@281 960 }
adamc@281 961
adamc@467 962 char *uw_Basis_sqlifyFloatN(uw_context ctx, uw_Basis_float *n) {
adamc@467 963 if (n == NULL)
adamc@467 964 return "NULL";
adamc@467 965 else
adamc@467 966 return uw_Basis_sqlifyFloat(ctx, *n);
adamc@467 967 }
adamc@467 968
adamc@281 969
adamc@311 970 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 971 char *r, *s2;
adamc@280 972
adamc@311 973 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 974
adamc@280 975 r = s2 = ctx->heap_front;
adamc@280 976 *s2++ = 'E';
adamc@280 977 *s2++ = '\'';
adamc@280 978
adamc@280 979 for (; *s; s++) {
adamc@280 980 char c = *s;
adamc@280 981
adamc@280 982 switch (c) {
adamc@280 983 case '\'':
adamc@280 984 strcpy(s2, "\\'");
adamc@280 985 s2 += 2;
adamc@280 986 break;
adamc@280 987 case '\\':
adamc@280 988 strcpy(s2, "\\\\");
adamc@280 989 s2 += 2;
adamc@280 990 break;
adamc@280 991 default:
adamc@280 992 if (isprint(c))
adamc@280 993 *s2++ = c;
adamc@280 994 else {
adamc@280 995 sprintf(s2, "\\%3o", c);
adamc@280 996 s2 += 4;
adamc@280 997 }
adamc@280 998 }
adamc@280 999 }
adamc@280 1000
adamc@281 1001 strcpy(s2, "'::text");
adamc@281 1002 ctx->heap_front = s2 + 8;
adamc@280 1003 return r;
adamc@280 1004 }
adamc@281 1005
adamc@467 1006 uw_Basis_string uw_Basis_sqlifyStringN(uw_context ctx, uw_Basis_string s) {
adamc@467 1007 if (s == NULL)
adamc@467 1008 return "NULL";
adamc@467 1009 else
adamc@467 1010 return uw_Basis_sqlifyString(ctx, s);
adamc@467 1011 }
adamc@467 1012
adamc@311 1013 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 1014 if (b == uw_Basis_False)
adamc@281 1015 return "FALSE";
adamc@281 1016 else
adamc@281 1017 return "TRUE";
adamc@281 1018 }
adamc@282 1019
adamc@467 1020 char *uw_Basis_sqlifyBoolN(uw_context ctx, uw_Basis_bool *b) {
adamc@467 1021 if (b == NULL)
adamc@467 1022 return "NULL";
adamc@467 1023 else
adamc@467 1024 return uw_Basis_sqlifyBool(ctx, *b);
adamc@467 1025 }
adamc@467 1026
adamc@439 1027 char *uw_Basis_sqlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@439 1028 size_t len;
adamc@439 1029 char *r;
adamc@439 1030 struct tm stm;
adamc@439 1031
adamc@439 1032 if (localtime_r(&t, &stm)) {
adamc@439 1033 uw_check_heap(ctx, TIMES_MAX);
adamc@439 1034 r = ctx->heap_front;
adamc@439 1035 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@439 1036 ctx->heap_front += len+1;
adamc@439 1037 return r;
adamc@439 1038 } else
adamc@439 1039 return "<Invalid time>";
adamc@439 1040 }
adamc@439 1041
adamc@467 1042 char *uw_Basis_sqlifyTimeN(uw_context ctx, uw_Basis_time *t) {
adamc@467 1043 if (t == NULL)
adamc@467 1044 return "NULL";
adamc@467 1045 else
adamc@467 1046 return uw_Basis_sqlifyTime(ctx, *t);
adamc@467 1047 }
adamc@467 1048
adamc@311 1049 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 1050 static uw_Basis_int true = 1;
adamc@311 1051 static uw_Basis_int false = 0;
adamc@282 1052
adamc@311 1053 if (b == uw_Basis_False)
adamc@282 1054 return (char *)&false;
adamc@282 1055 else
adamc@282 1056 return (char *)&true;
adamc@282 1057 }
adamc@284 1058
adamc@566 1059 uw_Basis_string uw_Basis_jsifyString(uw_context ctx, uw_Basis_string s) {
adamc@566 1060 char *r, *s2;
adamc@566 1061
adamc@566 1062 uw_check_heap(ctx, strlen(s) * 4 + 2);
adamc@566 1063
adamc@566 1064 r = s2 = ctx->heap_front;
adamc@566 1065 *s2++ = '"';
adamc@566 1066
adamc@566 1067 for (; *s; s++) {
adamc@566 1068 char c = *s;
adamc@566 1069
adamc@566 1070 switch (c) {
adamc@566 1071 case '"':
adamc@566 1072 strcpy(s2, "\\\"");
adamc@566 1073 s2 += 2;
adamc@566 1074 break;
adamc@566 1075 case '\\':
adamc@566 1076 strcpy(s2, "\\\\");
adamc@566 1077 s2 += 2;
adamc@566 1078 break;
adamc@566 1079 default:
adamc@566 1080 if (isprint(c))
adamc@566 1081 *s2++ = c;
adamc@566 1082 else {
adamc@566 1083 sprintf(s2, "\\%3o", c);
adamc@566 1084 s2 += 4;
adamc@566 1085 }
adamc@566 1086 }
adamc@566 1087 }
adamc@566 1088
adamc@566 1089 strcpy(s2, "\"");
adamc@566 1090 ctx->heap_front = s2 + 1;
adamc@566 1091 return r;
adamc@566 1092 }
adamc@566 1093
adamc@311 1094 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 1095 int len;
adamc@284 1096 char *r;
adamc@284 1097
adamc@311 1098 uw_check_heap(ctx, INTS_MAX);
adamc@284 1099 r = ctx->heap_front;
adamc@284 1100 sprintf(r, "%lld%n", n, &len);
adamc@284 1101 ctx->heap_front += len+1;
adamc@284 1102 return r;
adamc@284 1103 }
adamc@285 1104
adamc@311 1105 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 1106 int len;
adamc@285 1107 char *r;
adamc@285 1108
adamc@311 1109 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 1110 r = ctx->heap_front;
adamc@285 1111 sprintf(r, "%g%n", n, &len);
adamc@285 1112 ctx->heap_front += len+1;
adamc@285 1113 return r;
adamc@285 1114 }
adamc@285 1115
adamc@311 1116 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 1117 if (b == uw_Basis_False)
adamc@285 1118 return "False";
adamc@285 1119 else
adamc@285 1120 return "True";
adamc@285 1121 }
adamc@288 1122
adamc@436 1123 uw_Basis_string uw_Basis_timeToString(uw_context ctx, uw_Basis_time t) {
adamc@436 1124 size_t len;
adamc@436 1125 char *r;
adamc@436 1126 struct tm stm;
adamc@436 1127
adamc@436 1128 if (localtime_r(&t, &stm)) {
adamc@436 1129 uw_check_heap(ctx, TIMES_MAX);
adamc@436 1130 r = ctx->heap_front;
adamc@436 1131 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 1132 ctx->heap_front += len+1;
adamc@436 1133 return r;
adamc@436 1134 } else
adamc@436 1135 return "<Invalid time>";
adamc@436 1136 }
adamc@288 1137
adamc@311 1138 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 1139 char *endptr;
adamc@311 1140 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 1141
adamc@288 1142 if (*s != '\0' && *endptr == '\0') {
adamc@311 1143 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 1144 *r = n;
adamc@288 1145 return r;
adamc@288 1146 } else
adamc@288 1147 return NULL;
adamc@288 1148 }
adamc@289 1149
adamc@311 1150 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 1151 char *endptr;
adamc@311 1152 uw_Basis_float n = strtod(s, &endptr);
adamc@289 1153
adamc@289 1154 if (*s != '\0' && *endptr == '\0') {
adamc@311 1155 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 1156 *r = n;
adamc@289 1157 return r;
adamc@289 1158 } else
adamc@289 1159 return NULL;
adamc@289 1160 }
adamc@289 1161
adamc@311 1162 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 1163 static uw_Basis_bool true = uw_Basis_True;
adamc@311 1164 static uw_Basis_bool false = uw_Basis_False;
adamc@289 1165
adamc@289 1166 if (!strcasecmp (s, "True"))
adamc@289 1167 return &true;
adamc@289 1168 else if (!strcasecmp (s, "False"))
adamc@289 1169 return &false;
adamc@289 1170 else
adamc@289 1171 return NULL;
adamc@289 1172 }
adamc@292 1173
adamc@436 1174 uw_Basis_time *uw_Basis_stringToTime(uw_context ctx, uw_Basis_string s) {
adamc@438 1175 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1176 struct tm stm;
adamc@436 1177
adamc@439 1178 if (dot) {
adamc@439 1179 *dot = 0;
adamc@439 1180 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1181 *dot = '.';
adamc@439 1182 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1183 *r = mktime(&stm);
adamc@439 1184 return r;
adamc@439 1185 }
adamc@439 1186 else {
adamc@439 1187 *dot = '.';
adamc@439 1188 return NULL;
adamc@439 1189 }
adamc@436 1190 }
adamc@439 1191 else {
adamc@439 1192 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1193 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1194 *r = mktime(&stm);
adamc@439 1195 return r;
adamc@439 1196 }
adamc@439 1197 else if (strptime(s, TIME_FMT, &stm) == end) {
adamc@439 1198 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1199 *r = mktime(&stm);
adamc@439 1200 return r;
adamc@439 1201 }
adamc@439 1202 else
adamc@439 1203 return NULL;
adamc@439 1204 }
adamc@436 1205 }
adamc@436 1206
adamc@311 1207 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 1208 char *endptr;
adamc@311 1209 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 1210
adamc@292 1211 if (*s != '\0' && *endptr == '\0')
adamc@292 1212 return n;
adamc@292 1213 else
adamc@311 1214 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 1215 }
adamc@293 1216
adamc@311 1217 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 1218 char *endptr;
adamc@311 1219 uw_Basis_float n = strtod(s, &endptr);
adamc@293 1220
adamc@293 1221 if (*s != '\0' && *endptr == '\0')
adamc@293 1222 return n;
adamc@293 1223 else
adamc@311 1224 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 1225 }
adamc@293 1226
adamc@311 1227 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 1228 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 1229 return uw_Basis_True;
adamc@296 1230 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 1231 return uw_Basis_False;
adamc@293 1232 else
adamc@311 1233 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 1234 }
adamc@436 1235
adamc@436 1236 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
adamc@438 1237 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1238 struct tm stm = {};
adamc@436 1239
adamc@438 1240 if (dot) {
adamc@438 1241 *dot = 0;
adamc@438 1242 if (strptime(s, TIME_FMT_PG, &stm)) {
adamc@438 1243 *dot = '.';
adamc@438 1244 return mktime(&stm);
adamc@438 1245 }
adamc@438 1246 else {
adamc@438 1247 *dot = '.';
adamc@438 1248 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1249 }
adamc@438 1250 }
adamc@438 1251 else {
adamc@439 1252 if (strptime(s, TIME_FMT_PG, &stm) == end)
adamc@439 1253 return mktime(&stm);
adamc@439 1254 else if (strptime(s, TIME_FMT, &stm) == end)
adamc@438 1255 return mktime(&stm);
adamc@438 1256 else
adamc@438 1257 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1258 }
adamc@436 1259 }
adamc@457 1260
adamc@457 1261 uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
adamc@457 1262 int len = strlen(h);
adamc@457 1263 char *s = ctx->headers, *p;
adamc@457 1264
adamc@457 1265 while (p = strchr(s, ':')) {
adamc@457 1266 if (p - s == len && !strncasecmp(s, h, len)) {
adamc@458 1267 return p + 2;
adamc@457 1268 } else {
adamc@458 1269 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@458 1270 s += 2;
adamc@457 1271 else
adamc@457 1272 return NULL;
adamc@457 1273 }
adamc@457 1274 }
adamc@463 1275 }
adamc@458 1276
adamc@463 1277 uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
adamc@463 1278 int len = strlen(c);
adamc@474 1279 char *s = ctx->headers, *p = ctx->outHeaders;
adamc@474 1280
adamc@474 1281 while (p = strstr(p, "\nSet-Cookie: ")) {
adamc@474 1282 char *p2;
adamc@474 1283 p += 13;
adamc@474 1284 p2 = strchr(p, '=');
adamc@474 1285
adamc@474 1286 if (p2) {
adamc@474 1287 size_t sz = strcspn(p2+1, ";\r\n");
adamc@474 1288
adamc@474 1289 if (!strncasecmp(p, c, p2 - p)) {
adamc@474 1290 char *ret = uw_malloc(ctx, sz + 1);
adamc@474 1291 memcpy(ret, p2+1, sz);
adamc@474 1292 ret[sz] = 0;
adamc@474 1293 return ret;
adamc@474 1294 }
adamc@474 1295 }
adamc@474 1296 }
adamc@463 1297
adamc@463 1298 while (p = strchr(s, ':')) {
adamc@476 1299 if (!strncasecmp(s, "Cookie: ", 8)) {
adamc@476 1300 p += 2;
adamc@476 1301 while (1) {
adamc@476 1302 if (!strncmp(p, c, len)
adamc@476 1303 && p + len < ctx->headers_end && p[len] == '=')
adamc@476 1304 return p + 1 + len;
adamc@476 1305 else if (p = strchr(p, ';'))
adamc@476 1306 p += 2;
adamc@476 1307 else if ((s = strchr(s, 0)) && s < ctx->headers_end) {
adamc@476 1308 s += 2;
adamc@476 1309 break;
adamc@476 1310 }
adamc@476 1311 else
adamc@476 1312 return NULL;
adamc@476 1313 }
adamc@463 1314 } else {
adamc@463 1315 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@463 1316 s += 2;
adamc@463 1317 else
adamc@463 1318 return NULL;
adamc@463 1319 }
adamc@463 1320 }
adamc@457 1321 }
adamc@462 1322
adamc@466 1323 uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v) {
adamc@462 1324 uw_write_header(ctx, "Set-Cookie: ");
adamc@462 1325 uw_write_header(ctx, c);
adamc@462 1326 uw_write_header(ctx, "=");
adamc@462 1327 uw_write_header(ctx, v);
adamc@466 1328 uw_write_header(ctx, "; path=");
adamc@466 1329 uw_write_header(ctx, prefix);
adamc@462 1330 uw_write_header(ctx, "\r\n");
adamc@462 1331
adamc@462 1332 return uw_unit_v;
adamc@462 1333 }