annotate src/c/urweb.c @ 425:7009b0ac1501

Properly freeing libpq results on errors
author Adam Chlipala <adamc@hcoop.net>
date Fri, 24 Oct 2008 17:30:07 -0400
parents b91480c9a729
children 2a861b56969c
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@425 143 newLen *= 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@190 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@317 282 if (next == 0)
adamc@317 283 next = 1;
adamc@317 284 for (; next < desired; next *= 2);
adamc@117 285
adamc@117 286 new_page = realloc(ctx->page, next);
adamc@117 287 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@317 288 ctx->page_back = new_page + next;
adamc@117 289 ctx->page = new_page;
adamc@117 290 }
adamc@117 291
adamc@311 292 static void uw_writec_unsafe(uw_context ctx, char c) {
adamc@117 293 *(ctx->page_front)++ = c;
adamc@117 294 }
adamc@117 295
adamc@311 296 void uw_writec(uw_context ctx, char c) {
adamc@311 297 uw_check(ctx, 1);
adamc@311 298 uw_writec_unsafe(ctx, c);
adamc@117 299 }
adamc@117 300
adamc@311 301 static void uw_write_unsafe(uw_context ctx, const char* s) {
adamc@117 302 int len = strlen(s);
adamc@117 303 memcpy(ctx->page_front, s, len);
adamc@117 304 ctx->page_front += len;
adamc@117 305 }
adamc@117 306
adamc@311 307 void uw_write(uw_context ctx, const char* s) {
adamc@311 308 uw_check(ctx, strlen(s) + 1);
adamc@311 309 uw_write_unsafe(ctx, s);
adamc@183 310 *ctx->page_front = 0;
adamc@102 311 }
adamc@106 312
adamc@135 313
adamc@311 314 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
adamc@136 315 char *result;
adamc@136 316 int len;
adamc@311 317 uw_check_heap(ctx, INTS_MAX);
adamc@136 318 result = ctx->heap_front;
adamc@276 319 sprintf(result, "%lld%n", n, &len);
adamc@137 320 ctx->heap_front += len+1;
adamc@136 321 return result;
adamc@106 322 }
adamc@106 323
adamc@311 324 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@136 325 char *result;
adamc@136 326 int len;
adamc@311 327 uw_check_heap(ctx, FLOATS_MAX);
adamc@136 328 result = ctx->heap_front;
adamc@136 329 sprintf(result, "%g%n", n, &len);
adamc@137 330 ctx->heap_front += len+1;
adamc@136 331 return result;
adamc@106 332 }
adamc@106 333
adamc@311 334 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
adamc@136 335 int len = strlen(s);
adamc@136 336 char *result, *p;
adamc@311 337 uw_check_heap(ctx, len * 6 + 1);
adamc@136 338
adamc@136 339 result = p = ctx->heap_front;
adamc@136 340
adamc@136 341 for (; *s; s++) {
adamc@136 342 char c = *s;
adamc@136 343
adamc@136 344 if (c == '"') {
adamc@136 345 strcpy(p, "&quot;");
adamc@136 346 p += 6;
adamc@136 347 } else if (c == '&') {
adamc@136 348 strcpy(p, "&amp;");
adamc@136 349 p += 5;
adamc@136 350 }
adamc@136 351 else if (isprint(c))
adamc@136 352 *p++ = c;
adamc@136 353 else {
adamc@136 354 int len2;
adamc@136 355 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 356 p += len2;
adamc@136 357 }
adamc@136 358 }
adamc@136 359
adamc@137 360 *p++ = 0;
adamc@136 361 ctx->heap_front = p;
adamc@136 362 return result;
adamc@106 363 }
adamc@106 364
adamc@311 365 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@117 366 int len;
adamc@117 367
adamc@276 368 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@117 369 ctx->page_front += len;
adamc@106 370 }
adamc@106 371
adamc@311 372 void uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 373 uw_check(ctx, INTS_MAX);
adamc@311 374 uw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@106 375 }
adamc@106 376
adamc@311 377 void uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@117 378 int len;
adamc@117 379
adamc@311 380 uw_check(ctx, FLOATS_MAX);
adamc@117 381 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 382 ctx->page_front += len;
adamc@117 383 }
adamc@117 384
adamc@311 385 void uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 386 uw_check(ctx, strlen(s) * 6);
adamc@117 387
adamc@106 388 for (; *s; s++) {
adamc@106 389 char c = *s;
adamc@106 390
adamc@106 391 if (c == '"')
adamc@311 392 uw_write_unsafe(ctx, "&quot;");
adamc@136 393 else if (c == '&')
adamc@311 394 uw_write_unsafe(ctx, "&amp;");
adamc@106 395 else if (isprint(c))
adamc@311 396 uw_writec_unsafe(ctx, c);
adamc@106 397 else {
adamc@311 398 uw_write_unsafe(ctx, "&#");
adamc@311 399 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 400 uw_writec_unsafe(ctx, ';');
adamc@106 401 }
adamc@106 402 }
adamc@106 403 }
adamc@120 404
adamc@120 405
adamc@311 406 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@137 407 int len;
adamc@137 408 char *r;
adamc@137 409
adamc@311 410 uw_check_heap(ctx, INTS_MAX);
adamc@137 411 r = ctx->heap_front;
adamc@276 412 sprintf(r, "%lld%n", n, &len);
adamc@137 413 ctx->heap_front += len+1;
adamc@137 414 return r;
adamc@120 415 }
adamc@120 416
adamc@311 417 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@137 418 int len;
adamc@137 419 char *r;
adamc@137 420
adamc@311 421 uw_check_heap(ctx, FLOATS_MAX);
adamc@137 422 r = ctx->heap_front;
adamc@137 423 sprintf(r, "%g%n", n, &len);
adamc@137 424 ctx->heap_front += len+1;
adamc@137 425 return r;
adamc@120 426 }
adamc@120 427
adamc@311 428 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 429 char *r, *p;
adamc@137 430
adamc@311 431 uw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 432
adamc@137 433 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 434 char c = *s;
adamc@137 435
adamc@137 436 if (c == ' ')
adamc@137 437 *p++ = '+';
adamc@137 438 else if (isalnum(c))
adamc@137 439 *p++ = c;
adamc@137 440 else {
adamc@137 441 sprintf(p, "%%%02X", c);
adamc@137 442 p += 3;
adamc@137 443 }
adamc@137 444 }
adamc@137 445
adamc@137 446 *p++ = 0;
adamc@137 447 ctx->heap_front = p;
adamc@137 448 return r;
adamc@120 449 }
adamc@120 450
adamc@311 451 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 452 if (b == uw_Basis_False)
adamc@186 453 return "0";
adamc@186 454 else
adamc@186 455 return "1";
adamc@186 456 }
adamc@186 457
adamc@311 458 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@120 459 int len;
adamc@120 460
adamc@276 461 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@120 462 ctx->page_front += len;
adamc@120 463 }
adamc@120 464
adamc@311 465 void uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 466 uw_check(ctx, INTS_MAX);
adamc@311 467 uw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@120 468 }
adamc@120 469
adamc@311 470 void uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@120 471 int len;
adamc@120 472
adamc@311 473 uw_check(ctx, FLOATS_MAX);
adamc@120 474 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 475 ctx->page_front += len;
adamc@120 476 }
adamc@120 477
adamc@311 478 void uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 479 uw_check(ctx, strlen(s) * 3);
adamc@120 480
adamc@120 481 for (; *s; s++) {
adamc@120 482 char c = *s;
adamc@120 483
adamc@120 484 if (c == ' ')
adamc@311 485 uw_writec_unsafe(ctx, '+');
adamc@120 486 else if (isalnum(c))
adamc@311 487 uw_writec_unsafe(ctx, c);
adamc@120 488 else {
adamc@120 489 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 490 ctx->page_front += 3;
adamc@120 491 }
adamc@120 492 }
adamc@120 493 }
adamc@120 494
adamc@311 495 void uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 496 if (b == uw_Basis_False)
adamc@311 497 uw_writec(ctx, '0');
adamc@186 498 else
adamc@311 499 uw_writec(ctx, '1');
adamc@186 500 }
adamc@186 501
adamc@120 502
adamc@311 503 static char *uw_unurlify_advance(char *s) {
adamc@144 504 char *new_s = strchr(s, '/');
adamc@120 505
adamc@120 506 if (new_s)
adamc@120 507 *new_s++ = 0;
adamc@120 508 else
adamc@144 509 new_s = strchr(s, 0);
adamc@144 510
adamc@144 511 return new_s;
adamc@144 512 }
adamc@144 513
adamc@311 514 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 515 char *new_s = uw_unurlify_advance(*s);
adamc@311 516 uw_Basis_int r;
adamc@120 517
adamc@276 518 r = atoll(*s);
adamc@120 519 *s = new_s;
adamc@120 520 return r;
adamc@120 521 }
adamc@120 522
adamc@311 523 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 524 char *new_s = uw_unurlify_advance(*s);
adamc@311 525 uw_Basis_float r;
adamc@120 526
adamc@120 527 r = atof(*s);
adamc@120 528 *s = new_s;
adamc@120 529 return r;
adamc@120 530 }
adamc@120 531
adamc@311 532 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 533 char *s1, *s2;
adamc@144 534 int n;
adamc@136 535
adamc@144 536 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 537 char c = *s2;
adamc@136 538
adamc@136 539 switch (c) {
adamc@136 540 case '+':
adamc@136 541 *s1 = ' ';
adamc@136 542 break;
adamc@136 543 case '%':
adamc@169 544 if (s2[1] == 0)
adamc@311 545 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 546 if (s2[2] == 0)
adamc@311 547 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 548 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 549 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 550 *s1 = n;
adamc@136 551 s2 += 2;
adamc@136 552 break;
adamc@136 553 default:
adamc@136 554 *s1 = c;
adamc@136 555 }
adamc@136 556 }
adamc@136 557 *s1++ = 0;
adamc@144 558 return s1;
adamc@144 559 }
adamc@144 560
adamc@311 561 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 562 char *new_s = uw_unurlify_advance(*s);
adamc@311 563 uw_Basis_bool r;
adamc@186 564
adamc@186 565 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 566 r = uw_Basis_False;
adamc@186 567 else
adamc@311 568 r = uw_Basis_True;
adamc@186 569
adamc@186 570 *s = new_s;
adamc@186 571 return r;
adamc@186 572 }
adamc@186 573
adamc@311 574 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 575 char *new_s = uw_unurlify_advance(*s);
adamc@144 576 char *r, *s1, *s2;
adamc@144 577 int len, n;
adamc@144 578
adamc@200 579 len = strlen(*s);
adamc@311 580 uw_check_heap(ctx, len + 1);
adamc@144 581
adamc@144 582 r = ctx->heap_front;
adamc@311 583 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 584 *s = new_s;
adamc@136 585 return r;
adamc@120 586 }
adamc@135 587
adamc@135 588
adamc@311 589 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 590 int len;
adamc@286 591 char *r;
adamc@286 592
adamc@311 593 uw_check_heap(ctx, INTS_MAX);
adamc@286 594 r = ctx->heap_front;
adamc@286 595 sprintf(r, "%lld%n", n, &len);
adamc@286 596 ctx->heap_front += len+1;
adamc@286 597 return r;
adamc@286 598 }
adamc@286 599
adamc@311 600 void uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 601 int len;
adamc@286 602
adamc@311 603 uw_check(ctx, INTS_MAX);
adamc@286 604 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 605 ctx->page_front += len;
adamc@286 606 }
adamc@286 607
adamc@311 608 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 609 int len;
adamc@286 610 char *r;
adamc@286 611
adamc@311 612 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 613 r = ctx->heap_front;
adamc@286 614 sprintf(r, "%g%n", n, &len);
adamc@286 615 ctx->heap_front += len+1;
adamc@286 616 return r;
adamc@286 617 }
adamc@286 618
adamc@311 619 void uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 620 int len;
adamc@286 621
adamc@311 622 uw_check(ctx, FLOATS_MAX);
adamc@286 623 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 624 ctx->page_front += len;
adamc@286 625 }
adamc@286 626
adamc@311 627 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 628 char *r, *s2;
adamc@137 629
adamc@311 630 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 631
adamc@137 632 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 633 char c = *s;
adamc@137 634
adamc@137 635 switch (c) {
adamc@137 636 case '<':
adamc@137 637 strcpy(s2, "&lt;");
adamc@137 638 s2 += 4;
adamc@137 639 break;
adamc@137 640 case '&':
adamc@137 641 strcpy(s2, "&amp;");
adamc@137 642 s2 += 5;
adamc@137 643 break;
adamc@137 644 default:
adamc@137 645 if (isprint(c))
adamc@137 646 *s2++ = c;
adamc@137 647 else {
adamc@137 648 int len2;
adamc@137 649 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 650 s2 += len2;
adamc@137 651 }
adamc@137 652 }
adamc@137 653 }
adamc@137 654
adamc@137 655 *s2++ = 0;
adamc@137 656 ctx->heap_front = s2;
adamc@137 657 return r;
adamc@135 658 }
adamc@135 659
adamc@311 660 void uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 661 uw_check(ctx, strlen(s) * 6);
adamc@135 662
adamc@135 663 for (; *s; s++) {
adamc@135 664 char c = *s;
adamc@135 665
adamc@135 666 switch (c) {
adamc@135 667 case '<':
adamc@311 668 uw_write_unsafe(ctx, "&lt;");
adamc@135 669 break;
adamc@135 670 case '&':
adamc@311 671 uw_write_unsafe(ctx, "&amp;");
adamc@135 672 break;
adamc@135 673 default:
adamc@135 674 if (isprint(c))
adamc@311 675 uw_writec_unsafe(ctx, c);
adamc@135 676 else {
adamc@311 677 uw_write_unsafe(ctx, "&#");
adamc@311 678 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 679 uw_writec_unsafe(ctx, ';');
adamc@135 680 }
adamc@135 681 }
adamc@135 682 }
adamc@135 683 }
adamc@180 684
adamc@311 685 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 686 if (b == uw_Basis_False)
adamc@286 687 return "False";
adamc@286 688 else
adamc@286 689 return "True";
adamc@286 690 }
adamc@286 691
adamc@311 692 void uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 693 if (b == uw_Basis_False) {
adamc@311 694 uw_check(ctx, 6);
adamc@286 695 strcpy(ctx->page_front, "False");
adamc@286 696 ctx->page_front += 5;
adamc@286 697 } else {
adamc@311 698 uw_check(ctx, 5);
adamc@286 699 strcpy(ctx->page_front, "True");
adamc@286 700 ctx->page_front += 4;
adamc@286 701 }
adamc@286 702 }
adamc@286 703
adamc@311 704 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 705 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 706 char *s;
adamc@180 707
adamc@311 708 uw_check_heap(ctx, len);
adamc@180 709
adamc@180 710 s = ctx->heap_front;
adamc@180 711
adamc@180 712 strcpy(s, s1);
adamc@180 713 strcat(s, s2);
adamc@180 714 ctx->heap_front += len;
adamc@180 715
adamc@180 716 return s;
adamc@180 717 }
adamc@278 718
adamc@311 719 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 720 int len = strlen(s1) + 1;
adamc@278 721 char *s;
adamc@278 722
adamc@311 723 uw_check_heap(ctx, len);
adamc@278 724
adamc@278 725 s = ctx->heap_front;
adamc@278 726
adamc@278 727 strcpy(s, s1);
adamc@278 728 ctx->heap_front += len;
adamc@278 729
adamc@278 730 return s;
adamc@278 731 }
adamc@280 732
adamc@280 733
adamc@311 734 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 735 int len;
adamc@281 736 char *r;
adamc@281 737
adamc@311 738 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 739 r = ctx->heap_front;
adamc@281 740 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 741 ctx->heap_front += len+1;
adamc@281 742 return r;
adamc@281 743 }
adamc@281 744
adamc@311 745 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 746 int len;
adamc@281 747 char *r;
adamc@281 748
adamc@311 749 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 750 r = ctx->heap_front;
adamc@281 751 sprintf(r, "%g::float8%n", n, &len);
adamc@281 752 ctx->heap_front += len+1;
adamc@281 753 return r;
adamc@281 754 }
adamc@281 755
adamc@281 756
adamc@311 757 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 758 char *r, *s2;
adamc@280 759
adamc@311 760 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 761
adamc@280 762 r = s2 = ctx->heap_front;
adamc@280 763 *s2++ = 'E';
adamc@280 764 *s2++ = '\'';
adamc@280 765
adamc@280 766 for (; *s; s++) {
adamc@280 767 char c = *s;
adamc@280 768
adamc@280 769 switch (c) {
adamc@280 770 case '\'':
adamc@280 771 strcpy(s2, "\\'");
adamc@280 772 s2 += 2;
adamc@280 773 break;
adamc@280 774 case '\\':
adamc@280 775 strcpy(s2, "\\\\");
adamc@280 776 s2 += 2;
adamc@280 777 break;
adamc@280 778 default:
adamc@280 779 if (isprint(c))
adamc@280 780 *s2++ = c;
adamc@280 781 else {
adamc@280 782 sprintf(s2, "\\%3o", c);
adamc@280 783 s2 += 4;
adamc@280 784 }
adamc@280 785 }
adamc@280 786 }
adamc@280 787
adamc@281 788 strcpy(s2, "'::text");
adamc@281 789 ctx->heap_front = s2 + 8;
adamc@280 790 return r;
adamc@280 791 }
adamc@281 792
adamc@311 793 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 794 if (b == uw_Basis_False)
adamc@281 795 return "FALSE";
adamc@281 796 else
adamc@281 797 return "TRUE";
adamc@281 798 }
adamc@282 799
adamc@311 800 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 801 static uw_Basis_int true = 1;
adamc@311 802 static uw_Basis_int false = 0;
adamc@282 803
adamc@311 804 if (b == uw_Basis_False)
adamc@282 805 return (char *)&false;
adamc@282 806 else
adamc@282 807 return (char *)&true;
adamc@282 808 }
adamc@284 809
adamc@311 810 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 811 int len;
adamc@284 812 char *r;
adamc@284 813
adamc@311 814 uw_check_heap(ctx, INTS_MAX);
adamc@284 815 r = ctx->heap_front;
adamc@284 816 sprintf(r, "%lld%n", n, &len);
adamc@284 817 ctx->heap_front += len+1;
adamc@284 818 return r;
adamc@284 819 }
adamc@285 820
adamc@311 821 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 822 int len;
adamc@285 823 char *r;
adamc@285 824
adamc@311 825 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 826 r = ctx->heap_front;
adamc@285 827 sprintf(r, "%g%n", n, &len);
adamc@285 828 ctx->heap_front += len+1;
adamc@285 829 return r;
adamc@285 830 }
adamc@285 831
adamc@311 832 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 833 if (b == uw_Basis_False)
adamc@285 834 return "False";
adamc@285 835 else
adamc@285 836 return "True";
adamc@285 837 }
adamc@288 838
adamc@288 839
adamc@311 840 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 841 char *endptr;
adamc@311 842 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 843
adamc@288 844 if (*s != '\0' && *endptr == '\0') {
adamc@311 845 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 846 *r = n;
adamc@288 847 return r;
adamc@288 848 } else
adamc@288 849 return NULL;
adamc@288 850 }
adamc@289 851
adamc@311 852 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 853 char *endptr;
adamc@311 854 uw_Basis_float n = strtod(s, &endptr);
adamc@289 855
adamc@289 856 if (*s != '\0' && *endptr == '\0') {
adamc@311 857 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 858 *r = n;
adamc@289 859 return r;
adamc@289 860 } else
adamc@289 861 return NULL;
adamc@289 862 }
adamc@289 863
adamc@311 864 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 865 static uw_Basis_bool true = uw_Basis_True;
adamc@311 866 static uw_Basis_bool false = uw_Basis_False;
adamc@289 867
adamc@289 868 if (!strcasecmp (s, "True"))
adamc@289 869 return &true;
adamc@289 870 else if (!strcasecmp (s, "False"))
adamc@289 871 return &false;
adamc@289 872 else
adamc@289 873 return NULL;
adamc@289 874 }
adamc@292 875
adamc@311 876 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 877 char *endptr;
adamc@311 878 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 879
adamc@292 880 if (*s != '\0' && *endptr == '\0')
adamc@292 881 return n;
adamc@292 882 else
adamc@311 883 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 884 }
adamc@293 885
adamc@311 886 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 887 char *endptr;
adamc@311 888 uw_Basis_float n = strtod(s, &endptr);
adamc@293 889
adamc@293 890 if (*s != '\0' && *endptr == '\0')
adamc@293 891 return n;
adamc@293 892 else
adamc@311 893 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 894 }
adamc@293 895
adamc@311 896 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 897 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 898 return uw_Basis_True;
adamc@296 899 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 900 return uw_Basis_False;
adamc@293 901 else
adamc@311 902 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 903 }