/* Tokenize a header. tokens may be NULL, in which case the number of tokens are counted, allowing the caller to allocate enough room */ static void tokenize(const char *header, php_rfc822_token_t *tokens, int *ntokens, int report_errors) { register const char *p, *q, *start; int in_bracket = 0; /* NB: parser assumes that the header has two bytes of NUL terminator */ YYCURSOR = header; YYLIMIT = YYCURSOR + strlen(YYCURSOR) + 1; *ntokens = 0; state_ground: start = YYCURSOR; #if DEBUG_RFC822_SCANNER printf("ground: start=%p limit=%p cursor=%p: [%d] %s\n", start, YYLIMIT, YYCURSOR, *YYCURSOR, YYCURSOR); #endif { YYCTYPE yych; static const unsigned char yybm[] = { 0, 192, 192, 192, 192, 192, 192, 192, 192, 96, 96, 192, 192, 96, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 96, 64, 0, 192, 192, 64, 192, 192, 64, 64, 192, 192, 64, 192, 64, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 64, 64, 64, 64, 64, 64, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 64, 192, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, }; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; if (yybm[0+yych] & 32) { goto yy4; } if (yych <= '-') { if (yych <= '%') { if (yych <= '!') { if (yych <= 0x00) goto yy2; if (yych <= ' ') goto yy21; goto yy19; } else { if (yych <= '"') goto yy12; if (yych <= '$') goto yy21; goto yy19; } } else { if (yych <= ')') { if (yych <= '\'') goto yy21; if (yych <= '(') goto yy10; goto yy7; } else { if (yych == ',') goto yy19; goto yy21; } } } else { if (yych <= '>') { if (yych <= ';') { if (yych <= '/') goto yy19; if (yych <= '9') goto yy21; goto yy19; } else { if (yych <= '<') goto yy15; if (yych <= '=') goto yy19; goto yy17; } } else { if (yych <= '[') { if (yych <= '@') goto yy19; if (yych <= 'Z') goto yy21; goto yy19; } else { if (yych <= '\\') goto yy9; if (yych <= ']') goto yy19; goto yy21; } } } yy2: ++YYCURSOR; { goto stop; } yy4: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 32) { goto yy4; } { DBG_STATE("SPACE"); goto state_ground; } yy7: ++YYCURSOR; yy8: { REPORT_ERR("token not valid in ground state"); goto state_ground; } yy9: yych = *++YYCURSOR; if (yybm[0+yych] & 128) { goto yy21; } goto yy8; yy10: ++YYCURSOR; { DBG_STATE("START COMMENT"); if (tokens) { tokens->token = '('; tokens->value = start; tokens->valuelen = 0; } goto state_comment; } yy12: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 64) { goto yy12; } if (yych >= 0x01) goto yy26; yy15: ++YYCURSOR; if ((yych = *YYCURSOR) == '>') goto yy24; { DBG_STATE("LANGLE"); if (in_bracket) { REPORT_ERR("already in < bracket"); goto state_ground; } in_bracket = 1; ADD_ATOM_TOKEN(); goto state_ground; } yy17: ++YYCURSOR; { DBG_STATE("RANGLE"); if (!in_bracket) { REPORT_ERR("not in < bracket"); goto state_ground; } in_bracket = 0; ADD_ATOM_TOKEN(); goto state_ground; } yy19: ++YYCURSOR; { DBG_STATE("ATOM"); ADD_ATOM_TOKEN(); goto state_ground; } yy21: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy21; } { DBG_STATE("ANY"); if (tokens) { tokens->token = 0; tokens->valuelen = YYCURSOR - start; tokens->value = start; tokens++; } ++*ntokens; goto state_ground; } yy24: ++YYCURSOR; { DBG_STATE("NULL <>"); ADD_ATOM_TOKEN(); if (tokens) { tokens->token = 0; tokens->value = ""; tokens->valuelen = 0; tokens++; } ++*ntokens; start++; ADD_ATOM_TOKEN(); goto state_ground; } yy26: ++YYCURSOR; { DBG_STATE("QUOTE STRING"); if (tokens) { tokens->token = '"'; tokens->value = start + 1; tokens->valuelen = YYCURSOR - start - 2; tokens++; } ++*ntokens; goto state_ground; } } state_comment: { int comment_depth = 1; while (1) { if (*YYCURSOR == 0) { /* unexpected end of header */ REPORT_ERR("unexpected end of header"); /* fake a quoted string for this last token */ if (tokens) tokens->token = '"'; ++*ntokens; return; } else if (*YYCURSOR == '(') { comment_depth++; } else if (*YYCURSOR == ')' && --comment_depth == 0) { /* end of nested comment sequence */ YYCURSOR++; if (tokens) tokens->valuelen++; break; } else if (*YYCURSOR == '\\' && YYCURSOR[1]) { YYCURSOR++; if (tokens) tokens->valuelen++; } YYCURSOR++; } if (tokens) { tokens->valuelen = YYCURSOR - tokens->value; tokens++; } ++*ntokens; goto state_ground; } stop: #if DEBUG_RFC822_SCANNER printf("STOPing parser ntokens=%d YYCURSOR=%p YYLIMIT=%p start=%p " "cursor=[%d] %s start=%s\n", *ntokens, YYCURSOR, YYLIMIT, start, *YYCURSOR, YYCURSOR, start); #else ; #endif }
int STM_Execute1( STM_StateMachine *sm, STM_StateMachine **currSm ) { int action; /* Action to execute. */ STM_Input input; /* Input being processed. */ int nextState; /* Next state to change to. */ uint8_t *stateData; /* Ptr to state data for current state. */ STM_StateMachine *svSm; /* Saved value of STM_CurrStateMachine */ ASSERT( sm != NULL ); ASSERT( sm->magic == STM_MAGIC ); if (( input = GetInput( sm )) == STM_INPUT_NONE ) { /* * No input, indicate that we didn't do anything */ return FALSE; } /* * Set the global state machine variable, so that actions which use it * can access this state machine. Save the old value off so that action * routines can execute other state machines. */ if ( currSm != NULL ) { svSm = *currSm; *currSm = sm; } /* * We've got an input, run it through the state machine */ DBG_INPUT( "STM %s: processing input %s (%d)\n", sm->name, sm->currInputStr, sm->currInput ); stateData = &sm->stateData[ sm->currState * STM_BytesPerState( sm )]; nextState = stateData[ STM_NextStateOffset( input )]; /* * Exit the old state */ if ( nextState != sm->currState ) { int exitAction; /* * We're leaving the old state, call the exit routine if one is * defined */ exitAction = stateData[ STM_ExitOffset() ]; ExecuteAction( sm, exitAction, "exit " ); } /* * Call the action routine */ action = stateData[ STM_ActionOffset( input )]; ExecuteAction( sm, action, "" ); if ( nextState != sm->currState ) { int enterAction; /* * Enter the new state */ DBG_STATE( "STM %s: Changing states from %s (%d) to %s (%d)\n", sm->name, sm->stateStr[ sm->currState ], sm->currState, sm->stateStr[ nextState ], nextState ); sm->currState = nextState; stateData = &sm->stateData[ sm->currState * STM_BytesPerState( sm )]; /* * We're entering the new state, call the enter routine if one is * defined */ enterAction = stateData[ STM_EnterOffset() ]; ExecuteAction( sm, enterAction, "enter " ); } if ( currSm != NULL ) { *currSm = svSm; } /* * We processed an input, tell the caller */ sm->currInput = STM_INPUT_NONE; #if defined( STM_DEBUG ) sm->currInputStr = "- None -"; #endif return TRUE; } // STM_Execute1