// helper functions to test the parsing of config files and/or metaknobs
//
void testparse(int lineno, MACRO_SET & set, MACRO_EVAL_CONTEXT &ctx, MACRO_SOURCE & source, bool verbose, const char * tag, const char * params, const char * expected)
{
	int ret = Parse_config_string(source, 0, params, set, ctx);
	const char * hashout = NULL;
	if (ret < 0) {
		fprintf(stderr, "Failed %5d: test '%s' local=%s subsys=%s parse error %d\n",
			lineno, tag, ctx.localname ? ctx.localname : "", ctx.subsys ? ctx.subsys : "", ret);
		gmstr.clear();
		hashout = NULL;
	} else {
		dump_macro_set(set, gmstr, "\t");
		hashout = gmstr.c_str();
		if (gmstr != expected) {
			fprintf(stderr, "Failed %5d: test '%s' local=%s subsys=%s resulting hashtable does not match expected\n",
				lineno, tag, ctx.localname ? ctx.localname : "", ctx.subsys ? ctx.subsys : "");
			ret = -1;
		} else if (verbose) {
			fprintf(stdout, "    OK %5d: test '%s' local=%s subsys=%s\n",
				lineno, tag, ctx.localname ? ctx.localname : "", ctx.subsys ? ctx.subsys : "");
			ret = 0;
		}
	}
	if (verbose || ret) {
		fprintf(ret ? stderr : stdout, "\t---- parse input %d ----\n%s", lineno, params);
		if (hashout) fprintf(ret ? stderr : stdout, "\t---- resulting hash %d ----\n%s", lineno, hashout);
		if (ret)     fprintf(stderr, "\t---- expected hash %d ----\n%s", lineno, expected);
		fprintf(ret ? stderr : stdout, "\t---- end %d ----\n\n", lineno);
	}

	clear_macro_set(set);
}
Exemple #2
0
tst_t *Parse_config_string(bstring content) 
{
    Token *temp = NULL;
    void *parser = ParseAlloc(malloc);
    check_mem(parser);
    ParserState state = {.settings = NULL, .error = 0, .line_number = 1};

    char *p = bdata(content);
    char *pe = bdataofs(content, blength(content) - 1);
    char *eof = pe;
    int cs = -1;
    int act = -1;
    char *ts = NULL;
    char *te = NULL;

    
#line 114 "src/lexer.c"
	{
	cs = m2sh_lexer_start;
	ts = 0;
	te = 0;
	act = 0;
	}

#line 135 "src/lexer.rl"
    
#line 124 "src/lexer.c"
	{
	if ( p == pe )
		goto _test_eof;
	switch ( cs )
	{
tr1:
#line 77 "src/lexer.rl"
	{te = p+1;{ TKSTR(QSTRING) }}
	goto st6;
tr4:
#line 91 "src/lexer.rl"
	{te = p+1;}
	goto st6;
tr7:
#line 89 "src/lexer.rl"
	{te = p+1;}
	goto st6;
tr9:
#line 88 "src/lexer.rl"
	{te = p+1;{ state.line_number++; }}
	goto st6;
tr10:
#line 83 "src/lexer.rl"
	{te = p+1;{ TK(LPAREN) }}
	goto st6;
tr11:
#line 84 "src/lexer.rl"
	{te = p+1;{ TK(RPAREN) }}
	goto st6;
tr12:
#line 85 "src/lexer.rl"
	{te = p+1;{ TK(COMMA) }}
	goto st6;
tr14:
#line 86 "src/lexer.rl"
	{te = p+1;{ TK(COLON) }}
	goto st6;
tr15:
#line 78 "src/lexer.rl"
	{te = p+1;{ TK(EQ) }}
	goto st6;
tr17:
#line 81 "src/lexer.rl"
	{te = p+1;{ TK(LBRACE) }}
	goto st6;
tr18:
#line 82 "src/lexer.rl"
	{te = p+1;{ TK(RBRACE) }}
	goto st6;
tr20:
#line 79 "src/lexer.rl"
	{te = p+1;{ TK(LBRACKET) }}
	goto st6;
tr21:
#line 80 "src/lexer.rl"
	{te = p+1;{ TK(RBRACKET) }}
	goto st6;
tr22:
#line 93 "src/lexer.rl"
	{te = p;p--;{ TK(NUMBER) }}
	goto st6;
tr23:
#line 1 "NONE"
	{	switch( act ) {
	case 15:
	{{p = ((te))-1;} TK(CLASS) }
	break;
	case 16:
	{{p = ((te))-1;} TK(IDENT) }
	break;
	}
	}
	goto st6;
tr25:
#line 95 "src/lexer.rl"
	{te = p;p--;{ TK(IDENT) }}
	goto st6;
st6:
#line 1 "NONE"
	{ts = 0;}
	if ( ++p == pe )
		goto _test_eof6;
case 6:
#line 1 "NONE"
	{ts = p;}
#line 210 "src/lexer.c"
	switch( (*p) ) {
		case 10: goto tr9;
		case 32: goto tr7;
		case 34: goto st1;
		case 35: goto st3;
		case 39: goto st4;
		case 40: goto tr10;
		case 41: goto tr11;
		case 44: goto tr12;
		case 58: goto tr14;
		case 61: goto tr15;
		case 91: goto tr17;
		case 93: goto tr18;
		case 95: goto st9;
		case 123: goto tr20;
		case 125: goto tr21;
	}
	if ( (*p) < 48 ) {
		if ( 9 <= (*p) && (*p) <= 13 )
			goto tr7;
	} else if ( (*p) > 57 ) {
		if ( (*p) > 90 ) {
			if ( 97 <= (*p) && (*p) <= 122 )
				goto st9;
		} else if ( (*p) >= 65 )
			goto tr16;
	} else
		goto st7;
	goto st0;
st0:
cs = 0;
	goto _out;
st1:
	if ( ++p == pe )
		goto _test_eof1;
case 1:
	switch( (*p) ) {
		case 34: goto tr1;
		case 92: goto st2;
	}
	goto st1;
st2:
	if ( ++p == pe )
		goto _test_eof2;
case 2:
	goto st1;
st3:
	if ( ++p == pe )
		goto _test_eof3;
case 3:
	if ( (*p) == 10 )
		goto tr4;
	goto st3;
st4:
	if ( ++p == pe )
		goto _test_eof4;
case 4:
	switch( (*p) ) {
		case 39: goto tr1;
		case 92: goto st5;
	}
	goto st4;
st5:
	if ( ++p == pe )
		goto _test_eof5;
case 5:
	goto st4;
st7:
	if ( ++p == pe )
		goto _test_eof7;
case 7:
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st7;
	goto tr22;
tr16:
#line 1 "NONE"
	{te = p+1;}
#line 95 "src/lexer.rl"
	{act = 16;}
	goto st8;
tr24:
#line 1 "NONE"
	{te = p+1;}
#line 94 "src/lexer.rl"
	{act = 15;}
	goto st8;
st8:
	if ( ++p == pe )
		goto _test_eof8;
case 8:
#line 301 "src/lexer.c"
	if ( (*p) == 95 )
		goto st9;
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto st9;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr24;
	} else
		goto tr24;
	goto tr23;
st9:
	if ( ++p == pe )
		goto _test_eof9;
case 9:
	if ( (*p) == 95 )
		goto st9;
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto st9;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto st9;
	} else
		goto st9;
	goto tr25;
	}
	_test_eof6: cs = 6; goto _test_eof; 
	_test_eof1: cs = 1; goto _test_eof; 
	_test_eof2: cs = 2; goto _test_eof; 
	_test_eof3: cs = 3; goto _test_eof; 
	_test_eof4: cs = 4; goto _test_eof; 
	_test_eof5: cs = 5; goto _test_eof; 
	_test_eof7: cs = 7; goto _test_eof; 
	_test_eof8: cs = 8; goto _test_eof; 
	_test_eof9: cs = 9; goto _test_eof; 

	_test_eof: {}
	if ( p == eof )
	{
	switch ( cs ) {
	case 7: goto tr22;
	case 8: goto tr23;
	case 9: goto tr25;
	}
	}

	_out: {}
	}

#line 136 "src/lexer.rl"


    if(state.error) {
        Parse_print_error("SYNTAX ERROR", content, 
                (int)(ts - bdata(content)), ++state.line_number);
    } else if( cs == 
#line 359 "src/lexer.c"
0
#line 141 "src/lexer.rl"
 ) {
        Parse_print_error("INVALID CHARACTER", content,
                (int)(ts - bdata(content)), ++state.line_number);
    } else if( cs >= 
#line 366 "src/lexer.c"
6
#line 144 "src/lexer.rl"
 ) {
        Parse(parser, TKEOF, NULL, &state);
    } else {
        log_err("INCOMPLETE CONFIG FILE. There needs to be more to this.");
    }

    Parse(parser, 0, 0, &state);
    ParseFree(parser, free);

    return state.settings;

error:
    if(state.error) {
        Parse_print_error("SYNTAX ERROR", content, 
                (int)(ts - bdata(content)), ++state.line_number);
    }
    ParseFree(parser, free);
    return NULL;
}


tst_t *Parse_config_file(const char *path)
{
    FILE *script;
    bstring buffer = NULL;
    tst_t *settings = NULL;

    script = fopen(path, "r");
    check(script, "Failed to open file: %s", path);

    buffer = bread((bNread)fread, script);
    check_mem(buffer);

    fclose(script); script = NULL;

    // make sure there's a \n at the end
    bconchar(buffer, '\n');

    settings = Parse_config_string(buffer);
    check(settings != NULL, "Failed to parse file: %s", path);

    bdestroy(buffer);
    buffer = NULL;

    return settings;

error:
    bdestroy(buffer);
    if(script) fclose(script);
    return NULL;
}