annotate src/c/urweb.c @ 400:e756d3a47726

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