comparison src/c/urweb.c @ 756:8ce31c052dce

Subforms
author Adam Chlipala <adamc@hcoop.net>
date Tue, 28 Apr 2009 17:26:53 -0400
parents ee2feab275db
children 67cd8326f743
comparison
equal deleted inserted replaced
755:58d8f877e1ee 756:8ce31c052dce
282 unsigned client; 282 unsigned client;
283 buf msgs; 283 buf msgs;
284 } delta; 284 } delta;
285 285
286 typedef enum { 286 typedef enum {
287 UNSET, NORMAL, FIL 287 UNSET, NORMAL, FIL, SUBFORM
288 } input_kind; 288 } input_kind;
289 289
290 typedef struct { 290 typedef struct input {
291 input_kind kind; 291 input_kind kind;
292 union { 292 union {
293 char *normal; 293 char *normal;
294 uw_Basis_file file; 294 uw_Basis_file file;
295 struct {
296 struct input *fields, *prev;
297 } subform;
295 } data; 298 } data;
296 } input; 299 } input;
297 300
298 struct uw_context { 301 struct uw_context {
299 char *headers, *headers_end; 302 char *headers, *headers_end;
300 303
301 buf outHeaders, page, heap, script; 304 buf outHeaders, page, heap, script;
302 input *inputs; 305 input *inputs, *subinputs, *cur_inputs;
306 size_t n_subinputs, used_subinputs;
303 307
304 int source_count; 308 int source_count;
305 309
306 void *db; 310 void *db;
307 311
337 buf_init(&ctx->heap, 0); 341 buf_init(&ctx->heap, 0);
338 buf_init(&ctx->script, 1); 342 buf_init(&ctx->script, 1);
339 ctx->script.start[0] = 0; 343 ctx->script.start[0] = 0;
340 344
341 ctx->inputs = calloc(uw_inputs_len, sizeof(input)); 345 ctx->inputs = calloc(uw_inputs_len, sizeof(input));
346 ctx->cur_inputs = NULL;
347 ctx->subinputs = malloc(0);
348 ctx->n_subinputs = ctx->used_subinputs = 0;
342 349
343 ctx->db = NULL; 350 ctx->db = NULL;
344 351
345 ctx->regions = NULL; 352 ctx->regions = NULL;
346 353
381 buf_free(&ctx->outHeaders); 388 buf_free(&ctx->outHeaders);
382 buf_free(&ctx->script); 389 buf_free(&ctx->script);
383 buf_free(&ctx->page); 390 buf_free(&ctx->page);
384 buf_free(&ctx->heap); 391 buf_free(&ctx->heap);
385 free(ctx->inputs); 392 free(ctx->inputs);
393 free(ctx->subinputs);
386 free(ctx->cleanup); 394 free(ctx->cleanup);
387 395
388 for (i = 0; i < ctx->n_deltas; ++i) 396 for (i = 0; i < ctx->n_deltas; ++i)
389 buf_free(&ctx->deltas[i].msgs); 397 buf_free(&ctx->deltas[i].msgs);
390 398
391 free(ctx); 399 free(ctx);
392 } 400 }
393 401
394 void uw_reset_keep_error_message(uw_context ctx) { 402 void uw_reset_keep_error_message(uw_context ctx) {
403 size_t i;
404
395 buf_reset(&ctx->outHeaders); 405 buf_reset(&ctx->outHeaders);
396 buf_reset(&ctx->script); 406 buf_reset(&ctx->script);
397 ctx->script.start[0] = 0; 407 ctx->script.start[0] = 0;
398 buf_reset(&ctx->page); 408 buf_reset(&ctx->page);
399 buf_reset(&ctx->heap); 409 buf_reset(&ctx->heap);
410 } 420 }
411 421
412 void uw_reset(uw_context ctx) { 422 void uw_reset(uw_context ctx) {
413 uw_reset_keep_request(ctx); 423 uw_reset_keep_request(ctx);
414 memset(ctx->inputs, 0, uw_inputs_len * sizeof(input)); 424 memset(ctx->inputs, 0, uw_inputs_len * sizeof(input));
425 memset(ctx->subinputs, 0, ctx->n_subinputs * sizeof(input));
426 ctx->cur_inputs = NULL;
427 ctx->used_subinputs = 0;
415 } 428 }
416 429
417 void uw_db_init(uw_context); 430 void uw_db_init(uw_context);
418 void uw_handle(uw_context, char *); 431 void uw_handle(uw_context, char *);
419 432
562 return ctx->error_message; 575 return ctx->error_message;
563 } 576 }
564 577
565 extern int uw_input_num(const char*); 578 extern int uw_input_num(const char*);
566 579
580 #define INP(ctx) (ctx->cur_inputs ? ctx->cur_inputs : ctx->inputs)
581
567 void uw_set_input(uw_context ctx, const char *name, char *value) { 582 void uw_set_input(uw_context ctx, const char *name, char *value) {
568 int n = uw_input_num(name); 583 if (!strcasecmp(name, ".b")) {
569 584 size_t i;
570 if (n < 0) 585 int n = uw_input_num(value);
571 uw_error(ctx, FATAL, "Bad input name %s", name); 586 input *inps;
572 587
573 if (n >= uw_inputs_len) 588 if (n < 0)
574 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n); 589 uw_error(ctx, FATAL, "Bad subform name %s", value);
575 590
576 ctx->inputs[n].kind = NORMAL; 591 if (n >= uw_inputs_len)
577 ctx->inputs[n].data.normal = value; 592 uw_error(ctx, FATAL, "For subform name %s, index %d is out of range", value, n);
593
594 if (ctx->used_subinputs + uw_inputs_len >= ctx->n_subinputs) {
595 input *new_subinputs = realloc(ctx->subinputs, sizeof(input) * (ctx->used_subinputs + uw_inputs_len));
596 size_t offset = new_subinputs - ctx->subinputs;
597
598 for (i = 0; i < ctx->used_subinputs; ++i)
599 if (new_subinputs[i].kind == SUBFORM) {
600 new_subinputs[i].data.subform.fields += offset;
601 if (new_subinputs[i].data.subform.prev != NULL)
602 new_subinputs[i].data.subform.prev += offset;
603 }
604
605 for (i = 0; i < uw_inputs_len; ++i)
606 if (ctx->inputs[i].kind == SUBFORM) {
607 ctx->inputs[i].data.subform.fields += offset;
608 if (ctx->inputs[i].data.subform.prev != NULL)
609 ctx->inputs[i].data.subform.prev += offset;
610 }
611
612 if (ctx->cur_inputs != NULL)
613 ctx->cur_inputs += offset;
614
615 ctx->n_subinputs = ctx->used_subinputs + uw_inputs_len;
616 ctx->subinputs = new_subinputs;
617 }
618
619 ctx->inputs[n].kind = SUBFORM;
620 ctx->inputs[n].data.subform.prev = ctx->cur_inputs;
621 ctx->cur_inputs = ctx->inputs[n].data.subform.fields = &ctx->subinputs[ctx->used_subinputs];
622
623 for (i = 0; i < uw_inputs_len; ++i)
624 ctx->subinputs[ctx->used_subinputs++].kind = UNUSED;
625 } else if (!strcasecmp(name, ".e")) {
626 input *tmp;
627
628 if (ctx->cur_inputs == NULL)
629 uw_error(ctx, FATAL, "Unmatched subform closer");
630
631 tmp = ctx->cur_inputs;
632 ctx->cur_inputs = tmp->data.subform.prev;
633 tmp->data.subform.prev = NULL;
634 } else {
635 int n = uw_input_num(name);
636
637 if (n < 0)
638 uw_error(ctx, FATAL, "Bad input name %s", name);
639
640 if (n >= uw_inputs_len)
641 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n);
642
643 INP(ctx)[n].kind = NORMAL;
644 INP(ctx)[n].data.normal = value;
645 }
578 } 646 }
579 647
580 char *uw_get_input(uw_context ctx, int n) { 648 char *uw_get_input(uw_context ctx, int n) {
581 if (n < 0) 649 if (n < 0)
582 uw_error(ctx, FATAL, "Negative input index %d", n); 650 uw_error(ctx, FATAL, "Negative input index %d", n);
583 if (n >= uw_inputs_len) 651 if (n >= uw_inputs_len)
584 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); 652 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
585 653
586 switch (ctx->inputs[n].kind) { 654 switch (INP(ctx)[n].kind) {
587 case UNSET: 655 case UNSET:
588 return NULL; 656 return NULL;
589 case FIL: 657 case FIL:
590 uw_error(ctx, FATAL, "Tried to read a file form input as normal"); 658 uw_error(ctx, FATAL, "Tried to read a file form input as normal");
659 case SUBFORM:
660 uw_error(ctx, FATAL, "Tried to read a subform form input as normal");
591 case NORMAL: 661 case NORMAL:
592 return ctx->inputs[n].data.normal; 662 return INP(ctx)[n].data.normal;
593 default: 663 default:
594 uw_error(ctx, FATAL, "Impossible input kind"); 664 uw_error(ctx, FATAL, "Impossible input kind");
595 } 665 }
596 } 666 }
597 667
599 if (n < 0) 669 if (n < 0)
600 uw_error(ctx, FATAL, "Negative input index %d", n); 670 uw_error(ctx, FATAL, "Negative input index %d", n);
601 if (n >= uw_inputs_len) 671 if (n >= uw_inputs_len)
602 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); 672 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
603 673
604 switch (ctx->inputs[n].kind) { 674 switch (INP(ctx)[n].kind) {
605 case UNSET: 675 case UNSET:
606 return ""; 676 return "";
607 case FIL: 677 case FIL:
608 uw_error(ctx, FATAL, "Tried to read a file form input as normal"); 678 uw_error(ctx, FATAL, "Tried to read a file form input as normal");
679 case SUBFORM:
680 uw_error(ctx, FATAL, "Tried to read a subform form input as normal");
609 case NORMAL: 681 case NORMAL:
610 return ctx->inputs[n].data.normal; 682 return INP(ctx)[n].data.normal;
611 default: 683 default:
612 uw_error(ctx, FATAL, "Impossible input kind"); 684 uw_error(ctx, FATAL, "Impossible input kind");
613 } 685 }
614 } 686 }
615 687
632 if (n < 0) 704 if (n < 0)
633 uw_error(ctx, FATAL, "Negative file input index %d", n); 705 uw_error(ctx, FATAL, "Negative file input index %d", n);
634 if (n >= uw_inputs_len) 706 if (n >= uw_inputs_len)
635 uw_error(ctx, FATAL, "Out-of-bounds file input index %d", n); 707 uw_error(ctx, FATAL, "Out-of-bounds file input index %d", n);
636 708
637 switch (ctx->inputs[n].kind) { 709 switch (INP(ctx)[n].kind) {
638 case UNSET: 710 case UNSET:
639 { 711 {
640 char *data = uw_malloc(ctx, 0); 712 char *data = uw_malloc(ctx, 0);
641 uw_Basis_file f = {NULL, "", {0, data}}; 713 uw_Basis_file f = {NULL, "", {0, data}};
642 return f; 714 return f;
643 } 715 }
644 case FIL: 716 case FIL:
645 return ctx->inputs[n].data.file; 717 return INP(ctx)[n].data.file;
646 case NORMAL: 718 case NORMAL:
647 uw_error(ctx, FATAL, "Tried to read a normal form input as files"); 719 uw_error(ctx, FATAL, "Tried to read a normal form input as files");
720 case SUBFORM:
721 uw_error(ctx, FATAL, "Tried to read a subform form input as files");
648 default: 722 default:
649 uw_error(ctx, FATAL, "Impossible input kind"); 723 uw_error(ctx, FATAL, "Impossible input kind");
650 } 724 }
725 }
726
727 void uw_enter_subform(uw_context ctx, int n) {
728 if (n < 0)
729 uw_error(ctx, FATAL, "Negative subform index %d", n);
730 if (n >= uw_inputs_len)
731 uw_error(ctx, FATAL, "Out-of-bounds subform index %d", n);
732
733 switch (INP(ctx)[n].kind) {
734 case UNSET:
735 uw_error(ctx, FATAL, "Missing subform");
736 case FIL:
737 uw_error(ctx, FATAL, "Tried to read a file form input as subform");
738 case NORMAL:
739 uw_error(ctx, FATAL, "Tried to read a normal form input as subform");
740 case SUBFORM:
741 INP(ctx)[n].data.subform.prev = ctx->cur_inputs;
742 ctx->cur_inputs = INP(ctx)[n].data.subform.fields;
743 return;
744 default:
745 uw_error(ctx, FATAL, "Impossible input kind");
746 }
747 }
748
749 void uw_leave_subform(uw_context ctx) {
750 input *tmp;
751
752 if (ctx->cur_inputs == NULL)
753 uw_error(ctx, FATAL, "Unmatched uw_leave_subform");
754
755 tmp = ctx->cur_inputs;
756 ctx->cur_inputs = tmp->data.subform.prev;
757 tmp->data.subform.prev = NULL;
651 } 758 }
652 759
653 void uw_set_script_header(uw_context ctx, const char *s) { 760 void uw_set_script_header(uw_context ctx, const char *s) {
654 ctx->script_header = s; 761 ctx->script_header = s;
655 } 762 }