libidav/davqlparser.c

changeset 132
8c9b84f37af5
parent 131
32e7b3e6b482
child 185
cd42cccee550
equal deleted inserted replaced
131:32e7b3e6b482 132:8c9b84f37af5
427 #define dqlsec_malloc(stmt, ptr, type) ptr = malloc(sizeof(type)); \ 427 #define dqlsec_malloc(stmt, ptr, type) ptr = malloc(sizeof(type)); \
428 dqlsec_alloc_failed(ptr, stmt); 428 dqlsec_alloc_failed(ptr, stmt);
429 #define dqlsec_mallocz(stmt, ptr, type) ptr = calloc(1, sizeof(type)); \ 429 #define dqlsec_mallocz(stmt, ptr, type) ptr = calloc(1, sizeof(type)); \
430 dqlsec_alloc_failed(ptr, stmt); 430 dqlsec_alloc_failed(ptr, stmt);
431 431
432 #define dqlsec_list_append(stmt, list, data) \
433 { \
434 UcxList *_dqlsecbak_ = list; \
435 list = ucx_list_append(list, data); \
436 if (!list) { \
437 (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; \
438 list = _dqlsecbak_; \
439 } \
440 }
432 441
433 // special symbols are single tokens - the % sign MUST NOT be a special symbol 442 // special symbols are single tokens - the % sign MUST NOT be a special symbol
434 static const char *special_token_symbols = ",()+-*/&|^~=!<>"; 443 static const char *special_token_symbols = ",()+-*/&|^~=!<>";
435 444
436 static _Bool iskeyword(DavQLToken *token) { 445 static _Bool iskeyword(DavQLToken *token) {
501 token->tokenclass = DAVQL_TOKEN_INVALID; 510 token->tokenclass = DAVQL_TOKEN_INVALID;
502 } 511 }
503 } 512 }
504 513
505 514
506 return ucx_list_append(tokenlist, token); 515 UcxList *ret = ucx_list_append(tokenlist, token);
516 if (ret) {
517 return ret;
518 } else {
519 ucx_list_free(tokenlist);
520 return NULL;
521 }
507 } 522 }
508 523
509 static UcxList* dav_parse_tokenize(sstr_t src) { 524 static UcxList* dav_parse_tokenize(sstr_t src) {
510 #define alloc_token token = malloc(sizeof(DavQLToken));\ 525 #define alloc_token token = malloc(sizeof(DavQLToken));\
511 if(!token) {ucx_list_free(tokens); return NULL;} 526 if(!token) {ucx_list_free(tokens); return NULL;}
527 #define add_token tokens = dav_parse_add_token(tokens, token); \
528 if(!tokens) {return NULL;}
512 UcxList *tokens = NULL; 529 UcxList *tokens = NULL;
513 530
514 DavQLToken *token = NULL; 531 DavQLToken *token = NULL;
515 char insequence = '\0'; 532 char insequence = '\0';
516 for (size_t i = 0 ; i < src.length ; i++) { 533 for (size_t i = 0 ; i < src.length ; i++) {
523 token->value.length += 3; 540 token->value.length += 3;
524 i += 2; 541 i += 2;
525 } else { 542 } else {
526 // add quoted token to list 543 // add quoted token to list
527 token->value.length++; 544 token->value.length++;
528 tokens = dav_parse_add_token(tokens, token); 545 add_token
529 token = NULL; 546 token = NULL;
530 insequence = '\0'; 547 insequence = '\0';
531 } 548 }
532 } else if (insequence == '\0') { 549 } else if (insequence == '\0') {
533 insequence = src.ptr[i]; 550 insequence = src.ptr[i];
534 // always create new token for quoted strings 551 // always create new token for quoted strings
535 if (token) { 552 if (token) {
536 tokens = dav_parse_add_token(tokens, token); 553 add_token
537 } 554 }
538 alloc_token 555 alloc_token
539 token->value.ptr = src.ptr + i; 556 token->value.ptr = src.ptr + i;
540 token->value.length = 1; 557 token->value.length = 1;
541 } else { 558 } else {
545 } else if (insequence) { 562 } else if (insequence) {
546 token->value.length++; 563 token->value.length++;
547 } else if (isspace(src.ptr[i])) { 564 } else if (isspace(src.ptr[i])) {
548 // add token before spaces to list (if any) 565 // add token before spaces to list (if any)
549 if (token) { 566 if (token) {
550 tokens = dav_parse_add_token(tokens, token); 567 add_token
551 token = NULL; 568 token = NULL;
552 } 569 }
553 } else if (strchr(special_token_symbols, src.ptr[i])) { 570 } else if (strchr(special_token_symbols, src.ptr[i])) {
554 // add token before special symbol to list (if any) 571 // add token before special symbol to list (if any)
555 if (token) { 572 if (token) {
556 tokens = dav_parse_add_token(tokens, token); 573 add_token
557 token = NULL; 574 token = NULL;
558 } 575 }
559 // add special symbol as single token to list 576 // add special symbol as single token to list
560 alloc_token 577 alloc_token
561 token->value.ptr = src.ptr + i; 578 token->value.ptr = src.ptr + i;
562 token->value.length = 1; 579 token->value.length = 1;
563 tokens = dav_parse_add_token(tokens, token); 580 add_token
564 // set tokenizer ready to read more tokens 581 // set tokenizer ready to read more tokens
565 token = NULL; 582 token = NULL;
566 } else { 583 } else {
567 // if this is a new token, create memory for it 584 // if this is a new token, create memory for it
568 if (!token) { 585 if (!token) {
574 token->value.length++; 591 token->value.length++;
575 } 592 }
576 } 593 }
577 594
578 if (token) { 595 if (token) {
579 tokens = dav_parse_add_token(tokens, token); 596 add_token
580 } 597 }
581 598
582 alloc_token 599 alloc_token
583 token->tokenclass = DAVQL_TOKEN_END; 600 token->tokenclass = DAVQL_TOKEN_END;
584 token->value = S(""); 601 token->value = S("");
585 return ucx_list_append(tokens, token); 602 UcxList *ret = ucx_list_append(tokens, token);
603 if (ret) {
604 return ret;
605 } else {
606 ucx_list_free(tokens);
607 return NULL;
608 }
586 #undef alloc_token 609 #undef alloc_token
610 #undef add_token
587 } 611 }
588 612
589 static void dav_free_expression(DavQLExpression *expr) { 613 static void dav_free_expression(DavQLExpression *expr) {
590 if (expr) { 614 if (expr) {
591 if (expr->left) { 615 if (expr->left) {
966 DavQLField *field; 990 DavQLField *field;
967 dqlsec_malloc(stmt, field, DavQLField); 991 dqlsec_malloc(stmt, field, DavQLField);
968 dqlsec_mallocz(stmt, field->expr, DavQLExpression); 992 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
969 field->expr->type = DAVQL_IDENTIFIER; 993 field->expr->type = DAVQL_IDENTIFIER;
970 field->expr->srctext = field->name = token_sstr(token); 994 field->expr->srctext = field->name = token_sstr(token);
971 stmt->fields = ucx_list_append(stmt->fields, field); 995 dqlsec_list_append(stmt, stmt->fields, field);
972 return 1; 996 return 1;
973 } 997 }
974 998
975 // RULE: "*", {",", NamedExpression} 999 // RULE: "*", {",", NamedExpression}
976 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) { 1000 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) {
977 DavQLField *field; 1001 DavQLField *field;
978 dqlsec_malloc(stmt, field, DavQLField); 1002 dqlsec_malloc(stmt, field, DavQLField);
979 dqlsec_mallocz(stmt, field->expr, DavQLExpression); 1003 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
980 field->expr->type = DAVQL_IDENTIFIER; 1004 field->expr->type = DAVQL_IDENTIFIER;
981 field->expr->srctext = field->name = token_sstr(token); 1005 field->expr->srctext = field->name = token_sstr(token);
982 stmt->fields = ucx_list_append(stmt->fields, field); 1006 dqlsec_list_append(stmt, stmt->fields, field);
983 1007
984 int total_consumed = 0; 1008 int total_consumed = 0;
985 int consumed = 1; 1009 int consumed = 1;
986 1010
987 do { 1011 do {
994 consumed = dav_parse_named_field(stmt, token, &localfield); 1018 consumed = dav_parse_named_field(stmt, token, &localfield);
995 if (!stmt->errorcode && consumed) { 1019 if (!stmt->errorcode && consumed) {
996 DavQLField *field; 1020 DavQLField *field;
997 dqlsec_malloc(stmt, field, DavQLField); 1021 dqlsec_malloc(stmt, field, DavQLField);
998 memcpy(field, &localfield, sizeof(DavQLField)); 1022 memcpy(field, &localfield, sizeof(DavQLField));
999 stmt->fields = ucx_list_append(stmt->fields, field); 1023 dqlsec_list_append(stmt, stmt->fields, field);
1000 } 1024 }
1001 } else { 1025 } else {
1002 consumed = 0; 1026 consumed = 0;
1003 } 1027 }
1004 } while (consumed > 0); 1028 } while (consumed > 0);
1015 consumed = dav_parse_named_field(stmt, token, &localfield); 1039 consumed = dav_parse_named_field(stmt, token, &localfield);
1016 if (consumed) { 1040 if (consumed) {
1017 DavQLField *field; 1041 DavQLField *field;
1018 dqlsec_malloc(stmt, field, DavQLField); 1042 dqlsec_malloc(stmt, field, DavQLField);
1019 memcpy(field, &localfield, sizeof(DavQLField)); 1043 memcpy(field, &localfield, sizeof(DavQLField));
1020 stmt->fields = ucx_list_append(stmt->fields, field); 1044 dqlsec_list_append(stmt, stmt->fields, field);
1021 token = ucx_list_get(token, consumed); 1045 token = ucx_list_get(token, consumed);
1022 total_consumed += consumed; 1046 total_consumed += consumed;
1023 } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER) 1047 } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)
1024 // look ahead, if the field is JUST the identifier 1048 // look ahead, if the field is JUST the identifier
1025 && (token_is(token->next, DAVQL_TOKEN_COMMA) || 1049 && (token_is(token->next, DAVQL_TOKEN_COMMA) ||
1028 DavQLField *field; 1052 DavQLField *field;
1029 dqlsec_malloc(stmt, field, DavQLField); 1053 dqlsec_malloc(stmt, field, DavQLField);
1030 dqlsec_mallocz(stmt, field->expr, DavQLExpression); 1054 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
1031 field->expr->type = DAVQL_IDENTIFIER; 1055 field->expr->type = DAVQL_IDENTIFIER;
1032 field->expr->srctext = field->name = token_sstr(token); 1056 field->expr->srctext = field->name = token_sstr(token);
1033 stmt->fields = ucx_list_append(stmt->fields, field); 1057 dqlsec_list_append(stmt, stmt->fields, field);
1034 1058
1035 consumed = 1; 1059 consumed = 1;
1036 total_consumed++; 1060 total_consumed++;
1037 token = token->next; 1061 token = token->next;
1038 1062
1412 total_consumed += consumed; 1436 total_consumed += consumed;
1413 1437
1414 DavQLOrderCriterion *criterion; 1438 DavQLOrderCriterion *criterion;
1415 dqlsec_malloc(stmt, criterion, DavQLOrderCriterion); 1439 dqlsec_malloc(stmt, criterion, DavQLOrderCriterion);
1416 memcpy(criterion, &crit, sizeof(DavQLOrderCriterion)); 1440 memcpy(criterion, &crit, sizeof(DavQLOrderCriterion));
1417 stmt->orderby = ucx_list_append(stmt->orderby, criterion); 1441 dqlsec_list_append(stmt, stmt->orderby, criterion);
1418 1442
1419 if (token_is(token, DAVQL_TOKEN_COMMA)) { 1443 if (token_is(token, DAVQL_TOKEN_COMMA)) {
1420 total_consumed++; 1444 total_consumed++;
1421 token = token->next; 1445 token = token->next;
1422 } else { 1446 } else {
1553 stmt->depth = 1; 1577 stmt->depth = 1;
1554 1578
1555 // save trimmed source text 1579 // save trimmed source text
1556 stmt->srctext = sstrtrim(srctext); 1580 stmt->srctext = sstrtrim(srctext);
1557 1581
1558 // tokenization 1582 if (stmt->srctext.length) {
1559 UcxList* tokens = dav_parse_tokenize(stmt->srctext); 1583 // tokenization
1560 1584 UcxList* tokens = dav_parse_tokenize(stmt->srctext);
1561 if (tokens) { 1585
1562 // use first token to determine query type 1586 if (tokens) {
1563 1587 // use first token to determine query type
1564 if (tokenvalue_is(tokens, "select")) { 1588
1565 dav_parse_select_statement(stmt, tokens->next); 1589 if (tokenvalue_is(tokens, "select")) {
1566 } else if (tokenvalue_is(tokens, "set")) { 1590 dav_parse_select_statement(stmt, tokens->next);
1567 dav_parse_set_statement(stmt, tokens->next); 1591 } else if (tokenvalue_is(tokens, "set")) {
1592 dav_parse_set_statement(stmt, tokens->next);
1593 } else {
1594 stmt->type = DAVQL_ERROR;
1595 stmt->errorcode = DAVQL_ERROR_INVALID;
1596 stmt->errormessage = strdup(_error_invalid);
1597 }
1598
1599 // free token data
1600 UCX_FOREACH(token, tokens) {
1601 free(token->data);
1602 }
1603 ucx_list_free(tokens);
1568 } else { 1604 } else {
1569 stmt->type = DAVQL_ERROR; 1605 stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
1570 stmt->errorcode = DAVQL_ERROR_INVALID; 1606 }
1571 stmt->errormessage = strdup(_error_invalid);
1572 }
1573
1574 // free token data
1575 UCX_FOREACH(token, tokens) {
1576 free(token->data);
1577 }
1578 ucx_list_free(tokens);
1579 } else { 1607 } else {
1580 stmt->type = DAVQL_ERROR; 1608 stmt->type = DAVQL_ERROR;
1581 stmt->errorcode = DAVQL_ERROR_INVALID; 1609 stmt->errorcode = DAVQL_ERROR_INVALID;
1582 stmt->errormessage = strdup(_error_invalid); 1610 stmt->errormessage = strdup(_error_invalid);
1583 } 1611 }

mercurial