comparison src/c/urweb.c @ 759:67cd8326f743

subforms working
author Adam Chlipala <adamc@hcoop.net>
date Thu, 30 Apr 2009 13:47:46 -0400
parents 8ce31c052dce
children 21f6d2e65685
comparison
equal deleted inserted replaced
758:8323c1beef2e 759:67cd8326f743
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, SUBFORM 287 UNSET, NORMAL, FIL, SUBFORM, SUBFORMS, ENTRY
288 } input_kind; 288 } input_kind;
289 289
290 typedef struct input { 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 { 295 struct {
296 struct input *fields, *prev; 296 struct input *fields, *parent;
297 } subform; 297 } subform;
298 struct {
299 struct input *entries, *parent;
300 } subforms;
301 struct {
302 struct input *fields, *next, *parent;
303 } entry;
298 } data; 304 } data;
299 } input; 305 } input;
300 306
301 struct uw_context { 307 struct uw_context {
302 char *headers, *headers_end; 308 char *headers, *headers_end;
303 309
304 buf outHeaders, page, heap, script; 310 buf outHeaders, page, heap, script;
305 input *inputs, *subinputs, *cur_inputs; 311 input *inputs, *subinputs, *cur_container;
306 size_t n_subinputs, used_subinputs; 312 size_t n_subinputs, used_subinputs;
307 313
308 int source_count; 314 int source_count;
309 315
310 void *db; 316 void *db;
341 buf_init(&ctx->heap, 0); 347 buf_init(&ctx->heap, 0);
342 buf_init(&ctx->script, 1); 348 buf_init(&ctx->script, 1);
343 ctx->script.start[0] = 0; 349 ctx->script.start[0] = 0;
344 350
345 ctx->inputs = calloc(uw_inputs_len, sizeof(input)); 351 ctx->inputs = calloc(uw_inputs_len, sizeof(input));
346 ctx->cur_inputs = NULL; 352 ctx->cur_container = NULL;
347 ctx->subinputs = malloc(0); 353 ctx->subinputs = malloc(0);
348 ctx->n_subinputs = ctx->used_subinputs = 0; 354 ctx->n_subinputs = ctx->used_subinputs = 0;
349 355
350 ctx->db = NULL; 356 ctx->db = NULL;
351 357
410 ctx->regions = NULL; 416 ctx->regions = NULL;
411 ctx->cleanup_front = ctx->cleanup; 417 ctx->cleanup_front = ctx->cleanup;
412 ctx->source_count = 0; 418 ctx->source_count = 0;
413 ctx->used_deltas = 0; 419 ctx->used_deltas = 0;
414 ctx->client = NULL; 420 ctx->client = NULL;
421 ctx->cur_container = NULL;
415 } 422 }
416 423
417 void uw_reset_keep_request(uw_context ctx) { 424 void uw_reset_keep_request(uw_context ctx) {
418 uw_reset_keep_error_message(ctx); 425 uw_reset_keep_error_message(ctx);
419 ctx->error_message[0] = 0; 426 ctx->error_message[0] = 0;
421 428
422 void uw_reset(uw_context ctx) { 429 void uw_reset(uw_context ctx) {
423 uw_reset_keep_request(ctx); 430 uw_reset_keep_request(ctx);
424 memset(ctx->inputs, 0, uw_inputs_len * sizeof(input)); 431 memset(ctx->inputs, 0, uw_inputs_len * sizeof(input));
425 memset(ctx->subinputs, 0, ctx->n_subinputs * sizeof(input)); 432 memset(ctx->subinputs, 0, ctx->n_subinputs * sizeof(input));
426 ctx->cur_inputs = NULL;
427 ctx->used_subinputs = 0; 433 ctx->used_subinputs = 0;
428 } 434 }
429 435
430 void uw_db_init(uw_context); 436 void uw_db_init(uw_context);
431 void uw_handle(uw_context, char *); 437 void uw_handle(uw_context, char *);
575 return ctx->error_message; 581 return ctx->error_message;
576 } 582 }
577 583
578 extern int uw_input_num(const char*); 584 extern int uw_input_num(const char*);
579 585
580 #define INP(ctx) (ctx->cur_inputs ? ctx->cur_inputs : ctx->inputs) 586 static input *INP(uw_context ctx) {
587 if (ctx->cur_container == NULL)
588 return ctx->inputs;
589 else if (ctx->cur_container->kind == SUBFORM)
590 return ctx->cur_container->data.subform.fields;
591 else if (ctx->cur_container->kind == ENTRY)
592 return ctx->cur_container->data.entry.fields;
593 else
594 uw_error(ctx, FATAL, "INP: Wrong kind");
595 }
596
597 static void adjust_input(input *x, size_t offset) {
598 switch (x->kind) {
599 case SUBFORM:
600 x->data.subform.fields += offset;
601 if (x->data.subform.parent != NULL)
602 x->data.subform.parent += offset;
603 break;
604 case SUBFORMS:
605 if (x->data.subforms.entries != NULL)
606 x->data.subforms.entries += offset;
607 if (x->data.subforms.parent != NULL)
608 x->data.subforms.parent += offset;
609 break;
610 case ENTRY:
611 x->data.entry.fields += offset;
612 if (x->data.entry.next != NULL)
613 x->data.entry.next += offset;
614 if (x->data.entry.parent != NULL)
615 x->data.entry.parent += offset;
616 }
617 }
618
619 static input *check_input_space(uw_context ctx, size_t len) {
620 size_t i;
621 input *r;
622
623 if (ctx->used_subinputs + len >= ctx->n_subinputs) {
624 input *new_subinputs = realloc(ctx->subinputs, sizeof(input) * (ctx->used_subinputs + len));
625 size_t offset = new_subinputs - ctx->subinputs;
626
627 for (i = 0; i < ctx->used_subinputs; ++i)
628 adjust_input(&new_subinputs[i], offset);
629 for (i = 0; i < uw_inputs_len; ++i)
630 adjust_input(&ctx->inputs[i], offset);
631
632 if (ctx->cur_container >= ctx->subinputs && ctx->cur_container < ctx->subinputs + ctx->n_subinputs)
633 ctx->cur_container += offset;
634
635 ctx->n_subinputs = ctx->used_subinputs + len;
636 ctx->subinputs = new_subinputs;
637 }
638
639 r = &ctx->subinputs[ctx->used_subinputs];
640
641 for (i = 0; i < len; ++i)
642 ctx->subinputs[ctx->used_subinputs++].kind = UNUSED;
643
644 return r;
645 }
581 646
582 void uw_set_input(uw_context ctx, const char *name, char *value) { 647 void uw_set_input(uw_context ctx, const char *name, char *value) {
583 if (!strcasecmp(name, ".b")) { 648 if (!strcasecmp(name, ".b")) {
584 size_t i;
585 int n = uw_input_num(value); 649 int n = uw_input_num(value);
586 input *inps; 650 input *inps;
587 651
588 if (n < 0) 652 if (n < 0)
589 uw_error(ctx, FATAL, "Bad subform name %s", value); 653 uw_error(ctx, FATAL, "Bad subform name %s", value);
590 654
591 if (n >= uw_inputs_len) 655 if (n >= uw_inputs_len)
592 uw_error(ctx, FATAL, "For subform name %s, index %d is out of range", value, n); 656 uw_error(ctx, FATAL, "For subform name %s, index %d is out of range", value, n);
593 657
594 if (ctx->used_subinputs + uw_inputs_len >= ctx->n_subinputs) { 658 inps = check_input_space(ctx, uw_inputs_len);
595 input *new_subinputs = realloc(ctx->subinputs, sizeof(input) * (ctx->used_subinputs + uw_inputs_len)); 659
596 size_t offset = new_subinputs - ctx->subinputs; 660 INP(ctx)[n].kind = SUBFORM;
597 661 INP(ctx)[n].data.subform.parent = ctx->cur_container;
598 for (i = 0; i < ctx->used_subinputs; ++i) 662 INP(ctx)[n].data.subform.fields = inps;
599 if (new_subinputs[i].kind == SUBFORM) { 663 ctx->cur_container = &INP(ctx)[n];
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")) { 664 } else if (!strcasecmp(name, ".e")) {
626 input *tmp; 665 input *tmp;
627 666
628 if (ctx->cur_inputs == NULL) 667 if (ctx->cur_container == NULL)
629 uw_error(ctx, FATAL, "Unmatched subform closer"); 668 uw_error(ctx, FATAL, "Unmatched subform closer");
630 669
631 tmp = ctx->cur_inputs; 670 tmp = ctx->cur_container;
632 ctx->cur_inputs = tmp->data.subform.prev; 671 switch (tmp->kind) {
633 tmp->data.subform.prev = NULL; 672 case SUBFORM:
673 ctx->cur_container = tmp->data.subform.parent;
674 tmp->data.subform.parent = NULL;
675 break;
676 case SUBFORMS:
677 ctx->cur_container = tmp->data.subforms.parent;
678 tmp->data.subforms.parent = NULL;
679 break;
680 case ENTRY:
681 ctx->cur_container = tmp->data.entry.parent;
682 break;
683 default:
684 uw_error(ctx, FATAL, "uw_set_input: Wrong kind");
685 }
686 } else if (!strcasecmp(name, ".s")) {
687 int n = uw_input_num(value);
688
689 if (n < 0)
690 uw_error(ctx, FATAL, "Bad subforms name %s", value);
691
692 if (n >= uw_inputs_len)
693 uw_error(ctx, FATAL, "For subforms name %s, index %d is out of range", value, n);
694
695 INP(ctx)[n].kind = SUBFORMS;
696 INP(ctx)[n].data.subforms.parent = ctx->cur_container;
697 INP(ctx)[n].data.subforms.entries = NULL;
698 ctx->cur_container = &INP(ctx)[n];
699 } else if (!strcasecmp(name, ".i")) {
700 input *inps;
701
702 if (!ctx->cur_container)
703 uw_error(ctx, FATAL, "New entry without container");
704
705 if (ctx->cur_container->kind != SUBFORMS)
706 uw_error(ctx, FATAL, "Bad kind for entry parent");
707
708 inps = check_input_space(ctx, uw_inputs_len + 1);
709
710 inps->kind = ENTRY;
711 inps->data.entry.parent = ctx->cur_container;
712 inps->data.entry.next = ctx->cur_container->data.subforms.entries;
713 ctx->cur_container->data.subforms.entries = inps;
714
715 inps->data.entry.fields = inps+1;
716 ctx->cur_container = inps;
634 } else { 717 } else {
635 int n = uw_input_num(name); 718 int n = uw_input_num(name);
636 719
637 if (n < 0) 720 if (n < 0)
638 uw_error(ctx, FATAL, "Bad input name %s", name); 721 uw_error(ctx, FATAL, "Bad input name %s", name);
656 return NULL; 739 return NULL;
657 case FIL: 740 case FIL:
658 uw_error(ctx, FATAL, "Tried to read a file form input as normal"); 741 uw_error(ctx, FATAL, "Tried to read a file form input as normal");
659 case SUBFORM: 742 case SUBFORM:
660 uw_error(ctx, FATAL, "Tried to read a subform form input as normal"); 743 uw_error(ctx, FATAL, "Tried to read a subform form input as normal");
744 case SUBFORMS:
745 uw_error(ctx, FATAL, "Tried to read a subforms form input as normal");
746 case ENTRY:
747 uw_error(ctx, FATAL, "Tried to read an entry form input as normal");
661 case NORMAL: 748 case NORMAL:
662 return INP(ctx)[n].data.normal; 749 return INP(ctx)[n].data.normal;
663 default: 750 default:
664 uw_error(ctx, FATAL, "Impossible input kind"); 751 uw_error(ctx, FATAL, "Impossible input kind");
665 } 752 }
676 return ""; 763 return "";
677 case FIL: 764 case FIL:
678 uw_error(ctx, FATAL, "Tried to read a file form input as normal"); 765 uw_error(ctx, FATAL, "Tried to read a file form input as normal");
679 case SUBFORM: 766 case SUBFORM:
680 uw_error(ctx, FATAL, "Tried to read a subform form input as normal"); 767 uw_error(ctx, FATAL, "Tried to read a subform form input as normal");
768 case SUBFORMS:
769 uw_error(ctx, FATAL, "Tried to read a subforms form input as normal");
770 case ENTRY:
771 uw_error(ctx, FATAL, "Tried to read an entry form input as normal");
681 case NORMAL: 772 case NORMAL:
682 return INP(ctx)[n].data.normal; 773 return INP(ctx)[n].data.normal;
683 default: 774 default:
684 uw_error(ctx, FATAL, "Impossible input kind"); 775 uw_error(ctx, FATAL, "Impossible input kind");
685 } 776 }
717 return INP(ctx)[n].data.file; 808 return INP(ctx)[n].data.file;
718 case NORMAL: 809 case NORMAL:
719 uw_error(ctx, FATAL, "Tried to read a normal form input as files"); 810 uw_error(ctx, FATAL, "Tried to read a normal form input as files");
720 case SUBFORM: 811 case SUBFORM:
721 uw_error(ctx, FATAL, "Tried to read a subform form input as files"); 812 uw_error(ctx, FATAL, "Tried to read a subform form input as files");
813 case SUBFORMS:
814 uw_error(ctx, FATAL, "Tried to read a subforms form input as files");
815 case ENTRY:
816 uw_error(ctx, FATAL, "Tried to read an entry form input as files");
722 default: 817 default:
723 uw_error(ctx, FATAL, "Impossible input kind"); 818 uw_error(ctx, FATAL, "Impossible input kind");
724 } 819 }
725 } 820 }
726 821
735 uw_error(ctx, FATAL, "Missing subform"); 830 uw_error(ctx, FATAL, "Missing subform");
736 case FIL: 831 case FIL:
737 uw_error(ctx, FATAL, "Tried to read a file form input as subform"); 832 uw_error(ctx, FATAL, "Tried to read a file form input as subform");
738 case NORMAL: 833 case NORMAL:
739 uw_error(ctx, FATAL, "Tried to read a normal form input as subform"); 834 uw_error(ctx, FATAL, "Tried to read a normal form input as subform");
835 case SUBFORMS:
836 uw_error(ctx, FATAL, "Tried to read a subforms form input as subform");
837 case ENTRY:
838 uw_error(ctx, FATAL, "Tried to read an entry form input as subform");
740 case SUBFORM: 839 case SUBFORM:
741 INP(ctx)[n].data.subform.prev = ctx->cur_inputs; 840 INP(ctx)[n].data.subform.parent = ctx->cur_container;
742 ctx->cur_inputs = INP(ctx)[n].data.subform.fields; 841 ctx->cur_container = INP(ctx)[n].data.subform.fields;
743 return; 842 return;
744 default: 843 default:
745 uw_error(ctx, FATAL, "Impossible input kind"); 844 uw_error(ctx, FATAL, "Impossible input kind");
746 } 845 }
747 } 846 }
748 847
749 void uw_leave_subform(uw_context ctx) { 848 void uw_leave_subform(uw_context ctx) {
750 input *tmp; 849 input *tmp;
751 850
752 if (ctx->cur_inputs == NULL) 851 if (ctx->cur_container == NULL)
753 uw_error(ctx, FATAL, "Unmatched uw_leave_subform"); 852 uw_error(ctx, FATAL, "Unmatched uw_leave_subform");
754 853
755 tmp = ctx->cur_inputs; 854 tmp = ctx->cur_container;
756 ctx->cur_inputs = tmp->data.subform.prev; 855 ctx->cur_container = tmp->data.subform.parent;
757 tmp->data.subform.prev = NULL; 856 tmp->data.subform.parent = NULL;
857 }
858
859 int uw_enter_subforms(uw_context ctx, int n) {
860 input *inps;
861
862 if (n < 0)
863 uw_error(ctx, FATAL, "Negative subforms index %d", n);
864 if (n >= uw_inputs_len)
865 uw_error(ctx, FATAL, "Out-of-bounds subforms index %d", n);
866
867 switch (INP(ctx)[n].kind) {
868 case UNSET:
869 uw_error(ctx, FATAL, "Missing subforms");
870 case FIL:
871 uw_error(ctx, FATAL, "Tried to read a file form input as subforms");
872 case NORMAL:
873 uw_error(ctx, FATAL, "Tried to read a normal form input %p as subforms", &INP(ctx)[n]);
874 case SUBFORM:
875 uw_error(ctx, FATAL, "Tried to read a subform form input as subforms");
876 case ENTRY:
877 uw_error(ctx, FATAL, "Tried to read an entry form input as subforms");
878 case SUBFORMS:
879 inps = INP(ctx)[n].data.subforms.entries;
880 if (inps) {
881 INP(ctx)[n].data.subforms.parent = ctx->cur_container;
882 ctx->cur_container = INP(ctx)[n].data.subforms.entries;
883 return 1;
884 } else
885 return 0;
886 default:
887 uw_error(ctx, FATAL, "Impossible input kind");
888 }
889 }
890
891 int uw_next_entry(uw_context ctx) {
892 if (ctx->cur_container == NULL)
893 uw_error(ctx, FATAL, "uw_next_entry(NULL)");
894
895 switch (ctx->cur_container->kind) {
896 case UNSET:
897 uw_error(ctx, FATAL, "Missing entry");
898 case FIL:
899 uw_error(ctx, FATAL, "Tried to read a file form input as entry");
900 case NORMAL:
901 uw_error(ctx, FATAL, "Tried to read a normal form input as entry");
902 case SUBFORM:
903 uw_error(ctx, FATAL, "Tried to read a subform form input as entry");
904 case SUBFORMS:
905 uw_error(ctx, FATAL, "Tried to read a subforms form input as entry");
906 case ENTRY:
907 if (ctx->cur_container->data.entry.next) {
908 ctx->cur_container = ctx->cur_container->data.entry.next;
909 return 1;
910 } else {
911 ctx->cur_container = ctx->cur_container->data.entry.parent->data.subforms.parent;
912 return 0;
913 }
914 default:
915 uw_error(ctx, FATAL, "Impossible input kind");
916 }
758 } 917 }
759 918
760 void uw_set_script_header(uw_context ctx, const char *s) { 919 void uw_set_script_header(uw_context ctx, const char *s) {
761 ctx->script_header = s; 920 ctx->script_header = s;
762 } 921 }