예제 #1
0
파일: HTRules.c 프로젝트: ChatanW/WebDaM
PRIVATE int HTRule_flush (HTStream * me)
{
    if (me) {
	char * flush = HTChunk_data(me->buffer);
	if (flush) HTRule_parseLine(rules, flush);
	HTChunk_clear(me->buffer);
    }
    return HT_OK;
}
예제 #2
0
파일: HTRules.c 프로젝트: ChatanW/WebDaM
/*
**	Folding is either of CF LWS, LF LWS, CRLF LWS
*/
PRIVATE int HTRule_put_block (HTStream * me, const char * b, int l)
{
    while (l > 0) {
	if (me->EOLstate == EOL_FCR) {
	    if (*b == LF)				   	     /* CRLF */
		me->EOLstate = EOL_FLF;
	    else if (isspace((int) *b))				   /* Folding: CR SP */
		me->EOLstate = EOL_DOT;
	    else {						 /* New line */
		HTRule_parseLine(rules, HTChunk_data(me->buffer));
		me->EOLstate = EOL_BEGIN;
		HTChunk_clear(me->buffer);
		continue;
	    }
	} else if (me->EOLstate == EOL_FLF) {
	    if (isspace((int) *b))		       /* Folding: LF SP or CR LF SP */
		me->EOLstate = EOL_DOT;
	    else {						/* New line */
		HTRule_parseLine(rules, HTChunk_data(me->buffer));
		me->EOLstate = EOL_BEGIN;
		HTChunk_clear(me->buffer);
		continue;
	    }
	} else if (me->EOLstate == EOL_DOT) {
	    if (isspace((int) *b)) {
		me->EOLstate = EOL_BEGIN;
		HTChunk_putc(me->buffer, ' ');
	    } else {
		HTRule_parseLine(rules, HTChunk_data(me->buffer));
		me->EOLstate = EOL_BEGIN;
		HTChunk_clear(me->buffer);
		continue;
	    }
	} else if (*b == CR) {
	    me->EOLstate = EOL_FCR;
	} else if (*b == LF) {
	    me->EOLstate = EOL_FLF;			       /* Line found */
	} else
	    HTChunk_putc(me->buffer, *b);
	l--; b++;
    }
    return HT_OK;
}
예제 #3
0
파일: HTTPServ.c 프로젝트: Rjoydip/libwww
/*
**	Searches for HTTP Request Line before going into transparent mode
*/
PRIVATE int HTTPReceive_put_block (HTStream * me, const char * b, int l)
{
    if (!me->transparent) {
        const char *p=b;
        while (l>0 && *p!=CR && *p!=LF) l--, p++;
        HTChunk_putb(me->buffer, b, p-b);
        if (*p==CR || *p==LF) {
            int status = ParseRequest(me);
            HTChunk_clear(me->buffer);
            if (status != HT_OK) return status;
            me->transparent = YES;
            b=p;
        }
    }
    if (l > 0) {
        int status = PUTBLOCK(b, l);
        if (status == HT_LOADED) me->transparent = NO;
        return status;
    }
    return HT_OK;
}
예제 #4
0
파일: SGML.c 프로젝트: ChatanW/WebDaM
PRIVATE int SGML_write (HTStream * context, const char * b, int l)
    {
	const SGML_dtd	*dtd = context->dtd;
	HTChunk	*string = context->string;
	const char *text = b;
	int count = 0;
	
	while (l-- > 0)
	    {
		char c = *b++;
		switch(context->state)
		    {
		    got_element_open:
			/*
			** The label is jumped when the '>' of a the element
			** start tag has been detected. This DOES NOT FALL TO
			** THE CODE S_after_open, only processes the tag and
			** sets the state (c should still contain the
			** terminating character of the tag ('>'))
			*/
			if (context->current_tag && context->current_tag->name)
				start_element(context);
			context->state = S_after_open;
			break;

		    case S_after_open:
			/*
			** State S_after_open is entered only for single
			** character after the element opening tag to test
			** against newline. Strip one trainling newline only
			** after opening nonempty element.  - SGML: Ugh!
			*/
			text = b;
			count = 0;
			if (c == '\n' && (context->contents != SGML_EMPTY))
			    {
				context->state = S_text;
				break;
			    }
			--text;
			goto S_text;

		    S_text:
			context->state = S_text;
		    case S_text:
#ifdef ISO_2022_JP
			if (c == '\033')
			    {
				context->state = S_esc;
				++count;
				break;
			    }
#endif /* ISO_2022_JP */
			if (c == '&')
			    {
				if (count > 0)
					PUTB(text, count);
				count = 0;
				HTChunk_clear(string);
				context->state = S_ero;
			    }
			else if (c == '<')
			    {
				if (count > 0)
					PUTB(text, count);
				count = 0;
				HTChunk_clear(string);
				/* should scrap LITERAL, and use CDATA and
				   RCDATA -- msa */
				context->state =
					(context->contents == SGML_LITERAL) ?
						S_literal : S_tag;
			    }
			else if (c == '\n')
			    	/* Newline - ignore if before end tag! */
				context->state = S_nl;
			else
				++count;
			break;

		    case S_nl:
			if (c == '<')
			    {
				if (count > 0)
					PUTB(text, count);
				count = 0;
				HTChunk_clear(string);
				context->state =
					(context->contents == SGML_LITERAL) ?
						S_literal : S_nl_tago;
			    }
			else
			    {
				++count;
				goto S_text;
			    }
			break;

		    case S_nl_tago:	/* Had newline and tag opener */
			if (c != '/')
				PUTC('\n'); /* Only ignore newline before </ */
			context->state = S_tag;
			goto handle_S_tag;

#ifdef ISO_2022_JP
		    case S_esc:
			if (c=='$')
				context->state = S_dollar;
			else if (c=='(')
				context->state = S_paren;
			else
				context->state = S_text;
			++count;
			break;

		    case S_dollar:
			if (c=='@' || c=='B')
				context->state = S_nonascii_text;
			else
				context->state = S_text;
			++count;
			break;

		    case S_paren:
			if (c=='B' || c=='J')
				context->state = S_text;
			else
				context->state = S_text;
			++count;
			break;

		    case S_nonascii_text:
			if (c == '\033')
				context->state = S_esc;
			++count;
			break;
#endif /* ISO_2022_JP */

			/* In literal mode, waits only for specific end tag!
			** Only foir compatibility with old servers.
			*/
		    case S_literal:
			HTChunk_putc(string, c);
			if ( TOUPPER(c) !=
			    ((HTChunk_size(string) == 1) ? '/'
			     : context->current_tag->name[HTChunk_size(string)-2]))
			    {

				/* If complete match, end literal */
				if ((c == '>') &&
				    (!context->current_tag->name[HTChunk_size(string)-2]))
				    {
					end_element
						(context,context->current_tag);
					/*
					  ...setting SGML_MIXED below is a
					  bit of kludge, but a good guess that
					  currently works, anything other than
					  SGML_LITERAL would work... -- msa */
					context->contents = SGML_MIXED;
				    }
				else
				    {
					/* If Mismatch: recover string. */
					PUTC( '<');
					PUTB(HTChunk_data(string), HTChunk_size(string));
				    }
				context->state = S_text;
				text = b;
				count = 0;
			    }
			break;

			/*
			** Character reference or Entity
			*/
		    case S_ero:
			if (c == '#')
			    {
				/*   &# is Char Ref Open */ 
				context->state = S_cro;
				break;
			    }
			context->state = S_entity;

			/** FALL THROUGH TO S_entity !! ***/

			/*
			** Handle Entities
			*/
		    case S_entity:
			if (isalnum((int) c))
				HTChunk_putc(string, c);
			else
			    {
				HTChunk_terminate(string);
				handle_entity(context);
				text = b;
				count = 0;
				if (c != ';')
				    {
					--text;
					goto S_text;
				    }
				context->state = S_text;
			    }
			break;

			/*	Character reference
			 */
		    case S_cro:
			if (isalnum((int)c))
				/* accumulate a character NUMBER */
				HTChunk_putc(string, c);
			else
			    {
				int value;
				HTChunk_terminate(string);
				if (sscanf(HTChunk_data(string), "%d", &value)==1)
					PUTC((char)value);
				else
				    {
					PUTB("&#", 2);
					PUTB(HTChunk_data(string), HTChunk_size(string)-1);
				    }
				text = b;
				count = 0;
				if (c != ';')
				    {
					--text;
					goto S_text;
				    }
				context->state = S_text;
			    }
			break;

		    case S_tag:		/* new tag */
		    handle_S_tag:
			if (isalnum((int)c))
				HTChunk_putc(string, c);
			else { /* End of tag name */
			    int i;
			    if (c == '/') {
				if (HTChunk_size(string) > 0)
				    HTTRACE(SGML_TRACE, "`<%s/' found!\n" _ HTChunk_data(string));
				context->state = S_end;
				break;
			    } else if (c == '!') {
				if (HTChunk_size(string) > 0)
				    HTTRACE(SGML_TRACE, " `<%s!' found!\n" _ HTChunk_data(string));
				context->state = S_md;
				break;
			    }
			    HTChunk_terminate(string);
			    context->current_tag  = SGMLFindTag(dtd, HTChunk_data(string));
			    if (context->current_tag == NULL) {
				HTTRACE(SGML_TRACE, "*** Unknown element %s\n" _ HTChunk_data(string));
				(*context->actions->unparsed_begin_element)
				    (context->target, HTChunk_data(string), HTChunk_size(string));
			    } else {
				for (i=0; i<context->current_tag->number_of_attributes; i++) {
				    context->present[i] = NO;
				    context->value[i] = -1;
				}
			    }
			    context->token = 0;
			    HTChunk_clear(string);
			    context->current_attribute_number = INVALID;
			    goto S_tag_gap;
			}
			break;

		    S_tag_gap:
			context->state = S_tag_gap;
		    case S_tag_gap:		/* Expecting attribute or > */
			if (isspace((int) c))
				break;	/* Gap between attributes */

			if (c == '>')
				goto got_element_open;
			else
				goto S_attr;

		    S_attr:
			/*
			** Start collecting the attribute name and collect
			** it in S_attr.
			*/
			context->state = S_attr;
			HTChunk_truncate(string, context->token);
		    case S_attr:
			if (isspace((int) c) || c == '>' || c == '=')
				goto got_attribute_name;
			else
				HTChunk_putc(string, c);
			break;

		    got_attribute_name:
			/*
			** This label is entered when attribute name has been
			** collected. Process it and enter S_attr_gap for
			** potential value or start of the next attribute.
			*/
			HTChunk_terminate(string) ;
			handle_attribute_name
				(context, HTChunk_data(string) + context->token);
			HTChunk_truncate(string, context->token);
			context->state = S_attr_gap;
		    case S_attr_gap:	/* Expecting attribute or = or > */
			if (isspace((int) c))
				break;	/* Gap after attribute */

			if (c == '>')
				goto got_element_open;
			else if (c == '=')
				context->state = S_equals;
			else
				goto S_attr; /* Get next attribute */
			break;

		    case S_equals:	/* After attr = */ 
			if (isspace((int) c))
				break;	/* Before attribute value */

			if (c == '>')
			    {		/* End of tag */
				HTTRACE(SGML_TRACE, "found = but no value\n");
				goto got_element_open;
			    }
			else if (c == '\'')
				context->state = S_squoted;
			else if (c == '"')
				context->state = S_dquoted;
			else
				goto S_value;
			break;

		    S_value:
			context->state = S_value;
			HTChunk_truncate(string, context->token);
		    case S_value:
			if (isspace((int) c) || c == '>')
			    {
				HTChunk_terminate(string);
				handle_attribute_value(context);
				context->token = HTChunk_size(string);
				goto S_tag_gap;
			    }
			else
				HTChunk_putc(string, c);
			break;
		
		    case S_squoted:	/* Quoted attribute value */
			if (c == '\'')
			    {
				HTChunk_terminate(string);
				handle_attribute_value(context);
				context->token = HTChunk_size(string);
				context->state = S_tag_gap;
			    }
			else if (c && c != '\n' && c != '\r')
				HTChunk_putc(string, c);
			break;
	
		    case S_dquoted:	/* Quoted attribute value */
			if (c == '"')
			    {
				HTChunk_terminate(string);
				handle_attribute_value(context);
				context->token = HTChunk_size(string);
				context->state = S_tag_gap;
			    }
			else if (c && c != '\n' && c != '\r')
				HTChunk_putc(string, c);
			break;

		    case S_end:	/* </ */
			if (isalnum((int) c))
				HTChunk_putc(string, c);
			else
			    {		/* End of end tag name */
				HTTag *t;
				char * first;
				HTChunk_terminate(string);
				if ((first=HTChunk_data(string))!=NULL && *first != '\0')
				        t = SGMLFindTag(dtd, HTChunk_data(string));
				else
				    	/* Empty end tag */
					/* Original code popped here one
					   from the stack. If this feature
					   is required, I have to put the
					   stack back... -- msa */
					t = NULL;
				if (!t) {
				    HTTRACE(SGML_TRACE, "Unknown end tag </%s>\n" _ HTChunk_data(string));
				    (*context->actions->unparsed_end_element)
					(context->target, HTChunk_data(string), HTChunk_size(string));
				} else {
				    context->current_tag = NULL;
				    end_element(context, t);
				}
				HTChunk_clear(string);
				context->current_attribute_number = INVALID;
				if (c != '>')
				    {
					if (!isspace((int) c))
					    HTTRACE(SGML_TRACE, "`</%s%c' found!\n" _ HTChunk_data(string) _ c);
					context->state = S_junk_tag;
				    }
				else
				    {
					text = b;
					count = 0;
					context->state = S_text;
				    }
			    }
			break;

		    case S_junk_tag:
			if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

			/*
			** Scanning (actually skipping) declarations
			*/
		    case S_md:
			if (c == '-')
				context->state = S_com_1;
			else if (c == '"')
				context->state = S_md_dqs;
			else if (c == '\'')
				context->state = S_md_sqs;
			else if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_md_dqs: /* Skip double quoted string */
			if (c == '"')
				context->state = S_md;
			else if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_md_sqs: /* Skip single quoted string */
			if (c == '\'')
				context->state = S_md;
			else if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_com_1: /* Starting a comment? */
			context->state = (c == '-') ? S_com : S_md;
			if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_com: /* ..within comment */
			if (c == '-')
				context->state = S_com_2;
			break;

		    case S_com_2: /* Ending a comment ? */
			context->state = (c == '-') ? S_com_2a : S_com;
			break;
		    
		    case S_com_2a:
			if (c == '>') {
			    text = b;
			    count = 0;
			    context->state = S_text;
			} else if (c == '-') {
			    context->state = S_com_2a;
			} else
			    context->state = S_com;
			break;
		    }
	    }
	if (count > 0)
		PUTB(text, count);
	return HT_OK;
    }
예제 #5
0
PUBLIC NowIn_t CSParse_targetParser(CSParse_t * pCSParse, char demark, void * pVoid)
{
/*    ParseContext_t * pParseContext = pCSParse->pParseContext; */
    TargetObject_t * pTargetObject = pCSParse->pTargetObject;
    BOOL failedOnPunct = NO;
    char * token = 0;
    StateRet_t ret = StateRet_OK;
    int i;
static NowIn_t lastRet = NowIn_END;

    if (HTChunk_size(pCSParse->token)) {
        HTChunk_terminate(pCSParse->token);
        token = HTChunk_data(pCSParse->token);
    }
    for (i = 0; i < pTargetObject->stateTokenCount; i++) {
        StateToken_t * pStateToken = pTargetObject->stateTokens + i;
        pCSParse->pStateToken = pStateToken;

        if (!(pCSParse->currentSubState & pStateToken->validSubStates))
            continue;
        if (pStateToken->pCheck) {  /* use check function */
            StateRet_t checkRes;
            checkRes = (*pStateToken->pCheck)(pCSParse, pStateToken, token, demark);
            switch (checkRes) {
                case StateRet_WARN_BAD_PUNCT:
                    failedOnPunct = YES;
                case StateRet_WARN_NO_MATCH:
                    continue;
                case StateRet_ERROR_BAD_CHAR:
		    (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token, demark, StateRet_ERROR_BAD_CHAR);
		    /*                    if (pTargetObject->pDestroy)
		        (*pTargetObject->pDestroy)(pCSParse); */
                    return NowIn_ERROR;
	        default:
		    break;
            }
        } else {                    /* or match by name[s] */
            if (!(pStateToken->command & Command_MATCHANY)) {
	        if (token && pStateToken->name1) {
        	    if (strcasecomp(token, pStateToken->name1) && (!pStateToken->name2 || strcasecomp(token, pStateToken->name2)))
       		        continue;
	        } else {
		    if (token != pStateToken->name1)
	                continue;
	        }
	    }
            if (Punct_badDemark(pStateToken->validPunctuation, demark)) {
                failedOnPunct = YES;
                continue;
            }
        }
/* open or close and do the appropriate callbacks */
	if (lastRet != NowIn_CHAIN)
	    ParseTrace("%30s %c ", token ? token : "", demark);
        ParseTrace("%10s - %s:%10s => ", pCSParse->pTargetObject->note, CSParse_subState2str(pCSParse->currentSubState), pStateToken->note);
	if (pStateToken->command & Command_NOTOKEN) {
	    HTChunk_clear(pCSParse->token);
		token = 0;
	}
	if (pStateToken->command & Command_OPEN && pTargetObject->pOpen)
	    if ((*pTargetObject->pOpen)(pCSParse, token, demark) == StateRet_ERROR)
		return NowIn_ERROR;
        if (pStateToken->command & (Command_OPEN|Command_CLOSE) && pCSParse->pParseContext->pTargetChangeCallback) {
	    ParseTrace("%3d", pStateToken->command & Command_CLOSE ? -pTargetObject->targetChange : pTargetObject->targetChange);
	    if ((*pCSParse->pParseContext->pTargetChangeCallback)(pCSParse, pTargetObject, pTargetObject->targetChange, 
		(BOOL)(pStateToken->command & Command_CLOSE), pVoid) == StateRet_ERROR)
		return NowIn_ERROR;
	} else
	    ParseTrace("   ");
        if (pStateToken->command & Command_CLOSE && pTargetObject->pClose)
            ret = (*pTargetObject->pClose)(pCSParse, token, demark);

        if (pStateToken->pPrep && ret != NowIn_ERROR)
            ret = (*pStateToken->pPrep)(pCSParse, token, demark);
        if (pStateToken->pNextTargetObject)
            pCSParse->pTargetObject = pStateToken->pNextTargetObject;
        if (pStateToken->nextSubState != SubState_X)
            pCSParse->currentSubState = pStateToken->nextSubState;
        ParseTrace("%10s - %s", pCSParse->pTargetObject->note, CSParse_subState2str(pCSParse->currentSubState));
        if (pStateToken->command & Command_CHAIN) {
	    ParseTrace(" -O-O-");
            return lastRet = NowIn_CHAIN;
	}
	ParseTrace("\n");
        return lastRet = ret == StateRet_ERROR_BAD_CHAR ? NowIn_ERROR : ret == StateRet_DONE ? NowIn_END : NowIn_ENGINE;
    }
    (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token, demark, failedOnPunct ? StateRet_WARN_BAD_PUNCT : StateRet_WARN_NO_MATCH);
    if (pTargetObject->pDestroy)
	    (*pTargetObject->pDestroy)(pCSParse);
    return NowIn_ERROR;
}
예제 #6
0
/* CSParse_parseChunk - elemental parse engine for all pics nowIns. This passes 
 * tokenized data into the handler functions in the CSParse_t.handlersOf. These 
 * handlers are responsibel for placing the data in the appropriate target.
 * The text is broken into nowIns and passed a SubParser based on the current 
 * nowIn which is one of:
 *  NowIn_NEEDOPEN - get paren and go to NowIn_ENGINE, text is an error
 *  NowIn_ENGINE - in a containing structure, text goes to engineOf_
 *  NowIn_NEEDCLOSE - get paren and go to NowIn_ENGINE, text is an error
 *  NowIn_END - expect no more text or parens
 *  NowIn_ERROR - 
 */
PUBLIC CSDoMore_t CSParse_parseChunk (CSParse_t * pCSParse, const char * ptr, int len, void * pVoid)
{
    int i;
    if (!len || !ptr)
        return CSDoMore_error;
    for (i = 0; i < len; i++) {
        pCSParse->offset++;
        if (pCSParse->quoteState) {
            if (pCSParse->quoteState == ptr[i]) {
                pCSParse->quoteState = 0;
                pCSParse->demark = ' ';
            }
            else
                HTChunk_putb(pCSParse->token, ptr+i, 1);
            continue;
        }
        if (ptr[i] == SQUOTE || ptr[i] == DQUOTE) {
            if (pCSParse->demark) {
                while ((pCSParse->nowIn = (*pCSParse->pParseContext->engineOf)(pCSParse, ' ', pVoid)) == NowIn_CHAIN);
                HTChunk_clear(pCSParse->token);
                pCSParse->demark = 0;
            } else if (HTChunk_size(pCSParse->token) && 
/*                  && warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) */
		       callErrorHandler(pCSParse, ptr+i, ptr[i], 
					StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
		    pCSParse->nowIn = NowIn_ERROR;
            pCSParse->quoteState = ptr[i];
            pCSParse->pParseContext->observedQuotes = YES;
            continue;
        }
        switch (pCSParse->nowIn) {
            case NowIn_NEEDOPEN:
                if (ptr[i] == LPAREN) {
                    pCSParse->nowIn = NowIn_ENGINE;
                    continue;
                }
                if (isspace((int) ptr[i]))
                    continue;
/*                if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */
	        if (callErrorHandler(pCSParse, ptr+i, ptr[i], 
				     StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
		    pCSParse->nowIn = NowIn_ERROR;
                continue;
            case NowIn_ENGINE:
                if (isspace((int) ptr[i])) {
                    if (HTChunk_size(pCSParse->token))
                        pCSParse->demark = ' ';
                    continue;
                }
                if (ptr[i] == LPAREN || ptr[i] == RPAREN || pCSParse->demark) {
		    /* parens override space demarkation */
		    if (ptr[i] == LPAREN) pCSParse->demark = LPAREN;
		    if (ptr[i] == RPAREN) pCSParse->demark = RPAREN;
		    /* call the engine as long as it wants re-entrance */
                    while ((pCSParse->nowIn = (*pCSParse->pParseContext->engineOf)(pCSParse, pCSParse->demark, pVoid)) == NowIn_CHAIN);
                    HTChunk_clear(pCSParse->token);
                    pCSParse->demark = 0;
                    if (ptr[i] == LPAREN || ptr[i] == RPAREN)
                        continue;
                    /* continue with next token */
                }
                HTChunk_putb(pCSParse->token, ptr+i, 1);
                continue;
            case NowIn_NEEDCLOSE:
                if (ptr[i] == RPAREN) {
                    pCSParse->nowIn = NowIn_ENGINE;
                    continue;
                }
                if (isspace((int) ptr[i]))
                    continue;
		if (callErrorHandler(pCSParse, ptr+i, ptr[i], 
				     StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
		    pCSParse->nowIn = NowIn_ERROR;
/*                if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */
                continue;
            case NowIn_END:
#if 0 /* enable this to tell the parser to check the remainder of 
		 the stream after the parsed object thinks it is done */
                if (isspace(ptr[i]))
                    continue;
/*                if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */
		if (callErrorHandler(pCSParse, ptr+i, ptr[i], 
				     StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
		    pCSParse->nowIn = NowIn_ERROR;
                continue;
#else
                return CSDoMore_done;
#endif
            case NowIn_MATCHCLOSE:
                if (ptr[i] == RPAREN) {
                    if (!pCSParse->depth)
                        pCSParse->nowIn = NowIn_ENGINE;
                    else
                        pCSParse->depth--;
                }
                if (ptr[i] == LPAREN)
                    pCSParse->depth++;
                continue;
            case NowIn_ERROR:
                return CSDoMore_error;
                break;
            default:
		HTTRACE(PICS_TRACE, "PICS: Internal error in parser - bad nowIn:%d.\n" _
			pCSParse->nowIn);
		return CSDoMore_error;
        }
    }
    /* check completion */
    return pCSParse->nowIn == NowIn_END ? CSDoMore_done : CSDoMore_more;
}