libidav/davqlparser.c

changeset 291
8828260d2fd8
parent 288
cd3846cc8b25
child 356
699781a1d6fd
equal deleted inserted replaced
290:1e3e374d9386 291:8828260d2fd8
417 lp, prev.ptr, 417 lp, prev.ptr,
418 sfmtarg(tokenstr), 418 sfmtarg(tokenstr),
419 ln, pn).ptr; 419 ln, pn).ptr;
420 } 420 }
421 421
422 // TODO: this macro results in a memory leak - we return without freeing memory
423 #define dqlsec_alloc_failed(ptr, stmt) \ 422 #define dqlsec_alloc_failed(ptr, stmt) \
424 if (!(ptr)) { \ 423 if (!(ptr)) do { \
425 (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; \ 424 (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; \
426 return 0; \ 425 return 0; \
427 } 426 } while(0)
428 #define dqlsec_malloc(stmt, ptr, type) ptr = malloc(sizeof(type)); \ 427 #define dqlsec_malloc(stmt, ptr, type) \
429 dqlsec_alloc_failed(ptr, stmt); 428 dqlsec_alloc_failed(ptr = malloc(sizeof(type)), stmt)
430 #define dqlsec_mallocz(stmt, ptr, type) ptr = calloc(1, sizeof(type)); \ 429 #define dqlsec_mallocz(stmt, ptr, type) \
431 dqlsec_alloc_failed(ptr, stmt); 430 dqlsec_alloc_failed(ptr = calloc(1, sizeof(type)), stmt)
432 431
433 #define dqlsec_list_append(stmt, list, data) \ 432 #define dqlsec_list_append_or_free(stmt, list, data) \
434 { \ 433 do { \
435 UcxList *_dqlsecbak_ = list; \ 434 UcxList *_dqlsecbak_ = list; \
436 list = ucx_list_append(list, data); \ 435 list = ucx_list_append(list, data); \
437 if (!list) { \ 436 if (!list) { \
437 free(data); \
438 data = NULL; \
438 (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; \ 439 (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; \
439 list = _dqlsecbak_; \ 440 list = _dqlsecbak_; \
441 return 0; \
440 } \ 442 } \
441 } 443 } while(0)
442 444
443 // special symbols are single tokens - the % sign MUST NOT be a special symbol 445 // special symbols are single tokens - the % sign MUST NOT be a special symbol
444 static const char *special_token_symbols = ",()+-*/&|^~=!<>"; 446 static const char *special_token_symbols = ",()+-*/&|^~=!<>";
445 447
446 static _Bool iskeyword(DavQLToken *token) { 448 static _Bool iskeyword(DavQLToken *token) {
529 return NULL; 531 return NULL;
530 } 532 }
531 } 533 }
532 534
533 static UcxList* dav_parse_tokenize(sstr_t src) { 535 static UcxList* dav_parse_tokenize(sstr_t src) {
534 #define alloc_token token = malloc(sizeof(DavQLToken));\ 536 #define alloc_token() do {token = malloc(sizeof(DavQLToken));\
535 if(!token) {ucx_list_free(tokens); return NULL;} 537 if(!token) {ucx_list_free(tokens); return NULL;}} while(0)
536 #define add_token tokens = dav_parse_add_token(tokens, token); \ 538 #define add_token() do {tokens = dav_parse_add_token(tokens, token); \
537 if(!tokens) {return NULL;} 539 if(!tokens) {return NULL;}} while(0)
538 UcxList *tokens = NULL; 540 UcxList *tokens = NULL;
539 541
540 DavQLToken *token = NULL; 542 DavQLToken *token = NULL;
541 char insequence = '\0'; 543 char insequence = '\0';
542 for (size_t i = 0 ; i < src.length ; i++) { 544 for (size_t i = 0 ; i < src.length ; i++) {
549 token->value.length += 3; 551 token->value.length += 3;
550 i += 2; 552 i += 2;
551 } else { 553 } else {
552 // add quoted token to list 554 // add quoted token to list
553 token->value.length++; 555 token->value.length++;
554 add_token 556 add_token();
555 token = NULL; 557 token = NULL;
556 insequence = '\0'; 558 insequence = '\0';
557 } 559 }
558 } else if (insequence == '\0') { 560 } else if (insequence == '\0') {
559 insequence = src.ptr[i]; 561 insequence = src.ptr[i];
560 // always create new token for quoted strings 562 // always create new token for quoted strings
561 if (token) { 563 if (token) {
562 add_token 564 add_token();
563 } 565 }
564 alloc_token 566 alloc_token();
565 token->value.ptr = src.ptr + i; 567 token->value.ptr = src.ptr + i;
566 token->value.length = 1; 568 token->value.length = 1;
567 } else { 569 } else {
568 // add other kind of quotes to token 570 // add other kind of quotes to token
569 token->value.length++; 571 token->value.length++;
571 } else if (insequence) { 573 } else if (insequence) {
572 token->value.length++; 574 token->value.length++;
573 } else if (isspace(src.ptr[i])) { 575 } else if (isspace(src.ptr[i])) {
574 // add token before spaces to list (if any) 576 // add token before spaces to list (if any)
575 if (token) { 577 if (token) {
576 add_token 578 add_token();
577 token = NULL; 579 token = NULL;
578 } 580 }
579 } else if (strchr(special_token_symbols, src.ptr[i])) { 581 } else if (strchr(special_token_symbols, src.ptr[i])) {
580 // add token before special symbol to list (if any) 582 // add token before special symbol to list (if any)
581 if (token) { 583 if (token) {
582 add_token 584 add_token();
583 token = NULL; 585 token = NULL;
584 } 586 }
585 // add special symbol as single token to list 587 // add special symbol as single token to list
586 alloc_token 588 alloc_token();
587 token->value.ptr = src.ptr + i; 589 token->value.ptr = src.ptr + i;
588 token->value.length = 1; 590 token->value.length = 1;
589 add_token 591 add_token();
590 // set tokenizer ready to read more tokens 592 // set tokenizer ready to read more tokens
591 token = NULL; 593 token = NULL;
592 } else { 594 } else {
593 // if this is a new token, create memory for it 595 // if this is a new token, create memory for it
594 if (!token) { 596 if (!token) {
595 alloc_token 597 alloc_token();
596 token->value.ptr = src.ptr + i; 598 token->value.ptr = src.ptr + i;
597 token->value.length = 0; 599 token->value.length = 0;
598 } 600 }
599 // extend token length when reading more bytes 601 // extend token length when reading more bytes
600 token->value.length++; 602 token->value.length++;
601 } 603 }
602 } 604 }
603 605
604 if (token) { 606 if (token) {
605 add_token 607 add_token();
606 } 608 }
607 609
608 alloc_token 610 alloc_token();
609 token->tokenclass = DAVQL_TOKEN_END; 611 token->tokenclass = DAVQL_TOKEN_END;
610 token->value = S(""); 612 token->value = S("");
611 UcxList *ret = ucx_list_append(tokens, token); 613 UcxList *ret = ucx_list_append(tokens, token);
612 if (ret) { 614 if (ret) {
613 return ret; 615 return ret;
996 998
997 // RULE: "-" 999 // RULE: "-"
998 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "-")) { 1000 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "-")) {
999 DavQLField *field; 1001 DavQLField *field;
1000 dqlsec_malloc(stmt, field, DavQLField); 1002 dqlsec_malloc(stmt, field, DavQLField);
1003 dqlsec_list_append_or_free(stmt, stmt->fields, field);
1001 dqlsec_mallocz(stmt, field->expr, DavQLExpression); 1004 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
1002 field->expr->type = DAVQL_IDENTIFIER; 1005 field->expr->type = DAVQL_IDENTIFIER;
1003 field->expr->srctext = field->name = token_sstr(token); 1006 field->expr->srctext = field->name = token_sstr(token);
1004 dqlsec_list_append(stmt, stmt->fields, field);
1005 return 1; 1007 return 1;
1006 } 1008 }
1007 1009
1008 // RULE: "*", {",", NamedExpression} 1010 // RULE: "*", {",", NamedExpression}
1009 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) { 1011 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) {
1010 DavQLField *field; 1012 DavQLField *field;
1011 dqlsec_malloc(stmt, field, DavQLField); 1013 dqlsec_malloc(stmt, field, DavQLField);
1014 dqlsec_list_append_or_free(stmt, stmt->fields, field);
1012 dqlsec_mallocz(stmt, field->expr, DavQLExpression); 1015 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
1013 field->expr->type = DAVQL_IDENTIFIER; 1016 field->expr->type = DAVQL_IDENTIFIER;
1014 field->expr->srctext = field->name = token_sstr(token); 1017 field->expr->srctext = field->name = token_sstr(token);
1015 dqlsec_list_append(stmt, stmt->fields, field);
1016 1018
1017 int total_consumed = 0; 1019 int total_consumed = 0;
1018 int consumed = 1; 1020 int consumed = 1;
1019 1021
1020 do { 1022 do {
1027 consumed = dav_parse_named_field(stmt, token, &localfield); 1029 consumed = dav_parse_named_field(stmt, token, &localfield);
1028 if (!stmt->errorcode && consumed) { 1030 if (!stmt->errorcode && consumed) {
1029 DavQLField *field; 1031 DavQLField *field;
1030 dqlsec_malloc(stmt, field, DavQLField); 1032 dqlsec_malloc(stmt, field, DavQLField);
1031 memcpy(field, &localfield, sizeof(DavQLField)); 1033 memcpy(field, &localfield, sizeof(DavQLField));
1032 dqlsec_list_append(stmt, stmt->fields, field); 1034 dqlsec_list_append_or_free(stmt, stmt->fields, field);
1033 } 1035 }
1034 } else { 1036 } else {
1035 consumed = 0; 1037 consumed = 0;
1036 } 1038 }
1037 } while (consumed > 0); 1039 } while (consumed > 0);
1048 consumed = dav_parse_named_field(stmt, token, &localfield); 1050 consumed = dav_parse_named_field(stmt, token, &localfield);
1049 if (consumed) { 1051 if (consumed) {
1050 DavQLField *field; 1052 DavQLField *field;
1051 dqlsec_malloc(stmt, field, DavQLField); 1053 dqlsec_malloc(stmt, field, DavQLField);
1052 memcpy(field, &localfield, sizeof(DavQLField)); 1054 memcpy(field, &localfield, sizeof(DavQLField));
1053 dqlsec_list_append(stmt, stmt->fields, field); 1055 dqlsec_list_append_or_free(stmt, stmt->fields, field);
1054 token = ucx_list_get(token, consumed); 1056 token = ucx_list_get(token, consumed);
1055 total_consumed += consumed; 1057 total_consumed += consumed;
1056 } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER) 1058 } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)
1057 // look ahead, if the field is JUST the identifier 1059 // look ahead, if the field is JUST the identifier
1058 && (token_is(token->next, DAVQL_TOKEN_COMMA) || 1060 && (token_is(token->next, DAVQL_TOKEN_COMMA) ||
1061 DavQLField *field; 1063 DavQLField *field;
1062 dqlsec_malloc(stmt, field, DavQLField); 1064 dqlsec_malloc(stmt, field, DavQLField);
1063 dqlsec_mallocz(stmt, field->expr, DavQLExpression); 1065 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
1064 field->expr->type = DAVQL_IDENTIFIER; 1066 field->expr->type = DAVQL_IDENTIFIER;
1065 field->expr->srctext = field->name = token_sstr(token); 1067 field->expr->srctext = field->name = token_sstr(token);
1066 dqlsec_list_append(stmt, stmt->fields, field); 1068 dqlsec_list_append_or_free(stmt, stmt->fields, field);
1067 1069
1068 consumed = 1; 1070 consumed = 1;
1069 total_consumed++; 1071 total_consumed++;
1070 token = token->next; 1072 token = token->next;
1071 1073
1445 total_consumed += consumed; 1447 total_consumed += consumed;
1446 1448
1447 DavQLOrderCriterion *criterion; 1449 DavQLOrderCriterion *criterion;
1448 dqlsec_malloc(stmt, criterion, DavQLOrderCriterion); 1450 dqlsec_malloc(stmt, criterion, DavQLOrderCriterion);
1449 memcpy(criterion, &crit, sizeof(DavQLOrderCriterion)); 1451 memcpy(criterion, &crit, sizeof(DavQLOrderCriterion));
1450 dqlsec_list_append(stmt, stmt->orderby, criterion); 1452 dqlsec_list_append_or_free(stmt, stmt->orderby, criterion);
1451 1453
1452 if (token_is(token, DAVQL_TOKEN_COMMA)) { 1454 if (token_is(token, DAVQL_TOKEN_COMMA)) {
1453 total_consumed++; 1455 total_consumed++;
1454 token = token->next; 1456 token = token->next;
1455 } else { 1457 } else {

mercurial