247 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" |
247 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" |
248 #define _expected_token "expected token '%s' before '%.*s'" |
248 #define _expected_token "expected token '%s' before '%.*s'" |
249 #define _missing_quote "missing closing quote symbol (%.*s)" |
249 #define _missing_quote "missing closing quote symbol (%.*s)" |
250 #define _parser_state "parser reached invalid state" |
250 #define _parser_state "parser reached invalid state" |
251 #define _unknown_attribute "unknown attribute '%.*s'" |
251 #define _unknown_attribute "unknown attribute '%.*s'" |
|
252 #define _duplicated_attribute "duplicated attribute '%.*s'" |
252 #define _invalid_depth "invalid depth" |
253 #define _invalid_depth "invalid depth" |
253 |
254 |
254 static UcxList* dav_parse_tokenize(sstr_t src) { |
255 static UcxList* dav_parse_tokenize(sstr_t src) { |
255 UcxList *tokens = NULL; |
256 UcxList *tokens = NULL; |
256 |
257 |
406 sfmtarg(*token_sstr(token)), |
407 sfmtarg(*token_sstr(token)), |
407 sfmtarg(token->next?*token_sstr(token->next):emptystring)); |
408 sfmtarg(token->next?*token_sstr(token->next):emptystring)); |
408 stmt->errormessage = errormsg.ptr; |
409 stmt->errormessage = errormsg.ptr; |
409 } |
410 } |
410 |
411 |
|
412 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) { |
|
413 sstr_t tokendata = *token_sstr(token); |
|
414 /* |
|
415 * 0: key |
|
416 * 1: = |
|
417 * 2: value |
|
418 * TODO: commas |
|
419 */ |
|
420 static int parsestate = 0; |
|
421 |
|
422 /* |
|
423 * 1: depth |
|
424 */ |
|
425 int key = 0; |
|
426 static int keymask = 0; |
|
427 |
|
428 switch (parsestate) { |
|
429 case 0: |
|
430 if (!sstrcasecmp(tokendata, S("depth"))) { |
|
431 key = 1; |
|
432 parsestate = 1; |
|
433 } else { |
|
434 stmt->errorcode = DAVQL_ERROR_UNKNOWN_ATTRIBUTE; |
|
435 stmt->errormessage = ucx_sprintf(_unknown_attribute, |
|
436 sfmtarg(tokendata)).ptr; |
|
437 break; |
|
438 } |
|
439 if (keymask & key) { |
|
440 stmt->errorcode = DAVQL_ERROR_DUPLICATED_ATTRIBUTE; |
|
441 stmt->errormessage = ucx_sprintf(_duplicated_attribute, |
|
442 sfmtarg(tokendata)).ptr; |
|
443 } else { |
|
444 keymask |= key; |
|
445 } |
|
446 return 0; |
|
447 case 1: |
|
448 if (sstrcmp(tokendata, S("="))) { |
|
449 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
|
450 stmt->errormessage = ucx_sprintf(_expected_token, |
|
451 "=", sfmtarg(tokendata)).ptr; |
|
452 } else { |
|
453 parsestate = 2; |
|
454 } |
|
455 return 0; |
|
456 case 2: |
|
457 switch (key) { |
|
458 case 1: /* depth */ |
|
459 if (!sstrcasecmp(tokendata, S("infinity"))) { |
|
460 stmt->depth = DAV_DEPTH_INFINITY; |
|
461 } else { |
|
462 char *conv = malloc(tokendata.length+1); |
|
463 char *chk; |
|
464 memcpy(conv, tokendata.ptr, tokendata.length); |
|
465 conv[tokendata.length] = '\0'; |
|
466 stmt->depth = strtol(conv, &chk, 10); |
|
467 if (*chk || stmt->depth < -1) { |
|
468 stmt->errorcode = DAVQL_ERROR_INVALID_DEPTH; |
|
469 stmt->errormessage = strdup(_invalid_depth); |
|
470 } |
|
471 free(conv); |
|
472 } |
|
473 break; |
|
474 } |
|
475 parsestate = 0; |
|
476 return 1; |
|
477 default: |
|
478 return -1; |
|
479 } |
|
480 } |
|
481 |
411 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
482 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
412 stmt->type = DAVQL_GET; |
483 stmt->type = DAVQL_GET; |
413 |
484 |
414 /* |
485 /* |
415 * 10: field list |
486 * 10: field list |
416 * 20: FROM clause |
487 * 20: FROM clause |
417 * 530: expecting WHERE or WITH clause |
488 * 530: expecting WHERE or WITH clause |
418 * 30: WHERE clause |
489 * 30: WHERE clause |
419 * 540: expecting WITH clause |
490 * 540: expecting WITH clause |
|
491 * 541: expecting comma for WITH clause |
420 * 40: WITH clause |
492 * 40: WITH clause |
421 * 500: expect end |
493 * 500: expect end |
422 * |
494 * |
423 */ |
495 */ |
424 int step = 10; |
496 int step = 10; |
446 step = 30; |
518 step = 30; |
447 } |
519 } |
448 /* no break and no else*/ |
520 /* no break and no else*/ |
449 case 540: |
521 case 540: |
450 if (!sstrcasecmp(tokendata, S("with"))) { |
522 if (!sstrcasecmp(tokendata, S("with"))) { |
|
523 step = 40; |
|
524 } else { |
|
525 dav_parse_unexpected_token(stmt, token); |
|
526 goto ultrabreak; |
|
527 } |
|
528 break; |
|
529 case 541: |
|
530 if (!sstrcmp(tokendata, S(","))) { |
451 step = 40; |
531 step = 40; |
452 } else { |
532 } else { |
453 dav_parse_unexpected_token(stmt, token); |
533 dav_parse_unexpected_token(stmt, token); |
454 goto ultrabreak; |
534 goto ultrabreak; |
455 } |
535 } |
493 case 30: |
573 case 30: |
494 step = 540; |
574 step = 540; |
495 break; |
575 break; |
496 // with clause |
576 // with clause |
497 case 40: { |
577 case 40: { |
498 /* |
578 int withclause_result = dav_parse_with_clause(stmt, token); |
499 * 0: key |
579 if (withclause_result < 0) { |
500 * 1: = |
580 stmt->errorcode = DAVQL_ERROR_INVALID; |
501 * 2: value |
581 stmt->errormessage = strdup(_parser_state); |
502 * TODO: commas |
582 } else if (withclause_result > 0) { |
503 */ |
583 step = 541; |
504 static int withparser = 0; |
|
505 |
|
506 /* |
|
507 * 1: depth |
|
508 */ |
|
509 int key; |
|
510 |
|
511 switch (withparser) { |
|
512 case 0: |
|
513 if (!sstrcasecmp(tokendata, S("depth"))) { |
|
514 key = 1; |
|
515 withparser = 1; |
|
516 } else { |
|
517 stmt->errorcode = DAVQL_ERROR_UNKNOWN_ATTRIBUTE; |
|
518 stmt->errormessage = ucx_sprintf(_unknown_attribute, |
|
519 sfmtarg(tokendata)).ptr; |
|
520 } |
|
521 break; |
|
522 case 1: |
|
523 if (sstrcmp(tokendata, S("="))) { |
|
524 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
|
525 stmt->errormessage = ucx_sprintf(_expected_token, |
|
526 "=", sfmtarg(tokendata)).ptr; |
|
527 } else { |
|
528 withparser = 2; |
|
529 } |
|
530 break; |
|
531 case 2: |
|
532 switch (key) { |
|
533 case 1: /* depth */ |
|
534 if (!sstrcasecmp(tokendata, S("infinity"))) { |
|
535 stmt->depth = DAV_DEPTH_INFINITY; |
|
536 } else { |
|
537 char *conv = malloc(tokendata.length+1); |
|
538 char *chk; |
|
539 memcpy(conv, tokendata.ptr, tokendata.length); |
|
540 conv[tokendata.length] = '\0'; |
|
541 stmt->depth = strtol(conv, &chk, 10); |
|
542 if (*chk || stmt->depth < -1) { |
|
543 stmt->errorcode = DAVQL_ERROR_INVALID_DEPTH; |
|
544 stmt->errormessage = strdup(_invalid_depth); |
|
545 } |
|
546 free(conv); |
|
547 } |
|
548 break; |
|
549 } |
|
550 step = 500; |
|
551 break; |
|
552 } |
584 } |
553 break; |
585 break; |
554 } |
586 } |
555 default: |
587 default: |
556 stmt->errorcode = DAVQL_ERROR_INVALID; |
588 stmt->errorcode = DAVQL_ERROR_INVALID; |