Add Julian Scheid to credits, and add TODO note about character set support.
[vtparse.git] / vtparse.c
blob7627bb1b380116d861a59c961df610cf1b142dd9
1 /*
2 * VTParse - an implementation of Paul Williams' DEC compatible state machine parser
4 * Author: Joshua Haberman <joshua@reverberate.org>
6 * This code is in the public domain.
7 */
9 #include "vtparse.h"
11 void vtparse_init(vtparse_t *parser, vtparse_callback_t cb)
13 parser->state = VTPARSE_STATE_GROUND;
14 parser->num_intermediate_chars = 0;
15 parser->num_params = 0;
16 parser->ignore_flagged = 0;
17 parser->cb = cb;
20 static void do_action(vtparse_t *parser, vtparse_action_t action, char ch)
22 /* Some actions we handle internally (like parsing parameters), others
23 * we hand to our client for processing */
25 switch(action) {
26 case VTPARSE_ACTION_PRINT:
27 case VTPARSE_ACTION_EXECUTE:
28 case VTPARSE_ACTION_HOOK:
29 case VTPARSE_ACTION_PUT:
30 case VTPARSE_ACTION_OSC_START:
31 case VTPARSE_ACTION_OSC_PUT:
32 case VTPARSE_ACTION_OSC_END:
33 case VTPARSE_ACTION_UNHOOK:
34 case VTPARSE_ACTION_CSI_DISPATCH:
35 case VTPARSE_ACTION_ESC_DISPATCH:
36 parser->cb(parser, action, ch);
37 break;
39 case VTPARSE_ACTION_IGNORE:
40 /* do nothing */
41 break;
43 case VTPARSE_ACTION_COLLECT:
45 /* Append the character to the intermediate params */
46 if(parser->num_intermediate_chars + 1 > MAX_INTERMEDIATE_CHARS)
47 parser->ignore_flagged = 1;
48 else
49 parser->intermediate_chars[parser->num_intermediate_chars++] = ch;
51 break;
54 case VTPARSE_ACTION_PARAM:
56 /* process the param character */
57 if(ch == ';')
59 parser->num_params += 1;
60 parser->params[parser->num_params-1] = 0;
62 else
64 /* the character is a digit */
65 int current_param;
67 if(parser->num_params == 0)
69 parser->num_params = 1;
70 parser->params[0] = 0;
73 current_param = parser->num_params - 1;
74 parser->params[current_param] *= 10;
75 parser->params[current_param] += (ch - '0');
78 break;
81 case VTPARSE_ACTION_CLEAR:
82 parser->num_intermediate_chars = 0;
83 parser->num_params = 0;
84 parser->ignore_flagged = 0;
85 break;
87 default:
88 parser->cb(parser, VTPARSE_ACTION_ERROR, 0);
92 static void do_state_change(vtparse_t *parser, state_change_t change, char ch)
94 /* A state change is an action and/or a new state to transition to. */
96 vtparse_state_t new_state = STATE(change);
97 vtparse_action_t action = ACTION(change);
100 if(new_state)
102 /* Perform up to three actions:
103 * 1. the exit action of the old state
104 * 2. the action associated with the transition
105 * 3. the entry action of the new state
108 vtparse_action_t exit_action = EXIT_ACTIONS[parser->state-1];
109 vtparse_action_t entry_action = ENTRY_ACTIONS[new_state-1];
111 if(exit_action)
112 do_action(parser, exit_action, 0);
114 if(action)
115 do_action(parser, action, ch);
117 if(entry_action)
118 do_action(parser, entry_action, 0);
120 parser->state = new_state;
122 else
124 do_action(parser, action, ch);
128 void vtparse(vtparse_t *parser, unsigned char *data, int len)
130 int i;
131 for(i = 0; i < len; i++)
133 unsigned char ch = data[i];
134 state_change_t change = STATE_TABLE[parser->state-1][ch];
135 do_state_change(parser, change, ch);