static int calcitem_parse_expression(DC_ITEM *dc_item, expression_t *exp, char *error, int max_error_len) { const char *__function_name = "calcitem_parse_expression"; char *e, *f, *func = NULL, *params = NULL; size_t exp_alloc = 128, exp_offset = 0, len; int functionid, ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __function_name, dc_item->params); assert(dc_item); assert(exp); exp->exp = zbx_malloc(exp->exp, exp_alloc); for (e = dc_item->params; '\0' != *e; e++) { if (SUCCEED != is_function_char(*e)) { zbx_chrcpy_alloc(&exp->exp, &exp_alloc, &exp_offset, *e); continue; } if ((0 == strncmp("and", e, len = 3) || 0 == strncmp("not", e, 3) || 0 == strncmp("or", e, len = 2)) && NULL != strchr("()" ZBX_WHITESPACE, e[len])) { zbx_strncpy_alloc(&exp->exp, &exp_alloc, &exp_offset, e, len); e += len - 1; continue; } f = e; if (SUCCEED != parse_function(&e, &func, ¶ms)) { e = f; zbx_chrcpy_alloc(&exp->exp, &exp_alloc, &exp_offset, *f); continue; } else e--; functionid = calcitem_add_function(exp, func, params); zabbix_log(LOG_LEVEL_DEBUG, "%s() functionid:%d function:'%s(%s)'", __function_name, functionid, func, params); func = NULL; params = NULL; zbx_snprintf_alloc(&exp->exp, &exp_alloc, &exp_offset, "{%d}", functionid); } zabbix_log(LOG_LEVEL_DEBUG, "%s() expression:'%s'", __function_name, exp->exp); if (FAIL == (ret = substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &dc_item->host, NULL, NULL, &exp->exp, MACRO_TYPE_ITEM_EXPRESSION, error, max_error_len))) ret = NOTSUPPORTED; zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
bool resolve_symvar_functions( char * buf ) { static const char ampchar = '&'; inp_line * in_wk; char * workb; char * pw; char * pwend; char * p2; char * pchar; char * varstart; sub_index var_ind; symvar symvar_entry; symsub * symsubval; size_t buf_lg; int rc; bool functions_found; bool anything_substituted; char * var_unresolved; // ptr for resume search char * var_unresolved2;// ptr for resume search ProcFlags.substituted = false; ProcFlags.unresolved = false; if( NULL == strchr( buf, ampchar ) ) { // look for & in buffer return( false ); // no ampchar found, nothing to resolve } anything_substituted = false; var_unresolved = NULL; var_unresolved2 = NULL; functions_found = false; in_wk = mem_alloc( sizeof( inp_line ) + buf_size );// allocate workbuffer in_wk->next = NULL; workb = in_wk->value; // allocate workbuffer do { // until no more substitutions strcpy( workb, buf ); // copy input buffer buf_lg = strlen( buf ); pwend = workb + buf_lg - 1; if( var_unresolved == NULL ) { pw = workb; p2 = buf; } else { pw = workb + (var_unresolved2 - buf); p2 = var_unresolved2; } varstart = NULL; anything_substituted |= ProcFlags.substituted; ProcFlags.substituted = false; pchar = strchr( workb, ampchar ); // look for & in buffer while( pchar != NULL ) { // & found if( *(pchar + 1) == ' ' ) { // not a symbol substition or function pchar = strchr( pchar + 1, ampchar ); // look for next & in buffer continue; } while( pw < pchar ) { // copy all data preceding & *p2++ = *pw++; } buf_lg = strlen( buf ); if( isalpha( *(pchar + 1) ) && *(pchar + 2) == '\'' && *(pchar + 3) > ' ' ) { // not for .if '&*' eq '' .th ... // only .if '&x'foo' eq '' .th char * * ppval = &p2; /***********************************************************/ /* Some single letter functions are resolved here: */ /* */ /* functions used within the OW doc build system: */ /* &e' existance of variable 0 or 1 */ /* &l' length of variable content */ /* or if undefined variable length of name */ /* &u' upper */ /* */ /* &s' subscript */ /* &S' superscript */ /* */ /* other single letter functions are not used AFAIK */ /* */ /***********************************************************/ if( GlobalFlags.firstpass && input_cbs->fmflags & II_research ) { add_single_func_research( pchar + 1 ); } pw = scr_single_funcs( pchar, pwend, ppval ); pchar = strchr( pw, ampchar ); // look for next & in buffer continue; } if( *(pchar + 1) == '\'' ) {// perhaps a multi letter function char * pf; char * * ppval = &p2; int32_t valsize = buf_size - (p2 - buf); pf = pchar + 2; while( is_function_char( *pf ) ) { pf++; } if( *pf == '(' ) {// &'xyz( is start of multi char function /***********************************************************/ /* Some multi letter functions are resolved here: */ /* */ /* functions used within the OW doc build system: */ /* */ /* &'delstr( &'d2c( &'index( */ /* &'insert( &'left( &'length( */ /* &'lower( &'min( &'pos( */ /* &'right( &'strip( &'substr( */ /* &'subword( &'translate( &'upper( */ /* &'veclastpos( &'vecpos( &'word( */ /* &'wordpos( &'words( */ /* */ /* Others are recognized but not processed */ /* &'c2x( is used for test output */ /***********************************************************/ pw = scr_multi_funcs( pchar, pwend, ppval, valsize ); pchar = strchr( pw, ampchar );// look for next & in buffer continue; } *p2++ = *pw++; // copy & pchar = strchr( pw, ampchar ); // look for next & in buffer continue; // and ignore this &... for now } /***************************************************************/ /* & is neither start of single char function */ /* nor start of multi char function */ /* */ /* & is probably start of a variable */ /***************************************************************/ varstart = pw; // remember start of var pw++; // over & ProcFlags.suppress_msg = true; scan_err = false; pchar = scan_sym( pw, &symvar_entry, &var_ind ); if( scan_err && *pchar == '(' ) { // problem with subscript if( var_unresolved == NULL ) { ProcFlags.unresolved = true; var_unresolved = varstart; var_unresolved2 = p2; } else { if( var_unresolved != varstart ) { ProcFlags.unresolved = true; } } p2 += pchar - varstart; pw = pchar; pchar = strchr( pw, ampchar ); // look for next & in buffer continue; } ProcFlags.suppress_msg = false; if( symvar_entry.flags & local_var ) { // lookup var in dict rc = find_symvar_l( &input_cbs->local_dict, symvar_entry.name, var_ind, &symsubval ); } else { rc = find_symvar( &global_dict, symvar_entry.name, var_ind, &symsubval ); } if( rc == 2 ) { // variable found + resolved ProcFlags.substituted = true; if( !ProcFlags.CW_sep_ignore && symsubval->value[0] == CW_sep_char && symsubval->value[1] != CW_sep_char ) { // split record at control word separator // if variable starts with SINGLE cw separator // and ignore cw separator if( buf != buff2 ) { // splitting input if not outermost buffer ++++ TBD // needed ??? g_suicide(); } if( *pchar == '.' ) { pchar++; // skip optional terminating dot } *p2 = '\0'; split_input_var( buf, pchar, &symsubval->value[1], true ); pw = pwend + 1; // stop substitution for this record varstart = NULL; break; } else { pw = symsubval->value; if( symsubval->value[0] == CW_sep_char && symsubval->value[1] == CW_sep_char ) { pw++; // skip 1 CW_sep_char } strcpy( p2, pw ); // copy value p2 += strlen(pw); if( *pchar == '.' ) { pchar++; // skip optional terminating dot } pw = pchar; } } else { // variable not found if( (symvar_entry.flags & local_var ) // local var not found ) { if( (symvar_entry.name[0] == '\0') && (*pchar == ampchar) ) { // only &* as var name // followed by another var if( var_unresolved == NULL ) { ProcFlags.unresolved = true; var_unresolved = varstart; var_unresolved2 = p2; } else { if( var_unresolved != varstart ) { ProcFlags.unresolved = true; } } pw = varstart; while( pw < pchar ) { // treat var name as text *p2++ = *pw++; // and copy } continue; // pchar points already to next & } else { // replace not found local var by nullstring ProcFlags.substituted = true; if( *pchar == '.' ) { pchar++; // skip optional terminating dot } pw = pchar; } } else { // global var not found // .. or local var outside of macro /*******************************************************/ /* keep trying for constructs such as */ /* */ /* .se prodgml = "Open Watcom GML" */ /* .se name = "GML" */ /* */ /* My name is &prod&name..! */ /* */ /* to become */ /* */ /* My name is Open Watcom GML! */ /* */ /* This does not work for local variables, as these are*/ /* replaced by nullstring if not found */ /* My name is &*prod&*name..! */ /* will become */ /* My name is ! */ /*******************************************************/ if( var_unresolved == NULL ) { ProcFlags.unresolved = true; var_unresolved = varstart; var_unresolved2 = p2; } else { if( var_unresolved != varstart ) { ProcFlags.unresolved = true; } } pw = varstart; if( *pchar == '.' ) { pchar++; // copy terminating dot, too } while( pw < pchar ) { // treat var name as text *p2++ = *pw++; // and copy } } } pchar = strchr( pw, ampchar ); // look for next & in buffer } // while & found while( pw <= pwend) { // copy remaining input *p2++ = *pw++; } *p2 = 0; // terminate string } while( ProcFlags.unresolved && ProcFlags.substituted ); anything_substituted |= ProcFlags.substituted; mem_free( in_wk ); // free workbuffer return( anything_substituted ); }