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, &params))
		{
			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;
}
Example #2
0
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 );
}