PRIVATE int NewsPost_put_block (HTStream * me, const char* b, int l) { if (!me->target) { return HT_WOULD_BLOCK; } else if (me->transparent) return b ? PUTBLOCK(b, l) : HT_OK; else { int status; NewsPost_start(me, me->request); if ((status = PUTBLOCK(HTChunk_data(me->buffer), HTChunk_size(me->buffer))) == HT_OK) { me->transparent = YES; return b ? PUTBLOCK(b, l) : HT_OK; } return status; } }
/* ** Folding is either of CF LWS, LF LWS, CRLF LWS */ PRIVATE int CSUserList_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 */ CSUserList_addLine(me); me->EOLstate = EOL_BEGIN; HTChunkClear(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 */ CSUserList_addLine(me); me->EOLstate = EOL_BEGIN; HTChunkClear(me->buffer); continue; } } else if (me->EOLstate == EOL_DOT) { if (isspace((int) *b)) { me->EOLstate = EOL_BEGIN; HTChunkPutc(me->buffer, ' '); } else { CSUserList_addLine(me); me->EOLstate = EOL_BEGIN; HTChunkClear(me->buffer); continue; } } else if (*b == CR) { me->EOLstate = EOL_FCR; } else if (*b == LF) { me->EOLstate = EOL_FLF; /* Line found */ } else HTChunkPutc(me->buffer, *b); l--; b++; } if (HTChunk_size(me->buffer)) CSUserList_addLine(me); return HT_OK; }
/* Handle entity ** ------------- ** ** On entry, ** s contains the entity name zero terminated */ PRIVATE void handle_entity (HTStream * context) { const char ** entities = context->dtd->entity_names; const char *s = HTChunk_data(context->string); int high, low, i, diff; for(low=0, high = context->dtd->number_of_entities; high > low ; diff < 0 ? (low = i+1) : (high = i)) { i = (low + (high-low)/2); diff = strcmp(entities[i], s); /* Case sensitive! */ if (diff==0) { /* success: found it */ (*context->actions->put_entity)(context->target, i); return; } } /* If entity string not found */ HTTRACE(SGML_TRACE, "Unknown entity %s\n" _ s); (*context->actions->unparsed_entity) (context->target, HTChunk_data(context->string), HTChunk_size(context->string)); }
/* ** Header is terminated by CRCR, LFLF, CRLFLF, CRLFCRLF ** Folding is either of CF LWS, LF LWS, CRLF LWS */ PRIVATE int HTMIME_put_block (HTStream * me, const char * b, int l) { const char * start = b; const char * end = start; const char * value = HTChunk_size(me->value) > 0 ? b : NULL; int length = l; int status; while (!me->transparent) { if (me->EOLstate == EOL_FCR) { if (*b == CR) /* End of header */ me->EOLstate = EOL_END; else if (*b == LF) /* CRLF */ me->EOLstate = EOL_FLF; else if (isspace((int) *b)) /* Folding: CR SP */ me->EOLstate = EOL_FOLD; else /* New line */ me->EOLstate = EOL_LINE; } else if (me->EOLstate == EOL_FLF) { if (*b == CR) /* LF CR or CR LF CR */ me->EOLstate = EOL_SCR; else if (*b == LF) /* End of header */ me->EOLstate = EOL_END; else if (isspace((int) *b)) /* Folding: LF SP or CR LF SP */ me->EOLstate = EOL_FOLD; else /* New line */ me->EOLstate = EOL_LINE; } else if (me->EOLstate == EOL_SCR) { if (*b==CR || *b==LF) /* End of header */ me->EOLstate = EOL_END; else if (isspace((int) *b)) /* Folding: LF CR SP or CR LF CR SP */ me->EOLstate = EOL_FOLD; else /* New line */ me->EOLstate = EOL_LINE; } else if (*b == CR) me->EOLstate = EOL_FCR; else if (*b == LF) me->EOLstate = EOL_FLF; /* Line found */ else { if (!me->haveToken) { if (*b == ':' || isspace((int) *b)) { HTChunk_putb(me->token, start, end-start); HTChunk_putc(me->token, '\0'); me->haveToken = YES; } else { unsigned char ch = *(unsigned char *) b; ch = TOLOWER(ch); me->hash = (me->hash * 3 + ch) % MIME_HASH_SIZE; } } else if (value == NULL && *b != ':' && !isspace((int) *b)) value = b; end++; } switch (me->EOLstate) { case EOL_LINE: case EOL_END: { int ret = HT_ERROR; HTChunk_putb(me->value, value, end-value); HTChunk_putc(me->value, '\0'); ret = _stream2dispatchParsers(me); HTNet_addBytesRead(me->net, b-start); start=b, end=b; if (me->EOLstate == EOL_END) { /* EOL_END */ if (ret == HT_OK) { b++, l--; ret = pumpData(me); HTNet_addBytesRead(me->net, 1); if (me->mode & (HT_MIME_FOOTER | HT_MIME_CONT)) { HTHost_setConsumed(HTNet_host(me->net), length - l); return ret; } else { HTNet_setHeaderBytesRead(me->net, HTNet_bytesRead(me->net)); } } } else { /* EOL_LINE */ HTChunk_truncate(me->token,0); HTChunk_truncate(me->value,0); me->haveToken = NO; me->hash = 0; value = NULL; } me->EOLstate = EOL_BEGIN; if (ret != HT_OK && ret != HT_LOADED) return ret; break; } case EOL_FOLD: me->EOLstate = EOL_BEGIN; if (!me->haveToken) { HTChunk_putb(me->token, start, end-start); HTChunk_putc(me->token, '\0'); me->haveToken = YES; } else if (value) { HTChunk_putb(me->value, value, end-value); HTChunk_putc(me->value, ' '); } start=b, end=b; break; default: b++, l--; if (!l) { BOOL stop = NO; if (!me->haveToken) { /* If empty header then prepare to stop */ if (end-start) HTChunk_putb(me->token, start, end-start); else stop = YES; } else if (value) HTChunk_putb(me->value, value, end-value); HTHost_setConsumed(HTNet_host(me->net), length - l); return stop ? pumpData(me) : HT_OK; } } } if (length != l) HTHost_setConsumed(HTNet_host(me->net), length - l); /* ** Put the rest down the stream without touching the data but make sure ** that we get the correct content length of data. If we have a CL in ** the headers then this stream is responsible for the accountance. */ if (me->hasBody) { HTNet * net = me->net; /* Check if CL at all - thanks to [email protected] (John Wei) */ long cl = HTResponse_length(me->response); if (cl >= 0) { long bodyRead = HTNet_bytesRead(net) - HTNet_headerBytesRead(net); /* ** If we have more than we need then just take what belongs to us. */ if (bodyRead + l >= cl) { int consume = cl - bodyRead; if ((status = (*me->target->isa->put_block)(me->target, b, consume)) < 0) return status; else { HTAlertCallback * cbf = HTAlert_find(HT_PROG_DONE); HTNet_addBytesRead(net, consume); HTHost_setConsumed(HTNet_host(net), consume); if (cbf) (*cbf)(me->request, HT_PROG_DONE, HT_MSG_NULL, NULL, NULL, NULL); return HT_LOADED; } } else { if ((status = (*me->target->isa->put_block)(me->target, b, l)) < 0) return status; HTNet_addBytesRead(net, l); HTHost_setConsumed(HTNet_host(net), l); return status; } } return (*me->target->isa->put_block)(me->target, b, l); } else { HTAlertCallback * cbf = HTAlert_find(HT_PROG_DONE); if (cbf) (*cbf)(me->request, HT_PROG_DONE, HT_MSG_NULL, NULL, NULL, NULL); } return HT_LOADED; }
unsigned int BinURLInputStream::readBytes(XMLByte* const toFill , const unsigned int maxToRead) { unsigned int retval = 0; unsigned int bytesAsked = maxToRead; unsigned int bytesForCopy = 0; // Wipe out the old stuff from the destination buffer to fill. memset((void*)toFill, 0x00, sizeof(XMLByte) * maxToRead); // You can only read till the end of the remote resource file. // So, adjust the count of bytes you want to read now. if (fBytesProcessed + bytesAsked >= fRemoteFileSize) { bytesAsked = fRemoteFileSize - fBytesProcessed; } if (fBufferSize > 0) bytesForCopy = fBufferSize - fBufferIndex; if (bytesAsked <= bytesForCopy) { // ...then you can satisfy this request completely from fBuffer. // Simply copy over the bytes to the destination array. memcpy((void*) toFill, (void*) (fBuffer + fBufferIndex), bytesAsked); fBufferIndex += bytesAsked; if (fBufferIndex >= fBufferSize) { fBufferSize = 0; fBufferIndex = 0; } fBytesProcessed += bytesAsked; retval = bytesAsked; } else { // ...will need to read some more bytes out of the stream. unsigned int bufToFillIndex = 0; HTRequest* request = HTRequest_new(); HTChunk* result = NULL; char ranges[64]; // First copy over what is left in fBuffer, before reading another // chunk out of the stream. if (bytesForCopy != 0) { memcpy((void*) toFill, (void*) (fBuffer + fBufferSize), bytesForCopy); fBufferSize = 0; fBufferIndex = 0; fBytesProcessed += bytesForCopy; bufToFillIndex = bytesForCopy; retval = bytesForCopy; } unsigned int bytesRemainingForCopy = bytesAsked - bytesForCopy; // Now read a new chunk from the stream. HTTP lets you specify the // range of bytes that you would like. sprintf(ranges, "%ld-%ld", fBytesProcessed, fRemoteFileSize<(fBytesProcessed + URLISBUFMAXSIZE)? fRemoteFileSize - 1: fBytesProcessed + URLISBUFMAXSIZE - 1); HTRequest_addRange(request, "bytes", ranges); HTRequest_setOutputFormat(request, WWW_SOURCE); result = HTLoadAnchorToChunk(fAnchor, request); fBufferSize = HTChunk_size(result); if (fBufferSize > 0) { // Store the read chunk in fBuffer. memset((void*) fBuffer, 0x00, URLISBUFMAXSIZE); memcpy((void*) fBuffer, (void*) HTChunk_data(result), fBufferSize); fBufferIndex = 0; } HTRequest_delete(request); HTChunk_delete(result); // Now fill the destination buffer with the new data just read. bytesForCopy = fBufferSize; if (bytesRemainingForCopy > fBufferSize) { bytesRemainingForCopy = fBufferSize; } memcpy((void*) (toFill + bufToFillIndex), (void*) fBuffer, bytesRemainingForCopy); // Update counters. retval += bytesRemainingForCopy; fBufferIndex += bytesRemainingForCopy; fBytesProcessed += bytesRemainingForCopy; } return retval; }
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; }
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; }
/* 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; }