annotate src/c/urweb.c @ 317:6a4e365db60c

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