1/** \file 2 * This C source file was generated by $ANTLR version 3.2 debian-5 3 * 4 * - From the grammar source file : DAAP2SQL.g 5 * - On : 2011-09-11 15:48:50 6 * - for the tree parser : DAAP2SQLTreeParser * 7 * Editing it, at least manually, is not wise. 8 * 9 * C language generator and runtime by Jim Idle, jimi|hereisanat|idle|dotgoeshere|ws. 10 * 11 * 12*/ 13// [The "BSD licence"] 14// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC 15// http://www.temporal-wave.com 16// http://www.linkedin.com/in/jimidle 17// 18// All rights reserved. 19// 20// Redistribution and use in source and binary forms, with or without 21// modification, are permitted provided that the following conditions 22// are met: 23// 1. Redistributions of source code must retain the above copyright 24// notice, this list of conditions and the following disclaimer. 25// 2. Redistributions in binary form must reproduce the above copyright 26// notice, this list of conditions and the following disclaimer in the 27// documentation and/or other materials provided with the distribution. 28// 3. The name of the author may not be used to endorse or promote products 29// derived from this software without specific prior written permission. 30// 31// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 32// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 34// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 35// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 42 43/* ============================================================================= 44 * This is what the grammar programmer asked us to put at the top of every file. 45 */ 46 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <limits.h> 51 #include <errno.h> 52 53 #include "logger.h" 54 #include "db.h" 55 #include "daap_query.h" 56 57/* End of Header action. 58 * ============================================================================= 59 */ 60/* ----------------------------------------- 61 * Include the ANTLR3 generated header file. 62 */ 63#include "DAAP2SQL.h" 64/* ----------------------------------------- */ 65 66 67 68 69 70/* MACROS that hide the C interface implementations from the 71 * generated code, which makes it a little more understandable to the human eye. 72 * I am very much against using C pre-processor macros for function calls and bits 73 * of code as you cannot see what is happening when single stepping in debuggers 74 * and so on. The exception (in my book at least) is for generated code, where you are 75 * not maintaining it, but may wish to read and understand it. If you single step it, you know that input() 76 * hides some indirect calls, but is always referring to the input stream. This is 77 * probably more readable than ctx->input->istream->input(snarfle0->blarg) and allows me to rejig 78 * the runtime interfaces without changing the generated code too often, without 79 * confusing the reader of the generated output, who may not wish to know the gory 80 * details of the interface inheritance. 81 */ 82 83#define CTX ctx 84 85/* Aids in accessing scopes for grammar programmers 86 */ 87#undef SCOPE_TYPE 88#undef SCOPE_STACK 89#undef SCOPE_TOP 90#define SCOPE_TYPE(scope) pDAAP2SQL_##scope##_SCOPE 91#define SCOPE_STACK(scope) pDAAP2SQL_##scope##Stack 92#define SCOPE_TOP(scope) ctx->pDAAP2SQL_##scope##Top 93#define SCOPE_SIZE(scope) ctx->pDAAP2SQL_##scope##Stack_limit 94#define SCOPE_INSTANCE(scope, i) (ctx->SCOPE_STACK(scope)->get(ctx->SCOPE_STACK(scope),i)) 95 96/* Macros for accessing things in the parser 97 */ 98 99#undef PARSER 100#undef RECOGNIZER 101#undef HAVEPARSEDRULE 102#undef INPUT 103#undef STRSTREAM 104#undef HASEXCEPTION 105#undef EXCEPTION 106#undef MATCHT 107#undef MATCHANYT 108#undef FOLLOWSTACK 109#undef FOLLOWPUSH 110#undef FOLLOWPOP 111#undef PRECOVER 112#undef PREPORTERROR 113#undef LA 114#undef LT 115#undef CONSTRUCTEX 116#undef CONSUME 117#undef MARK 118#undef REWIND 119#undef REWINDLAST 120#undef PERRORRECOVERY 121#undef HASFAILED 122#undef FAILEDFLAG 123#undef RECOVERFROMMISMATCHEDSET 124#undef RECOVERFROMMISMATCHEDELEMENT 125#undef BACKTRACKING 126#undef ADAPTOR 127#undef RULEMEMO 128#undef SEEK 129#undef INDEX 130#undef DBG 131 132#define PARSER ctx->pTreeParser 133#define RECOGNIZER PARSER->rec 134#define PSRSTATE RECOGNIZER->state 135#define HAVEPARSEDRULE(r) RECOGNIZER->alreadyParsedRule(RECOGNIZER, r) 136#define INPUT PARSER->ctnstream 137#define ISTREAM INPUT->tnstream->istream 138#define STRSTREAM INPUT->tnstream 139#define HASEXCEPTION() (PSRSTATE->error == ANTLR3_TRUE) 140#define EXCEPTION PSRSTATE->exception 141#define MATCHT(t, fs) RECOGNIZER->match(RECOGNIZER, t, fs) 142#define MATCHANYT() RECOGNIZER->matchAny(RECOGNIZER) 143#define FOLLOWSTACK PSRSTATE->following 144#define FOLLOWPUSH(x) FOLLOWSTACK->push(FOLLOWSTACK, ((void *)(&(x))), NULL) 145#define FOLLOWPOP() FOLLOWSTACK->pop(FOLLOWSTACK) 146#define PRECOVER() RECOGNIZER->recover(RECOGNIZER) 147#define PREPORTERROR() RECOGNIZER->reportError(RECOGNIZER) 148#define LA(n) ISTREAM->_LA(ISTREAM, n) 149#define LT(n) INPUT->tnstream->_LT(INPUT->tnstream, n) 150#define CONSTRUCTEX() RECOGNIZER->exConstruct(RECOGNIZER) 151#define CONSUME() ISTREAM->consume(ISTREAM) 152#define MARK() ISTREAM->mark(ISTREAM) 153#define REWIND(m) ISTREAM->rewind(ISTREAM, m) 154#define REWINDLAST() ISTREAM->rewindLast(ISTREAM) 155#define PERRORRECOVERY PSRSTATE->errorRecovery 156#define FAILEDFLAG PSRSTATE->failed 157#define HASFAILED() (FAILEDFLAG == ANTLR3_TRUE) 158#define BACKTRACKING PSRSTATE->backtracking 159#define RECOVERFROMMISMATCHEDSET(s) RECOGNIZER->recoverFromMismatchedSet(RECOGNIZER, s) 160#define RECOVERFROMMISMATCHEDELEMENT(e) RECOGNIZER->recoverFromMismatchedElement(RECOGNIZER, s) 161#define ADAPTOR INPUT->adaptor 162#define RULEMEMO PSRSTATE->ruleMemo 163#define SEEK(n) ISTREAM->seek(ISTREAM, n) 164#define INDEX() ISTREAM->index(ISTREAM) 165#define DBG RECOGNIZER->debugger 166 167 168#define TOKTEXT(tok, txt) tok, (pANTLR3_UINT8)txt 169 170/* The 4 tokens defined below may well clash with your own #defines or token types. If so 171 * then for the present you must use different names for your defines as these are hard coded 172 * in the code generator. It would be better not to use such names internally, and maybe 173 * we can change this in a forthcoming release. I deliberately do not #undef these 174 * here as this will at least give you a redefined error somewhere if they clash. 175 */ 176#define UP ANTLR3_TOKEN_UP 177#define DOWN ANTLR3_TOKEN_DOWN 178#define EOR ANTLR3_TOKEN_EOR 179#define INVALID ANTLR3_TOKEN_INVALID 180 181 182/* ============================================================================= 183 * Functions to create and destroy scopes. First come the rule scopes, followed 184 * by the global declared scopes. 185 */ 186 187 188 189/* ============================================================================= */ 190 191/* ============================================================================= 192 * Start of recognizer 193 */ 194 195 196 197/** \brief Table of all token names in symbolic order, mainly used for 198 * error reporting. 199 */ 200pANTLR3_UINT8 DAAP2SQLTokenNames[8+4] 201 = { 202 (pANTLR3_UINT8) "<invalid>", /* String to print to indicate an invalid token */ 203 (pANTLR3_UINT8) "<EOR>", 204 (pANTLR3_UINT8) "<DOWN>", 205 (pANTLR3_UINT8) "<UP>", 206 (pANTLR3_UINT8) "NEWLINE", 207 (pANTLR3_UINT8) "OPOR", 208 (pANTLR3_UINT8) "OPAND", 209 (pANTLR3_UINT8) "LPAR", 210 (pANTLR3_UINT8) "RPAR", 211 (pANTLR3_UINT8) "STR", 212 (pANTLR3_UINT8) "QUOTE", 213 (pANTLR3_UINT8) "ESCAPED" 214 }; 215 216 217 218// Forward declare the locally static matching functions we have generated. 219// 220static pANTLR3_STRING query (pDAAP2SQL ctx); 221static DAAP2SQL_expr_return expr (pDAAP2SQL ctx); 222static void DAAP2SQLFree(pDAAP2SQL ctx); 223/* For use in tree output where we are accumulating rule labels via label += ruleRef 224 * we need a function that knows how to free a return scope when the list is destroyed. 225 * We cannot just use ANTLR3_FREE because in debug tracking mode, this is a macro. 226 */ 227static void ANTLR3_CDECL freeScope(void * scope) 228{ 229 ANTLR3_FREE(scope); 230} 231 232/** \brief Name of the grammar file that generated this code 233 */ 234static const char fileName[] = "DAAP2SQL.g"; 235 236/** \brief Return the name of the grammar file that generated this code. 237 */ 238static const char * getGrammarFileName() 239{ 240 return fileName; 241} 242/** \brief Create a new DAAP2SQL parser and return a context for it. 243 * 244 * \param[in] instream Pointer to an input stream interface. 245 * 246 * \return Pointer to new parser context upon success. 247 */ 248ANTLR3_API pDAAP2SQL 249DAAP2SQLNew (pANTLR3_COMMON_TREE_NODE_STREAM instream) 250{ 251 // See if we can create a new parser with the standard constructor 252 // 253 return DAAP2SQLNewSSD(instream, NULL); 254} 255 256/** \brief Create a new DAAP2SQL parser and return a context for it. 257 * 258 * \param[in] instream Pointer to an input stream interface. 259 * 260 * \return Pointer to new parser context upon success. 261 */ 262ANTLR3_API pDAAP2SQL 263DAAP2SQLNewSSD (pANTLR3_COMMON_TREE_NODE_STREAM instream, pANTLR3_RECOGNIZER_SHARED_STATE state) 264{ 265 pDAAP2SQL ctx; /* Context structure we will build and return */ 266 267 ctx = (pDAAP2SQL) ANTLR3_CALLOC(1, sizeof(DAAP2SQL)); 268 269 if (ctx == NULL) 270 { 271 // Failed to allocate memory for parser context 272 // 273 return NULL; 274 } 275 276 /* ------------------------------------------------------------------- 277 * Memory for basic structure is allocated, now to fill in 278 * the base ANTLR3 structures. We initialize the function pointers 279 * for the standard ANTLR3 parser function set, but upon return 280 * from here, the programmer may set the pointers to provide custom 281 * implementations of each function. 282 * 283 * We don't use the macros defined in DAAP2SQL.h here, in order that you can get a sense 284 * of what goes where. 285 */ 286 287 /* Create a base Tree parser/recognizer, using the supplied tree node stream 288 */ 289 ctx->pTreeParser = antlr3TreeParserNewStream(ANTLR3_SIZE_HINT, instream, state); 290 /* Install the implementation of our DAAP2SQL interface 291 */ 292 ctx->query = query; 293 ctx->expr = expr; 294 ctx->free = DAAP2SQLFree; 295 ctx->getGrammarFileName = getGrammarFileName; 296 297 /* Install the scope pushing methods. 298 */ 299 300 301 302 303 304 /* Install the token table 305 */ 306 PSRSTATE->tokenNames = DAAP2SQLTokenNames; 307 308 309 /* Return the newly built parser to the caller 310 */ 311 return ctx; 312} 313 314/** Free the parser resources 315 */ 316 static void 317 DAAP2SQLFree(pDAAP2SQL ctx) 318 { 319 /* Free any scope memory 320 */ 321 322 323 // Free this parser 324 // 325 ctx->pTreeParser->free(ctx->pTreeParser); 326 ANTLR3_FREE(ctx); 327 328 /* Everything is released, so we can return 329 */ 330 return; 331 } 332 333/** Return token names used by this tree parser 334 * 335 * The returned pointer is used as an index into the token names table (using the token 336 * number as the index). 337 * 338 * \return Pointer to first char * in the table. 339 */ 340static pANTLR3_UINT8 *getTokenNames() 341{ 342 return DAAP2SQLTokenNames; 343} 344 345 346 struct dmap_query_field_map { 347 char *dmap_field; 348 char *db_col; 349 int as_int; 350 }; 351 352 /* gperf static hash, daap_query.gperf */ 353 #include "daap_query_hash.c" 354 355 356/* Declare the bitsets 357 */ 358 359/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_query70 */ 360static ANTLR3_BITWORD FOLLOW_expr_in_query70_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000002) }; 361static ANTLR3_BITSET_LIST FOLLOW_expr_in_query70 = { FOLLOW_expr_in_query70_bits, 1 }; 362/** Bitset defining follow set for error recovery in rule state: FOLLOW_OPAND_in_expr95 */ 363static ANTLR3_BITWORD FOLLOW_OPAND_in_expr95_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000004) }; 364static ANTLR3_BITSET_LIST FOLLOW_OPAND_in_expr95 = { FOLLOW_OPAND_in_expr95_bits, 1 }; 365/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr101 */ 366static ANTLR3_BITWORD FOLLOW_expr_in_expr101_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000260) }; 367static ANTLR3_BITSET_LIST FOLLOW_expr_in_expr101 = { FOLLOW_expr_in_expr101_bits, 1 }; 368/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr107 */ 369static ANTLR3_BITWORD FOLLOW_expr_in_expr107_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000008) }; 370static ANTLR3_BITSET_LIST FOLLOW_expr_in_expr107 = { FOLLOW_expr_in_expr107_bits, 1 }; 371/** Bitset defining follow set for error recovery in rule state: FOLLOW_OPOR_in_expr118 */ 372static ANTLR3_BITWORD FOLLOW_OPOR_in_expr118_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000004) }; 373static ANTLR3_BITSET_LIST FOLLOW_OPOR_in_expr118 = { FOLLOW_OPOR_in_expr118_bits, 1 }; 374/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr124 */ 375static ANTLR3_BITWORD FOLLOW_expr_in_expr124_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000260) }; 376static ANTLR3_BITSET_LIST FOLLOW_expr_in_expr124 = { FOLLOW_expr_in_expr124_bits, 1 }; 377/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr130 */ 378static ANTLR3_BITWORD FOLLOW_expr_in_expr130_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000008) }; 379static ANTLR3_BITSET_LIST FOLLOW_expr_in_expr130 = { FOLLOW_expr_in_expr130_bits, 1 }; 380/** Bitset defining follow set for error recovery in rule state: FOLLOW_STR_in_expr140 */ 381static ANTLR3_BITWORD FOLLOW_STR_in_expr140_bits[] = { ANTLR3_UINT64_LIT(0x0000000000000002) }; 382static ANTLR3_BITSET_LIST FOLLOW_STR_in_expr140 = { FOLLOW_STR_in_expr140_bits, 1 }; 383 384 385 386 387/* ============================================== 388 * Parsing rules 389 */ 390/** 391 * $ANTLR start query 392 * DAAP2SQL.g:50:1: query returns [ pANTLR3_STRING result ] : e= expr ; 393 */ 394static pANTLR3_STRING 395query(pDAAP2SQL ctx) 396{ 397 pANTLR3_STRING result = NULL; 398 399 DAAP2SQL_expr_return e; 400 #undef RETURN_TYPE_e 401 #define RETURN_TYPE_e DAAP2SQL_expr_return 402 403 /* Initialize rule variables 404 */ 405 406 407 result= NULL; 408 { 409 // DAAP2SQL.g:52:2: (e= expr ) 410 // DAAP2SQL.g:52:4: e= expr 411 { 412 FOLLOWPUSH(FOLLOW_expr_in_query70); 413 e=expr(ctx); 414 415 FOLLOWPOP(); 416 if (HASEXCEPTION()) 417 { 418 goto rulequeryEx; 419 } 420 421 { 422 423 if (!e.valid) 424 { 425 result= NULL; 426 } 427 else 428 { 429 result= e.result->factory->newRaw(e.result->factory); 430 result->append8(result, "("); 431 result->appendS(result, e.result); 432 result->append8(result, ")"); 433 } 434 435 } 436 437 } 438 439 } 440 441 442 // This is where rules clean up and exit 443 // 444 goto rulequeryEx; /* Prevent compiler warnings */ 445 rulequeryEx: ; 446 447 if (HASEXCEPTION()) 448 { 449 PREPORTERROR(); 450 PRECOVER(); 451 } 452 453 454 return result; 455} 456/* $ANTLR end query */ 457 458/** 459 * $ANTLR start expr 460 * DAAP2SQL.g:68:1: expr returns [ pANTLR3_STRING result, int valid ] : ( ^( OPAND a= expr b= expr ) | ^( OPOR a= expr b= expr ) | STR ); 461 */ 462static DAAP2SQL_expr_return 463expr(pDAAP2SQL ctx) 464{ 465 DAAP2SQL_expr_return retval; 466 467 pANTLR3_BASE_TREE STR1; 468 DAAP2SQL_expr_return a; 469 #undef RETURN_TYPE_a 470 #define RETURN_TYPE_a DAAP2SQL_expr_return 471 472 DAAP2SQL_expr_return b; 473 #undef RETURN_TYPE_b 474 #define RETURN_TYPE_b DAAP2SQL_expr_return 475 476 /* Initialize rule variables 477 */ 478 479 480 retval.result= NULL; retval.valid= 1; 481 STR1 = NULL; 482 retval.start = LT(1); retval.stop = retval.start; 483 484 { 485 { 486 // DAAP2SQL.g:70:2: ( ^( OPAND a= expr b= expr ) | ^( OPOR a= expr b= expr ) | STR ) 487 488 ANTLR3_UINT32 alt1; 489 490 alt1=3; 491 492 switch ( LA(1) ) 493 { 494 case OPAND: 495 { 496 alt1=1; 497 } 498 break; 499 case OPOR: 500 { 501 alt1=2; 502 } 503 break; 504 case STR: 505 { 506 alt1=3; 507 } 508 break; 509 510 default: 511 CONSTRUCTEX(); 512 EXCEPTION->type = ANTLR3_NO_VIABLE_ALT_EXCEPTION; 513 EXCEPTION->message = (void *)""; 514 EXCEPTION->decisionNum = 1; 515 EXCEPTION->state = 0; 516 517 518 goto ruleexprEx; 519 } 520 521 switch (alt1) 522 { 523 case 1: 524 // DAAP2SQL.g:70:4: ^( OPAND a= expr b= expr ) 525 { 526 MATCHT(OPAND, &FOLLOW_OPAND_in_expr95); 527 if (HASEXCEPTION()) 528 { 529 goto ruleexprEx; 530 } 531 532 533 MATCHT(ANTLR3_TOKEN_DOWN, NULL); 534 if (HASEXCEPTION()) 535 { 536 goto ruleexprEx; 537 } 538 539 FOLLOWPUSH(FOLLOW_expr_in_expr101); 540 a=expr(ctx); 541 542 FOLLOWPOP(); 543 if (HASEXCEPTION()) 544 { 545 goto ruleexprEx; 546 } 547 548 FOLLOWPUSH(FOLLOW_expr_in_expr107); 549 b=expr(ctx); 550 551 FOLLOWPOP(); 552 if (HASEXCEPTION()) 553 { 554 goto ruleexprEx; 555 } 556 557 558 MATCHT(ANTLR3_TOKEN_UP, NULL); 559 if (HASEXCEPTION()) 560 { 561 goto ruleexprEx; 562 } 563 564 { 565 566 if (!a.valid || !b.valid) 567 { 568 retval.valid= 0; 569 } 570 else 571 { 572 retval.result= a.result->factory->newRaw(a.result->factory); 573 retval.result->append8(retval.result, "("); 574 retval.result->appendS(retval.result, a.result); 575 retval.result->append8(retval.result, " AND "); 576 retval.result->appendS(retval.result, b.result); 577 retval.result->append8(retval.result, ")"); 578 } 579 580 } 581 582 } 583 break; 584 case 2: 585 // DAAP2SQL.g:86:4: ^( OPOR a= expr b= expr ) 586 { 587 MATCHT(OPOR, &FOLLOW_OPOR_in_expr118); 588 if (HASEXCEPTION()) 589 { 590 goto ruleexprEx; 591 } 592 593 594 MATCHT(ANTLR3_TOKEN_DOWN, NULL); 595 if (HASEXCEPTION()) 596 { 597 goto ruleexprEx; 598 } 599 600 FOLLOWPUSH(FOLLOW_expr_in_expr124); 601 a=expr(ctx); 602 603 FOLLOWPOP(); 604 if (HASEXCEPTION()) 605 { 606 goto ruleexprEx; 607 } 608 609 FOLLOWPUSH(FOLLOW_expr_in_expr130); 610 b=expr(ctx); 611 612 FOLLOWPOP(); 613 if (HASEXCEPTION()) 614 { 615 goto ruleexprEx; 616 } 617 618 619 MATCHT(ANTLR3_TOKEN_UP, NULL); 620 if (HASEXCEPTION()) 621 { 622 goto ruleexprEx; 623 } 624 625 { 626 627 if (!a.valid || !b.valid) 628 { 629 retval.valid= 0; 630 } 631 else 632 { 633 retval.result= a.result->factory->newRaw(a.result->factory); 634 retval.result->append8(retval.result, "("); 635 retval.result->appendS(retval.result, a.result); 636 retval.result->append8(retval.result, " OR "); 637 retval.result->appendS(retval.result, b.result); 638 retval.result->append8(retval.result, ")"); 639 } 640 641 } 642 643 } 644 break; 645 case 3: 646 // DAAP2SQL.g:102:4: STR 647 { 648 STR1 = (pANTLR3_BASE_TREE) MATCHT(STR, &FOLLOW_STR_in_expr140); 649 if (HASEXCEPTION()) 650 { 651 goto ruleexprEx; 652 } 653 654 { 655 656 pANTLR3_STRING str; 657 pANTLR3_UINT8 field; 658 pANTLR3_UINT8 val; 659 pANTLR3_UINT8 escaped; 660 ANTLR3_UINT8 op; 661 int neg_op; 662 const struct dmap_query_field_map *dqfm; 663 char *end; 664 long long llval; 665 666 escaped = NULL; 667 668 retval.result= (STR1->getText(STR1))->factory->newRaw((STR1->getText(STR1))->factory); 669 670 str = (STR1->getText(STR1))->toUTF8((STR1->getText(STR1))); 671 672 /* NOTE: the lexer delivers the string without quotes 673 which may not be obvious from the grammar due to embedded code 674 */ 675 676 /* Make daap.songalbumid:0 a no-op */ 677 if (strcmp((char *)str->chars, "daap.songalbumid:0") == 0) 678 { 679 retval.result->append8(retval.result, "1 = 1"); 680 681 goto STR_out; 682 } 683 684 field = str->chars; 685 686 val = field; 687 while ((*val != '\0') && ((*val == '.') 688 || (*val == '-') 689 || ((*val >= 'a') && (*val <= 'z')) 690 || ((*val >= 'A') && (*val <= 'Z')) 691 || ((*val >= '0') && (*val <= '9')))) 692 { 693 val++; 694 } 695 696 if (*field == '\0') 697 { 698 DPRINTF(E_LOG, L_DAAP, "No field name found in clause '%s'\n", field); 699 retval.valid= 0; 700 goto STR_result_valid_0; /* ABORT */ 701 } 702 703 if (*val == '\0') 704 { 705 DPRINTF(E_LOG, L_DAAP, "No operator found in clause '%s'\n", field); 706 retval.valid= 0; 707 goto STR_result_valid_0; /* ABORT */ 708 } 709 710 op = *val; 711 *val = '\0'; 712 val++; 713 714 if (op == '!') 715 { 716 if (*val == '\0') 717 { 718 DPRINTF(E_LOG, L_DAAP, "Negation found but operator missing in clause '%s%c'\n", field, op); 719 retval.valid= 0; 720 goto STR_result_valid_0; /* ABORT */ 721 } 722 723 neg_op = 1; 724 op = *val; 725 val++; 726 } 727 else 728 neg_op = 0; 729 730 /* Lookup DMAP field in the query field map */ 731 dqfm = daap_query_field_lookup((char *)field, strlen((char *)field)); 732 if (!dqfm) 733 { 734 DPRINTF(E_LOG, L_DAAP, "DMAP field '%s' is not a valid field in queries\n", field); 735 retval.valid= 0; 736 goto STR_result_valid_0; /* ABORT */ 737 } 738 739 /* Empty values OK for string fields, NOK for integer */ 740 if (*val == '\0') 741 { 742 if (dqfm->as_int) 743 { 744 DPRINTF(E_LOG, L_DAAP, "No value given in clause '%s%s%c'\n", field, (neg_op) ? "!" : "", op); 745 retval.valid= 0; 746 goto STR_result_valid_0; /* ABORT */ 747 } 748 749 /* Need to check against NULL too */ 750 if (op == ':') 751 retval.result->append8(retval.result, "("); 752 } 753 754 retval.result->append8(retval.result, dqfm->db_col); 755 756 /* Int field: check integer conversion */ 757 if (dqfm->as_int) 758 { 759 errno = 0; 760 llval = strtoll((const char *)val, &end, 10); 761 762 763 if (((errno == ERANGE) && ((llval == LLONG_MAX) || (llval == LLONG_MIN))) 764 || ((errno != 0) && (llval == 0))) 765 { 766 DPRINTF(E_LOG, L_DAAP, "Value '%s' in clause '%s%s%c%s' does not convert to an integer type\n", 767 val, field, (neg_op) ? "!" : "", op, val); 768 retval.valid= 0; 769 goto STR_result_valid_0; /* ABORT */ 770 } 771 772 if (end == (char *)val) 773 { 774 DPRINTF(E_LOG, L_DAAP, "Value '%s' in clause '%s%s%c%s' does not represent an integer value\n", 775 val, field, (neg_op) ? "!" : "", op, val); 776 retval.valid= 0; 777 goto STR_result_valid_0; /* ABORT */ 778 } 779 780 *end = '\0'; /* Cut out potential garbage - we're being kind */ 781 } 782 /* String field: escape string, check for '*' */ 783 else 784 { 785 if (op != ':') 786 { 787 DPRINTF(E_LOG, L_DAAP, "Operation '%c' not valid for string values\n", op); 788 retval.valid= 0; 789 goto STR_result_valid_0; /* ABORT */ 790 } 791 792 escaped = (pANTLR3_UINT8)db_escape_string((char *)val); 793 if (!escaped) 794 { 795 DPRINTF(E_LOG, L_DAAP, "Could not escape value\n"); 796 retval.valid= 0; 797 goto STR_result_valid_0; /* ABORT */ 798 } 799 800 val = escaped; 801 802 if (val[0] == '*') 803 { 804 op = '%'; 805 val[0] = '%'; 806 } 807 808 if (val[strlen((char *)val) - 1] == '*') 809 { 810 op = '%'; 811 val[strlen((char *)val) - 1] = '%'; 812 } 813 } 814 815 switch(op) 816 { 817 case ':': 818 if (neg_op) 819 retval.result->append8(retval.result, " <> "); 820 else 821 retval.result->append8(retval.result, " = "); 822 break; 823 824 case '+': 825 if (neg_op) 826 retval.result->append8(retval.result, " <= "); 827 else 828 retval.result->append8(retval.result, " > "); 829 break; 830 831 case '-': 832 if (neg_op) 833 retval.result->append8(retval.result, " >= "); 834 else 835 retval.result->append8(retval.result, " < "); 836 break; 837 838 case '%': 839 retval.result->append8(retval.result, " LIKE "); 840 break; 841 842 default: 843 if (neg_op) 844 DPRINTF(E_LOG, L_DAAP, "Missing or unknown operator '%c' in clause '%s!%c%s'\n", op, field, op, val); 845 else 846 DPRINTF(E_LOG, L_DAAP, "Unknown operator '%c' in clause '%s%c%s'\n", op, field, op, val); 847 retval.valid= 0; 848 goto STR_result_valid_0; /* ABORT */ 849 break; 850 } 851 852 if (!dqfm->as_int) 853 retval.result->append8(retval.result, "'"); 854 855 retval.result->append8(retval.result, (const char *)val); 856 857 if (!dqfm->as_int) 858 retval.result->append8(retval.result, "'"); 859 860 /* For empty string value, we need to check against NULL too */ 861 if ((*val == '\0') && (op == ':')) 862 { 863 if (neg_op) 864 retval.result->append8(retval.result, " AND "); 865 else 866 retval.result->append8(retval.result, " OR "); 867 868 retval.result->append8(retval.result, dqfm->db_col); 869 870 if (neg_op) 871 retval.result->append8(retval.result, " IS NOT NULL"); 872 else 873 retval.result->append8(retval.result, " IS NULL"); 874 875 retval.result->append8(retval.result, ")"); 876 } 877 878 STR_result_valid_0: /* bail out label */ 879 ; 880 881 if (escaped) 882 free(escaped); 883 884 STR_out: /* get out of here */ 885 ; 886 887 } 888 889 } 890 break; 891 892 } 893 } 894 } 895 896 897 // This is where rules clean up and exit 898 // 899 goto ruleexprEx; /* Prevent compiler warnings */ 900 ruleexprEx: ; 901 902 if (HASEXCEPTION()) 903 { 904 PREPORTERROR(); 905 PRECOVER(); 906 } 907 908 909 return retval; 910} 911/* $ANTLR end expr */ 912/* End of parsing rules 913 * ============================================== 914 */ 915 916/* ============================================== 917 * Syntactic predicates 918 */ 919/* End of syntactic predicates 920 * ============================================== 921 */ 922 923 924 925 926 927 928/* End of code 929 * ============================================================================= 930 */ 931