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
762printf("val =%s end=%08x llval=%d\n",val,end,llval);
763
764        	            				if (((errno == ERANGE) && ((llval == LLONG_MAX) || (llval == LLONG_MIN)))
765        	            					|| ((errno != 0) && (llval == 0)))
766        	            				{
767        	            					DPRINTF(E_LOG, L_DAAP, "Value '%s' in clause '%s%s%c%s' does not convert to an integer type\n",
768        	            					val, field, (neg_op) ? "!" : "", op, val);
769        	            					retval.valid= 0;
770        	            					goto STR_result_valid_0; /* ABORT */
771        	            				}
772
773        	            				if (end == (char *)val)
774        	            				{
775        	            					DPRINTF(E_LOG, L_DAAP, "Value '%s' in clause '%s%s%c%s' does not represent an integer value\n",
776        	            					val, field, (neg_op) ? "!" : "", op, val);
777        	            					retval.valid= 0;
778        	            					goto STR_result_valid_0; /* ABORT */
779        	            				}
780
781        	            				*end = '\0'; /* Cut out potential garbage - we're being kind */
782        	            			}
783        	            			/* String field: escape string, check for '*' */
784        	            			else
785        	            			{
786        	            				if (op != ':')
787        	            				{
788        	            					DPRINTF(E_LOG, L_DAAP, "Operation '%c' not valid for string values\n", op);
789        	            					retval.valid= 0;
790        	            					goto STR_result_valid_0; /* ABORT */
791        	            				}
792
793        	            				escaped = (pANTLR3_UINT8)db_escape_string((char *)val);
794        	            				if (!escaped)
795        	            				{
796        	            					DPRINTF(E_LOG, L_DAAP, "Could not escape value\n");
797        	            					retval.valid= 0;
798        	            					goto STR_result_valid_0; /* ABORT */
799        	            				}
800
801        	            				val = escaped;
802
803        	            				if (val[0] == '*')
804        	            				{
805        	            					op = '%';
806        	            					val[0] = '%';
807        	            				}
808
809        	            				if (val[strlen((char *)val) - 1] == '*')
810        	            				{
811        	            					op = '%';
812        	            					val[strlen((char *)val) - 1] = '%';
813        	            				}
814        	            			}
815
816        	            			switch(op)
817        	            			{
818        	            				case ':':
819        	            					if (neg_op)
820        	            						retval.result->append8(retval.result, " <> ");
821        	            					else
822        	            						retval.result->append8(retval.result, " = ");
823        	            					break;
824
825        	            				case '+':
826        	            					if (neg_op)
827        	            						retval.result->append8(retval.result, " <= ");
828        	            					else
829        	            						retval.result->append8(retval.result, " > ");
830        	            					break;
831
832        	            				case '-':
833        	            					if (neg_op)
834        	            						retval.result->append8(retval.result, " >= ");
835        	            					else
836        	            						retval.result->append8(retval.result, " < ");
837        	            					break;
838
839        	            				case '%':
840        	            					retval.result->append8(retval.result, " LIKE ");
841        	            					break;
842
843        	            				default:
844        	            					if (neg_op)
845        	            						DPRINTF(E_LOG, L_DAAP, "Missing or unknown operator '%c' in clause '%s!%c%s'\n", op, field, op, val);
846        	            					else
847        	            						DPRINTF(E_LOG, L_DAAP, "Unknown operator '%c' in clause '%s%c%s'\n", op, field, op, val);
848        	            					retval.valid= 0;
849        	            					goto STR_result_valid_0; /* ABORT */
850        	            					break;
851        	            			}
852
853        	            			if (!dqfm->as_int)
854        	            				retval.result->append8(retval.result, "'");
855
856        	            			retval.result->append8(retval.result, (const char *)val);
857
858        	            			if (!dqfm->as_int)
859        	            				retval.result->append8(retval.result, "'");
860
861        	            			/* For empty string value, we need to check against NULL too */
862        	            			if ((*val == '\0') && (op == ':'))
863        	            			{
864        	            				if (neg_op)
865        	            					retval.result->append8(retval.result, " AND ");
866        	            				else
867        	            					retval.result->append8(retval.result, " OR ");
868
869        	            				retval.result->append8(retval.result, dqfm->db_col);
870
871        	            				if (neg_op)
872        	            					retval.result->append8(retval.result, " IS NOT NULL");
873        	            				else
874        	            					retval.result->append8(retval.result, " IS NULL");
875
876        	            				retval.result->append8(retval.result, ")");
877        	            			}
878
879        	            			STR_result_valid_0: /* bail out label */
880        	            				;
881
882        	            			if (escaped)
883        	            				free(escaped);
884
885        	            			STR_out: /* get out of here */
886        	            				;
887
888        	        }
889
890        	    }
891        	    break;
892
893            }
894        }
895    }
896
897
898    // This is where rules clean up and exit
899    //
900    goto ruleexprEx; /* Prevent compiler warnings */
901    ruleexprEx: ;
902
903            if (HASEXCEPTION())
904            {
905                PREPORTERROR();
906                PRECOVER();
907            }
908
909
910    return retval;
911}
912/* $ANTLR end expr */
913/* End of parsing rules
914 * ==============================================
915 */
916
917/* ==============================================
918 * Syntactic predicates
919 */
920/* End of syntactic predicates
921 * ==============================================
922 */
923
924
925
926
927
928
929/* End of code
930 * =============================================================================
931 */
932