annotate src/c/urweb.c @ 430:0af37c883358

mkdir -p BIN
author Adam Chlipala <adamc@hcoop.net>
date Sat, 25 Oct 2008 12:18:33 -0400
parents 3ca00463de20
children 024478c34f4d
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@311 10 uw_unit uw_unit_v = {};
adamc@102 11
adamc@167 12 #define ERROR_BUF_LEN 1024
adamc@167 13
adamc@323 14 typedef struct regions {
adamc@323 15 struct regions *next;
adamc@323 16 } regions;
adamc@323 17
adamc@425 18 typedef struct {
adamc@425 19 void (*func)(void*);
adamc@425 20 void *arg;
adamc@425 21 } cleanup;
adamc@425 22
adamc@311 23 struct uw_context {
adamc@117 24 char *page, *page_front, *page_back;
adamc@136 25 char *heap, *heap_front, *heap_back;
adamc@144 26 char **inputs;
adamc@167 27
adamc@272 28 void *db;
adamc@272 29
adamc@167 30 jmp_buf jmp_buf;
adamc@167 31
adamc@323 32 regions *regions;
adamc@323 33
adamc@425 34 cleanup *cleanup, *cleanup_front, *cleanup_back;
adamc@425 35
adamc@167 36 char error_message[ERROR_BUF_LEN];
adamc@117 37 };
adamc@117 38
adamc@311 39 extern int uw_inputs_len;
adamc@144 40
adamc@311 41 uw_context uw_init(size_t page_len, size_t heap_len) {
adamc@311 42 uw_context ctx = malloc(sizeof(struct uw_context));
adamc@136 43
adamc@117 44 ctx->page_front = ctx->page = malloc(page_len);
adamc@117 45 ctx->page_back = ctx->page_front + page_len;
adamc@136 46
adamc@136 47 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@136 48 ctx->heap_back = ctx->heap_front + heap_len;
adamc@136 49
adamc@311 50 ctx->inputs = calloc(uw_inputs_len, sizeof(char *));
adamc@144 51
adamc@272 52 ctx->db = NULL;
adamc@272 53
adamc@323 54 ctx->regions = NULL;
adamc@323 55
adamc@425 56 ctx->cleanup_front = ctx->cleanup_back = ctx->cleanup = malloc(0);
adamc@425 57
adamc@167 58 ctx->error_message[0] = 0;
adamc@167 59
adamc@117 60 return ctx;
adamc@106 61 }
adamc@106 62
adamc@311 63 void uw_set_db(uw_context ctx, void *db) {
adamc@272 64 ctx->db = db;
adamc@272 65 }
adamc@272 66
adamc@311 67 void *uw_get_db(uw_context ctx) {
adamc@272 68 return ctx->db;
adamc@272 69 }
adamc@272 70
adamc@311 71 void uw_free(uw_context ctx) {
adamc@117 72 free(ctx->page);
adamc@136 73 free(ctx->heap);
adamc@144 74 free(ctx->inputs);
adamc@425 75 free(ctx->cleanup);
adamc@136 76 free(ctx);
adamc@136 77 }
adamc@136 78
adamc@311 79 void uw_reset_keep_request(uw_context ctx) {
adamc@138 80 ctx->page_front = ctx->page;
adamc@138 81 ctx->heap_front = ctx->heap;
adamc@323 82 ctx->regions = NULL;
adamc@425 83 ctx->cleanup_front = ctx->cleanup;
adamc@167 84
adamc@167 85 ctx->error_message[0] = 0;
adamc@167 86 }
adamc@167 87
adamc@311 88 void uw_reset_keep_error_message(uw_context ctx) {
adamc@167 89 ctx->page_front = ctx->page;
adamc@167 90 ctx->heap_front = ctx->heap;
adamc@323 91 ctx->regions = NULL;
adamc@425 92 ctx->cleanup_front = ctx->cleanup;
adamc@167 93 }
adamc@167 94
adamc@311 95 void uw_reset(uw_context ctx) {
adamc@311 96 uw_reset_keep_request(ctx);
adamc@311 97 memset(ctx->inputs, 0, uw_inputs_len * sizeof(char *));
adamc@144 98 }
adamc@144 99
adamc@311 100 void uw_db_init(uw_context);
adamc@311 101 void uw_handle(uw_context, char *);
adamc@167 102
adamc@311 103 failure_kind uw_begin_init(uw_context ctx) {
adamc@272 104 int r = setjmp(ctx->jmp_buf);
adamc@272 105
adamc@272 106 if (r == 0)
adamc@311 107 uw_db_init(ctx);
adamc@272 108
adamc@272 109 return r;
adamc@272 110 }
adamc@272 111
adamc@311 112 failure_kind uw_begin(uw_context ctx, char *path) {
adamc@190 113 int r = setjmp(ctx->jmp_buf);
adamc@190 114
adamc@190 115 if (r == 0)
adamc@311 116 uw_handle(ctx, path);
adamc@167 117
adamc@190 118 return r;
adamc@167 119 }
adamc@167 120
adamc@311 121 __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) {
adamc@425 122 cleanup *cl;
adamc@425 123
adamc@167 124 va_list ap;
adamc@167 125 va_start(ap, fmt);
adamc@167 126
adamc@167 127 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
adamc@167 128
adamc@425 129 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
adamc@425 130 cl->func(cl->arg);
adamc@425 131
adamc@425 132 ctx->cleanup_front = ctx->cleanup;
adamc@425 133
adamc@190 134 longjmp(ctx->jmp_buf, fk);
adamc@167 135 }
adamc@167 136
adamc@425 137 void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) {
adamc@425 138 if (ctx->cleanup_front >= ctx->cleanup_back) {
adamc@425 139 int len = ctx->cleanup_back - ctx->cleanup, newLen;
adamc@425 140 if (len == 0)
adamc@425 141 newLen = 1;
adamc@425 142 else
adamc@428 143 newLen = len * 2;
adamc@425 144 ctx->cleanup = realloc(ctx->cleanup, newLen);
adamc@425 145 ctx->cleanup_front = ctx->cleanup + len;
adamc@425 146 ctx->cleanup_back = ctx->cleanup + newLen;
adamc@425 147 }
adamc@425 148
adamc@425 149 ctx->cleanup_front->func = func;
adamc@425 150 ctx->cleanup_front->arg = arg;
adamc@425 151 ++ctx->cleanup_front;
adamc@425 152 }
adamc@425 153
adamc@425 154 void uw_pop_cleanup(uw_context ctx) {
adamc@425 155 if (ctx->cleanup_front == ctx->cleanup)
adamc@425 156 uw_error(ctx, FATAL, "Attempt to pop from empty cleanup action stack");
adamc@425 157
adamc@425 158 --ctx->cleanup_front;
adamc@425 159 ctx->cleanup_front->func(ctx->cleanup_front->arg);
adamc@425 160 }
adamc@425 161
adamc@311 162 char *uw_error_message(uw_context ctx) {
adamc@167 163 return ctx->error_message;
adamc@167 164 }
adamc@167 165
adamc@311 166 int uw_input_num(char*);
adamc@144 167
adamc@311 168 void uw_set_input(uw_context ctx, char *name, char *value) {
adamc@311 169 int n = uw_input_num(name);
adamc@144 170
adamc@169 171 if (n < 0)
adamc@311 172 uw_error(ctx, FATAL, "Bad input name %s", name);
adamc@144 173
adamc@311 174 if (n >= uw_inputs_len)
adamc@311 175 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n);
adamc@169 176
adamc@144 177 ctx->inputs[n] = value;
adamc@144 178
adamc@282 179 //printf("[%d] %s = %s\n", n, name, value);
adamc@144 180 }
adamc@144 181
adamc@311 182 char *uw_get_input(uw_context ctx, int n) {
adamc@169 183 if (n < 0)
adamc@311 184 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 185 if (n >= uw_inputs_len)
adamc@311 186 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@282 187 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@144 188 return ctx->inputs[n];
adamc@138 189 }
adamc@138 190
adamc@311 191 char *uw_get_optional_input(uw_context ctx, int n) {
adamc@190 192 if (n < 0)
adamc@311 193 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 194 if (n >= uw_inputs_len)
adamc@311 195 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@426 196 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@190 197 return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]);
adamc@190 198 }
adamc@190 199
adamc@311 200 static void uw_check_heap(uw_context ctx, size_t extra) {
adamc@136 201 if (ctx->heap_back - ctx->heap_front < extra) {
adamc@321 202 size_t desired = ctx->heap_front - ctx->heap + extra, next;
adamc@136 203 char *new_heap;
adamc@136 204
adamc@317 205 next = ctx->heap_back - ctx->heap;
adamc@317 206 if (next == 0)
adamc@317 207 next = 1;
adamc@317 208 for (; next < desired; next *= 2);
adamc@136 209
adamc@136 210 new_heap = realloc(ctx->heap, next);
adamc@321 211 ctx->heap_front = new_heap + (ctx->heap_front - ctx->heap);
adamc@169 212 ctx->heap_back = new_heap + next;
adamc@136 213
adamc@136 214 if (new_heap != ctx->heap) {
adamc@136 215 ctx->heap = new_heap;
adamc@311 216 uw_error(ctx, UNLIMITED_RETRY, "Couldn't allocate new heap chunk contiguously");
adamc@136 217 }
adamc@136 218
adamc@169 219 ctx->heap = new_heap;
adamc@136 220 }
adamc@136 221 }
adamc@136 222
adamc@311 223 void *uw_malloc(uw_context ctx, size_t len) {
adamc@136 224 void *result;
adamc@136 225
adamc@311 226 uw_check_heap(ctx, len);
adamc@136 227
adamc@136 228 result = ctx->heap_front;
adamc@136 229 ctx->heap_front += len;
adamc@136 230 return result;
adamc@117 231 }
adamc@117 232
adamc@323 233 void uw_begin_region(uw_context ctx) {
adamc@323 234 regions *r = (regions *) ctx->heap_front;
adamc@323 235
adamc@323 236 uw_check_heap(ctx, sizeof(regions));
adamc@323 237
adamc@323 238 ctx->heap_front += sizeof(regions);
adamc@323 239
adamc@323 240 r->next = ctx->regions;
adamc@323 241 ctx->regions = r;
adamc@323 242 }
adamc@323 243
adamc@323 244 void uw_end_region(uw_context ctx) {
adamc@323 245 regions *r = ctx->regions;
adamc@323 246
adamc@323 247 if (r == NULL)
adamc@323 248 uw_error(ctx, FATAL, "Region stack underflow");
adamc@323 249
adamc@323 250 ctx->heap_front = (char *) r;
adamc@323 251 ctx->regions = r->next;
adamc@323 252 }
adamc@323 253
adamc@324 254 void uw_memstats(uw_context ctx) {
adamc@324 255 printf("Page: %d/%d\n", ctx->page_front - ctx->page, ctx->page_back - ctx->page);
adamc@324 256 printf("Heap: %d/%d\n", ctx->heap_front - ctx->heap, ctx->heap_back - ctx->heap);
adamc@324 257 }
adamc@324 258
adamc@311 259 int uw_really_send(int sock, const void *buf, ssize_t len) {
adamc@117 260 while (len > 0) {
adamc@117 261 ssize_t n = send(sock, buf, len, 0);
adamc@117 262
adamc@117 263 if (n < 0)
adamc@117 264 return n;
adamc@117 265
adamc@117 266 buf += n;
adamc@117 267 len -= n;
adamc@117 268 }
adamc@117 269
adamc@117 270 return 0;
adamc@117 271 }
adamc@117 272
adamc@311 273 int uw_send(uw_context ctx, int sock) {
adamc@311 274 return uw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
adamc@117 275 }
adamc@117 276
adamc@311 277 static void uw_check(uw_context ctx, size_t extra) {
adamc@321 278 size_t desired = ctx->page_front - ctx->page + extra, next;
adamc@117 279 char *new_page;
adamc@117 280
adamc@317 281 next = ctx->page_back - ctx->page;
adamc@428 282 if (next < desired) {
adamc@428 283 if (next == 0)
adamc@428 284 next = 1;
adamc@428 285 for (; next < desired; next *= 2);
adamc@117 286
adamc@428 287 new_page = realloc(ctx->page, next);
adamc@428 288 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@428 289 ctx->page_back = new_page + next;
adamc@428 290 ctx->page = new_page;
adamc@428 291 }
adamc@117 292 }
adamc@117 293
adamc@311 294 static void uw_writec_unsafe(uw_context ctx, char c) {
adamc@117 295 *(ctx->page_front)++ = c;
adamc@117 296 }
adamc@117 297
adamc@311 298 void uw_writec(uw_context ctx, char c) {
adamc@311 299 uw_check(ctx, 1);
adamc@311 300 uw_writec_unsafe(ctx, c);
adamc@117 301 }
adamc@117 302
adamc@311 303 static void uw_write_unsafe(uw_context ctx, const char* s) {
adamc@117 304 int len = strlen(s);
adamc@117 305 memcpy(ctx->page_front, s, len);
adamc@117 306 ctx->page_front += len;
adamc@117 307 }
adamc@117 308
adamc@311 309 void uw_write(uw_context ctx, const char* s) {
adamc@311 310 uw_check(ctx, strlen(s) + 1);
adamc@311 311 uw_write_unsafe(ctx, s);
adamc@183 312 *ctx->page_front = 0;
adamc@102 313 }
adamc@106 314
adamc@135 315
adamc@311 316 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
adamc@136 317 char *result;
adamc@136 318 int len;
adamc@311 319 uw_check_heap(ctx, INTS_MAX);
adamc@136 320 result = ctx->heap_front;
adamc@276 321 sprintf(result, "%lld%n", n, &len);
adamc@137 322 ctx->heap_front += len+1;
adamc@136 323 return result;
adamc@106 324 }
adamc@106 325
adamc@311 326 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@136 327 char *result;
adamc@136 328 int len;
adamc@311 329 uw_check_heap(ctx, FLOATS_MAX);
adamc@136 330 result = ctx->heap_front;
adamc@136 331 sprintf(result, "%g%n", n, &len);
adamc@137 332 ctx->heap_front += len+1;
adamc@136 333 return result;
adamc@106 334 }
adamc@106 335
adamc@311 336 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
adamc@136 337 int len = strlen(s);
adamc@136 338 char *result, *p;
adamc@311 339 uw_check_heap(ctx, len * 6 + 1);
adamc@136 340
adamc@136 341 result = p = ctx->heap_front;
adamc@136 342
adamc@136 343 for (; *s; s++) {
adamc@136 344 char c = *s;
adamc@136 345
adamc@136 346 if (c == '"') {
adamc@136 347 strcpy(p, "&quot;");
adamc@136 348 p += 6;
adamc@136 349 } else if (c == '&') {
adamc@136 350 strcpy(p, "&amp;");
adamc@136 351 p += 5;
adamc@136 352 }
adamc@136 353 else if (isprint(c))
adamc@136 354 *p++ = c;
adamc@136 355 else {
adamc@136 356 int len2;
adamc@136 357 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 358 p += len2;
adamc@136 359 }
adamc@136 360 }
adamc@136 361
adamc@137 362 *p++ = 0;
adamc@136 363 ctx->heap_front = p;
adamc@136 364 return result;
adamc@106 365 }
adamc@106 366
adamc@311 367 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@117 368 int len;
adamc@117 369
adamc@276 370 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@117 371 ctx->page_front += len;
adamc@106 372 }
adamc@106 373
adamc@428 374 uw_unit uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 375 uw_check(ctx, INTS_MAX);
adamc@311 376 uw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@428 377
adamc@428 378 return uw_unit_v;
adamc@106 379 }
adamc@106 380
adamc@428 381 uw_unit uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@117 382 int len;
adamc@117 383
adamc@311 384 uw_check(ctx, FLOATS_MAX);
adamc@117 385 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 386 ctx->page_front += len;
adamc@428 387
adamc@428 388 return uw_unit_v;
adamc@117 389 }
adamc@117 390
adamc@428 391 uw_unit uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 392 uw_check(ctx, strlen(s) * 6);
adamc@117 393
adamc@106 394 for (; *s; s++) {
adamc@106 395 char c = *s;
adamc@106 396
adamc@106 397 if (c == '"')
adamc@311 398 uw_write_unsafe(ctx, "&quot;");
adamc@136 399 else if (c == '&')
adamc@311 400 uw_write_unsafe(ctx, "&amp;");
adamc@106 401 else if (isprint(c))
adamc@311 402 uw_writec_unsafe(ctx, c);
adamc@106 403 else {
adamc@311 404 uw_write_unsafe(ctx, "&#");
adamc@311 405 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 406 uw_writec_unsafe(ctx, ';');
adamc@106 407 }
adamc@106 408 }
adamc@428 409
adamc@428 410 return uw_unit_v;
adamc@106 411 }
adamc@120 412
adamc@120 413
adamc@311 414 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@137 415 int len;
adamc@137 416 char *r;
adamc@137 417
adamc@311 418 uw_check_heap(ctx, INTS_MAX);
adamc@137 419 r = ctx->heap_front;
adamc@276 420 sprintf(r, "%lld%n", n, &len);
adamc@137 421 ctx->heap_front += len+1;
adamc@137 422 return r;
adamc@120 423 }
adamc@120 424
adamc@311 425 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@137 426 int len;
adamc@137 427 char *r;
adamc@137 428
adamc@311 429 uw_check_heap(ctx, FLOATS_MAX);
adamc@137 430 r = ctx->heap_front;
adamc@137 431 sprintf(r, "%g%n", n, &len);
adamc@137 432 ctx->heap_front += len+1;
adamc@137 433 return r;
adamc@120 434 }
adamc@120 435
adamc@311 436 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 437 char *r, *p;
adamc@137 438
adamc@311 439 uw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 440
adamc@137 441 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 442 char c = *s;
adamc@137 443
adamc@137 444 if (c == ' ')
adamc@137 445 *p++ = '+';
adamc@137 446 else if (isalnum(c))
adamc@137 447 *p++ = c;
adamc@137 448 else {
adamc@137 449 sprintf(p, "%%%02X", c);
adamc@137 450 p += 3;
adamc@137 451 }
adamc@137 452 }
adamc@137 453
adamc@137 454 *p++ = 0;
adamc@137 455 ctx->heap_front = p;
adamc@137 456 return r;
adamc@120 457 }
adamc@120 458
adamc@311 459 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 460 if (b == uw_Basis_False)
adamc@186 461 return "0";
adamc@186 462 else
adamc@186 463 return "1";
adamc@186 464 }
adamc@186 465
adamc@311 466 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@120 467 int len;
adamc@120 468
adamc@276 469 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@120 470 ctx->page_front += len;
adamc@120 471 }
adamc@120 472
adamc@428 473 uw_unit uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 474 uw_check(ctx, INTS_MAX);
adamc@311 475 uw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@428 476
adamc@428 477 return uw_unit_v;
adamc@120 478 }
adamc@120 479
adamc@428 480 uw_unit uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@120 481 int len;
adamc@120 482
adamc@311 483 uw_check(ctx, FLOATS_MAX);
adamc@120 484 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 485 ctx->page_front += len;
adamc@428 486
adamc@428 487 return uw_unit_v;
adamc@120 488 }
adamc@120 489
adamc@428 490 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 491 uw_check(ctx, strlen(s) * 3);
adamc@120 492
adamc@120 493 for (; *s; s++) {
adamc@120 494 char c = *s;
adamc@120 495
adamc@120 496 if (c == ' ')
adamc@311 497 uw_writec_unsafe(ctx, '+');
adamc@120 498 else if (isalnum(c))
adamc@311 499 uw_writec_unsafe(ctx, c);
adamc@120 500 else {
adamc@120 501 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 502 ctx->page_front += 3;
adamc@120 503 }
adamc@120 504 }
adamc@428 505
adamc@428 506 return uw_unit_v;
adamc@120 507 }
adamc@120 508
adamc@428 509 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 510 if (b == uw_Basis_False)
adamc@311 511 uw_writec(ctx, '0');
adamc@186 512 else
adamc@311 513 uw_writec(ctx, '1');
adamc@428 514
adamc@428 515 return uw_unit_v;
adamc@186 516 }
adamc@186 517
adamc@120 518
adamc@311 519 static char *uw_unurlify_advance(char *s) {
adamc@144 520 char *new_s = strchr(s, '/');
adamc@120 521
adamc@120 522 if (new_s)
adamc@120 523 *new_s++ = 0;
adamc@120 524 else
adamc@144 525 new_s = strchr(s, 0);
adamc@144 526
adamc@144 527 return new_s;
adamc@144 528 }
adamc@144 529
adamc@311 530 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 531 char *new_s = uw_unurlify_advance(*s);
adamc@311 532 uw_Basis_int r;
adamc@120 533
adamc@276 534 r = atoll(*s);
adamc@120 535 *s = new_s;
adamc@120 536 return r;
adamc@120 537 }
adamc@120 538
adamc@311 539 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 540 char *new_s = uw_unurlify_advance(*s);
adamc@311 541 uw_Basis_float r;
adamc@120 542
adamc@120 543 r = atof(*s);
adamc@120 544 *s = new_s;
adamc@120 545 return r;
adamc@120 546 }
adamc@120 547
adamc@311 548 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 549 char *s1, *s2;
adamc@144 550 int n;
adamc@136 551
adamc@144 552 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 553 char c = *s2;
adamc@136 554
adamc@136 555 switch (c) {
adamc@136 556 case '+':
adamc@136 557 *s1 = ' ';
adamc@136 558 break;
adamc@136 559 case '%':
adamc@169 560 if (s2[1] == 0)
adamc@311 561 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 562 if (s2[2] == 0)
adamc@311 563 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 564 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 565 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 566 *s1 = n;
adamc@136 567 s2 += 2;
adamc@136 568 break;
adamc@136 569 default:
adamc@136 570 *s1 = c;
adamc@136 571 }
adamc@136 572 }
adamc@136 573 *s1++ = 0;
adamc@144 574 return s1;
adamc@144 575 }
adamc@144 576
adamc@311 577 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 578 char *new_s = uw_unurlify_advance(*s);
adamc@311 579 uw_Basis_bool r;
adamc@186 580
adamc@186 581 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 582 r = uw_Basis_False;
adamc@186 583 else
adamc@311 584 r = uw_Basis_True;
adamc@186 585
adamc@186 586 *s = new_s;
adamc@186 587 return r;
adamc@186 588 }
adamc@186 589
adamc@311 590 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 591 char *new_s = uw_unurlify_advance(*s);
adamc@144 592 char *r, *s1, *s2;
adamc@144 593 int len, n;
adamc@144 594
adamc@200 595 len = strlen(*s);
adamc@311 596 uw_check_heap(ctx, len + 1);
adamc@144 597
adamc@144 598 r = ctx->heap_front;
adamc@311 599 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 600 *s = new_s;
adamc@136 601 return r;
adamc@120 602 }
adamc@135 603
adamc@135 604
adamc@311 605 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 606 int len;
adamc@286 607 char *r;
adamc@286 608
adamc@311 609 uw_check_heap(ctx, INTS_MAX);
adamc@286 610 r = ctx->heap_front;
adamc@286 611 sprintf(r, "%lld%n", n, &len);
adamc@286 612 ctx->heap_front += len+1;
adamc@286 613 return r;
adamc@286 614 }
adamc@286 615
adamc@428 616 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 617 int len;
adamc@286 618
adamc@311 619 uw_check(ctx, INTS_MAX);
adamc@286 620 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 621 ctx->page_front += len;
adamc@428 622
adamc@428 623 return uw_unit_v;
adamc@286 624 }
adamc@286 625
adamc@311 626 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 627 int len;
adamc@286 628 char *r;
adamc@286 629
adamc@311 630 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 631 r = ctx->heap_front;
adamc@286 632 sprintf(r, "%g%n", n, &len);
adamc@286 633 ctx->heap_front += len+1;
adamc@286 634 return r;
adamc@286 635 }
adamc@286 636
adamc@428 637 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 638 int len;
adamc@286 639
adamc@311 640 uw_check(ctx, FLOATS_MAX);
adamc@286 641 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 642 ctx->page_front += len;
adamc@428 643
adamc@428 644 return uw_unit_v;
adamc@286 645 }
adamc@286 646
adamc@311 647 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 648 char *r, *s2;
adamc@137 649
adamc@311 650 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 651
adamc@137 652 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 653 char c = *s;
adamc@137 654
adamc@137 655 switch (c) {
adamc@137 656 case '<':
adamc@137 657 strcpy(s2, "&lt;");
adamc@137 658 s2 += 4;
adamc@137 659 break;
adamc@137 660 case '&':
adamc@137 661 strcpy(s2, "&amp;");
adamc@137 662 s2 += 5;
adamc@137 663 break;
adamc@137 664 default:
adamc@137 665 if (isprint(c))
adamc@137 666 *s2++ = c;
adamc@137 667 else {
adamc@137 668 int len2;
adamc@137 669 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 670 s2 += len2;
adamc@137 671 }
adamc@137 672 }
adamc@137 673 }
adamc@137 674
adamc@137 675 *s2++ = 0;
adamc@137 676 ctx->heap_front = s2;
adamc@137 677 return r;
adamc@135 678 }
adamc@135 679
adamc@428 680 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 681 uw_check(ctx, strlen(s) * 6);
adamc@135 682
adamc@135 683 for (; *s; s++) {
adamc@135 684 char c = *s;
adamc@135 685
adamc@135 686 switch (c) {
adamc@135 687 case '<':
adamc@311 688 uw_write_unsafe(ctx, "&lt;");
adamc@135 689 break;
adamc@135 690 case '&':
adamc@311 691 uw_write_unsafe(ctx, "&amp;");
adamc@135 692 break;
adamc@135 693 default:
adamc@135 694 if (isprint(c))
adamc@311 695 uw_writec_unsafe(ctx, c);
adamc@135 696 else {
adamc@311 697 uw_write_unsafe(ctx, "&#");
adamc@311 698 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 699 uw_writec_unsafe(ctx, ';');
adamc@135 700 }
adamc@135 701 }
adamc@135 702 }
adamc@428 703
adamc@428 704 return uw_unit_v;
adamc@135 705 }
adamc@180 706
adamc@311 707 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 708 if (b == uw_Basis_False)
adamc@286 709 return "False";
adamc@286 710 else
adamc@286 711 return "True";
adamc@286 712 }
adamc@286 713
adamc@428 714 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 715 if (b == uw_Basis_False) {
adamc@311 716 uw_check(ctx, 6);
adamc@286 717 strcpy(ctx->page_front, "False");
adamc@286 718 ctx->page_front += 5;
adamc@286 719 } else {
adamc@311 720 uw_check(ctx, 5);
adamc@286 721 strcpy(ctx->page_front, "True");
adamc@286 722 ctx->page_front += 4;
adamc@286 723 }
adamc@428 724
adamc@428 725 return uw_unit_v;
adamc@286 726 }
adamc@286 727
adamc@311 728 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 729 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 730 char *s;
adamc@180 731
adamc@311 732 uw_check_heap(ctx, len);
adamc@180 733
adamc@180 734 s = ctx->heap_front;
adamc@180 735
adamc@180 736 strcpy(s, s1);
adamc@180 737 strcat(s, s2);
adamc@180 738 ctx->heap_front += len;
adamc@180 739
adamc@180 740 return s;
adamc@180 741 }
adamc@278 742
adamc@311 743 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 744 int len = strlen(s1) + 1;
adamc@278 745 char *s;
adamc@278 746
adamc@311 747 uw_check_heap(ctx, len);
adamc@278 748
adamc@278 749 s = ctx->heap_front;
adamc@278 750
adamc@278 751 strcpy(s, s1);
adamc@278 752 ctx->heap_front += len;
adamc@278 753
adamc@278 754 return s;
adamc@278 755 }
adamc@280 756
adamc@280 757
adamc@311 758 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 759 int len;
adamc@281 760 char *r;
adamc@281 761
adamc@311 762 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 763 r = ctx->heap_front;
adamc@281 764 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 765 ctx->heap_front += len+1;
adamc@281 766 return r;
adamc@281 767 }
adamc@281 768
adamc@311 769 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 770 int len;
adamc@281 771 char *r;
adamc@281 772
adamc@311 773 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 774 r = ctx->heap_front;
adamc@281 775 sprintf(r, "%g::float8%n", n, &len);
adamc@281 776 ctx->heap_front += len+1;
adamc@281 777 return r;
adamc@281 778 }
adamc@281 779
adamc@281 780
adamc@311 781 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 782 char *r, *s2;
adamc@280 783
adamc@311 784 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 785
adamc@280 786 r = s2 = ctx->heap_front;
adamc@280 787 *s2++ = 'E';
adamc@280 788 *s2++ = '\'';
adamc@280 789
adamc@280 790 for (; *s; s++) {
adamc@280 791 char c = *s;
adamc@280 792
adamc@280 793 switch (c) {
adamc@280 794 case '\'':
adamc@280 795 strcpy(s2, "\\'");
adamc@280 796 s2 += 2;
adamc@280 797 break;
adamc@280 798 case '\\':
adamc@280 799 strcpy(s2, "\\\\");
adamc@280 800 s2 += 2;
adamc@280 801 break;
adamc@280 802 default:
adamc@280 803 if (isprint(c))
adamc@280 804 *s2++ = c;
adamc@280 805 else {
adamc@280 806 sprintf(s2, "\\%3o", c);
adamc@280 807 s2 += 4;
adamc@280 808 }
adamc@280 809 }
adamc@280 810 }
adamc@280 811
adamc@281 812 strcpy(s2, "'::text");
adamc@281 813 ctx->heap_front = s2 + 8;
adamc@280 814 return r;
adamc@280 815 }
adamc@281 816
adamc@311 817 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 818 if (b == uw_Basis_False)
adamc@281 819 return "FALSE";
adamc@281 820 else
adamc@281 821 return "TRUE";
adamc@281 822 }
adamc@282 823
adamc@311 824 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 825 static uw_Basis_int true = 1;
adamc@311 826 static uw_Basis_int false = 0;
adamc@282 827
adamc@311 828 if (b == uw_Basis_False)
adamc@282 829 return (char *)&false;
adamc@282 830 else
adamc@282 831 return (char *)&true;
adamc@282 832 }
adamc@284 833
adamc@311 834 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 835 int len;
adamc@284 836 char *r;
adamc@284 837
adamc@311 838 uw_check_heap(ctx, INTS_MAX);
adamc@284 839 r = ctx->heap_front;
adamc@284 840 sprintf(r, "%lld%n", n, &len);
adamc@284 841 ctx->heap_front += len+1;
adamc@284 842 return r;
adamc@284 843 }
adamc@285 844
adamc@311 845 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 846 int len;
adamc@285 847 char *r;
adamc@285 848
adamc@311 849 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 850 r = ctx->heap_front;
adamc@285 851 sprintf(r, "%g%n", n, &len);
adamc@285 852 ctx->heap_front += len+1;
adamc@285 853 return r;
adamc@285 854 }
adamc@285 855
adamc@311 856 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 857 if (b == uw_Basis_False)
adamc@285 858 return "False";
adamc@285 859 else
adamc@285 860 return "True";
adamc@285 861 }
adamc@288 862
adamc@288 863
adamc@311 864 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 865 char *endptr;
adamc@311 866 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 867
adamc@288 868 if (*s != '\0' && *endptr == '\0') {
adamc@311 869 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 870 *r = n;
adamc@288 871 return r;
adamc@288 872 } else
adamc@288 873 return NULL;
adamc@288 874 }
adamc@289 875
adamc@311 876 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 877 char *endptr;
adamc@311 878 uw_Basis_float n = strtod(s, &endptr);
adamc@289 879
adamc@289 880 if (*s != '\0' && *endptr == '\0') {
adamc@311 881 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 882 *r = n;
adamc@289 883 return r;
adamc@289 884 } else
adamc@289 885 return NULL;
adamc@289 886 }
adamc@289 887
adamc@311 888 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 889 static uw_Basis_bool true = uw_Basis_True;
adamc@311 890 static uw_Basis_bool false = uw_Basis_False;
adamc@289 891
adamc@289 892 if (!strcasecmp (s, "True"))
adamc@289 893 return &true;
adamc@289 894 else if (!strcasecmp (s, "False"))
adamc@289 895 return &false;
adamc@289 896 else
adamc@289 897 return NULL;
adamc@289 898 }
adamc@292 899
adamc@311 900 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 901 char *endptr;
adamc@311 902 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 903
adamc@292 904 if (*s != '\0' && *endptr == '\0')
adamc@292 905 return n;
adamc@292 906 else
adamc@311 907 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 908 }
adamc@293 909
adamc@311 910 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 911 char *endptr;
adamc@311 912 uw_Basis_float n = strtod(s, &endptr);
adamc@293 913
adamc@293 914 if (*s != '\0' && *endptr == '\0')
adamc@293 915 return n;
adamc@293 916 else
adamc@311 917 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 918 }
adamc@293 919
adamc@311 920 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 921 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 922 return uw_Basis_True;
adamc@296 923 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 924 return uw_Basis_False;
adamc@293 925 else
adamc@311 926 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 927 }