annotate src/c/urweb.c @ 615:3c77133afd9a

Start of Featherweight Ur semantics
author Adam Chlipala <adamc@hcoop.net>
date Tue, 17 Feb 2009 14:49:28 -0500
parents 889dc9fceb3a
children aa2290c32ce2
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@599 385 sprintf(r, "<script>%s</script>", ctx->script);
adamc@565 386 return r;
adamc@565 387 }
adamc@565 388 }
adamc@565 389
adamc@574 390 uw_Basis_string uw_Basis_jsifyString(uw_context ctx, uw_Basis_string s) {
adamc@574 391 char *r, *s2;
adamc@574 392
adamc@574 393 uw_check_heap(ctx, strlen(s) * 4 + 2);
adamc@574 394
adamc@574 395 r = s2 = ctx->heap_front;
adamc@574 396 *s2++ = '"';
adamc@574 397
adamc@574 398 for (; *s; s++) {
adamc@574 399 char c = *s;
adamc@574 400
adamc@574 401 switch (c) {
adamc@574 402 case '"':
adamc@574 403 strcpy(s2, "\\\"");
adamc@574 404 s2 += 2;
adamc@574 405 break;
adamc@574 406 case '\\':
adamc@574 407 strcpy(s2, "\\\\");
adamc@574 408 s2 += 2;
adamc@574 409 break;
adamc@574 410 default:
adamc@574 411 if (isprint(c))
adamc@574 412 *s2++ = c;
adamc@574 413 else {
adamc@574 414 sprintf(s2, "\\%3o", c);
adamc@574 415 s2 += 4;
adamc@574 416 }
adamc@574 417 }
adamc@574 418 }
adamc@574 419
adamc@574 420 strcpy(s2, "\"");
adamc@574 421 ctx->heap_front = s2 + 1;
adamc@574 422 return r;
adamc@574 423 }
adamc@574 424
adamc@574 425 uw_Basis_string uw_Basis_jsifyString_ws(uw_context ctx, uw_Basis_string s) {
adamc@574 426 char *r, *s2;
adamc@574 427
adamc@574 428 uw_check_script(ctx, strlen(s) * 4 + 2);
adamc@574 429
adamc@574 430 r = s2 = ctx->script_front;
adamc@574 431 *s2++ = '"';
adamc@574 432
adamc@574 433 for (; *s; s++) {
adamc@574 434 char c = *s;
adamc@574 435
adamc@574 436 switch (c) {
adamc@577 437 case '\'':
adamc@574 438 strcpy(s2, "\\\"");
adamc@574 439 s2 += 2;
adamc@574 440 break;
adamc@574 441 case '\\':
adamc@574 442 strcpy(s2, "\\\\");
adamc@574 443 s2 += 2;
adamc@574 444 break;
adamc@574 445 default:
adamc@574 446 if (isprint(c))
adamc@574 447 *s2++ = c;
adamc@574 448 else {
adamc@574 449 sprintf(s2, "\\%3o", c);
adamc@574 450 s2 += 4;
adamc@574 451 }
adamc@574 452 }
adamc@574 453 }
adamc@574 454
adamc@574 455 strcpy(s2, "\"");
adamc@574 456 ctx->script_front = s2 + 1;
adamc@574 457 return r;
adamc@574 458 }
adamc@574 459
adamc@577 460 uw_Basis_int uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
adamc@577 461 int len;
adamc@577 462 size_t s_len = strlen(s);
adamc@562 463
adamc@577 464 uw_check_script(ctx, 12 + INTS_MAX + s_len);
adamc@574 465 sprintf(ctx->script_front, "var s%d=sc(%n", ctx->source_count, &len);
adamc@562 466 ctx->script_front += len;
adamc@577 467 strcpy(ctx->script_front, s);
adamc@577 468 ctx->script_front += s_len;
adamc@577 469 strcpy(ctx->script_front, ");");
adamc@577 470 ctx->script_front += 2;
adamc@562 471
adamc@565 472 return ctx->source_count++;
adamc@117 473 }
adamc@117 474
adamc@577 475 uw_unit uw_Basis_set_client_source(uw_context ctx, uw_Basis_int n, uw_Basis_string s) {
adamc@577 476 int len;
adamc@577 477 size_t s_len = strlen(s);
adamc@577 478
adamc@577 479 uw_check_script(ctx, 6 + INTS_MAX + s_len);
adamc@577 480 sprintf(ctx->script_front, "s%d.v=%n", (int)n, &len);
adamc@577 481 ctx->script_front += len;
adamc@577 482 strcpy(ctx->script_front, s);
adamc@577 483 ctx->script_front += s_len;
adamc@577 484 strcpy(ctx->script_front, ";");
adamc@577 485 ctx->script_front++;
adamc@577 486
adamc@577 487 return uw_unit_v;
adamc@577 488 }
adamc@577 489
adamc@311 490 static void uw_check(uw_context ctx, size_t extra) {
adamc@321 491 size_t desired = ctx->page_front - ctx->page + extra, next;
adamc@117 492 char *new_page;
adamc@117 493
adamc@317 494 next = ctx->page_back - ctx->page;
adamc@428 495 if (next < desired) {
adamc@428 496 if (next == 0)
adamc@428 497 next = 1;
adamc@428 498 for (; next < desired; next *= 2);
adamc@117 499
adamc@428 500 new_page = realloc(ctx->page, next);
adamc@428 501 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@428 502 ctx->page_back = new_page + next;
adamc@428 503 ctx->page = new_page;
adamc@428 504 }
adamc@117 505 }
adamc@117 506
adamc@311 507 static void uw_writec_unsafe(uw_context ctx, char c) {
adamc@117 508 *(ctx->page_front)++ = c;
adamc@117 509 }
adamc@117 510
adamc@311 511 void uw_writec(uw_context ctx, char c) {
adamc@311 512 uw_check(ctx, 1);
adamc@311 513 uw_writec_unsafe(ctx, c);
adamc@117 514 }
adamc@117 515
adamc@311 516 static void uw_write_unsafe(uw_context ctx, const char* s) {
adamc@117 517 int len = strlen(s);
adamc@117 518 memcpy(ctx->page_front, s, len);
adamc@117 519 ctx->page_front += len;
adamc@117 520 }
adamc@117 521
adamc@311 522 void uw_write(uw_context ctx, const char* s) {
adamc@311 523 uw_check(ctx, strlen(s) + 1);
adamc@311 524 uw_write_unsafe(ctx, s);
adamc@183 525 *ctx->page_front = 0;
adamc@102 526 }
adamc@106 527
adamc@135 528
adamc@311 529 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
adamc@136 530 char *result;
adamc@136 531 int len;
adamc@311 532 uw_check_heap(ctx, INTS_MAX);
adamc@136 533 result = ctx->heap_front;
adamc@276 534 sprintf(result, "%lld%n", n, &len);
adamc@137 535 ctx->heap_front += len+1;
adamc@136 536 return result;
adamc@106 537 }
adamc@106 538
adamc@311 539 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@136 540 char *result;
adamc@136 541 int len;
adamc@311 542 uw_check_heap(ctx, FLOATS_MAX);
adamc@136 543 result = ctx->heap_front;
adamc@136 544 sprintf(result, "%g%n", n, &len);
adamc@137 545 ctx->heap_front += len+1;
adamc@136 546 return result;
adamc@106 547 }
adamc@106 548
adamc@311 549 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
adamc@136 550 int len = strlen(s);
adamc@136 551 char *result, *p;
adamc@311 552 uw_check_heap(ctx, len * 6 + 1);
adamc@136 553
adamc@136 554 result = p = ctx->heap_front;
adamc@136 555
adamc@136 556 for (; *s; s++) {
adamc@136 557 char c = *s;
adamc@136 558
adamc@136 559 if (c == '"') {
adamc@136 560 strcpy(p, "&quot;");
adamc@136 561 p += 6;
adamc@136 562 } else if (c == '&') {
adamc@136 563 strcpy(p, "&amp;");
adamc@136 564 p += 5;
adamc@136 565 }
adamc@136 566 else if (isprint(c))
adamc@136 567 *p++ = c;
adamc@136 568 else {
adamc@136 569 int len2;
adamc@136 570 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 571 p += len2;
adamc@136 572 }
adamc@136 573 }
adamc@136 574
adamc@137 575 *p++ = 0;
adamc@136 576 ctx->heap_front = p;
adamc@136 577 return result;
adamc@106 578 }
adamc@106 579
adamc@311 580 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@117 581 int len;
adamc@117 582
adamc@276 583 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@117 584 ctx->page_front += len;
adamc@106 585 }
adamc@106 586
adamc@428 587 uw_unit uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 588 uw_check(ctx, INTS_MAX);
adamc@311 589 uw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@428 590
adamc@428 591 return uw_unit_v;
adamc@106 592 }
adamc@106 593
adamc@428 594 uw_unit uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@117 595 int len;
adamc@117 596
adamc@311 597 uw_check(ctx, FLOATS_MAX);
adamc@117 598 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 599 ctx->page_front += len;
adamc@428 600
adamc@428 601 return uw_unit_v;
adamc@117 602 }
adamc@117 603
adamc@428 604 uw_unit uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 605 uw_check(ctx, strlen(s) * 6);
adamc@117 606
adamc@106 607 for (; *s; s++) {
adamc@106 608 char c = *s;
adamc@106 609
adamc@106 610 if (c == '"')
adamc@311 611 uw_write_unsafe(ctx, "&quot;");
adamc@136 612 else if (c == '&')
adamc@311 613 uw_write_unsafe(ctx, "&amp;");
adamc@106 614 else if (isprint(c))
adamc@311 615 uw_writec_unsafe(ctx, c);
adamc@106 616 else {
adamc@311 617 uw_write_unsafe(ctx, "&#");
adamc@311 618 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 619 uw_writec_unsafe(ctx, ';');
adamc@106 620 }
adamc@106 621 }
adamc@428 622
adamc@428 623 return uw_unit_v;
adamc@106 624 }
adamc@120 625
adamc@120 626
adamc@311 627 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@137 628 int len;
adamc@137 629 char *r;
adamc@137 630
adamc@311 631 uw_check_heap(ctx, INTS_MAX);
adamc@137 632 r = ctx->heap_front;
adamc@276 633 sprintf(r, "%lld%n", n, &len);
adamc@137 634 ctx->heap_front += len+1;
adamc@137 635 return r;
adamc@120 636 }
adamc@120 637
adamc@311 638 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@137 639 int len;
adamc@137 640 char *r;
adamc@137 641
adamc@311 642 uw_check_heap(ctx, FLOATS_MAX);
adamc@137 643 r = ctx->heap_front;
adamc@137 644 sprintf(r, "%g%n", n, &len);
adamc@137 645 ctx->heap_front += len+1;
adamc@137 646 return r;
adamc@120 647 }
adamc@120 648
adamc@311 649 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 650 char *r, *p;
adamc@137 651
adamc@311 652 uw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 653
adamc@137 654 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 655 char c = *s;
adamc@137 656
adamc@137 657 if (c == ' ')
adamc@137 658 *p++ = '+';
adamc@137 659 else if (isalnum(c))
adamc@137 660 *p++ = c;
adamc@137 661 else {
adamc@137 662 sprintf(p, "%%%02X", c);
adamc@137 663 p += 3;
adamc@137 664 }
adamc@137 665 }
adamc@137 666
adamc@137 667 *p++ = 0;
adamc@137 668 ctx->heap_front = p;
adamc@137 669 return r;
adamc@120 670 }
adamc@120 671
adamc@311 672 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 673 if (b == uw_Basis_False)
adamc@186 674 return "0";
adamc@186 675 else
adamc@186 676 return "1";
adamc@186 677 }
adamc@186 678
adamc@311 679 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@120 680 int len;
adamc@120 681
adamc@276 682 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@120 683 ctx->page_front += len;
adamc@120 684 }
adamc@120 685
adamc@428 686 uw_unit uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 687 uw_check(ctx, INTS_MAX);
adamc@311 688 uw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@428 689
adamc@428 690 return uw_unit_v;
adamc@120 691 }
adamc@120 692
adamc@428 693 uw_unit uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@120 694 int len;
adamc@120 695
adamc@311 696 uw_check(ctx, FLOATS_MAX);
adamc@120 697 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 698 ctx->page_front += len;
adamc@428 699
adamc@428 700 return uw_unit_v;
adamc@120 701 }
adamc@120 702
adamc@488 703 uw_Basis_string uw_Basis_urlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@488 704 return uw_Basis_urlifyInt(ctx, t);
adamc@488 705 }
adamc@488 706
adamc@428 707 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 708 uw_check(ctx, strlen(s) * 3);
adamc@120 709
adamc@120 710 for (; *s; s++) {
adamc@120 711 char c = *s;
adamc@120 712
adamc@120 713 if (c == ' ')
adamc@311 714 uw_writec_unsafe(ctx, '+');
adamc@120 715 else if (isalnum(c))
adamc@311 716 uw_writec_unsafe(ctx, c);
adamc@120 717 else {
adamc@120 718 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 719 ctx->page_front += 3;
adamc@120 720 }
adamc@120 721 }
adamc@428 722
adamc@428 723 return uw_unit_v;
adamc@120 724 }
adamc@120 725
adamc@428 726 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 727 if (b == uw_Basis_False)
adamc@311 728 uw_writec(ctx, '0');
adamc@186 729 else
adamc@311 730 uw_writec(ctx, '1');
adamc@428 731
adamc@428 732 return uw_unit_v;
adamc@186 733 }
adamc@186 734
adamc@120 735
adamc@311 736 static char *uw_unurlify_advance(char *s) {
adamc@144 737 char *new_s = strchr(s, '/');
adamc@120 738
adamc@120 739 if (new_s)
adamc@120 740 *new_s++ = 0;
adamc@120 741 else
adamc@144 742 new_s = strchr(s, 0);
adamc@144 743
adamc@144 744 return new_s;
adamc@144 745 }
adamc@144 746
adamc@311 747 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 748 char *new_s = uw_unurlify_advance(*s);
adamc@311 749 uw_Basis_int r;
adamc@120 750
adamc@276 751 r = atoll(*s);
adamc@120 752 *s = new_s;
adamc@120 753 return r;
adamc@120 754 }
adamc@120 755
adamc@311 756 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 757 char *new_s = uw_unurlify_advance(*s);
adamc@311 758 uw_Basis_float r;
adamc@120 759
adamc@120 760 r = atof(*s);
adamc@120 761 *s = new_s;
adamc@120 762 return r;
adamc@120 763 }
adamc@120 764
adamc@488 765 uw_Basis_time uw_Basis_unurlifyTime(uw_context ctx, char **s) {
adamc@488 766 return uw_Basis_unurlifyInt(ctx, s);
adamc@488 767 }
adamc@488 768
adamc@311 769 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 770 char *s1, *s2;
adamc@144 771 int n;
adamc@136 772
adamc@144 773 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 774 char c = *s2;
adamc@136 775
adamc@136 776 switch (c) {
adamc@136 777 case '+':
adamc@136 778 *s1 = ' ';
adamc@136 779 break;
adamc@136 780 case '%':
adamc@169 781 if (s2[1] == 0)
adamc@311 782 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 783 if (s2[2] == 0)
adamc@311 784 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 785 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 786 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 787 *s1 = n;
adamc@136 788 s2 += 2;
adamc@136 789 break;
adamc@136 790 default:
adamc@136 791 *s1 = c;
adamc@136 792 }
adamc@136 793 }
adamc@136 794 *s1++ = 0;
adamc@144 795 return s1;
adamc@144 796 }
adamc@144 797
adamc@311 798 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 799 char *new_s = uw_unurlify_advance(*s);
adamc@311 800 uw_Basis_bool r;
adamc@186 801
adamc@186 802 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 803 r = uw_Basis_False;
adamc@186 804 else
adamc@311 805 r = uw_Basis_True;
adamc@186 806
adamc@186 807 *s = new_s;
adamc@186 808 return r;
adamc@186 809 }
adamc@186 810
adamc@311 811 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 812 char *new_s = uw_unurlify_advance(*s);
adamc@144 813 char *r, *s1, *s2;
adamc@144 814 int len, n;
adamc@144 815
adamc@200 816 len = strlen(*s);
adamc@311 817 uw_check_heap(ctx, len + 1);
adamc@144 818
adamc@144 819 r = ctx->heap_front;
adamc@311 820 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 821 *s = new_s;
adamc@136 822 return r;
adamc@120 823 }
adamc@135 824
adamc@135 825
adamc@311 826 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 827 int len;
adamc@286 828 char *r;
adamc@286 829
adamc@311 830 uw_check_heap(ctx, INTS_MAX);
adamc@286 831 r = ctx->heap_front;
adamc@286 832 sprintf(r, "%lld%n", n, &len);
adamc@286 833 ctx->heap_front += len+1;
adamc@286 834 return r;
adamc@286 835 }
adamc@286 836
adamc@428 837 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 838 int len;
adamc@286 839
adamc@311 840 uw_check(ctx, INTS_MAX);
adamc@286 841 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 842 ctx->page_front += len;
adamc@428 843
adamc@428 844 return uw_unit_v;
adamc@286 845 }
adamc@286 846
adamc@311 847 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 848 int len;
adamc@286 849 char *r;
adamc@286 850
adamc@311 851 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 852 r = ctx->heap_front;
adamc@286 853 sprintf(r, "%g%n", n, &len);
adamc@286 854 ctx->heap_front += len+1;
adamc@286 855 return r;
adamc@286 856 }
adamc@286 857
adamc@428 858 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 859 int len;
adamc@286 860
adamc@311 861 uw_check(ctx, FLOATS_MAX);
adamc@286 862 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 863 ctx->page_front += len;
adamc@428 864
adamc@428 865 return uw_unit_v;
adamc@286 866 }
adamc@286 867
adamc@311 868 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 869 char *r, *s2;
adamc@137 870
adamc@311 871 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 872
adamc@137 873 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 874 char c = *s;
adamc@137 875
adamc@137 876 switch (c) {
adamc@137 877 case '<':
adamc@137 878 strcpy(s2, "&lt;");
adamc@137 879 s2 += 4;
adamc@137 880 break;
adamc@137 881 case '&':
adamc@137 882 strcpy(s2, "&amp;");
adamc@137 883 s2 += 5;
adamc@137 884 break;
adamc@137 885 default:
adamc@137 886 if (isprint(c))
adamc@137 887 *s2++ = c;
adamc@137 888 else {
adamc@137 889 int len2;
adamc@137 890 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 891 s2 += len2;
adamc@137 892 }
adamc@137 893 }
adamc@137 894 }
adamc@137 895
adamc@137 896 *s2++ = 0;
adamc@137 897 ctx->heap_front = s2;
adamc@137 898 return r;
adamc@135 899 }
adamc@135 900
adamc@428 901 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 902 uw_check(ctx, strlen(s) * 6);
adamc@135 903
adamc@135 904 for (; *s; s++) {
adamc@135 905 char c = *s;
adamc@135 906
adamc@135 907 switch (c) {
adamc@135 908 case '<':
adamc@311 909 uw_write_unsafe(ctx, "&lt;");
adamc@135 910 break;
adamc@135 911 case '&':
adamc@311 912 uw_write_unsafe(ctx, "&amp;");
adamc@135 913 break;
adamc@135 914 default:
adamc@135 915 if (isprint(c))
adamc@311 916 uw_writec_unsafe(ctx, c);
adamc@135 917 else {
adamc@311 918 uw_write_unsafe(ctx, "&#");
adamc@311 919 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 920 uw_writec_unsafe(ctx, ';');
adamc@135 921 }
adamc@135 922 }
adamc@135 923 }
adamc@428 924
adamc@428 925 return uw_unit_v;
adamc@135 926 }
adamc@180 927
adamc@311 928 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 929 if (b == uw_Basis_False)
adamc@286 930 return "False";
adamc@286 931 else
adamc@286 932 return "True";
adamc@286 933 }
adamc@286 934
adamc@428 935 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 936 if (b == uw_Basis_False) {
adamc@311 937 uw_check(ctx, 6);
adamc@286 938 strcpy(ctx->page_front, "False");
adamc@286 939 ctx->page_front += 5;
adamc@286 940 } else {
adamc@311 941 uw_check(ctx, 5);
adamc@286 942 strcpy(ctx->page_front, "True");
adamc@286 943 ctx->page_front += 4;
adamc@286 944 }
adamc@428 945
adamc@428 946 return uw_unit_v;
adamc@286 947 }
adamc@286 948
adamc@436 949 #define TIME_FMT "%x %X"
adamc@438 950 #define TIME_FMT_PG "%Y-%m-%d %T"
adamc@436 951
adamc@436 952 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@436 953 size_t len;
adamc@436 954 char *r;
adamc@436 955 struct tm stm;
adamc@436 956
adamc@436 957 if (localtime_r(&t, &stm)) {
adamc@436 958 uw_check_heap(ctx, TIMES_MAX);
adamc@436 959 r = ctx->heap_front;
adamc@436 960 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 961 ctx->heap_front += len+1;
adamc@436 962 return r;
adamc@436 963 } else
adamc@436 964 return "<i>Invalid time</i>";
adamc@436 965 }
adamc@436 966
adamc@436 967 uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
adamc@436 968 size_t len;
adamc@436 969 char *r;
adamc@436 970 struct tm stm;
adamc@436 971
adamc@436 972 if (localtime_r(&t, &stm)) {
adamc@436 973 uw_check(ctx, TIMES_MAX);
adamc@436 974 r = ctx->page_front;
adamc@436 975 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 976 ctx->page_front += len;
adamc@436 977 } else {
adamc@436 978 uw_check(ctx, 20);
adamc@436 979 strcpy(ctx->page_front, "<i>Invalid time</i>");
adamc@436 980 ctx->page_front += 19;
adamc@436 981 }
adamc@436 982
adamc@436 983 return uw_unit_v;
adamc@436 984 }
adamc@436 985
adamc@311 986 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 987 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 988 char *s;
adamc@180 989
adamc@311 990 uw_check_heap(ctx, len);
adamc@180 991
adamc@180 992 s = ctx->heap_front;
adamc@180 993
adamc@180 994 strcpy(s, s1);
adamc@180 995 strcat(s, s2);
adamc@180 996 ctx->heap_front += len;
adamc@180 997
adamc@180 998 return s;
adamc@180 999 }
adamc@278 1000
adamc@311 1001 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 1002 int len = strlen(s1) + 1;
adamc@278 1003 char *s;
adamc@278 1004
adamc@311 1005 uw_check_heap(ctx, len);
adamc@278 1006
adamc@278 1007 s = ctx->heap_front;
adamc@278 1008
adamc@278 1009 strcpy(s, s1);
adamc@278 1010 ctx->heap_front += len;
adamc@278 1011
adamc@278 1012 return s;
adamc@278 1013 }
adamc@280 1014
adamc@493 1015 uw_Basis_string uw_Basis_maybe_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@493 1016 if (s1)
adamc@493 1017 return uw_Basis_strdup(ctx, s1);
adamc@493 1018 else
adamc@493 1019 return NULL;
adamc@493 1020 }
adamc@493 1021
adamc@280 1022
adamc@311 1023 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 1024 int len;
adamc@281 1025 char *r;
adamc@281 1026
adamc@311 1027 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 1028 r = ctx->heap_front;
adamc@281 1029 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 1030 ctx->heap_front += len+1;
adamc@281 1031 return r;
adamc@281 1032 }
adamc@281 1033
adamc@467 1034 char *uw_Basis_sqlifyIntN(uw_context ctx, uw_Basis_int *n) {
adamc@467 1035 if (n == NULL)
adamc@467 1036 return "NULL";
adamc@467 1037 else
adamc@467 1038 return uw_Basis_sqlifyInt(ctx, *n);
adamc@467 1039 }
adamc@467 1040
adamc@311 1041 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 1042 int len;
adamc@281 1043 char *r;
adamc@281 1044
adamc@311 1045 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 1046 r = ctx->heap_front;
adamc@281 1047 sprintf(r, "%g::float8%n", n, &len);
adamc@281 1048 ctx->heap_front += len+1;
adamc@281 1049 return r;
adamc@281 1050 }
adamc@281 1051
adamc@467 1052 char *uw_Basis_sqlifyFloatN(uw_context ctx, uw_Basis_float *n) {
adamc@467 1053 if (n == NULL)
adamc@467 1054 return "NULL";
adamc@467 1055 else
adamc@467 1056 return uw_Basis_sqlifyFloat(ctx, *n);
adamc@467 1057 }
adamc@467 1058
adamc@281 1059
adamc@311 1060 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 1061 char *r, *s2;
adamc@280 1062
adamc@311 1063 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 1064
adamc@280 1065 r = s2 = ctx->heap_front;
adamc@280 1066 *s2++ = 'E';
adamc@280 1067 *s2++ = '\'';
adamc@280 1068
adamc@280 1069 for (; *s; s++) {
adamc@280 1070 char c = *s;
adamc@280 1071
adamc@280 1072 switch (c) {
adamc@280 1073 case '\'':
adamc@280 1074 strcpy(s2, "\\'");
adamc@280 1075 s2 += 2;
adamc@280 1076 break;
adamc@280 1077 case '\\':
adamc@280 1078 strcpy(s2, "\\\\");
adamc@280 1079 s2 += 2;
adamc@280 1080 break;
adamc@280 1081 default:
adamc@280 1082 if (isprint(c))
adamc@280 1083 *s2++ = c;
adamc@280 1084 else {
adamc@280 1085 sprintf(s2, "\\%3o", c);
adamc@280 1086 s2 += 4;
adamc@280 1087 }
adamc@280 1088 }
adamc@280 1089 }
adamc@280 1090
adamc@281 1091 strcpy(s2, "'::text");
adamc@281 1092 ctx->heap_front = s2 + 8;
adamc@280 1093 return r;
adamc@280 1094 }
adamc@281 1095
adamc@467 1096 uw_Basis_string uw_Basis_sqlifyStringN(uw_context ctx, uw_Basis_string s) {
adamc@467 1097 if (s == NULL)
adamc@467 1098 return "NULL";
adamc@467 1099 else
adamc@467 1100 return uw_Basis_sqlifyString(ctx, s);
adamc@467 1101 }
adamc@467 1102
adamc@311 1103 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 1104 if (b == uw_Basis_False)
adamc@281 1105 return "FALSE";
adamc@281 1106 else
adamc@281 1107 return "TRUE";
adamc@281 1108 }
adamc@282 1109
adamc@467 1110 char *uw_Basis_sqlifyBoolN(uw_context ctx, uw_Basis_bool *b) {
adamc@467 1111 if (b == NULL)
adamc@467 1112 return "NULL";
adamc@467 1113 else
adamc@467 1114 return uw_Basis_sqlifyBool(ctx, *b);
adamc@467 1115 }
adamc@467 1116
adamc@439 1117 char *uw_Basis_sqlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@439 1118 size_t len;
adamc@439 1119 char *r;
adamc@439 1120 struct tm stm;
adamc@439 1121
adamc@439 1122 if (localtime_r(&t, &stm)) {
adamc@439 1123 uw_check_heap(ctx, TIMES_MAX);
adamc@439 1124 r = ctx->heap_front;
adamc@439 1125 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@439 1126 ctx->heap_front += len+1;
adamc@439 1127 return r;
adamc@439 1128 } else
adamc@439 1129 return "<Invalid time>";
adamc@439 1130 }
adamc@439 1131
adamc@467 1132 char *uw_Basis_sqlifyTimeN(uw_context ctx, uw_Basis_time *t) {
adamc@467 1133 if (t == NULL)
adamc@467 1134 return "NULL";
adamc@467 1135 else
adamc@467 1136 return uw_Basis_sqlifyTime(ctx, *t);
adamc@467 1137 }
adamc@467 1138
adamc@311 1139 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 1140 static uw_Basis_int true = 1;
adamc@311 1141 static uw_Basis_int false = 0;
adamc@282 1142
adamc@311 1143 if (b == uw_Basis_False)
adamc@282 1144 return (char *)&false;
adamc@282 1145 else
adamc@282 1146 return (char *)&true;
adamc@282 1147 }
adamc@284 1148
adamc@311 1149 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 1150 int len;
adamc@284 1151 char *r;
adamc@284 1152
adamc@311 1153 uw_check_heap(ctx, INTS_MAX);
adamc@284 1154 r = ctx->heap_front;
adamc@284 1155 sprintf(r, "%lld%n", n, &len);
adamc@284 1156 ctx->heap_front += len+1;
adamc@284 1157 return r;
adamc@284 1158 }
adamc@285 1159
adamc@311 1160 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 1161 int len;
adamc@285 1162 char *r;
adamc@285 1163
adamc@311 1164 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 1165 r = ctx->heap_front;
adamc@285 1166 sprintf(r, "%g%n", n, &len);
adamc@285 1167 ctx->heap_front += len+1;
adamc@285 1168 return r;
adamc@285 1169 }
adamc@285 1170
adamc@311 1171 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 1172 if (b == uw_Basis_False)
adamc@285 1173 return "False";
adamc@285 1174 else
adamc@285 1175 return "True";
adamc@285 1176 }
adamc@288 1177
adamc@436 1178 uw_Basis_string uw_Basis_timeToString(uw_context ctx, uw_Basis_time t) {
adamc@436 1179 size_t len;
adamc@436 1180 char *r;
adamc@436 1181 struct tm stm;
adamc@436 1182
adamc@436 1183 if (localtime_r(&t, &stm)) {
adamc@436 1184 uw_check_heap(ctx, TIMES_MAX);
adamc@436 1185 r = ctx->heap_front;
adamc@436 1186 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 1187 ctx->heap_front += len+1;
adamc@436 1188 return r;
adamc@436 1189 } else
adamc@436 1190 return "<Invalid time>";
adamc@436 1191 }
adamc@288 1192
adamc@311 1193 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 1194 char *endptr;
adamc@311 1195 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 1196
adamc@288 1197 if (*s != '\0' && *endptr == '\0') {
adamc@311 1198 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 1199 *r = n;
adamc@288 1200 return r;
adamc@288 1201 } else
adamc@288 1202 return NULL;
adamc@288 1203 }
adamc@289 1204
adamc@311 1205 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 1206 char *endptr;
adamc@311 1207 uw_Basis_float n = strtod(s, &endptr);
adamc@289 1208
adamc@289 1209 if (*s != '\0' && *endptr == '\0') {
adamc@311 1210 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 1211 *r = n;
adamc@289 1212 return r;
adamc@289 1213 } else
adamc@289 1214 return NULL;
adamc@289 1215 }
adamc@289 1216
adamc@311 1217 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 1218 static uw_Basis_bool true = uw_Basis_True;
adamc@311 1219 static uw_Basis_bool false = uw_Basis_False;
adamc@289 1220
adamc@289 1221 if (!strcasecmp (s, "True"))
adamc@289 1222 return &true;
adamc@289 1223 else if (!strcasecmp (s, "False"))
adamc@289 1224 return &false;
adamc@289 1225 else
adamc@289 1226 return NULL;
adamc@289 1227 }
adamc@292 1228
adamc@436 1229 uw_Basis_time *uw_Basis_stringToTime(uw_context ctx, uw_Basis_string s) {
adamc@438 1230 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1231 struct tm stm;
adamc@436 1232
adamc@439 1233 if (dot) {
adamc@439 1234 *dot = 0;
adamc@439 1235 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1236 *dot = '.';
adamc@439 1237 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1238 *r = mktime(&stm);
adamc@439 1239 return r;
adamc@439 1240 }
adamc@439 1241 else {
adamc@439 1242 *dot = '.';
adamc@439 1243 return NULL;
adamc@439 1244 }
adamc@436 1245 }
adamc@439 1246 else {
adamc@439 1247 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1248 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1249 *r = mktime(&stm);
adamc@439 1250 return r;
adamc@439 1251 }
adamc@439 1252 else if (strptime(s, TIME_FMT, &stm) == end) {
adamc@439 1253 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1254 *r = mktime(&stm);
adamc@439 1255 return r;
adamc@439 1256 }
adamc@439 1257 else
adamc@439 1258 return NULL;
adamc@439 1259 }
adamc@436 1260 }
adamc@436 1261
adamc@311 1262 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 1263 char *endptr;
adamc@311 1264 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 1265
adamc@292 1266 if (*s != '\0' && *endptr == '\0')
adamc@292 1267 return n;
adamc@292 1268 else
adamc@311 1269 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 1270 }
adamc@293 1271
adamc@311 1272 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 1273 char *endptr;
adamc@311 1274 uw_Basis_float n = strtod(s, &endptr);
adamc@293 1275
adamc@293 1276 if (*s != '\0' && *endptr == '\0')
adamc@293 1277 return n;
adamc@293 1278 else
adamc@311 1279 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 1280 }
adamc@293 1281
adamc@311 1282 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 1283 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 1284 return uw_Basis_True;
adamc@296 1285 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 1286 return uw_Basis_False;
adamc@293 1287 else
adamc@311 1288 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 1289 }
adamc@436 1290
adamc@436 1291 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
adamc@438 1292 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1293 struct tm stm = {};
adamc@436 1294
adamc@438 1295 if (dot) {
adamc@438 1296 *dot = 0;
adamc@438 1297 if (strptime(s, TIME_FMT_PG, &stm)) {
adamc@438 1298 *dot = '.';
adamc@438 1299 return mktime(&stm);
adamc@438 1300 }
adamc@438 1301 else {
adamc@438 1302 *dot = '.';
adamc@438 1303 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1304 }
adamc@438 1305 }
adamc@438 1306 else {
adamc@439 1307 if (strptime(s, TIME_FMT_PG, &stm) == end)
adamc@439 1308 return mktime(&stm);
adamc@439 1309 else if (strptime(s, TIME_FMT, &stm) == end)
adamc@438 1310 return mktime(&stm);
adamc@438 1311 else
adamc@438 1312 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1313 }
adamc@436 1314 }
adamc@457 1315
adamc@457 1316 uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
adamc@457 1317 int len = strlen(h);
adamc@457 1318 char *s = ctx->headers, *p;
adamc@457 1319
adamc@457 1320 while (p = strchr(s, ':')) {
adamc@457 1321 if (p - s == len && !strncasecmp(s, h, len)) {
adamc@458 1322 return p + 2;
adamc@457 1323 } else {
adamc@458 1324 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@458 1325 s += 2;
adamc@457 1326 else
adamc@457 1327 return NULL;
adamc@457 1328 }
adamc@457 1329 }
adamc@463 1330 }
adamc@458 1331
adamc@463 1332 uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
adamc@463 1333 int len = strlen(c);
adamc@474 1334 char *s = ctx->headers, *p = ctx->outHeaders;
adamc@474 1335
adamc@474 1336 while (p = strstr(p, "\nSet-Cookie: ")) {
adamc@474 1337 char *p2;
adamc@474 1338 p += 13;
adamc@474 1339 p2 = strchr(p, '=');
adamc@474 1340
adamc@474 1341 if (p2) {
adamc@474 1342 size_t sz = strcspn(p2+1, ";\r\n");
adamc@474 1343
adamc@474 1344 if (!strncasecmp(p, c, p2 - p)) {
adamc@474 1345 char *ret = uw_malloc(ctx, sz + 1);
adamc@474 1346 memcpy(ret, p2+1, sz);
adamc@474 1347 ret[sz] = 0;
adamc@474 1348 return ret;
adamc@474 1349 }
adamc@474 1350 }
adamc@474 1351 }
adamc@463 1352
adamc@463 1353 while (p = strchr(s, ':')) {
adamc@476 1354 if (!strncasecmp(s, "Cookie: ", 8)) {
adamc@476 1355 p += 2;
adamc@476 1356 while (1) {
adamc@476 1357 if (!strncmp(p, c, len)
adamc@476 1358 && p + len < ctx->headers_end && p[len] == '=')
adamc@476 1359 return p + 1 + len;
adamc@476 1360 else if (p = strchr(p, ';'))
adamc@476 1361 p += 2;
adamc@476 1362 else if ((s = strchr(s, 0)) && s < ctx->headers_end) {
adamc@476 1363 s += 2;
adamc@476 1364 break;
adamc@476 1365 }
adamc@476 1366 else
adamc@476 1367 return NULL;
adamc@476 1368 }
adamc@463 1369 } else {
adamc@463 1370 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@463 1371 s += 2;
adamc@463 1372 else
adamc@463 1373 return NULL;
adamc@463 1374 }
adamc@463 1375 }
adamc@457 1376 }
adamc@462 1377
adamc@466 1378 uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v) {
adamc@462 1379 uw_write_header(ctx, "Set-Cookie: ");
adamc@462 1380 uw_write_header(ctx, c);
adamc@462 1381 uw_write_header(ctx, "=");
adamc@462 1382 uw_write_header(ctx, v);
adamc@466 1383 uw_write_header(ctx, "; path=");
adamc@466 1384 uw_write_header(ctx, prefix);
adamc@462 1385 uw_write_header(ctx, "\r\n");
adamc@462 1386
adamc@462 1387 return uw_unit_v;
adamc@462 1388 }