Ejemplo n.º 1
0
void sinsp_filter::compile(const string& fltstr)
{
	m_fltstr = fltstr;
	m_scansize = (uint32_t)m_fltstr.size();

	while(true)
	{
		char a = next();

		switch(a)
		{
		case 0:
			//
			// Finished parsing the filter string
			//
			if(m_nest_level != 0)
			{
				throw sinsp_exception("filter error: unexpected end of filter");
			}

			if(m_state != ST_EXPRESSION_DONE)
			{
				throw sinsp_exception("filter error: unexpected end of filter at position " + to_string((long long) m_scanpos));
			}

			//
			// Good filter
			//
			return;

			break;
		case '(':
			if(m_state != ST_NEED_EXPRESSION)
			{
				throw sinsp_exception("unexpected '(' after " + m_fltstr.substr(0, m_scanpos));
			}

			push_expression(m_last_boolop);

			break;
		case ')':
			pop_expression();
			break;
		case 'o':
			if(next() == 'r')
			{
				m_last_boolop = BO_OR;
			}
			else
			{
				throw sinsp_exception("syntax error in filter at position " + to_string((long long) m_scanpos));
			}

			if(m_state != ST_EXPRESSION_DONE)
			{
				throw sinsp_exception("unexpected 'or' after " + m_fltstr.substr(0, m_scanpos));
			}

			m_state = ST_NEED_EXPRESSION;

			break;
		case 'a':
			if(next() == 'n' && next() == 'd')
			{
				m_last_boolop = BO_AND;
			}
			else
			{
				throw sinsp_exception("syntax error in filter at position " + to_string((long long) m_scanpos));
			}

			if(m_state != ST_EXPRESSION_DONE)
			{
				throw sinsp_exception("unexpected 'and' after " + m_fltstr.substr(0, m_scanpos));
			}

			m_state = ST_NEED_EXPRESSION;

			break;
		case 'n':
			if(next() == 'o' && next() == 't')
			{
				m_last_boolop = (boolop)((uint32_t)m_last_boolop | BO_NOT);
			}
			else
			{
				throw sinsp_exception("syntax error in filter at position " + to_string((long long) m_scanpos));
			}

			if(m_state != ST_EXPRESSION_DONE && m_state != ST_NEED_EXPRESSION)
			{
				throw sinsp_exception("unexpected 'not' after " + m_fltstr.substr(0, m_scanpos));
			}

			m_state = ST_NEED_EXPRESSION;

			break;
		default:
			parse_check(m_curexpr, m_last_boolop);

			m_state = ST_EXPRESSION_DONE;

			break;
		}
	}

	vector<string> components = sinsp_split(m_fltstr, ' ');
}
Ejemplo n.º 2
0
void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op)
{
	uint32_t startpos = m_scanpos;
	vector<char> operand1 = next_operand(true, false);
	string str_operand1 = string((char *)&operand1[0]);
	sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true);

	if(chk == NULL)
	{
		throw sinsp_exception("filter error: unrecognized field " +
			str_operand1 + " at pos " + to_string((long long) startpos));
	}

	if(m_ttable_only)
	{
		if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE))
		{
			throw sinsp_exception("the given filter is not supported for thread table filtering");
		}
	}

	ppm_cmp_operator co = next_comparison_operator();

	chk->m_boolop = op;
	chk->m_cmpop = co;

	chk->parse_field_name((char *)&operand1[0], true);

	//
	// In this case we need to create '(field=value1 or field=value2 ...)'
	//
	if(co == CO_IN)
	{
		//
		// Separate the 'or's from the
		// rest of the conditions
		//
		push_expression(op);

		//
		// Skip spaces
		//
		if(isblank(m_fltstr[m_scanpos]))
		{
			next();
		}

		if(m_fltstr[m_scanpos] != '(')
		{
			throw sinsp_exception("expected '(' after 'in' operand");
		}

		//
		// Skip '('
		//
		m_scanpos++;

		//
		// The first boolean operand will be BO_NONE
		// Then we will start putting BO_ORs
		//
		op = BO_NONE;

		//
		// Create the 'or' sequence
		//
		while(true)
		{
			// 'in' clause aware
			vector<char> operand2 = next_operand(false, true);

			//
			// Append every sinsp_filter_check creating the 'or' sequence
			//
			sinsp_filter_check* newchk = g_filterlist.new_filter_check_from_another(chk);
			newchk->m_boolop = op;
			newchk->m_cmpop = CO_EQ;
			newchk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1);

			//
			// We pushed another expression before
			// so 'parent_expr' still referers to
			// the old one, this is the new nested
			// level for the 'or' sequence
			//
			m_curexpr->add_check(newchk);

			next();

			if(m_fltstr[m_scanpos] == ')')
			{
				break;
			}
			else if(m_fltstr[m_scanpos] == ',')
			{
				m_scanpos++;
			}
			else
			{
				throw sinsp_exception("expected either ')' or ',' after a value inside the 'in' clause");
			}

			//
			// From now on we 'or' every newchk
			//
			op = BO_OR;
		}

		//
		// Come back to the rest of the filter
		//
		pop_expression();
	}
	else
	{
		//
		// In this case we want next() to return the very next character
		// At this moment m_scanpos is already at it
		// e.g. "(field exists) and ..."
		//
		if(co == CO_EXISTS)
		{
			m_scanpos--;
		}
		//
		// Otherwise we need a value for the operand
		//
		else
		{
			vector<char> operand2 = next_operand(false, false);
			chk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1);
		}

		parent_expr->add_check(chk);
	}
}