/** \file
 *  This C source file was generated by $ANTLR version 3.2 debian-5
 *
 *     -  From the grammar source file : DAAP2SQL.g
 *     -                            On : 2011-09-11 16:17:21
 *     -           for the tree parser : DAAP2SQLTreeParser *
 * Editing it, at least manually, is not wise. 
 *
 * C language generator and runtime by Jim Idle, jimi|hereisanat|idle|dotgoeshere|ws.
 *
 *
*/
// [The "BSD licence"]
// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
// http://www.temporal-wave.com
// http://www.linkedin.com/in/jimidle
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. The name of the author may not be used to endorse or promote products
//    derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


/* =============================================================================
 * This is what the grammar programmer asked us to put at the top of every file.
 */

	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include <limits.h>
	#include <errno.h>

	#include "logger.h"
	#include "db.h"
	#include "daap_query.h"

/* End of Header action.
 * =============================================================================
 */
/* -----------------------------------------
 * Include the ANTLR3 generated header file.
 */
#include    "DAAP2SQL.h"
/* ----------------------------------------- */





/* MACROS that hide the C interface implementations from the
 * generated code, which makes it a little more understandable to the human eye.
 * I am very much against using C pre-processor macros for function calls and bits
 * of code as you cannot see what is happening when single stepping in debuggers
 * and so on. The exception (in my book at least) is for generated code, where you are
 * not maintaining it, but may wish to read and understand it. If you single step it, you know that input()
 * hides some indirect calls, but is always referring to the input stream. This is
 * probably more readable than ctx->input->istream->input(snarfle0->blarg) and allows me to rejig
 * the runtime interfaces without changing the generated code too often, without
 * confusing the reader of the generated output, who may not wish to know the gory
 * details of the interface inheritance.
 */
 
#define		CTX	ctx

/* Aids in accessing scopes for grammar programmers
 */
#undef	SCOPE_TYPE
#undef	SCOPE_STACK
#undef	SCOPE_TOP
#define	SCOPE_TYPE(scope)   pDAAP2SQL_##scope##_SCOPE
#define SCOPE_STACK(scope)  pDAAP2SQL_##scope##Stack
#define	SCOPE_TOP(scope)    ctx->pDAAP2SQL_##scope##Top
#define	SCOPE_SIZE(scope)		ctx->pDAAP2SQL_##scope##Stack_limit
#define SCOPE_INSTANCE(scope, i)	(ctx->SCOPE_STACK(scope)->get(ctx->SCOPE_STACK(scope),i))

/* Macros for accessing things in the parser
 */
 
#undef	    PARSER
#undef	    RECOGNIZER		    
#undef	    HAVEPARSEDRULE
#undef	    INPUT
#undef	    STRSTREAM
#undef	    HASEXCEPTION
#undef	    EXCEPTION
#undef	    MATCHT
#undef	    MATCHANYT
#undef	    FOLLOWSTACK
#undef	    FOLLOWPUSH
#undef	    FOLLOWPOP
#undef	    PRECOVER
#undef	    PREPORTERROR
#undef	    LA
#undef	    LT
#undef	    CONSTRUCTEX
#undef	    CONSUME
#undef	    MARK
#undef	    REWIND
#undef	    REWINDLAST
#undef	    PERRORRECOVERY
#undef	    HASFAILED
#undef	    FAILEDFLAG
#undef	    RECOVERFROMMISMATCHEDSET
#undef	    RECOVERFROMMISMATCHEDELEMENT
#undef	    BACKTRACKING
#undef      ADAPTOR
#undef	    RULEMEMO		
#undef		SEEK    
#undef		INDEX
#undef		DBG

#define	    PARSER							ctx->pTreeParser  
#define	    RECOGNIZER						PARSER->rec
#define		PSRSTATE						RECOGNIZER->state
#define	    HAVEPARSEDRULE(r)				RECOGNIZER->alreadyParsedRule(RECOGNIZER, r)
#define	    INPUT							PARSER->ctnstream
#define		ISTREAM							INPUT->tnstream->istream
#define	    STRSTREAM						INPUT->tnstream
#define	    HASEXCEPTION()					(PSRSTATE->error == ANTLR3_TRUE)
#define	    EXCEPTION						PSRSTATE->exception
#define	    MATCHT(t, fs)					RECOGNIZER->match(RECOGNIZER, t, fs)
#define	    MATCHANYT()						RECOGNIZER->matchAny(RECOGNIZER)
#define	    FOLLOWSTACK					    PSRSTATE->following
#define	    FOLLOWPUSH(x)					FOLLOWSTACK->push(FOLLOWSTACK, ((void *)(&(x))), NULL)
#define	    FOLLOWPOP()						FOLLOWSTACK->pop(FOLLOWSTACK)
#define	    PRECOVER()						RECOGNIZER->recover(RECOGNIZER)
#define	    PREPORTERROR()					RECOGNIZER->reportError(RECOGNIZER)
#define	    LA(n)							ISTREAM->_LA(ISTREAM, n)
#define	    LT(n)							INPUT->tnstream->_LT(INPUT->tnstream, n)
#define	    CONSTRUCTEX()					RECOGNIZER->exConstruct(RECOGNIZER)
#define	    CONSUME()						ISTREAM->consume(ISTREAM)
#define	    MARK()							ISTREAM->mark(ISTREAM)
#define	    REWIND(m)						ISTREAM->rewind(ISTREAM, m)
#define	    REWINDLAST()					ISTREAM->rewindLast(ISTREAM)
#define	    PERRORRECOVERY					PSRSTATE->errorRecovery
#define	    FAILEDFLAG						PSRSTATE->failed
#define	    HASFAILED()						(FAILEDFLAG == ANTLR3_TRUE)
#define	    BACKTRACKING					PSRSTATE->backtracking
#define	    RECOVERFROMMISMATCHEDSET(s)		RECOGNIZER->recoverFromMismatchedSet(RECOGNIZER, s)
#define	    RECOVERFROMMISMATCHEDELEMENT(e)	RECOGNIZER->recoverFromMismatchedElement(RECOGNIZER, s)
#define     ADAPTOR                         INPUT->adaptor
#define		RULEMEMO						PSRSTATE->ruleMemo
#define		SEEK(n)							ISTREAM->seek(ISTREAM, n)
#define		INDEX()							ISTREAM->index(ISTREAM)
#define		DBG								RECOGNIZER->debugger


#define		TOKTEXT(tok, txt)				tok, (pANTLR3_UINT8)txt

/* The 4 tokens defined below may well clash with your own #defines or token types. If so
 * then for the present you must use different names for your defines as these are hard coded
 * in the code generator. It would be better not to use such names internally, and maybe
 * we can change this in a forthcoming release. I deliberately do not #undef these
 * here as this will at least give you a redefined error somewhere if they clash.
 */
#define	    UP	    ANTLR3_TOKEN_UP
#define	    DOWN    ANTLR3_TOKEN_DOWN
#define	    EOR	    ANTLR3_TOKEN_EOR
#define	    INVALID ANTLR3_TOKEN_INVALID


/* =============================================================================
 * Functions to create and destroy scopes. First come the rule scopes, followed
 * by the global declared scopes.
 */



/* ============================================================================= */

/* =============================================================================
 * Start of recognizer
 */



/** \brief Table of all token names in symbolic order, mainly used for
 *         error reporting.
 */
pANTLR3_UINT8   DAAP2SQLTokenNames[8+4]
     = {
        (pANTLR3_UINT8) "<invalid>",       /* String to print to indicate an invalid token */
        (pANTLR3_UINT8) "<EOR>",
        (pANTLR3_UINT8) "<DOWN>", 
        (pANTLR3_UINT8) "<UP>", 
        (pANTLR3_UINT8) "NEWLINE",
        (pANTLR3_UINT8) "OPOR",
        (pANTLR3_UINT8) "OPAND",
        (pANTLR3_UINT8) "LPAR",
        (pANTLR3_UINT8) "RPAR",
        (pANTLR3_UINT8) "STR",
        (pANTLR3_UINT8) "QUOTE",
        (pANTLR3_UINT8) "ESCAPED"
       };

        

// Forward declare the locally static matching functions we have generated.
//
static pANTLR3_STRING	query    (pDAAP2SQL ctx);
static DAAP2SQL_expr_return	expr    (pDAAP2SQL ctx);
static void	DAAP2SQLFree(pDAAP2SQL ctx);
/* For use in tree output where we are accumulating rule labels via label += ruleRef
 * we need a function that knows how to free a return scope when the list is destroyed. 
 * We cannot just use ANTLR3_FREE because in debug tracking mode, this is a macro.
 */
static	void ANTLR3_CDECL freeScope(void * scope)
{
    ANTLR3_FREE(scope);
}

/** \brief Name of the grammar file that generated this code
 */
static const char fileName[] = "DAAP2SQL.g";

/** \brief Return the name of the grammar file that generated this code.
 */
static const char * getGrammarFileName()
{
	return fileName;
}
/** \brief Create a new DAAP2SQL parser and return a context for it.
 *
 * \param[in] instream Pointer to an input stream interface.
 *
 * \return Pointer to new parser context upon success.
 */
ANTLR3_API pDAAP2SQL
DAAP2SQLNew   (pANTLR3_COMMON_TREE_NODE_STREAM instream)
{
	// See if we can create a new parser with the standard constructor
	//
	return DAAP2SQLNewSSD(instream, NULL);
}

/** \brief Create a new DAAP2SQL parser and return a context for it.
 *
 * \param[in] instream Pointer to an input stream interface.
 *
 * \return Pointer to new parser context upon success.
 */
ANTLR3_API pDAAP2SQL
DAAP2SQLNewSSD   (pANTLR3_COMMON_TREE_NODE_STREAM instream, pANTLR3_RECOGNIZER_SHARED_STATE state)
{
    pDAAP2SQL ctx;	    /* Context structure we will build and return   */
    
    ctx	= (pDAAP2SQL) ANTLR3_CALLOC(1, sizeof(DAAP2SQL));
    
    if	(ctx == NULL)
    {
		// Failed to allocate memory for parser context
		//
        return  NULL;
    }
    
    /* -------------------------------------------------------------------
     * Memory for basic structure is allocated, now to fill in
     * the base ANTLR3 structures. We initialize the function pointers
     * for the standard ANTLR3 parser function set, but upon return
     * from here, the programmer may set the pointers to provide custom
     * implementations of each function. 
     *
     * We don't use the macros defined in DAAP2SQL.h here, in order that you can get a sense
     * of what goes where.
     */

    /* Create a base Tree parser/recognizer, using the supplied tree node stream
     */
    ctx->pTreeParser		= antlr3TreeParserNewStream(ANTLR3_SIZE_HINT, instream, state);
    /* Install the implementation of our DAAP2SQL interface
     */
    ctx->query	= query;
    ctx->expr	= expr;
    ctx->free			= DAAP2SQLFree;
    ctx->getGrammarFileName	= getGrammarFileName;
    
    /* Install the scope pushing methods.
     */

        
    

	
    /* Install the token table
     */
    PSRSTATE->tokenNames   = DAAP2SQLTokenNames;
    
    
    /* Return the newly built parser to the caller
     */
    return  ctx;
}

/** Free the parser resources
 */
 static void
 DAAP2SQLFree(pDAAP2SQL ctx)
 {
    /* Free any scope memory
     */
    
        
	// Free this parser
	//
    ctx->pTreeParser->free(ctx->pTreeParser);
    ANTLR3_FREE(ctx);

    /* Everything is released, so we can return
     */
    return;
 }
 
/** Return token names used by this tree parser
 *
 * The returned pointer is used as an index into the token names table (using the token 
 * number as the index).
 * 
 * \return Pointer to first char * in the table.
 */
static pANTLR3_UINT8    *getTokenNames() 
{
        return DAAP2SQLTokenNames; 
}


    	struct dmap_query_field_map {
    	  char *dmap_field;
    	  char *db_col;
    	  int as_int;
    	};

    	/* gperf static hash, daap_query.gperf */
    	#include "daap_query_hash.c"

    
/* Declare the bitsets
 */

/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_query70  */
static	ANTLR3_BITWORD FOLLOW_expr_in_query70_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000002) };
static  ANTLR3_BITSET_LIST FOLLOW_expr_in_query70	= { FOLLOW_expr_in_query70_bits, 1	};
/** Bitset defining follow set for error recovery in rule state: FOLLOW_OPAND_in_expr95  */
static	ANTLR3_BITWORD FOLLOW_OPAND_in_expr95_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000004) };
static  ANTLR3_BITSET_LIST FOLLOW_OPAND_in_expr95	= { FOLLOW_OPAND_in_expr95_bits, 1	};
/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr101  */
static	ANTLR3_BITWORD FOLLOW_expr_in_expr101_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000260) };
static  ANTLR3_BITSET_LIST FOLLOW_expr_in_expr101	= { FOLLOW_expr_in_expr101_bits, 1	};
/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr107  */
static	ANTLR3_BITWORD FOLLOW_expr_in_expr107_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000008) };
static  ANTLR3_BITSET_LIST FOLLOW_expr_in_expr107	= { FOLLOW_expr_in_expr107_bits, 1	};
/** Bitset defining follow set for error recovery in rule state: FOLLOW_OPOR_in_expr118  */
static	ANTLR3_BITWORD FOLLOW_OPOR_in_expr118_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000004) };
static  ANTLR3_BITSET_LIST FOLLOW_OPOR_in_expr118	= { FOLLOW_OPOR_in_expr118_bits, 1	};
/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr124  */
static	ANTLR3_BITWORD FOLLOW_expr_in_expr124_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000260) };
static  ANTLR3_BITSET_LIST FOLLOW_expr_in_expr124	= { FOLLOW_expr_in_expr124_bits, 1	};
/** Bitset defining follow set for error recovery in rule state: FOLLOW_expr_in_expr130  */
static	ANTLR3_BITWORD FOLLOW_expr_in_expr130_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000008) };
static  ANTLR3_BITSET_LIST FOLLOW_expr_in_expr130	= { FOLLOW_expr_in_expr130_bits, 1	};
/** Bitset defining follow set for error recovery in rule state: FOLLOW_STR_in_expr140  */
static	ANTLR3_BITWORD FOLLOW_STR_in_expr140_bits[]	= { ANTLR3_UINT64_LIT(0x0000000000000002) };
static  ANTLR3_BITSET_LIST FOLLOW_STR_in_expr140	= { FOLLOW_STR_in_expr140_bits, 1	};
     

 
 
/* ==============================================
 * Parsing rules
 */
/** 
 * $ANTLR start query
 * DAAP2SQL.g:50:1: query returns [ pANTLR3_STRING result ] : e= expr ;
 */
static pANTLR3_STRING
query(pDAAP2SQL ctx)
{   
    pANTLR3_STRING result = NULL;

    DAAP2SQL_expr_return e;
    #undef	RETURN_TYPE_e
    #define	RETURN_TYPE_e DAAP2SQL_expr_return

    /* Initialize rule variables
     */


     result= NULL; 
    {
        // DAAP2SQL.g:52:2: (e= expr )
        // DAAP2SQL.g:52:4: e= expr
        {
            FOLLOWPUSH(FOLLOW_expr_in_query70);
            e=expr(ctx);

            FOLLOWPOP();
            if  (HASEXCEPTION())
            {
                goto rulequeryEx;
            }

            {

                			if (!e.valid)
                			{
                				result= NULL;
                			}
                			else
                			{
                				result= e.result->factory->newRaw(e.result->factory);
                				result->append8(result, "(");
                				result->appendS(result, e.result);
                				result->append8(result, ")");
                			}
                		
            }

        }

    }
    

    // This is where rules clean up and exit
    //
    goto rulequeryEx; /* Prevent compiler warnings */
    rulequeryEx: ;

            if (HASEXCEPTION())
            {
                PREPORTERROR();
                PRECOVER();
            }


    return result;
}
/* $ANTLR end query */

/** 
 * $ANTLR start expr
 * DAAP2SQL.g:68:1: expr returns [ pANTLR3_STRING result, int valid ] : ( ^( OPAND a= expr b= expr ) | ^( OPOR a= expr b= expr ) | STR );
 */
static DAAP2SQL_expr_return
expr(pDAAP2SQL ctx)
{   
    DAAP2SQL_expr_return retval;

    pANTLR3_BASE_TREE    STR1;
    DAAP2SQL_expr_return a;
    #undef	RETURN_TYPE_a
    #define	RETURN_TYPE_a DAAP2SQL_expr_return

    DAAP2SQL_expr_return b;
    #undef	RETURN_TYPE_b
    #define	RETURN_TYPE_b DAAP2SQL_expr_return

    /* Initialize rule variables
     */


     retval.result= NULL; retval.valid= 1; 
    STR1       = NULL;
    retval.start = LT(1); retval.stop = retval.start;

    {
        {
            //  DAAP2SQL.g:70:2: ( ^( OPAND a= expr b= expr ) | ^( OPOR a= expr b= expr ) | STR )
            
            ANTLR3_UINT32 alt1;

            alt1=3;

            switch ( LA(1) ) 
            {
            case OPAND:
            	{
            		alt1=1;
            	}
                break;
            case OPOR:
            	{
            		alt1=2;
            	}
                break;
            case STR:
            	{
            		alt1=3;
            	}
                break;

            default:
                CONSTRUCTEX();
                EXCEPTION->type         = ANTLR3_NO_VIABLE_ALT_EXCEPTION;
                EXCEPTION->message      = (void *)"";
                EXCEPTION->decisionNum  = 1;
                EXCEPTION->state        = 0;


                goto ruleexprEx;
            }

            switch (alt1) 
            {
        	case 1:
        	    // DAAP2SQL.g:70:4: ^( OPAND a= expr b= expr )
        	    {
        	         MATCHT(OPAND, &FOLLOW_OPAND_in_expr95); 
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }


        	        MATCHT(ANTLR3_TOKEN_DOWN, NULL); 
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }

        	        FOLLOWPUSH(FOLLOW_expr_in_expr101);
        	        a=expr(ctx);

        	        FOLLOWPOP();
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }

        	        FOLLOWPUSH(FOLLOW_expr_in_expr107);
        	        b=expr(ctx);

        	        FOLLOWPOP();
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }


        	        MATCHT(ANTLR3_TOKEN_UP, NULL); 
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }

        	        {

        	            			if (!a.valid || !b.valid)
        	            			{
        	            				retval.valid= 0;
        	            			}
        	            			else
        	            			{
        	            				retval.result= a.result->factory->newRaw(a.result->factory);
        	            				retval.result->append8(retval.result, "(");
        	            				retval.result->appendS(retval.result, a.result);
        	            				retval.result->append8(retval.result, " AND ");
        	            				retval.result->appendS(retval.result, b.result);
        	            				retval.result->append8(retval.result, ")");
        	            			}
        	            		
        	        }

        	    }
        	    break;
        	case 2:
        	    // DAAP2SQL.g:86:4: ^( OPOR a= expr b= expr )
        	    {
        	         MATCHT(OPOR, &FOLLOW_OPOR_in_expr118); 
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }


        	        MATCHT(ANTLR3_TOKEN_DOWN, NULL); 
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }

        	        FOLLOWPUSH(FOLLOW_expr_in_expr124);
        	        a=expr(ctx);

        	        FOLLOWPOP();
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }

        	        FOLLOWPUSH(FOLLOW_expr_in_expr130);
        	        b=expr(ctx);

        	        FOLLOWPOP();
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }


        	        MATCHT(ANTLR3_TOKEN_UP, NULL); 
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }

        	        {

        	            			if (!a.valid || !b.valid)
        	            			{
        	            				retval.valid= 0;
        	            			}
        	            			else
        	            			{
        	            				retval.result= a.result->factory->newRaw(a.result->factory);
        	            				retval.result->append8(retval.result, "(");
        	            				retval.result->appendS(retval.result, a.result);
        	            				retval.result->append8(retval.result, " OR ");
        	            				retval.result->appendS(retval.result, b.result);
        	            				retval.result->append8(retval.result, ")");
        	            			}
        	            		
        	        }

        	    }
        	    break;
        	case 3:
        	    // DAAP2SQL.g:102:4: STR
        	    {
        	        STR1 = (pANTLR3_BASE_TREE) MATCHT(STR, &FOLLOW_STR_in_expr140); 
        	        if  (HASEXCEPTION())
        	        {
        	            goto ruleexprEx;
        	        }

        	        {

        	            			pANTLR3_STRING str;
        	            			pANTLR3_UINT8 field;
        	            			pANTLR3_UINT8 val;
        	            			pANTLR3_UINT8 escaped;
        	            			ANTLR3_UINT8 op;
        	            			int neg_op;
        	            			const struct dmap_query_field_map *dqfm;
        	            			char *end;
        	            			long long llval;

        	            			escaped = NULL;

        	            			retval.result= (STR1->getText(STR1))->factory->newRaw((STR1->getText(STR1))->factory);

        	            			str = (STR1->getText(STR1))->toUTF8((STR1->getText(STR1)));

        	            			/* NOTE: the lexer delivers the string without quotes
        	            			which may not be obvious from the grammar due to embedded code
        	            			*/

        	            			/* Make daap.songalbumid:0 a no-op */
        	            			if (strcmp((char *)str->chars, "daap.songalbumid:0") == 0)
        	            			{
        	            				retval.result->append8(retval.result, "1 = 1");

        	            				goto STR_out;
        	            			}

        	            			field = str->chars;

        	            			val = field;
        	            			while ((*val != '\0') && ((*val == '.')
        	            				|| ((*val >= 'a') && (*val <= 'z'))
        	            				|| ((*val >= 'A') && (*val <= 'Z'))
        	            				|| ((*val >= '0') && (*val <= '9'))))
        	            			{
        	            				val++;
        	            			}

        	            			if (*field == '\0')
        	            			{
        	            				DPRINTF(E_LOG, L_DAAP, "No field name found in clause '%s'\n", field);
        	            				retval.valid= 0;
        	            				goto STR_result_valid_0; /* ABORT */
        	            			}

        	            			if (*val == '\0')
        	            			{
        	            				DPRINTF(E_LOG, L_DAAP, "No operator found in clause '%s'\n", field);
        	            				retval.valid= 0;
        	            				goto STR_result_valid_0; /* ABORT */
        	            			}

        	            			op = *val;
        	            			*val = '\0';
        	            			val++;

        	            			if (op == '!')
        	            			{
        	            				if (*val == '\0')
        	            				{
        	            					DPRINTF(E_LOG, L_DAAP, "Negation found but operator missing in clause '%s%c'\n", field, op);
        	            					retval.valid= 0;
        	            					goto STR_result_valid_0; /* ABORT */
        	            				}

        	            				neg_op = 1;
        	            				op = *val;
        	            				val++;
        	            			}
        	            			else
        	            				neg_op = 0;

        	            			/* Lookup DMAP field in the query field map */
        	            			dqfm = daap_query_field_lookup((char *)field, strlen((char *)field));
        	            			if (!dqfm)
        	            			{
        	            				DPRINTF(E_LOG, L_DAAP, "DMAP field '%s' is not a valid field in queries\n", field);
        	            				retval.valid= 0;
        	            				goto STR_result_valid_0; /* ABORT */
        	            			}

        	            			/* Empty values OK for string fields, NOK for integer */
        	            			if (*val == '\0')
        	            			{
        	            				if (dqfm->as_int)
        	            				{
        	            					DPRINTF(E_LOG, L_DAAP, "No value given in clause '%s%s%c'\n", field, (neg_op) ? "!" : "", op);
        	            					retval.valid= 0;
        	            					goto STR_result_valid_0; /* ABORT */
        	            				}

        	            				/* Need to check against NULL too */
        	            				if (op == ':')
        	            					retval.result->append8(retval.result, "(");
        	            			}

        	            			retval.result->append8(retval.result, dqfm->db_col);

        	            			/* Int field: check integer conversion */
        	            			if (dqfm->as_int)
        	            			{
        	            				errno = 0;
        	            				llval = strtoll((const char *)val, &end, 10);

        	            				if (((errno == ERANGE) && ((llval == LLONG_MAX) || (llval == LLONG_MIN)))
        	            					|| ((errno != 0) && (llval == 0)))
        	            				{
        	            					DPRINTF(E_LOG, L_DAAP, "Value '%s' in clause '%s%s%c%s' does not convert to an integer type\n",
        	            					val, field, (neg_op) ? "!" : "", op, val);
        	            					retval.valid= 0;
        	            					goto STR_result_valid_0; /* ABORT */
        	            				}

        	            				if (end == (char *)val)
        	            				{
        	            					DPRINTF(E_LOG, L_DAAP, "Value '%s' in clause '%s%s%c%s' does not represent an integer value\n",
        	            					val, field, (neg_op) ? "!" : "", op, val);
        	            					retval.valid= 0;
        	            					goto STR_result_valid_0; /* ABORT */
        	            				}

        	            				*end = '\0'; /* Cut out potential garbage - we're being kind */
        	            			}
        	            			/* String field: escape string, check for '*' */
        	            			else
        	            			{
        	            				if (op != ':')
        	            				{
        	            					DPRINTF(E_LOG, L_DAAP, "Operation '%c' not valid for string values\n", op);
        	            					retval.valid= 0;
        	            					goto STR_result_valid_0; /* ABORT */
        	            				}

        	            				escaped = (pANTLR3_UINT8)db_escape_string((char *)val);
        	            				if (!escaped)
        	            				{
        	            					DPRINTF(E_LOG, L_DAAP, "Could not escape value\n");
        	            					retval.valid= 0;
        	            					goto STR_result_valid_0; /* ABORT */
        	            				}

        	            				val = escaped;

        	            				if (val[0] == '*')
        	            				{
        	            					op = '%';
        	            					val[0] = '%';
        	            				}

        	            				if (val[strlen((char *)val) - 1] == '*')
        	            				{
        	            					op = '%';
        	            					val[strlen((char *)val) - 1] = '%';
        	            				}
        	            			}

        	            			switch(op)
        	            			{
        	            				case ':':
        	            					if (neg_op)
        	            						retval.result->append8(retval.result, " <> ");
        	            					else
        	            						retval.result->append8(retval.result, " = ");
        	            					break;

        	            				case '+':
        	            					if (neg_op)
        	            						retval.result->append8(retval.result, " <= ");
        	            					else
        	            						retval.result->append8(retval.result, " > ");
        	            					break;

        	            				case '-':
        	            					if (neg_op)
        	            						retval.result->append8(retval.result, " >= ");
        	            					else
        	            						retval.result->append8(retval.result, " < ");
        	            					break;

        	            				case '%':
        	            					retval.result->append8(retval.result, " LIKE ");
        	            					break;

        	            				default:
        	            					if (neg_op)
        	            						DPRINTF(E_LOG, L_DAAP, "Missing or unknown operator '%c' in clause '%s!%c%s'\n", op, field, op, val);
        	            					else
        	            						DPRINTF(E_LOG, L_DAAP, "Unknown operator '%c' in clause '%s%c%s'\n", op, field, op, val);
        	            					retval.valid= 0;
        	            					goto STR_result_valid_0; /* ABORT */
        	            					break;
        	            			}

        	            			if (!dqfm->as_int)
        	            				retval.result->append8(retval.result, "'");
        	            	
        	            			retval.result->append8(retval.result, (const char *)val);
        	            	
        	            			if (!dqfm->as_int)
        	            				retval.result->append8(retval.result, "'");

        	            			/* For empty string value, we need to check against NULL too */
        	            			if ((*val == '\0') && (op == ':'))
        	            			{
        	            				if (neg_op)
        	            					retval.result->append8(retval.result, " AND ");
        	            				else
        	            					retval.result->append8(retval.result, " OR ");

        	            				retval.result->append8(retval.result, dqfm->db_col);

        	            				if (neg_op)
        	            					retval.result->append8(retval.result, " IS NOT NULL");
        	            				else
        	            					retval.result->append8(retval.result, " IS NULL");

        	            				retval.result->append8(retval.result, ")");
        	            			}

        	            			STR_result_valid_0: /* bail out label */
        	            				;

        	            			if (escaped)
        	            				free(escaped);

        	            			STR_out: /* get out of here */
        	            				;
        	            		
        	        }

        	    }
        	    break;

            }
        }
    }
    

    // This is where rules clean up and exit
    //
    goto ruleexprEx; /* Prevent compiler warnings */
    ruleexprEx: ;

            if (HASEXCEPTION())
            {
                PREPORTERROR();
                PRECOVER();
            }


    return retval;
}
/* $ANTLR end expr */
/* End of parsing rules
 * ==============================================
 */

/* ==============================================
 * Syntactic predicates
 */
/* End of syntactic predicates
 * ==============================================
 */

 
 



/* End of code
 * =============================================================================
 */
