From 682f23e7bb4a52bedf46eff5c4859e1308eda124 Mon Sep 17 00:00:00 2001 From: Michał Cichoń Date: Tue, 25 Aug 2015 19:56:24 +0200 Subject: Update build ref --- vtparse/src/vtparse.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 vtparse/src/vtparse.c (limited to 'vtparse/src/vtparse.c') diff --git a/vtparse/src/vtparse.c b/vtparse/src/vtparse.c new file mode 100644 index 0000000..b24a4a4 --- /dev/null +++ b/vtparse/src/vtparse.c @@ -0,0 +1,152 @@ +/* + * VTParse - an implementation of Paul Williams' DEC compatible state machine parser + * + * Author: Joshua Haberman + * + * This code is in the public domain. + */ + +#include +#include +#include + +#include "vtparse.h" + +void vtparse_init(vtparse_t *parser, vtparse_callback_t cb) +{ + parser->state = VTPARSE_STATE_GROUND; + parser->intermediate_chars[0] = '\0'; + parser->num_params = 0; + parser->ignore_flagged = 0; + parser->cb = cb; +} + +static void do_action(vtparse_t *parser, vtparse_action_t action, char ch) +{ + /* Some actions we handle internally (like parsing parameters), others + * we hand to our client for processing */ + + switch(action) { + case VTPARSE_ACTION_PRINT: + case VTPARSE_ACTION_EXECUTE: + case VTPARSE_ACTION_HOOK: + case VTPARSE_ACTION_PUT: + case VTPARSE_ACTION_OSC_START: + case VTPARSE_ACTION_OSC_PUT: + case VTPARSE_ACTION_OSC_END: + case VTPARSE_ACTION_UNHOOK: + case VTPARSE_ACTION_CSI_DISPATCH: + case VTPARSE_ACTION_ESC_DISPATCH: + parser->cb(parser, action, ch); + break; + + case VTPARSE_ACTION_IGNORE: + /* do nothing */ + break; + + case VTPARSE_ACTION_COLLECT: + { + /* Append the character to the intermediate params */ + int num_intermediate_chars = strlen((char*)parser->intermediate_chars); + + if(num_intermediate_chars + 1 > MAX_INTERMEDIATE_CHARS) + parser->ignore_flagged = 1; + else + parser->intermediate_chars[num_intermediate_chars++] = ch; + + break; + } + + case VTPARSE_ACTION_PARAM: + { + /* process the param character */ + if(ch == ';') + { + parser->num_params += 1; + parser->params[parser->num_params-1] = 0; + } + else + { + /* the character is a digit */ + int current_param; + + if(parser->num_params == 0) + { + parser->num_params = 1; + parser->params[0] = 0; + } + + current_param = parser->num_params - 1; + parser->params[current_param] *= 10; + parser->params[current_param] += (ch - '0'); + } + + break; + } + + case VTPARSE_ACTION_CLEAR: + parser->intermediate_chars[0] = '\0'; + parser->num_params = 0; + parser->ignore_flagged = 0; + break; + + default: + fprintf(stderr, "Internal error, unknown action %d", action); + } +} + +static void do_state_change(vtparse_t *parser, state_change_t change, char ch) +{ + /* A state change is an action and/or a new state to transition to. */ + + vtparse_state_t new_state = STATE(change); + vtparse_action_t action = ACTION(change); + + + if(new_state) + { + /* Perform up to three actions: + * 1. the exit action of the old state + * 2. the action associated with the transition + * 3. the entry actionk of the new action + */ + + vtparse_action_t exit_action = EXIT_ACTIONS[parser->state]; + vtparse_action_t entry_action = ENTRY_ACTIONS[new_state]; + + if(exit_action) + do_action(parser, exit_action, 0); + + if(action) + do_action(parser, action, ch); + + if(entry_action) + do_action(parser, entry_action, 0); + + parser->state = new_state; + } + else + { + do_action(parser, action, ch); + } +} + +void vtparse(vtparse_t *parser, unsigned char *data, int len) +{ + int i; + for(i = 0; i < len; i++) + { + unsigned char ch = data[i]; + + /* If a transition is defined from the "anywhere" state, always + * use that. Otherwise use the transition from the current state. */ + + state_change_t change = STATE_TABLE[VTPARSE_STATE_ANYWHERE][ch]; + + if(!change) + change = STATE_TABLE[parser->state][ch]; + + do_state_change(parser, change, data[i]); + } +} + -- cgit v1.2.3