Natural Tiny Shell (NT-Shell) library is a tiny shell library for a small embedded system. The interface is really simple. You should only know ntshell_execute in ntshell.h. So you can port it to any embedded system easily. Please enjoy your small embedded system with it. :)
Dependents: NaturalTinyShell_TestProgram
vtparse.c@0:7147d6024de8, 2011-05-22 (annotated)
- Committer:
- shintamainjp
- Date:
- Sun May 22 02:51:35 2011 +0000
- Revision:
- 0:7147d6024de8
Initial version.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
shintamainjp | 0:7147d6024de8 | 1 | /** |
shintamainjp | 0:7147d6024de8 | 2 | * @file vtparse.c |
shintamainjp | 0:7147d6024de8 | 3 | * @brief VTParse |
shintamainjp | 0:7147d6024de8 | 4 | * @details |
shintamainjp | 0:7147d6024de8 | 5 | * An implementation of Paul Williams' DEC compatible state machine parser |
shintamainjp | 0:7147d6024de8 | 6 | * This code is in the public domain. |
shintamainjp | 0:7147d6024de8 | 7 | * @author Joshua Haberman <joshua@reverberate.org> |
shintamainjp | 0:7147d6024de8 | 8 | */ |
shintamainjp | 0:7147d6024de8 | 9 | |
shintamainjp | 0:7147d6024de8 | 10 | #include <string.h> |
shintamainjp | 0:7147d6024de8 | 11 | #include <stdlib.h> |
shintamainjp | 0:7147d6024de8 | 12 | #include <stdio.h> |
shintamainjp | 0:7147d6024de8 | 13 | |
shintamainjp | 0:7147d6024de8 | 14 | #include "vtparse.h" |
shintamainjp | 0:7147d6024de8 | 15 | #include "vtparse_table.h" |
shintamainjp | 0:7147d6024de8 | 16 | #include "ntlibc.h" |
shintamainjp | 0:7147d6024de8 | 17 | |
shintamainjp | 0:7147d6024de8 | 18 | void vtparse_init(vtparse_t *parser, vtparse_callback_t cb) |
shintamainjp | 0:7147d6024de8 | 19 | { |
shintamainjp | 0:7147d6024de8 | 20 | parser->state = VTPARSE_STATE_GROUND; |
shintamainjp | 0:7147d6024de8 | 21 | parser->intermediate_chars[0] = '\0'; |
shintamainjp | 0:7147d6024de8 | 22 | parser->num_params = 0; |
shintamainjp | 0:7147d6024de8 | 23 | parser->ignore_flagged = 0; |
shintamainjp | 0:7147d6024de8 | 24 | parser->cb = cb; |
shintamainjp | 0:7147d6024de8 | 25 | } |
shintamainjp | 0:7147d6024de8 | 26 | |
shintamainjp | 0:7147d6024de8 | 27 | static void do_action(vtparse_t *parser, vtparse_action_t action, char ch) |
shintamainjp | 0:7147d6024de8 | 28 | { |
shintamainjp | 0:7147d6024de8 | 29 | /* Some actions we handle internally (like parsing parameters), others |
shintamainjp | 0:7147d6024de8 | 30 | * we hand to our client for processing */ |
shintamainjp | 0:7147d6024de8 | 31 | |
shintamainjp | 0:7147d6024de8 | 32 | switch(action) { |
shintamainjp | 0:7147d6024de8 | 33 | case VTPARSE_ACTION_PRINT: |
shintamainjp | 0:7147d6024de8 | 34 | case VTPARSE_ACTION_EXECUTE: |
shintamainjp | 0:7147d6024de8 | 35 | case VTPARSE_ACTION_HOOK: |
shintamainjp | 0:7147d6024de8 | 36 | case VTPARSE_ACTION_PUT: |
shintamainjp | 0:7147d6024de8 | 37 | case VTPARSE_ACTION_OSC_START: |
shintamainjp | 0:7147d6024de8 | 38 | case VTPARSE_ACTION_OSC_PUT: |
shintamainjp | 0:7147d6024de8 | 39 | case VTPARSE_ACTION_OSC_END: |
shintamainjp | 0:7147d6024de8 | 40 | case VTPARSE_ACTION_UNHOOK: |
shintamainjp | 0:7147d6024de8 | 41 | case VTPARSE_ACTION_CSI_DISPATCH: |
shintamainjp | 0:7147d6024de8 | 42 | case VTPARSE_ACTION_ESC_DISPATCH: |
shintamainjp | 0:7147d6024de8 | 43 | parser->cb(parser, action, ch); |
shintamainjp | 0:7147d6024de8 | 44 | break; |
shintamainjp | 0:7147d6024de8 | 45 | |
shintamainjp | 0:7147d6024de8 | 46 | case VTPARSE_ACTION_IGNORE: |
shintamainjp | 0:7147d6024de8 | 47 | /* do nothing */ |
shintamainjp | 0:7147d6024de8 | 48 | break; |
shintamainjp | 0:7147d6024de8 | 49 | |
shintamainjp | 0:7147d6024de8 | 50 | case VTPARSE_ACTION_COLLECT: |
shintamainjp | 0:7147d6024de8 | 51 | { |
shintamainjp | 0:7147d6024de8 | 52 | /* Append the character to the intermediate params */ |
shintamainjp | 0:7147d6024de8 | 53 | int num_intermediate_chars = ntlibc_strlen((char*)parser->intermediate_chars); |
shintamainjp | 0:7147d6024de8 | 54 | |
shintamainjp | 0:7147d6024de8 | 55 | if(num_intermediate_chars + 1 > MAX_INTERMEDIATE_CHARS) |
shintamainjp | 0:7147d6024de8 | 56 | parser->ignore_flagged = 1; |
shintamainjp | 0:7147d6024de8 | 57 | else |
shintamainjp | 0:7147d6024de8 | 58 | parser->intermediate_chars[num_intermediate_chars++] = ch; |
shintamainjp | 0:7147d6024de8 | 59 | |
shintamainjp | 0:7147d6024de8 | 60 | break; |
shintamainjp | 0:7147d6024de8 | 61 | } |
shintamainjp | 0:7147d6024de8 | 62 | |
shintamainjp | 0:7147d6024de8 | 63 | case VTPARSE_ACTION_PARAM: |
shintamainjp | 0:7147d6024de8 | 64 | { |
shintamainjp | 0:7147d6024de8 | 65 | /* process the param character */ |
shintamainjp | 0:7147d6024de8 | 66 | if(ch == ';') |
shintamainjp | 0:7147d6024de8 | 67 | { |
shintamainjp | 0:7147d6024de8 | 68 | parser->num_params += 1; |
shintamainjp | 0:7147d6024de8 | 69 | parser->params[parser->num_params-1] = 0; |
shintamainjp | 0:7147d6024de8 | 70 | } |
shintamainjp | 0:7147d6024de8 | 71 | else |
shintamainjp | 0:7147d6024de8 | 72 | { |
shintamainjp | 0:7147d6024de8 | 73 | /* the character is a digit */ |
shintamainjp | 0:7147d6024de8 | 74 | int current_param; |
shintamainjp | 0:7147d6024de8 | 75 | |
shintamainjp | 0:7147d6024de8 | 76 | if(parser->num_params == 0) |
shintamainjp | 0:7147d6024de8 | 77 | { |
shintamainjp | 0:7147d6024de8 | 78 | parser->num_params = 1; |
shintamainjp | 0:7147d6024de8 | 79 | parser->params[0] = 0; |
shintamainjp | 0:7147d6024de8 | 80 | } |
shintamainjp | 0:7147d6024de8 | 81 | |
shintamainjp | 0:7147d6024de8 | 82 | current_param = parser->num_params - 1; |
shintamainjp | 0:7147d6024de8 | 83 | parser->params[current_param] *= 10; |
shintamainjp | 0:7147d6024de8 | 84 | parser->params[current_param] += (ch - '0'); |
shintamainjp | 0:7147d6024de8 | 85 | } |
shintamainjp | 0:7147d6024de8 | 86 | |
shintamainjp | 0:7147d6024de8 | 87 | break; |
shintamainjp | 0:7147d6024de8 | 88 | } |
shintamainjp | 0:7147d6024de8 | 89 | |
shintamainjp | 0:7147d6024de8 | 90 | case VTPARSE_ACTION_CLEAR: |
shintamainjp | 0:7147d6024de8 | 91 | parser->intermediate_chars[0] = '\0'; |
shintamainjp | 0:7147d6024de8 | 92 | parser->num_params = 0; |
shintamainjp | 0:7147d6024de8 | 93 | parser->ignore_flagged = 0; |
shintamainjp | 0:7147d6024de8 | 94 | break; |
shintamainjp | 0:7147d6024de8 | 95 | |
shintamainjp | 0:7147d6024de8 | 96 | default: |
shintamainjp | 0:7147d6024de8 | 97 | // Internal error: Unknown action. |
shintamainjp | 0:7147d6024de8 | 98 | break; |
shintamainjp | 0:7147d6024de8 | 99 | } |
shintamainjp | 0:7147d6024de8 | 100 | } |
shintamainjp | 0:7147d6024de8 | 101 | |
shintamainjp | 0:7147d6024de8 | 102 | static void do_state_change(vtparse_t *parser, state_change_t change, char ch) |
shintamainjp | 0:7147d6024de8 | 103 | { |
shintamainjp | 0:7147d6024de8 | 104 | /* A state change is an action and/or a new state to transition to. */ |
shintamainjp | 0:7147d6024de8 | 105 | |
shintamainjp | 0:7147d6024de8 | 106 | vtparse_state_t new_state = STATE(change); |
shintamainjp | 0:7147d6024de8 | 107 | vtparse_action_t action = ACTION(change); |
shintamainjp | 0:7147d6024de8 | 108 | |
shintamainjp | 0:7147d6024de8 | 109 | |
shintamainjp | 0:7147d6024de8 | 110 | if(new_state) |
shintamainjp | 0:7147d6024de8 | 111 | { |
shintamainjp | 0:7147d6024de8 | 112 | /* Perform up to three actions: |
shintamainjp | 0:7147d6024de8 | 113 | * 1. the exit action of the old state |
shintamainjp | 0:7147d6024de8 | 114 | * 2. the action associated with the transition |
shintamainjp | 0:7147d6024de8 | 115 | * 3. the entry actionk of the new action |
shintamainjp | 0:7147d6024de8 | 116 | */ |
shintamainjp | 0:7147d6024de8 | 117 | |
shintamainjp | 0:7147d6024de8 | 118 | vtparse_action_t exit_action = GET_EXIT_ACTIONS(parser->state); |
shintamainjp | 0:7147d6024de8 | 119 | vtparse_action_t entry_action = GET_ENTRY_ACTIONS(new_state); |
shintamainjp | 0:7147d6024de8 | 120 | |
shintamainjp | 0:7147d6024de8 | 121 | if(exit_action) |
shintamainjp | 0:7147d6024de8 | 122 | do_action(parser, exit_action, 0); |
shintamainjp | 0:7147d6024de8 | 123 | |
shintamainjp | 0:7147d6024de8 | 124 | if(action) |
shintamainjp | 0:7147d6024de8 | 125 | do_action(parser, action, ch); |
shintamainjp | 0:7147d6024de8 | 126 | |
shintamainjp | 0:7147d6024de8 | 127 | if(entry_action) |
shintamainjp | 0:7147d6024de8 | 128 | do_action(parser, entry_action, 0); |
shintamainjp | 0:7147d6024de8 | 129 | |
shintamainjp | 0:7147d6024de8 | 130 | parser->state = new_state; |
shintamainjp | 0:7147d6024de8 | 131 | } |
shintamainjp | 0:7147d6024de8 | 132 | else |
shintamainjp | 0:7147d6024de8 | 133 | { |
shintamainjp | 0:7147d6024de8 | 134 | do_action(parser, action, ch); |
shintamainjp | 0:7147d6024de8 | 135 | } |
shintamainjp | 0:7147d6024de8 | 136 | } |
shintamainjp | 0:7147d6024de8 | 137 | |
shintamainjp | 0:7147d6024de8 | 138 | void vtparse(vtparse_t *parser, unsigned char *data, int len) |
shintamainjp | 0:7147d6024de8 | 139 | { |
shintamainjp | 0:7147d6024de8 | 140 | int i; |
shintamainjp | 0:7147d6024de8 | 141 | for(i = 0; i < len; i++) |
shintamainjp | 0:7147d6024de8 | 142 | { |
shintamainjp | 0:7147d6024de8 | 143 | unsigned char ch = data[i]; |
shintamainjp | 0:7147d6024de8 | 144 | |
shintamainjp | 0:7147d6024de8 | 145 | /* If a transition is defined from the "anywhere" state, always |
shintamainjp | 0:7147d6024de8 | 146 | * use that. Otherwise use the transition from the current state. */ |
shintamainjp | 0:7147d6024de8 | 147 | |
shintamainjp | 0:7147d6024de8 | 148 | state_change_t change = GET_STATE_TABLE(VTPARSE_STATE_ANYWHERE, ch); |
shintamainjp | 0:7147d6024de8 | 149 | |
shintamainjp | 0:7147d6024de8 | 150 | if(!change) |
shintamainjp | 0:7147d6024de8 | 151 | change = GET_STATE_TABLE(parser->state, ch); |
shintamainjp | 0:7147d6024de8 | 152 | |
shintamainjp | 0:7147d6024de8 | 153 | do_state_change(parser, change, data[i]); |
shintamainjp | 0:7147d6024de8 | 154 | } |
shintamainjp | 0:7147d6024de8 | 155 | } |
shintamainjp | 0:7147d6024de8 | 156 |