1 /* CSParse.c
2 ** PICS CONFIGURATION MANAGER FOR CLIENTS AND SERVERS
3 **
4 ** (c) COPYRIGHT MIT 1995.
5 ** Please first read the full copyright statement in the file COPYRIGHT.
6 **
7 ** This module converts application/xpics streams (files or network) to PICS_ class data
8 **
9 ** History:
10 ** 4 Dec 95 EGP start
11 ** 15 Feb 96 EGP alpha 1
12 **
13 ** BUGS: no code yet; doesn't actually do anything
14 */
15
16 /* Library include files */
17 #include "wwwsys.h"
18 #include "HTChunk.h"
19 #include "HTString.h"
20 #include "CSLUtils.h"
21 #include "CSParse.h"
22
23 PUBLIC int ParseDebug = 0; /* For use with LablPars and RatPars */
24
BVal_readVal(BVal_t * pBVal,const char * valueStr)25 PUBLIC BOOL BVal_readVal(BVal_t * pBVal, const char * valueStr)
26 {
27 if (!strcasecomp(valueStr, "true") ||
28 !strcasecomp(valueStr, "yes"))
29 pBVal->state = BVal_YES;
30 else if (strcasecomp(valueStr, "false") &&
31 strcasecomp(valueStr, "no"))
32 return NO;;
33 pBVal->state |= BVal_INITIALIZED;
34 return YES;
35 }
36
BVal_initialized(const BVal_t * pBVal)37 PUBLIC BOOL BVal_initialized(const BVal_t * pBVal)
38 {
39 return (pBVal->state & BVal_INITIALIZED);
40 }
41
BVal_value(const BVal_t * pBVal)42 PUBLIC BOOL BVal_value(const BVal_t * pBVal)
43 {
44 return ((pBVal->state & BVal_YES) ? 1 : 0);
45 }
46
BVal_set(BVal_t * pBVal,BOOL value)47 PUBLIC void BVal_set(BVal_t * pBVal, BOOL value)
48 {
49 if (value)
50 pBVal->state = BVal_YES;
51 pBVal->state |= BVal_INITIALIZED;
52 return;
53 }
54
BVal_clear(BVal_t * pBVal)55 PUBLIC void BVal_clear(BVal_t * pBVal)
56 {
57 if (pBVal)
58 pBVal->state = BVal_UNINITIALIZED;
59 return;
60 }
61
FVal_readVal(FVal_t * pFVal,const char * valueStr)62 PUBLIC BOOL FVal_readVal(FVal_t * pFVal, const char * valueStr)
63 {
64 if (!strcasecomp(valueStr, "+INF")) {
65 pFVal->stat = FVal_POSITIVE_INF;
66 return YES;
67 }
68 if (!strcasecomp(valueStr, "-INF")) {
69 pFVal->stat = FVal_NEGATIVE_INF;
70 return YES;
71 }
72 pFVal->stat = FVal_VALUE;
73 sscanf(valueStr, "%f", &pFVal->value);
74 return YES;
75 }
76
FVal_initialized(const FVal_t * pFVal)77 PUBLIC BOOL FVal_initialized(const FVal_t * pFVal)
78 {
79 return (pFVal->stat != FVal_UNINITIALIZED);
80 }
81
FVal_value(const FVal_t * pFVal)82 PUBLIC float FVal_value(const FVal_t * pFVal)
83 {
84 return (pFVal->value);
85 }
86
87 /* C U T T I N G E D G E M A T H T E C H N O L O G Y H E R E */
FVal_lessThan(const FVal_t * pSmall,const FVal_t * pBig)88 PUBLIC BOOL FVal_lessThan(const FVal_t * pSmall, const FVal_t * pBig)
89 {
90 if (pBig->stat == FVal_UNINITIALIZED || pSmall->stat == FVal_UNINITIALIZED)
91 return FALSE;
92 if (pBig->stat == FVal_POSITIVE_INF || pSmall->stat == FVal_NEGATIVE_INF) {
93 if (pSmall->stat == FVal_POSITIVE_INF)
94 return FALSE;
95 return TRUE;
96 }
97 if (pBig->stat == FVal_NEGATIVE_INF || pSmall->stat == FVal_POSITIVE_INF) {
98 return FALSE;
99 }
100 return pSmall->value < pBig->value;
101 }
102
FVal_minus(const FVal_t * pBig,const FVal_t * pSmall)103 PUBLIC FVal_t FVal_minus(const FVal_t * pBig, const FVal_t * pSmall)
104 {
105 FVal_t ret = FVal_NEW_UNINITIALIZED;
106 /* no notion of 2 time infinity so please keep your limits to a minimum */
107 if (pBig->stat == FVal_UNINITIALIZED || pSmall->stat == FVal_UNINITIALIZED)
108 return ret;
109 FVal_set(&ret, (float)0.0);
110 if (pBig->stat == FVal_POSITIVE_INF || pSmall->stat == FVal_NEGATIVE_INF) {
111 if (pSmall->stat != FVal_POSITIVE_INF)
112 FVal_setInfinite(&ret, 0);
113 return ret;
114 }
115 if (pBig->stat == FVal_NEGATIVE_INF || pSmall->stat == FVal_POSITIVE_INF) {
116 if (pSmall->stat != FVal_NEGATIVE_INF)
117 FVal_setInfinite(&ret, 0);
118 return ret;
119 }
120 ret.value = pBig->value - pSmall->value;
121 return (ret);
122 }
123
FVal_nearerZero(const FVal_t * pRef,const FVal_t * pCheck)124 PUBLIC BOOL FVal_nearerZero(const FVal_t * pRef, const FVal_t * pCheck)
125 {
126 if (pRef->stat == FVal_UNINITIALIZED || pCheck->stat == FVal_UNINITIALIZED ||
127 pCheck->stat == FVal_POSITIVE_INF || pCheck->stat == FVal_NEGATIVE_INF)
128 return NO;
129 if (pRef->stat == FVal_POSITIVE_INF || pRef->stat == FVal_NEGATIVE_INF)
130 return YES;
131 if (pRef->value < 0.0) {
132 if (pCheck->value < 0.0)
133 return pCheck->value > pRef->value;
134 return pCheck->value < -pRef->value;
135 }
136 if (pCheck->value < 0.0)
137 return pCheck->value > -pRef->value;
138 return pCheck->value < pRef->value;
139 }
140
FVal_isZero(const FVal_t * pFVal)141 PUBLIC BOOL FVal_isZero(const FVal_t * pFVal)
142 {
143 if (pFVal->stat == FVal_VALUE && pFVal->value == 0.0)
144 return YES;
145 return NO;
146 }
147
FVal_set(FVal_t * pFVal,float value)148 PUBLIC void FVal_set(FVal_t * pFVal, float value)
149 {
150 pFVal->value = value;
151 pFVal->stat = FVal_VALUE;
152 }
153
FVal_setInfinite(FVal_t * pFVal,BOOL negative)154 PUBLIC void FVal_setInfinite(FVal_t * pFVal, BOOL negative)
155 {
156 pFVal->stat = negative ? FVal_NEGATIVE_INF : FVal_POSITIVE_INF;
157 }
158
FVal_isInfinite(const FVal_t * pFVal)159 PUBLIC int FVal_isInfinite(const FVal_t * pFVal)
160 {
161 return (pFVal->stat == FVal_POSITIVE_INF ? 1 : pFVal->stat == FVal_NEGATIVE_INF ? -1 : 0);
162 }
163
FVal_clear(FVal_t * pFVal)164 PUBLIC void FVal_clear(FVal_t * pFVal)
165 {
166 if (pFVal)
167 pFVal->stat = FVal_UNINITIALIZED;
168 return;
169 }
170
FVal_toStr(FVal_t * pFVal)171 PUBLIC char * FVal_toStr(FVal_t * pFVal)
172 {
173 char * ptr;
174 if ((ptr = (char *)HT_MALLOC(40)) == NULL)
175 HT_OUTOFMEM("FVal buffer");
176 sprintf(ptr, "%.1f", FVal_value(pFVal));
177 return ptr;
178 }
179
SVal_readVal(SVal_t * pSVal,const char * valueStr)180 PUBLIC BOOL SVal_readVal(SVal_t * pSVal, const char * valueStr)
181 {
182 pSVal->initialized = YES;
183 StrAllocCopy(pSVal->value, valueStr);
184 return YES;
185 }
186
SVal_initialized(const SVal_t * pSVal)187 PUBLIC BOOL SVal_initialized(const SVal_t * pSVal)
188 {
189 return (pSVal->initialized != NO);
190 }
191
SVal_value(const SVal_t * pSVal)192 PUBLIC char * SVal_value(const SVal_t * pSVal)
193 {
194 return (pSVal->value);
195 }
196
SVal_clear(SVal_t * pSVal)197 PUBLIC void SVal_clear(SVal_t * pSVal)
198 {
199 if (SVal_initialized(pSVal)) {
200 HT_FREE(pSVal->value);
201 pSVal->initialized = NO;
202 }
203 return;
204 }
205
206 #if 0
207 int year;
208 int month;
209 int day;
210 int hour;
211 int minute;
212 int timeZoneHours;
213 int timeZoneMinutes;
214 #endif
DVal_readVal(DVal_t * pDVal,const char * valueStr)215 PUBLIC BOOL DVal_readVal(DVal_t * pDVal, const char * valueStr)
216 {
217 char space[] = "1994.11.05T08:15-0500";
218 char timeZoneSign;
219 char timeZoneMinutesMSB;
220 if (strlen(valueStr) != 0x15)
221 return NO;
222 memcpy(space, valueStr, 0x15);
223 timeZoneSign = space[16];
224 timeZoneMinutesMSB = space[19];
225 space[4] = space[7] = space[10] = space[13] = space[16] = space[19] = 0;
226 pDVal->year = atoi(space);
227 pDVal->month = atoi(space+5);
228 pDVal->day = atoi(space+8);
229 pDVal->hour = atoi(space+11);
230 pDVal->minute = atoi(space+14);
231 pDVal->timeZoneHours = atoi(space+17);
232 space[19] = timeZoneMinutesMSB;
233 pDVal->timeZoneMinutes = atoi(space+19);
234 if (timeZoneSign == '-') {
235 pDVal->timeZoneHours = -pDVal->timeZoneHours;
236 pDVal->timeZoneMinutes = -pDVal->timeZoneMinutes;
237 }
238 StrAllocCopy(pDVal->value, valueStr);
239 pDVal->initialized = YES;
240 return YES;
241 }
242
DVal_initialized(const DVal_t * pDVal)243 PUBLIC BOOL DVal_initialized(const DVal_t * pDVal)
244 {
245 return (pDVal->initialized != NO);
246 }
247
DVal_compare(const DVal_t * a,const DVal_t * b)248 PUBLIC int DVal_compare(const DVal_t * a, const DVal_t * b)
249 {
250 if (a->year > b->year) return 1;
251 if (a->year < b->year) return -1;
252 if (a->month > b->month) return 1;
253 if (a->month < b->month) return -1;
254 if (a->day > b->day) return 1;
255 if (a->day < b->day) return -1;
256 if (a->hour+a->timeZoneHours > b->hour+b->timeZoneHours) return 1;
257 if (a->hour+a->timeZoneHours < b->hour+b->timeZoneHours) return -1;
258 if (a->minute+a->timeZoneMinutes > b->minute+b->timeZoneMinutes) return 1;
259 if (a->minute+a->timeZoneMinutes < b->minute+b->timeZoneMinutes) return -1;
260 return 0;
261 }
262
DVal_value(const DVal_t * pDVal)263 PUBLIC char * DVal_value(const DVal_t * pDVal)
264 {
265 return (pDVal->value);
266 }
267
DVal_clear(DVal_t * pDVal)268 PUBLIC void DVal_clear(DVal_t * pDVal)
269 {
270 if (DVal_initialized(pDVal)) {
271 HT_FREE(pDVal->value);
272 pDVal->initialized = NO;
273 }
274 return;
275 }
276
Range_toStr(Range_t * pRange)277 PUBLIC char * Range_toStr(Range_t * pRange)
278 {
279 HTChunk * pChunk;
280 char * ptr;
281 pChunk = HTChunk_new(20);
282 ptr = FVal_toStr(&pRange->min);
283 HTChunk_puts(pChunk, ptr);
284 HT_FREE(ptr);
285 if (FVal_initialized(&pRange->max)) {
286 ptr = FVal_toStr(&pRange->max);
287 HTChunk_puts(pChunk, ":");
288 HTChunk_puts(pChunk, ptr);
289 HT_FREE(ptr);
290 }
291 return HTChunk_toCString(pChunk);
292 }
293
294 /* Range_gap - find gap between 2 ranges. Either of these ranges may be a
295 * single value (in the min)
296 * negative vector indicates that ref is greater than test
297 */
Range_gap(Range_t * a,Range_t * b)298 PUBLIC FVal_t Range_gap(Range_t * a, Range_t * b)
299 {
300 Range_t aN = *a;
301 Range_t bN = *b;
302 FVal_t ret = FVal_NEW_UNINITIALIZED;
303 if (!FVal_initialized(&a->min) || !FVal_initialized(&b->min))
304 return (ret);
305
306 /* set ret for successful 0 returns */
307 FVal_set(&ret, (float)0.0);
308
309 /* normalize our ranges */
310 if (FVal_lessThan(&aN.max, &aN.min)) {
311 aN.max = a->min;
312 aN.min = a->max;
313 }
314 if (FVal_lessThan(&bN.max, &bN.min)) {
315 bN.max = b->min;
316 bN.min = b->max;
317 }
318
319 /* check partial ranges (just a min, no max) */
320 if (!FVal_initialized(&aN.max)) {
321 if (!FVal_initialized(&bN.max))
322 return FVal_minus(&aN.min, &bN.min);
323 if (FVal_lessThan(&aN.min, &bN.min))
324 return FVal_minus(&bN.min, &aN.min);
325 if (FVal_lessThan(&bN.max, &aN.min))
326 return FVal_minus(&bN.max, &aN.min);
327 return ret;
328 }
329 /* we have four values to compare */
330 {
331 FVal_t minDif = FVal_minus(&bN.min, &aN.min);
332 FVal_t maxDif = FVal_minus(&bN.max, &aN.max);
333 Range_t common;
334 common.min = FVal_lessThan(&bN.min, &aN.min) ? aN.min : bN.min;
335 common.max = FVal_lessThan(&bN.max, &aN.max) ? bN.max : aN.max;
336 if (!FVal_lessThan(&common.max, &common.min))
337 return ret;
338 /* failure - indicate how far we are off */
339 return FVal_nearerZero(&minDif, &maxDif) ? minDif : maxDif;
340 }
341 }
342
343 /* ------------------------------------------------------------------------- */
344
345 /* C O N S T R U C T O R S */
CSParse_new(void)346 PUBLIC CSParse_t * CSParse_new(void)
347 {
348 CSParse_t * me;
349 if ((me = (CSParse_t *) HT_CALLOC(1, sizeof(CSParse_t))) == NULL)
350 HT_OUTOFMEM("CSParse");
351 me->nowIn = NowIn_NEEDOPEN;
352 me->token = HTChunk_new(0x10);
353 if ((me->pParseContext = (ParseContext_t *) HT_CALLOC(1, sizeof(ParseContext_t))) == NULL)
354 HT_OUTOFMEM("ParseContext_t");
355 return me;
356 }
357
CSParse_delete(CSParse_t * me)358 PUBLIC void CSParse_delete(CSParse_t * me)
359 {
360 HT_FREE(me->pParseContext);
361 HTChunk_delete(me->token);
362 HT_FREE(me);
363 }
364
365 /* L A B E L P A R S E R S */
callErrorHandler(CSParse_t * pCSParse,const char * errorLocation,char demark,StateRet_t errorCode)366 PRIVATE StateRet_t callErrorHandler(CSParse_t * pCSParse,
367 const char * errorLocation,
368 char demark, StateRet_t errorCode)
369 {
370 char * token = HTChunk_data(pCSParse->token);
371 pCSParse->pParseContext->pTokenError = (char *) errorLocation;
372 return (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token,
373 demark, StateRet_ERROR_BAD_CHAR);
374 }
375
376 /* CSParse_parseChunk - elemental parse engine for all pics nowIns. This passes
377 * tokenized data into the handler functions in the CSParse_t.handlersOf. These
378 * handlers are responsibel for placing the data in the appropriate target.
379 * The text is broken into nowIns and passed a SubParser based on the current
380 * nowIn which is one of:
381 * NowIn_NEEDOPEN - get paren and go to NowIn_ENGINE, text is an error
382 * NowIn_ENGINE - in a containing structure, text goes to engineOf_
383 * NowIn_NEEDCLOSE - get paren and go to NowIn_ENGINE, text is an error
384 * NowIn_END - expect no more text or parens
385 * NowIn_ERROR -
386 */
CSParse_parseChunk(CSParse_t * pCSParse,const char * ptr,int len,void * pVoid)387 PUBLIC CSDoMore_t CSParse_parseChunk (CSParse_t * pCSParse, const char * ptr, int len, void * pVoid)
388 {
389 int i;
390 if (!len || !ptr)
391 return CSDoMore_error;
392 for (i = 0; i < len; i++) {
393 pCSParse->offset++;
394 if (pCSParse->quoteState) {
395 if (pCSParse->quoteState == ptr[i]) {
396 pCSParse->quoteState = 0;
397 pCSParse->demark = ' ';
398 }
399 else
400 HTChunk_putb(pCSParse->token, ptr+i, 1);
401 continue;
402 }
403 if (ptr[i] == SQUOTE || ptr[i] == DQUOTE) {
404 if (pCSParse->demark) {
405 while ((pCSParse->nowIn = (*pCSParse->pParseContext->engineOf)(pCSParse, ' ', pVoid)) == NowIn_CHAIN);
406 HTChunk_clear(pCSParse->token);
407 pCSParse->demark = 0;
408 } else if (HTChunk_size(pCSParse->token) &&
409 /* && warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) */
410 callErrorHandler(pCSParse, ptr+i, ptr[i],
411 StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
412 pCSParse->nowIn = NowIn_ERROR;
413 pCSParse->quoteState = ptr[i];
414 pCSParse->pParseContext->observedQuotes = YES;
415 continue;
416 }
417 switch (pCSParse->nowIn) {
418 case NowIn_NEEDOPEN:
419 if (ptr[i] == LPAREN) {
420 pCSParse->nowIn = NowIn_ENGINE;
421 continue;
422 }
423 if (isspace((int) ptr[i]))
424 continue;
425 /* if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */
426 if (callErrorHandler(pCSParse, ptr+i, ptr[i],
427 StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
428 pCSParse->nowIn = NowIn_ERROR;
429 continue;
430 case NowIn_ENGINE:
431 if (isspace((int) ptr[i])) {
432 if (HTChunk_size(pCSParse->token))
433 pCSParse->demark = ' ';
434 continue;
435 }
436 if (ptr[i] == LPAREN || ptr[i] == RPAREN || pCSParse->demark) {
437 /* parens override space demarkation */
438 if (ptr[i] == LPAREN) pCSParse->demark = LPAREN;
439 if (ptr[i] == RPAREN) pCSParse->demark = RPAREN;
440 /* call the engine as long as it wants re-entrance */
441 while ((pCSParse->nowIn = (*pCSParse->pParseContext->engineOf)(pCSParse, pCSParse->demark, pVoid)) == NowIn_CHAIN);
442 HTChunk_clear(pCSParse->token);
443 pCSParse->demark = 0;
444 if (ptr[i] == LPAREN || ptr[i] == RPAREN)
445 continue;
446 /* continue with next token */
447 }
448 HTChunk_putb(pCSParse->token, ptr+i, 1);
449 continue;
450 case NowIn_NEEDCLOSE:
451 if (ptr[i] == RPAREN) {
452 pCSParse->nowIn = NowIn_ENGINE;
453 continue;
454 }
455 if (isspace((int) ptr[i]))
456 continue;
457 if (callErrorHandler(pCSParse, ptr+i, ptr[i],
458 StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
459 pCSParse->nowIn = NowIn_ERROR;
460 /* if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */
461 continue;
462 case NowIn_END:
463 #if 0 /* enable this to tell the parser to check the remainder of
464 the stream after the parsed object thinks it is done */
465 if (isspace(ptr[i]))
466 continue;
467 /* if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */
468 if (callErrorHandler(pCSParse, ptr+i, ptr[i],
469 StateRet_ERROR_BAD_CHAR) !=StateRet_OK)
470 pCSParse->nowIn = NowIn_ERROR;
471 continue;
472 #else
473 return CSDoMore_done;
474 #endif
475 case NowIn_MATCHCLOSE:
476 if (ptr[i] == RPAREN) {
477 if (!pCSParse->depth)
478 pCSParse->nowIn = NowIn_ENGINE;
479 else
480 pCSParse->depth--;
481 }
482 if (ptr[i] == LPAREN)
483 pCSParse->depth++;
484 continue;
485 case NowIn_ERROR:
486 return CSDoMore_error;
487 break;
488 default:
489 HTTRACE(PICS_TRACE, "PICS: Internal error in parser - bad nowIn:%d.\n" _
490 pCSParse->nowIn);
491 return CSDoMore_error;
492 }
493 }
494 /* check completion */
495 return pCSParse->nowIn == NowIn_END ? CSDoMore_done : CSDoMore_more;
496 }
497
Punct_badDemark(Punct_t validPunctuation,char demark)498 PUBLIC BOOL Punct_badDemark(Punct_t validPunctuation, char demark)
499 {
500 switch (demark) {
501 case ' ': return (!(validPunctuation & Punct_WHITE));
502 case LPAREN: return (!(validPunctuation & Punct_LPAREN));
503 case RPAREN: return (!(validPunctuation & Punct_RPAREN));
504 }
505 return YES;
506 }
507
CSParse_subState2str(SubState_t subState)508 PUBLIC char * CSParse_subState2str(SubState_t subState)
509 {
510 static char space[33];
511 space[0] = 0;
512 if (subState == SubState_N)
513 strcpy(space, "N");
514 else if (subState == SubState_X)
515 strcpy(space, "X");
516 else {
517 int i;
518 SubState_t comp;
519 char ch[] = "A";
520 for (i = 1, comp = SubState_A; i < (sizeof(SubState_t)*8 - 1); i++, (*ch)++, comp<<=1)
521 if (comp & subState)
522 strcat(space, ch);
523 }
524 return space;
525 }
526
ParseTrace(const char * fmt,...)527 PRIVATE int ParseTrace(const char * fmt, ...)
528 {
529 va_list pArgs;
530 va_start(pArgs, fmt);
531 if (!ParseDebug)
532 return 0;
533 return (vfprintf(stderr, fmt, pArgs));
534 }
535
CSParse_targetParser(CSParse_t * pCSParse,char demark,void * pVoid)536 PUBLIC NowIn_t CSParse_targetParser(CSParse_t * pCSParse, char demark, void * pVoid)
537 {
538 /* ParseContext_t * pParseContext = pCSParse->pParseContext; */
539 TargetObject_t * pTargetObject = pCSParse->pTargetObject;
540 BOOL failedOnPunct = NO;
541 char * token = 0;
542 StateRet_t ret = StateRet_OK;
543 int i;
544 static NowIn_t lastRet = NowIn_END;
545
546 if (HTChunk_size(pCSParse->token)) {
547 HTChunk_terminate(pCSParse->token);
548 token = HTChunk_data(pCSParse->token);
549 }
550 for (i = 0; i < pTargetObject->stateTokenCount; i++) {
551 StateToken_t * pStateToken = pTargetObject->stateTokens + i;
552 pCSParse->pStateToken = pStateToken;
553
554 if (!(pCSParse->currentSubState & pStateToken->validSubStates))
555 continue;
556 if (pStateToken->pCheck) { /* use check function */
557 StateRet_t checkRes;
558 checkRes = (*pStateToken->pCheck)(pCSParse, pStateToken, token, demark);
559 switch (checkRes) {
560 case StateRet_WARN_BAD_PUNCT:
561 failedOnPunct = YES;
562 case StateRet_WARN_NO_MATCH:
563 continue;
564 case StateRet_ERROR_BAD_CHAR:
565 (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token, demark, StateRet_ERROR_BAD_CHAR);
566 /* if (pTargetObject->pDestroy)
567 (*pTargetObject->pDestroy)(pCSParse); */
568 return NowIn_ERROR;
569 default:
570 break;
571 }
572 } else { /* or match by name[s] */
573 if (!(pStateToken->command & Command_MATCHANY)) {
574 if (token && pStateToken->name1) {
575 if (strcasecomp(token, pStateToken->name1) && (!pStateToken->name2 || strcasecomp(token, pStateToken->name2)))
576 continue;
577 } else {
578 if (token != pStateToken->name1)
579 continue;
580 }
581 }
582 if (Punct_badDemark(pStateToken->validPunctuation, demark)) {
583 failedOnPunct = YES;
584 continue;
585 }
586 }
587 /* open or close and do the appropriate callbacks */
588 if (lastRet != NowIn_CHAIN)
589 ParseTrace("%30s %c ", token ? token : "", demark);
590 ParseTrace("%10s - %s:%10s => ", pCSParse->pTargetObject->note, CSParse_subState2str(pCSParse->currentSubState), pStateToken->note);
591 if (pStateToken->command & Command_NOTOKEN) {
592 HTChunk_clear(pCSParse->token);
593 token = 0;
594 }
595 if (pStateToken->command & Command_OPEN && pTargetObject->pOpen)
596 if ((*pTargetObject->pOpen)(pCSParse, token, demark) == StateRet_ERROR)
597 return NowIn_ERROR;
598 if (pStateToken->command & (Command_OPEN|Command_CLOSE) && pCSParse->pParseContext->pTargetChangeCallback) {
599 ParseTrace("%3d", pStateToken->command & Command_CLOSE ? -pTargetObject->targetChange : pTargetObject->targetChange);
600 if ((*pCSParse->pParseContext->pTargetChangeCallback)(pCSParse, pTargetObject, pTargetObject->targetChange,
601 (BOOL)(pStateToken->command & Command_CLOSE), pVoid) == StateRet_ERROR)
602 return NowIn_ERROR;
603 } else
604 ParseTrace(" ");
605 if (pStateToken->command & Command_CLOSE && pTargetObject->pClose)
606 ret = (*pTargetObject->pClose)(pCSParse, token, demark);
607
608 if (pStateToken->pPrep && ret != NowIn_ERROR)
609 ret = (*pStateToken->pPrep)(pCSParse, token, demark);
610 if (pStateToken->pNextTargetObject)
611 pCSParse->pTargetObject = pStateToken->pNextTargetObject;
612 if (pStateToken->nextSubState != SubState_X)
613 pCSParse->currentSubState = pStateToken->nextSubState;
614 ParseTrace("%10s - %s", pCSParse->pTargetObject->note, CSParse_subState2str(pCSParse->currentSubState));
615 if (pStateToken->command & Command_CHAIN) {
616 ParseTrace(" -O-O-");
617 return lastRet = NowIn_CHAIN;
618 }
619 ParseTrace("\n");
620 return lastRet = ret == StateRet_ERROR_BAD_CHAR ? NowIn_ERROR : ret == StateRet_DONE ? NowIn_END : NowIn_ENGINE;
621 }
622 (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token, demark, failedOnPunct ? StateRet_WARN_BAD_PUNCT : StateRet_WARN_NO_MATCH);
623 if (pTargetObject->pDestroy)
624 (*pTargetObject->pDestroy)(pCSParse);
625 return NowIn_ERROR;
626 }
627
628