int ParseParamGroup( ParseContext* ctx )
{
	ConfigToken ParamTokens[] = { Token_IP, Token_Port, Token_KeyFile, Token_Pwd, Token_PwdFile, Token_RightBrace };
	ConfigToken token = Token_Unknown;
	char token_checks[TOKEN_COUNT];
	int rc = 0; 

	memset( token_checks, 0, sizeof(token_checks) );

	if( MatchToken( ctx, Token_LeftBrace ) == CONFIG_PARSE_ERROR ) return CONFIG_PARSE_ERROR;

	do 
	{
		/* get the parameter */
		token = ParseOneOf( ctx, ParamTokens, ARRAY_SIZE( ParamTokens ) );
		if( token == CONFIG_PARSE_ERROR ) rc = CONFIG_PARSE_ERROR;

		if( rc == 0 && token != Token_RightBrace )
		{
			token_checks[token] = 1;
			/* get the value */
			Advance( ctx );
			if( ctx->token == NULL )
			{
				sprintf( error_buffer, "%s: unexpected EOF found near '%s'", ERROR_PREFIX, TokenToString( token ) );
				rc = CONFIG_PARSE_ERROR;
			}

			/* assign the parameter value */
			if( rc == 0 ) rc = AssignParam( ctx, token, ctx->token );
		}

	} while( rc == 0 && token != Token_RightBrace );

	if( rc == 0 ) 
	{
		/* validate the current server settings */
		if( !token_checks[Token_IP] ) rc = FormatMissingServerParamError( Token_IP );
		if( rc == 0 && !token_checks[Token_KeyFile] ) rc = FormatMissingServerParamError( Token_KeyFile );
		if( rc == 0 && !token_checks[Token_Port] ) rc = FormatMissingServerParamError( Token_Port );

		if( rc == 0 && token_checks[Token_Pwd] && token_checks[Token_PwdFile] )
		{
			sprintf( error_buffer, "%s: Error in server definition: Either 'pwdfile' (recommended) or 'pwd' parameter is expected, but not both",
					ERROR_PREFIX );
			rc = CONFIG_PARSE_ERROR;
		}
	}

	return rc;
}
int LoadConfig( const u_char* conf, SSLConfig* cfg )
{
	ParseContext ctx;
	u_char* conf_copy = NULL;
	ConfigToken TopLevelTokens[] = { Token_Server, Token_EOF };
	ConfigToken token = Token_Unknown;

	error_buffer[0] = 0;

	conf_copy = (u_char*) malloc( strlen( conf ) + 1 );
	strcpy( conf_copy, conf );

	memset( &ctx, 0, sizeof(ctx) );
	ctx.input = conf_copy;
	ctx.config = cfg;

	do 
	{
		token = ParseOneOf( &ctx, TopLevelTokens, ARRAY_SIZE( TopLevelTokens ) );

		if( token == Token_Server ) 
		{
			if( ParseServer( &ctx ) == CONFIG_PARSE_ERROR ) token = CONFIG_PARSE_ERROR;
		}
	} while ( token == Token_Server );

	free( conf_copy ); conf_copy = ctx.input = NULL;

	/* make sure we have at least one server set up */
	if( token != CONFIG_PARSE_ERROR && ctx.config->server_cnt == 0 )
	{
		sprintf( error_buffer, "%s: at least one SSL server's configuration is expected", ERROR_PREFIX );
		token = CONFIG_PARSE_ERROR;
	}

	if( token == CONFIG_PARSE_ERROR ) 
	{
		if( strlen( error_buffer ) )
		{
			_dpd.fatalMsg( "%s(%d) => %s", *(_dpd.config_file), *(_dpd.config_line), error_buffer );
		}
		return CONFIG_PARSE_ERROR;
	}

	PrintSSLConfig( ctx.config );
	return 0;
}
asCScriptNode *asCParser::ParseTypeMod(bool isParam)
{
	asCScriptNode *node = new asCScriptNode(snDataType);

	sToken t;

	// Parse possible & token
	GetToken(&t);
	RewindTo(&t);
	if( t.type == ttAmp )
	{
		node->AddChildLast(ParseToken(ttAmp));
		if( isSyntaxError ) return node;

		if( isParam )
		{
			GetToken(&t);
			RewindTo(&t);

			if( t.type == ttIn || t.type == ttOut || t.type == ttInOut )
			{
				int tokens[3] = {ttIn, ttOut, ttInOut};
				node->AddChildLast(ParseOneOf(tokens, 3));
			}
		}
	}

	// Parse possible + token 
	GetToken(&t);
	RewindTo(&t);
	if( t.type == ttPlus )
	{
		node->AddChildLast(ParseToken(ttPlus));
		if( isSyntaxError ) return node;
	}

	return node;
}