void sinsp_filter_compiler::parse_check() { 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); boolop op = m_last_boolop; 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"); } } cmpop co = next_comparison_operator(); chk->m_boolop = op; chk->m_cmpop = co; chk->parse_field_name((char *)&operand1[0], true); if(co == CO_IN || co == CO_PMATCH) { // // Skip spaces // if(isblank(m_fltstr[m_scanpos])) { next(); } if(m_fltstr[m_scanpos] != '(') { throw sinsp_exception("expected '(' after 'in/pmatch' operand"); } // // Skip '(' // m_scanpos++; if(chk->get_field_info()->m_type == PT_CHARBUF) { // // For character buffers, we can check all // values at once by putting them in a set and // checking for set membership. // // // Create the 'or' sequence // uint64_t num_values = 0; while(true) { // 'in' clause aware vector<char> operand2 = next_operand(false, true); chk->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1, num_values); num_values++; 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/pmatch' clause"); } } m_filter->add_check(chk); } else if (co == CO_PMATCH) { // the pmatch operator can only work on charbufs throw sinsp_exception("pmatch requires all charbuf arguments"); } else { // // In this case we need to create '(field=value1 or field=value2 ...)' // // // Separate the 'or's from the // rest of the conditions // m_filter->push_expression(op); m_last_boolop = BO_NONE; m_nest_level++; // // The first boolean operand will be BO_NONE // Then we will start putting BO_ORs // op = BO_NONE; // // Create the 'or' sequence // uint64_t num_values = 0; 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->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1, num_values); num_values++; m_filter->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 // m_filter->pop_expression(); m_nest_level--; } } 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->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1); } m_filter->add_check(chk); } }
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); } }