You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
527 lines
11 KiB
527 lines
11 KiB
7 years ago
|
|
||
|
/* #line 1 "user/ini_parser.rl" */
|
||
|
|
||
|
/* Ragel constants block */
|
||
|
#include "ini_parser.h"
|
||
|
|
||
|
// Ragel setup
|
||
|
|
||
|
/* #line 10 "user/ini_parser.c" */
|
||
|
static const char _ini_actions[] ESP_CONST_DATA = {
|
||
|
0, 1, 1, 1, 2, 1, 3, 1,
|
||
|
4, 1, 5, 1, 6, 1, 7, 1,
|
||
|
8, 1, 9, 1, 10, 1, 11, 1,
|
||
|
13, 2, 0, 4, 2, 12, 4
|
||
|
};
|
||
|
|
||
|
static const char _ini_eof_actions[] ESP_CONST_DATA = {
|
||
|
0, 23, 5, 5, 15, 15, 15, 15,
|
||
|
19, 19, 0, 0, 0, 0, 0, 0,
|
||
|
0
|
||
|
};
|
||
|
|
||
|
static const int ini_start = 1;
|
||
|
static const int ini_first_final = 12;
|
||
|
static const int ini_error = 0;
|
||
|
|
||
|
static const int ini_en_section = 2;
|
||
|
static const int ini_en_keyvalue = 4;
|
||
|
static const int ini_en_comment = 8;
|
||
|
static const int ini_en_discard2eol = 10;
|
||
|
static const int ini_en_main = 1;
|
||
|
|
||
|
|
||
|
/* #line 10 "user/ini_parser.rl" */
|
||
|
|
||
|
|
||
|
// Persistent state
|
||
|
static int8_t cs = -1; //!< Ragel's Current State variable
|
||
|
static uint32_t buff_i = 0; //!< Write pointer for the buffers
|
||
|
static char value_quote = 0; //!< Quote character of the currently collected value
|
||
|
static bool value_nextesc = false; //!< Next character is escaped, trated specially, and if quote, as literal quote character
|
||
|
static IniParserCallback keyCallback = NULL; //!< Currently assigned callback
|
||
|
static void *userdata = NULL; //!< Currently assigned user data for the callback
|
||
|
|
||
|
// Buffers
|
||
|
static char keybuf[INI_KEY_MAX];
|
||
|
static char secbuf[INI_KEY_MAX];
|
||
|
static char valbuf[INI_VALUE_MAX];
|
||
|
|
||
|
// See header for doxygen!
|
||
|
|
||
|
void ICACHE_FLASH_ATTR
|
||
|
ini_parse_reset_partial(void)
|
||
|
{
|
||
|
buff_i = 0;
|
||
|
value_quote = 0;
|
||
|
value_nextesc = false;
|
||
|
}
|
||
|
|
||
|
void ICACHE_FLASH_ATTR
|
||
|
ini_parse_reset(void)
|
||
|
{
|
||
|
ini_parse_reset_partial();
|
||
|
keybuf[0] = secbuf[0] = valbuf[0] = 0;
|
||
|
|
||
|
/* #line 67 "user/ini_parser.c" */
|
||
|
{
|
||
|
cs = ini_start;
|
||
|
}
|
||
|
|
||
|
/* #line 41 "user/ini_parser.rl" */
|
||
|
}
|
||
|
|
||
|
void ICACHE_FLASH_ATTR
|
||
|
ini_parser_error(const char* msg)
|
||
|
{
|
||
|
ini_error("Parser error: %s", msg);
|
||
|
ini_parse_reset_partial();
|
||
|
}
|
||
|
|
||
|
|
||
|
void ICACHE_FLASH_ATTR
|
||
|
ini_parse_begin(IniParserCallback callback, void *userData)
|
||
|
{
|
||
|
keyCallback = callback;
|
||
|
userdata = userData;
|
||
|
ini_parse_reset();
|
||
|
}
|
||
|
|
||
|
|
||
|
void ICACHE_FLASH_ATTR
|
||
|
*ini_parse_end(void)
|
||
|
{
|
||
|
ini_parse("\n", 1);
|
||
|
if (keyCallback) {
|
||
|
keyCallback = NULL;
|
||
|
}
|
||
|
|
||
|
void *ud = userdata;
|
||
|
userdata = NULL;
|
||
|
return ud;
|
||
|
}
|
||
|
|
||
|
|
||
|
void ICACHE_FLASH_ATTR
|
||
|
ini_parse_file(const char *text, size_t len, IniParserCallback callback, void *userData)
|
||
|
{
|
||
|
ini_parse_begin(callback, userData);
|
||
|
ini_parse(text, len);
|
||
|
ini_parse_end();
|
||
|
}
|
||
|
|
||
|
static void ICACHE_FLASH_ATTR
|
||
|
rtrim_buf(char *buf, int32_t end)
|
||
|
{
|
||
|
if (end > 0) {
|
||
|
while ((uint8_t)buf[--end] < 33);
|
||
|
end++; // go past the last character
|
||
|
}
|
||
|
|
||
|
buf[end] = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void ICACHE_FLASH_ATTR
|
||
|
ini_parse(const char *newstr, size_t len)
|
||
|
{
|
||
|
int32_t i;
|
||
|
char c;
|
||
|
bool isnl;
|
||
|
bool isquot;
|
||
|
|
||
|
// Load new data to Ragel vars
|
||
|
const uint8_t *p;
|
||
|
const uint8_t *eof;
|
||
|
const uint8_t *pe;
|
||
|
|
||
|
if (len == 0) while(newstr[++len] != 0); // alternative to strlen
|
||
|
|
||
|
p = (const uint8_t *) newstr;
|
||
|
eof = NULL;
|
||
|
pe = (const uint8_t *) (newstr + len);
|
||
|
|
||
|
// Init Ragel on the first run
|
||
|
if (cs == -1) {
|
||
|
ini_parse_reset();
|
||
|
}
|
||
|
|
||
|
// The parser
|
||
|
|
||
|
/* #line 152 "user/ini_parser.c" */
|
||
|
{
|
||
|
const char *_acts;
|
||
|
unsigned int _nacts;
|
||
|
|
||
|
if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
if ( cs == 0 )
|
||
|
goto _out;
|
||
|
_resume:
|
||
|
switch ( cs ) {
|
||
|
case 1:
|
||
|
switch( (*p) ) {
|
||
|
case 32u: goto tr1;
|
||
|
case 35u: goto tr3;
|
||
|
case 58u: goto tr0;
|
||
|
case 59u: goto tr3;
|
||
|
case 61u: goto tr0;
|
||
|
case 91u: goto tr4;
|
||
|
}
|
||
|
if ( (*p) < 9u ) {
|
||
|
if ( (*p) <= 8u )
|
||
|
goto tr0;
|
||
|
} else if ( (*p) > 13u ) {
|
||
|
if ( 14u <= (*p) && (*p) <= 31u )
|
||
|
goto tr0;
|
||
|
} else
|
||
|
goto tr1;
|
||
|
goto tr2;
|
||
|
case 0:
|
||
|
goto _out;
|
||
|
case 12:
|
||
|
goto tr0;
|
||
|
case 2:
|
||
|
switch( (*p) ) {
|
||
|
case 9u: goto tr6;
|
||
|
case 32u: goto tr6;
|
||
|
case 93u: goto tr5;
|
||
|
}
|
||
|
if ( (*p) <= 31u )
|
||
|
goto tr5;
|
||
|
goto tr7;
|
||
|
case 3:
|
||
|
if ( (*p) == 93u )
|
||
|
goto tr8;
|
||
|
if ( (*p) > 8u ) {
|
||
|
if ( 10u <= (*p) && (*p) <= 31u )
|
||
|
goto tr5;
|
||
|
} else
|
||
|
goto tr5;
|
||
|
goto tr7;
|
||
|
case 13:
|
||
|
goto tr5;
|
||
|
case 4:
|
||
|
switch( (*p) ) {
|
||
|
case 10u: goto tr10;
|
||
|
case 58u: goto tr11;
|
||
|
case 61u: goto tr11;
|
||
|
}
|
||
|
goto tr9;
|
||
|
case 5:
|
||
|
switch( (*p) ) {
|
||
|
case 9u: goto tr13;
|
||
|
case 10u: goto tr14;
|
||
|
case 13u: goto tr15;
|
||
|
case 32u: goto tr13;
|
||
|
}
|
||
|
goto tr12;
|
||
|
case 6:
|
||
|
switch( (*p) ) {
|
||
|
case 10u: goto tr14;
|
||
|
case 13u: goto tr15;
|
||
|
}
|
||
|
goto tr12;
|
||
|
case 14:
|
||
|
goto tr10;
|
||
|
case 7:
|
||
|
if ( (*p) == 10u )
|
||
|
goto tr14;
|
||
|
goto tr10;
|
||
|
case 8:
|
||
|
switch( (*p) ) {
|
||
|
case 10u: goto tr17;
|
||
|
case 13u: goto tr18;
|
||
|
}
|
||
|
goto tr16;
|
||
|
case 15:
|
||
|
goto tr19;
|
||
|
case 9:
|
||
|
if ( (*p) == 10u )
|
||
|
goto tr17;
|
||
|
goto tr19;
|
||
|
case 10:
|
||
|
switch( (*p) ) {
|
||
|
case 10u: goto tr21;
|
||
|
case 13u: goto tr22;
|
||
|
}
|
||
|
goto tr20;
|
||
|
case 16:
|
||
|
goto tr23;
|
||
|
case 11:
|
||
|
if ( (*p) == 10u )
|
||
|
goto tr21;
|
||
|
goto tr23;
|
||
|
}
|
||
|
|
||
|
tr23: cs = 0; goto _again;
|
||
|
tr0: cs = 0; goto f0;
|
||
|
tr5: cs = 0; goto f4;
|
||
|
tr10: cs = 0; goto f7;
|
||
|
tr19: cs = 0; goto f11;
|
||
|
tr1: cs = 1; goto _again;
|
||
|
tr6: cs = 2; goto _again;
|
||
|
tr7: cs = 3; goto f5;
|
||
|
tr9: cs = 4; goto f8;
|
||
|
tr13: cs = 5; goto _again;
|
||
|
tr11: cs = 5; goto f9;
|
||
|
tr12: cs = 6; goto f10;
|
||
|
tr15: cs = 7; goto _again;
|
||
|
tr16: cs = 8; goto _again;
|
||
|
tr18: cs = 9; goto _again;
|
||
|
tr20: cs = 10; goto _again;
|
||
|
tr22: cs = 11; goto _again;
|
||
|
tr2: cs = 12; goto f1;
|
||
|
tr3: cs = 12; goto f2;
|
||
|
tr4: cs = 12; goto f3;
|
||
|
tr8: cs = 13; goto f6;
|
||
|
tr14: cs = 14; goto f10;
|
||
|
tr17: cs = 15; goto f12;
|
||
|
tr21: cs = 16; goto f13;
|
||
|
|
||
|
f5: _acts = _ini_actions + 1; goto execFuncs;
|
||
|
f6: _acts = _ini_actions + 3; goto execFuncs;
|
||
|
f4: _acts = _ini_actions + 5; goto execFuncs;
|
||
|
f1: _acts = _ini_actions + 7; goto execFuncs;
|
||
|
f8: _acts = _ini_actions + 9; goto execFuncs;
|
||
|
f9: _acts = _ini_actions + 11; goto execFuncs;
|
||
|
f10: _acts = _ini_actions + 13; goto execFuncs;
|
||
|
f7: _acts = _ini_actions + 15; goto execFuncs;
|
||
|
f12: _acts = _ini_actions + 17; goto execFuncs;
|
||
|
f11: _acts = _ini_actions + 19; goto execFuncs;
|
||
|
f13: _acts = _ini_actions + 21; goto execFuncs;
|
||
|
f0: _acts = _ini_actions + 23; goto execFuncs;
|
||
|
f3: _acts = _ini_actions + 25; goto execFuncs;
|
||
|
f2: _acts = _ini_actions + 28; goto execFuncs;
|
||
|
|
||
|
execFuncs:
|
||
|
_nacts = *_acts++;
|
||
|
while ( _nacts-- > 0 ) {
|
||
|
switch ( *_acts++ ) {
|
||
|
case 0:
|
||
|
/* #line 130 "user/ini_parser.rl" */
|
||
|
{
|
||
|
buff_i = 0;
|
||
|
{cs = 2;goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
/* #line 135 "user/ini_parser.rl" */
|
||
|
{
|
||
|
if (buff_i >= INI_KEY_MAX) {
|
||
|
ini_parser_error("Section name too long");
|
||
|
{cs = 10;goto _again;}
|
||
|
}
|
||
|
keybuf[buff_i++] = (*p);
|
||
|
}
|
||
|
break;
|
||
|
case 2:
|
||
|
/* #line 143 "user/ini_parser.rl" */
|
||
|
{
|
||
|
// we need a separate buffer for the result, otherwise a failed
|
||
|
// partial parse would corrupt the section string
|
||
|
rtrim_buf(keybuf, buff_i);
|
||
|
for (i = 0; (c = keybuf[i]) != 0; i++) secbuf[i] = c;
|
||
|
secbuf[i] = 0;
|
||
|
{cs = 1;goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 3:
|
||
|
/* #line 155 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in [section]");
|
||
|
if((*p) == '\n') {cs = 1;goto _again;} else {cs = 10;goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 4:
|
||
|
/* #line 162 "user/ini_parser.rl" */
|
||
|
{
|
||
|
buff_i = 0;
|
||
|
keybuf[buff_i++] = (*p); // add the first char
|
||
|
{cs = 4;goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 5:
|
||
|
/* #line 168 "user/ini_parser.rl" */
|
||
|
{
|
||
|
if (buff_i >= INI_KEY_MAX) {
|
||
|
ini_parser_error("Key too long");
|
||
|
{cs = 10;goto _again;}
|
||
|
}
|
||
|
keybuf[buff_i++] = (*p);
|
||
|
}
|
||
|
break;
|
||
|
case 6:
|
||
|
/* #line 176 "user/ini_parser.rl" */
|
||
|
{
|
||
|
rtrim_buf(keybuf, buff_i);
|
||
|
|
||
|
// --- Value begin ---
|
||
|
buff_i = 0;
|
||
|
value_quote = 0;
|
||
|
value_nextesc = false;
|
||
|
}
|
||
|
break;
|
||
|
case 7:
|
||
|
/* #line 185 "user/ini_parser.rl" */
|
||
|
{
|
||
|
isnl = ((*p) == '\r' || (*p) == '\n');
|
||
|
isquot = ((*p) == '\'' || (*p) == '"');
|
||
|
|
||
|
// detect our starting quote
|
||
|
if (isquot && !value_nextesc && buff_i == 0 && value_quote == 0) {
|
||
|
value_quote = (*p);
|
||
|
goto valueCharDone;
|
||
|
}
|
||
|
|
||
|
if (buff_i >= INI_VALUE_MAX) {
|
||
|
ini_parser_error("Value too long");
|
||
|
{cs = 10;goto _again;}
|
||
|
}
|
||
|
|
||
|
// end of string - clean up and report
|
||
|
if ((!value_nextesc && (*p) == value_quote) || isnl) {
|
||
|
if (isnl && value_quote) {
|
||
|
ini_parser_error("Unterminated string");
|
||
|
{cs = 1;goto _again;}
|
||
|
}
|
||
|
|
||
|
// unquoted: trim from the end
|
||
|
if (!value_quote) {
|
||
|
rtrim_buf(valbuf, buff_i);
|
||
|
} else {
|
||
|
valbuf[buff_i] = 0;
|
||
|
}
|
||
|
|
||
|
if (keyCallback) {
|
||
|
keyCallback(secbuf, keybuf, valbuf, userdata);
|
||
|
}
|
||
|
|
||
|
// we don't want to discard to eol if the string was terminated by eol
|
||
|
// - would delete the next line
|
||
|
|
||
|
if (isnl) {cs = 1;goto _again;} else {cs = 10;goto _again;}
|
||
|
}
|
||
|
|
||
|
c = (*p);
|
||
|
// escape...
|
||
|
if (value_nextesc) {
|
||
|
if ((*p) == 'n') c = '\n';
|
||
|
else if ((*p) == 'r') c = '\r';
|
||
|
else if ((*p) == 't') c = '\t';
|
||
|
else if ((*p) == 'e') c = '\033';
|
||
|
}
|
||
|
|
||
|
// collecting characters...
|
||
|
if (value_nextesc || (*p) != '\\') { // is quoted, or is not a quoting backslash - literal character
|
||
|
valbuf[buff_i++] = c;
|
||
|
}
|
||
|
|
||
|
value_nextesc = (!value_nextesc && (*p) == '\\');
|
||
|
valueCharDone:;
|
||
|
}
|
||
|
break;
|
||
|
case 8:
|
||
|
/* #line 247 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in key=value");
|
||
|
if((*p) == '\n') {cs = 1;goto _again;} else {cs = 10;goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 9:
|
||
|
/* #line 257 "user/ini_parser.rl" */
|
||
|
{ {cs = 1;goto _again;} }
|
||
|
break;
|
||
|
case 10:
|
||
|
/* #line 258 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in comment");
|
||
|
if((*p) == '\n') {cs = 1;goto _again;} else {cs = 10;goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 11:
|
||
|
/* #line 265 "user/ini_parser.rl" */
|
||
|
{ {cs = 1;goto _again;} }
|
||
|
break;
|
||
|
case 12:
|
||
|
/* #line 273 "user/ini_parser.rl" */
|
||
|
{ {cs = 8;goto _again;} }
|
||
|
break;
|
||
|
case 13:
|
||
|
/* #line 276 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in root");
|
||
|
{cs = 10;goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
/* #line 458 "user/ini_parser.c" */
|
||
|
}
|
||
|
}
|
||
|
goto _again;
|
||
|
|
||
|
_again:
|
||
|
if ( cs == 0 )
|
||
|
goto _out;
|
||
|
if ( ++p != pe )
|
||
|
goto _resume;
|
||
|
_test_eof: {}
|
||
|
if ( p == eof )
|
||
|
{
|
||
|
const char *__acts = _ini_actions + _ini_eof_actions[cs];
|
||
|
unsigned int __nacts = (unsigned int) *__acts++;
|
||
|
while ( __nacts-- > 0 ) {
|
||
|
switch ( *__acts++ ) {
|
||
|
case 3:
|
||
|
/* #line 155 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in [section]");
|
||
|
if((*p) == '\n') {cs = 1; if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
goto _again;} else {cs = 10; if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 8:
|
||
|
/* #line 247 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in key=value");
|
||
|
if((*p) == '\n') {cs = 1; if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
goto _again;} else {cs = 10; if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 10:
|
||
|
/* #line 258 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in comment");
|
||
|
if((*p) == '\n') {cs = 1; if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
goto _again;} else {cs = 10; if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
case 13:
|
||
|
/* #line 276 "user/ini_parser.rl" */
|
||
|
{
|
||
|
ini_parser_error("Syntax error in root");
|
||
|
{cs = 10; if ( p == pe )
|
||
|
goto _test_eof;
|
||
|
goto _again;}
|
||
|
}
|
||
|
break;
|
||
|
/* #line 517 "user/ini_parser.c" */
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_out: {}
|
||
|
}
|
||
|
|
||
|
/* #line 283 "user/ini_parser.rl" */
|
||
|
|
||
|
}
|