void PCB_CALCULATOR_FRAME::TransfPanelDataToAttenuator()
{
    wxString msg;

    msg = m_AttValueCtrl->GetValue();
    m_currAttenuator->m_Attenuation = DoubleFromString(msg);
    msg = m_ZinValueCtrl->GetValue();
    m_currAttenuator->m_Zin = DoubleFromString(msg);
    msg = m_ZoutValueCtrl->GetValue();
    m_currAttenuator->m_Zout = DoubleFromString(msg);
}
REGULATOR_DATA * DIALOG_EDITOR_DATA::BuildRegulatorFromData()
{
    double vref = DoubleFromString( m_textCtrlVref->GetValue() );
    double iadj = DoubleFromString( m_RegulIadjValue->GetValue() );
    int type = m_choiceRegType->GetSelection();
    if( type != 1 )
        iadj = 0.0;
    REGULATOR_DATA * item = new REGULATOR_DATA( m_textCtrlName->GetValue(),
                                                vref, type, iadj );
    return item;
}
Пример #3
0
static void test_double_from_string(void)
{
    {
        double val;
        assert_true(DoubleFromString("1.2k", &val));
        assert_double_close(1200.0, val);
    }

    {
        double val;
        assert_false(DoubleFromString("abc", &val));
    }
}
void PCB_CALCULATOR_FRAME::ElectricalSpacingUpdateData( double aUnitScale )
{
    wxString txt;
    double voltage = 500.0;     // to calculate values at V > 500V
    txt = m_ElectricalSpacingVoltage->GetValue();
    if( ! txt.IsEmpty() )
        voltage = DoubleFromString(txt);
    if( voltage < 500.0 )
        voltage = 500.0;
    txt.Printf( wxT( "%g" ), voltage );
    m_ElectricalSpacingVoltage->SetValue( txt );

    for( int ii = 0; ii < CLASS_COUNT-1; ii++ )
    {
        for( int jj = 0; jj < VALUE_COUNT; jj++ )
        {
            txt.Printf( wxT( "%g" ), clist[ii][jj] / aUnitScale );
            m_gridElectricalSpacingValues->SetCellValue( ii, jj, txt );
        }
    }

    for( int jj = 0; jj < VALUE_COUNT; jj++ )
    {
        double spacing = clist[CLASS_COUNT-2][jj];
        double spacing_extra = clist[CLASS_COUNT-1][jj];
        spacing += spacing_extra * ( voltage - 500.0 );
        txt.Printf( wxT( "%g" ), spacing / aUnitScale );
        m_gridElectricalSpacingValues->SetCellValue( CLASS_COUNT-1, jj, txt );
    }
}
void PCB_CALCULATOR_FRAME::OnTWCalculateFromIntWidth( wxCommandEvent& event )
{
    // Setting the calculated values generates further events. Stop them.
    if( m_TWNested )
    {
        event.StopPropagation();
        return;
    }

    m_TWNested = true;

    // Update state.
    if( m_TWMode != TW_MASTER_INT_WIDTH )
    {
        m_TWMode = TW_MASTER_INT_WIDTH;
        TWUpdateModeDisplay();
    }

    // Load parameters.
    double current;
    double extThickness  = std::abs( DoubleFromString( m_ExtTrackThicknessValue->GetValue() ) );
    double intThickness  = std::abs( DoubleFromString( m_IntTrackThicknessValue->GetValue() ) );
    double deltaT_C      = std::abs( DoubleFromString( m_TrackDeltaTValue->GetValue() ) );
    double extTrackWidth;
    double intTrackWidth = std::abs( DoubleFromString( m_IntTrackWidthValue->GetValue() ) );

    // Normalize units.
    extThickness  *= m_ExtTrackThicknessUnit->GetUnitScale();
    intThickness  *= m_IntTrackThicknessUnit->GetUnitScale();
    intTrackWidth *= m_TW_IntTrackWidth_choiceUnit->GetUnitScale();

    // Calculate the maximum current.
    current = TWCalculateCurrent( intTrackWidth, intThickness, deltaT_C, true );

    // And now calculate the corresponding external width.
    extTrackWidth = TWCalculateWidth( current, extThickness, deltaT_C, false );

    // Update the display.
    TWDisplayValues( current, extTrackWidth, intTrackWidth, extThickness, intThickness );

    // Re-enable the events.
    m_TWNested = false;
}
void PCB_CALCULATOR_FRAME::OnTWCalculateFromCurrent( wxCommandEvent& event )
{
    // Setting the calculated values generates further events. Stop them.
    if( m_TWNested )
    {
        event.StopPropagation();
        return;
    }

    m_TWNested = true;

    // Update state.
    if( m_TWMode != TW_MASTER_CURRENT )
    {
        m_TWMode = TW_MASTER_CURRENT;
        TWUpdateModeDisplay();
    }

    // Prepare parameters:
    double current      = std::abs( DoubleFromString( m_TrackCurrentValue->GetValue() ) );
    double extThickness = std::abs( DoubleFromString( m_ExtTrackThicknessValue->GetValue() ) );
    double intThickness = std::abs( DoubleFromString( m_IntTrackThicknessValue->GetValue() ) );
    double deltaT_C     = std::abs( DoubleFromString( m_TrackDeltaTValue->GetValue() ) );
    double extTrackWidth;
    double intTrackWidth;

    // Normalize units.
    extThickness *= m_ExtTrackThicknessUnit->GetUnitScale();
    intThickness *= m_IntTrackThicknessUnit->GetUnitScale();

    // Calculate the widths.
    extTrackWidth = TWCalculateWidth( current, extThickness, deltaT_C, false );
    intTrackWidth = TWCalculateWidth( current, intThickness, deltaT_C, true );

    // Update the display.
    TWDisplayValues( current, extTrackWidth, intTrackWidth, extThickness, intThickness );

    // Re-enable the events.
    m_TWNested = false;
}
Пример #7
0
static SyntaxTypeMatch CheckParseReal(const char *lval, const char *s, const char *range)
{
    Item *split;
    double max = (double) CF_LOWINIT, min = (double) CF_HIGHINIT, val;
    int n;

    CfDebug("\nCheckParseReal(%s => %s/%s)\n", lval, s, range);

    if (strcmp(s, "inf") == 0)
    {
        return SYNTAX_TYPE_MATCH_ERROR_REAL_INF;
    }

    if (IsCf3VarString(s))
    {
        return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED;
    }

/* Numeric types are registered by range separated by comma str "min,max" */

    split = SplitString(range, ',');

    if ((n = ListLen(split)) != 2)
    {
        ProgrammingError("Format specifier for real rvalues is not ok for lval %s - %d items", lval, n);
    }

    sscanf(split->name, "%lf", &min);
    sscanf(split->next->name, "%lf", &max);
    DeleteItemList(split);

    if (min == CF_HIGHINIT || max == CF_LOWINIT)
    {
        ProgrammingError("Could not parse format specifier for int rvalues for lval %s", lval);
    }

    if (!DoubleFromString(s, &val))
    {
        return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE;
    }

    if (val > max || val < min)
    {
        return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE;
    }

    return SYNTAX_TYPE_MATCH_OK;
}
bool DIALOG_EDITOR_DATA::IsOK()
{
    bool ok = true;
    if( m_textCtrlName->GetValue().IsEmpty() )
        ok = false;
    if( m_textCtrlVref->GetValue().IsEmpty() )
        ok = false;
    else
    {
        double vref = DoubleFromString( m_textCtrlVref->GetValue() );
        if( fabs(vref) < 0.01 )
            ok = false;
    }
    if( m_choiceRegType->GetSelection() == 1 )
    {
        if( m_RegulIadjValue->GetValue().IsEmpty() )
            ok = false;
    }

    return ok;
}
Пример #9
0
PromiseResult VerifyVarPromise(EvalContext *ctx, const Promise *pp, bool allow_duplicates)
{
    ConvergeVariableOptions opts = CollectConvergeVariableOptions(ctx, pp, allow_duplicates);
    if (!opts.should_converge)
    {
        return PROMISE_RESULT_NOOP;
    }

    Attributes a = { {0} };
    // More consideration needs to be given to using these
    //a.transaction = GetTransactionConstraints(pp);
    a.classes = GetClassDefinitionConstraints(ctx, pp);

    VarRef *ref = VarRefParseFromBundle(pp->promiser, PromiseGetBundle(pp));
    if (strcmp("meta", pp->parent_promise_type->name) == 0)
    {
        VarRefSetMeta(ref, true);
    }

    DataType existing_value_type = CF_DATA_TYPE_NONE;
    const void *const existing_value =
        IsExpandable(pp->promiser) ? NULL : EvalContextVariableGet(ctx, ref, &existing_value_type);

    PromiseResult result = PROMISE_RESULT_NOOP;
    Rval rval = opts.cp_save->rval;

    if (rval.item != NULL)
    {
        DataType data_type = DataTypeFromString(opts.cp_save->lval);

        if (opts.cp_save->rval.type == RVAL_TYPE_FNCALL)
        {
            FnCall *fp = RvalFnCallValue(rval);
            const FnCallType *fn = FnCallTypeGet(fp->name);
            if (!fn)
            {
                assert(false && "Canary: should have been caught before this point");
                FatalError(ctx, "While setting variable '%s' in bundle '%s', unknown function '%s'",
                           pp->promiser, PromiseGetBundle(pp)->name, fp->name);
            }

            if (fn->dtype != DataTypeFromString(opts.cp_save->lval))
            {
                FatalError(ctx, "While setting variable '%s' in bundle '%s', variable declared type '%s' but function '%s' returns type '%s'",
                           pp->promiser, PromiseGetBundle(pp)->name, opts.cp_save->lval,
                           fp->name, DataTypeToString(fn->dtype));
            }

            if (existing_value_type != CF_DATA_TYPE_NONE)
            {
                // Already did this
                VarRefDestroy(ref);
                return PROMISE_RESULT_NOOP;
            }

            FnCallResult res = FnCallEvaluate(ctx, PromiseGetPolicy(pp), fp, pp);

            if (res.status == FNCALL_FAILURE)
            {
                /* We do not assign variables to failed fn calls */
                RvalDestroy(res.rval);
                VarRefDestroy(ref);
                return PROMISE_RESULT_NOOP;
            }
            else
            {
                rval = res.rval;
            }
        }
        else
        {
            Buffer *conv = BufferNew();
            bool malformed = false, misprint = false;

            if (strcmp(opts.cp_save->lval, "int") == 0)
            {
                long int asint = IntFromString(opts.cp_save->rval.item);
                if (asint == CF_NOINT)
                {
                    malformed = true;
                }
                else if (0 > BufferPrintf(conv, "%ld", asint))
                {
                    misprint = true;
                }
                else
                {
                    rval = RvalNew(BufferData(conv), opts.cp_save->rval.type);
                }
            }
            else if (strcmp(opts.cp_save->lval, "real") == 0)
            {
                double real_value;
                if (!DoubleFromString(opts.cp_save->rval.item, &real_value))
                {
                    malformed = true;
                }
                else if (0 > BufferPrintf(conv, "%lf", real_value))
                {
                    misprint = true;
                }
                else
                {
                    rval = RvalNew(BufferData(conv), opts.cp_save->rval.type);
                }
            }
            else
            {
                rval = RvalCopy(opts.cp_save->rval);
            }
            BufferDestroy(conv);

            if (malformed)
            {
                /* Arises when opts->cp_save->rval.item isn't yet expanded. */
                /* Has already been logged by *FromString */
                VarRefDestroy(ref);
                return PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
            }
            else if (misprint)
            {
                /* Even though no problems with memory allocation can
                 * get here, there might be other problems. */
                UnexpectedError("Problems writing to buffer");
                VarRefDestroy(ref);
                return PROMISE_RESULT_NOOP;
            }
            else if (rval.type == RVAL_TYPE_LIST)
            {
                Rlist *rval_list = RvalRlistValue(rval);
                RlistFlatten(ctx, &rval_list);
                rval.item = rval_list;
            }
        }

        if (Epimenides(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, pp->promiser, rval, 0))
        {
            Log(LOG_LEVEL_ERR, "Variable '%s' contains itself indirectly - an unkeepable promise", pp->promiser);
            exit(EXIT_FAILURE);
        }
        else
        {
            /* See if the variable needs recursively expanding again */

            Rval returnval = EvaluateFinalRval(ctx, PromiseGetPolicy(pp), ref->ns, ref->scope, rval, true, pp);

            RvalDestroy(rval);

            // freed before function exit
            rval = returnval;
        }

        if (existing_value_type != CF_DATA_TYPE_NONE)
        {
            if (!opts.ok_redefine)    /* only on second iteration, else we ignore broken promises */
            {
                if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON &&
                     !CompareRval(existing_value, DataTypeToRvalType(existing_value_type),
                                  rval.item, rval.type))
                {
                    switch (rval.type)
                    {
                    case RVAL_TYPE_SCALAR:
                        Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant scalar '%s', was '%s' now '%s'",
                            pp->promiser, (const char *)existing_value, RvalScalarValue(rval));
                        PromiseRef(LOG_LEVEL_VERBOSE, pp);
                        break;

                    case RVAL_TYPE_LIST:
                        {
                            Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant list '%s'", pp->promiser);
                            Writer *w = StringWriter();
                            RlistWrite(w, existing_value);
                            char *oldstr = StringWriterClose(w);
                            Log(LOG_LEVEL_VERBOSE, "Old value '%s'", oldstr);
                            free(oldstr);

                            w = StringWriter();
                            RlistWrite(w, rval.item);
                            char *newstr = StringWriterClose(w);
                            Log(LOG_LEVEL_VERBOSE, " New value '%s'", newstr);
                            free(newstr);
                            PromiseRef(LOG_LEVEL_VERBOSE, pp);
                        }
                        break;

                    case RVAL_TYPE_CONTAINER:
                    case RVAL_TYPE_FNCALL:
                    case RVAL_TYPE_NOPROMISEE:
                        break;
                    }
                }

                RvalDestroy(rval);
                VarRefDestroy(ref);
                return result;
            }
        }

        if (IsCf3VarString(pp->promiser))
        {
            // Unexpanded variables, we don't do anything with
            RvalDestroy(rval);
            VarRefDestroy(ref);
            return result;
        }

        if (!IsValidVariableName(pp->promiser))
        {
            Log(LOG_LEVEL_ERR, "Variable identifier contains illegal characters");
            PromiseRef(LOG_LEVEL_ERR, pp);
            RvalDestroy(rval);
            VarRefDestroy(ref);
            return result;
        }

        if (rval.type == RVAL_TYPE_LIST)
        {
            if (opts.drop_undefined)
            {
                for (Rlist *rp = RvalRlistValue(rval); rp; rp = rp->next)
                {
                    if (IsNakedVar(RlistScalarValue(rp), '@'))
                    {
                        free(rp->val.item);
                        rp->val.item = xstrdup(CF_NULL_VALUE);
                    }
                }
            }

            for (const Rlist *rp = RvalRlistValue(rval); rp; rp = rp->next)
            {
                switch (rp->val.type)
                {
                case RVAL_TYPE_SCALAR:
                    break;

                default:
                    // Cannot assign variable because value is a list containing a non-scalar item
                    VarRefDestroy(ref);
                    RvalDestroy(rval);
                    return result;
                }
            }
        }

        if (ref->num_indices > 0)
        {
            if (data_type == CF_DATA_TYPE_CONTAINER)
            {
                char *lval_str = VarRefToString(ref, true);
                Log(LOG_LEVEL_ERR, "Cannot assign a container to an indexed variable name '%s'. Should be assigned to '%s' instead",
                    lval_str, ref->lval);
                free(lval_str);
                VarRefDestroy(ref);
                RvalDestroy(rval);
                return result;
            }
            else
            {
                DataType existing_type = CF_DATA_TYPE_NONE;
                VarRef *base_ref = VarRefCopyIndexless(ref);
                if (EvalContextVariableGet(ctx, ref, &existing_type) && existing_type == CF_DATA_TYPE_CONTAINER)
                {
                    char *lval_str = VarRefToString(ref, true);
                    char *base_ref_str = VarRefToString(base_ref, true);
                    Log(LOG_LEVEL_ERR, "Cannot assign value to indexed variable name '%s', because a container is already assigned to the base name '%s'",
                        lval_str, base_ref_str);
                    free(lval_str);
                    free(base_ref_str);
                    VarRefDestroy(base_ref);
                    VarRefDestroy(ref);
                    RvalDestroy(rval);
                    return result;
                }
                VarRefDestroy(base_ref);
            }
        }


        DataType required_datatype = DataTypeFromString(opts.cp_save->lval);
        if (rval.type != DataTypeToRvalType(required_datatype))
        {
            char *ref_str = VarRefToString(ref, true);
            char *value_str = RvalToString(rval);
            Log(LOG_LEVEL_ERR, "Variable '%s' expected a variable of type '%s', but was given incompatible value '%s'",
                ref_str, DataTypeToString(required_datatype), value_str);
            PromiseRef(LOG_LEVEL_ERR, pp);
            free(ref_str);
            free(value_str);
            VarRefDestroy(ref);
            RvalDestroy(rval);
            return PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        }

        if (!EvalContextVariablePut(ctx, ref, rval.item, required_datatype, "source=promise"))
        {
            Log(LOG_LEVEL_VERBOSE,
                "Unable to converge %s.%s value (possibly empty or infinite regression)",
                ref->scope, pp->promiser);
            PromiseRef(LOG_LEVEL_VERBOSE, pp);
            result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        }
        else
        {
            Rlist *promise_meta = PromiseGetConstraintAsList(ctx, "meta", pp);
            if (promise_meta)
            {
                StringSet *class_meta = EvalContextVariableTags(ctx, ref);
                Buffer *print;
                for (const Rlist *rp = promise_meta; rp; rp = rp->next)
                {
                    StringSetAdd(class_meta, xstrdup(RlistScalarValue(rp)));
                    print = StringSetToBuffer(class_meta, ',');
                    Log(LOG_LEVEL_DEBUG,
                        "Added tag %s to class %s, tags now [%s]",
                        RlistScalarValue(rp), pp->promiser, BufferData(print));
                    BufferDestroy(print);
                }
            }
        }
    }
    else
    {
        Log(LOG_LEVEL_ERR, "Variable %s has no promised value", pp->promiser);
        Log(LOG_LEVEL_ERR, "Rule from %s at/before line %llu",
            PromiseGetBundle(pp)->source_path,
            (unsigned long long)opts.cp_save->offset.line);
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

    /*
     * FIXME: Variable promise are exempt from normal evaluation logic still, so
     * they are not pushed to evaluation stack before being evaluated. Due to
     * this reason, we cannot call cfPS here to set classes, as it will error
     * out with ProgrammingError.
     *
     * In order to support 'classes' body for variables as well, we call
     * ClassAuditLog explicitly.
     */
    ClassAuditLog(ctx, pp, a, result);

    VarRefDestroy(ref);
    RvalDestroy(rval);

    return result;
}
Пример #10
0
static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config)
{
    CFD_MAXPROCESSES = 30;
    MAXTRIES = 5;
    DENYBADCLOCKS = true;
    CFRUNCOMMAND[0] = '\0';
    SetChecksumUpdatesDefault(ctx, true);

    /* Keep promised agent behaviour - control bodies */

    Banner("Server control promises..");

    PolicyResolve(ctx, policy, config);

    /* Now expand */

    Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER);
    if (constraints)
    {
        for (size_t i = 0; i < SeqLength(constraints); i++)
        {
            Constraint *cp = SeqAt(constraints, i);
#define IsControlBody(e) (strcmp(cp->lval, CFS_CONTROLBODY[e].lval) == 0)

            if (!IsDefinedClass(ctx, cp->classes))
            {
                continue;
            }

            VarRef *ref = VarRefParseFromScope(cp->lval, "control_server");
            const void *value = EvalContextVariableGet(ctx, ref, NULL);
            VarRefDestroy(ref);

            if (!value)
            {
                Log(LOG_LEVEL_ERR,
                    "Unknown lval '%s' in server control body",
                    cp->lval);
            }
            else if (IsControlBody(SERVER_CONTROL_SERVER_FACILITY))
            {
                SetFacility(value);
            }
            else if (IsControlBody(SERVER_CONTROL_DENY_BAD_CLOCKS))
            {
                DENYBADCLOCKS = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting denybadclocks to '%s'",
                    DENYBADCLOCKS ? "true" : "false");
            }
            else if (IsControlBody(SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS))
            {
                LOGENCRYPT = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting logencrypt to '%s'",
                    LOGENCRYPT ? "true" : "false");
            }
            else if (IsControlBody(SERVER_CONTROL_LOG_ALL_CONNECTIONS))
            {
                SV.logconns = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting logconns to %d", SV.logconns);
            }
            else if (IsControlBody(SERVER_CONTROL_MAX_CONNECTIONS))
            {
                CFD_MAXPROCESSES = (int) IntFromString(value);
                MAXTRIES = CFD_MAXPROCESSES / 3;
                Log(LOG_LEVEL_VERBOSE,
                    "Setting maxconnections to %d",
                    CFD_MAXPROCESSES);
                /* The handling of max_readers in LMDB is not ideal, but
                 * here is how it is right now: We know that both cf-serverd and
                 * cf-hub will access the lastseen database. Worst case every
                 * single thread and process will do it at the same time, and
                 * this has in fact been observed. So we add the maximum of
                 * those two values together to provide a safe ceiling. In
                 * addition, cf-agent can access the database occasionally as
                 * well, so add a few extra for that too. */
                DBSetMaximumConcurrentTransactions(CFD_MAXPROCESSES
                                                   + EnterpriseGetMaxCfHubProcesses() + 10);
                continue;
            }
            else if (IsControlBody(SERVER_CONTROL_CALL_COLLECT_INTERVAL))
            {
                COLLECT_INTERVAL = (int) 60 * IntFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting call_collect_interval to %d (seconds)",
                    COLLECT_INTERVAL);
            }
            else if (IsControlBody(SERVER_CONTROL_LISTEN))
            {
                SERVER_LISTEN = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting server listen to '%s' ",
                    SERVER_LISTEN ? "true" : "false");
            }
            else if (IsControlBody(SERVER_CONTROL_CALL_COLLECT_WINDOW))
            {
                COLLECT_WINDOW = (int) IntFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting collect_window to %d (seconds)",
                    COLLECT_INTERVAL);
            }
            else if (IsControlBody(SERVER_CONTROL_CF_RUN_COMMAND))
            {
                strlcpy(CFRUNCOMMAND, value, sizeof(CFRUNCOMMAND));
                Log(LOG_LEVEL_VERBOSE,
                    "Setting cfruncommand to '%s'",
                    CFRUNCOMMAND);
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOW_CONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.nonattackerlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.nonattackerlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_DENY_CONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting denying connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.attackerlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.attackerlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_SKIP_VERIFY))
            {
                /* Skip. */
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOW_ALL_CONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing multiple connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.multiconnlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.multiconnlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOW_USERS))
            {
                Log(LOG_LEVEL_VERBOSE, "SET Allowing users ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.allowuserlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.allowuserlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_TRUST_KEYS_FROM))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting trust keys from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.trustkeylist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.trustkeylist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOWLEGACYCONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing legacy connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.allowlegacyconnects, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.allowlegacyconnects, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_PORT_NUMBER))
            {
                CFENGINE_PORT = IntFromString(value);
                strlcpy(CFENGINE_PORT_STR, value, sizeof(CFENGINE_PORT_STR));
                Log(LOG_LEVEL_VERBOSE, "Setting default port number to %d",
                    CFENGINE_PORT);
            }
            else if (IsControlBody(SERVER_CONTROL_BIND_TO_INTERFACE))
            {
                strlcpy(BINDINTERFACE, value, sizeof(BINDINTERFACE));
                Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE);
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOWCIPHERS))
            {

                SV.allowciphers = xstrdup(value);
                Log(LOG_LEVEL_VERBOSE, "Setting allowciphers to '%s'", SV.allowciphers);
            }
#undef IsControlBody
        }
    }

    const void *value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST);
    if (value)
    {
        /* Don't resolve syslog_host now, better do it per log request. */
        if (!SetSyslogHost(value))
        {
            Log(LOG_LEVEL_ERR, "Failed to set syslog_host, '%s' too long", (const char *)value);
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (const char *)value);
        }
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT);
    if (value)
    {
        SetSyslogPort(IntFromString(value));
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE);
    if (value)
    {
        FIPS_MODE = BooleanFromString(value);
        Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to to '%s'", FIPS_MODE ? "true" : "false");
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER);
    if (value)
    {
        LASTSEENEXPIREAFTER = IntFromString(value) * 60;
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BWLIMIT);
    if (value)
    {
        double bval;
        if (DoubleFromString(value, &bval))
        {
            bwlimit_kbytes = (uint32_t) ( bval / 1000.0);
            Log(LOG_LEVEL_VERBOSE, "Setting rate limit to %d kBytes/sec", bwlimit_kbytes);
        }
    }

}
Пример #11
0
static SyntaxTypeMatch CheckParseRealRange(const char *lval, const char *s, const char *range)
{
 Item *split, *rangep, *ip;
 double max = (double) CF_LOWINIT, min = (double) CF_HIGHINIT, val;
 int n;

 if (*s == '[' || *s == '(')
    {
    return SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED;
    }

 if (strcmp(s, "inf") == 0)
    {
    return SYNTAX_TYPE_MATCH_ERROR_REAL_INF;
    }

 if (IsCf3VarString(s))
    {
    return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED;
    }

/* Numeric types are registered by range separated by comma str "min,max" */

 split = SplitString(range, ',');

 if ((n = ListLen(split)) != 2)
    {
    ProgrammingError("Format specifier for real rvalues is not ok for lval %s - %d items", lval, n);
    }

 sscanf(split->name, "%lf", &min);
 sscanf(split->next->name, "%lf", &max);
 DeleteItemList(split);

 if (min == CF_HIGHINIT || max == CF_LOWINIT)
    {
    ProgrammingError("Could not parse format specifier for int rvalues for lval %s", lval);
    }

 rangep = SplitString(s, ',');

 if ((n = ListLen(rangep)) != 2)
    {
    return SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS;
    }

 for (ip = rangep; ip != NULL; ip = ip->next)
    {
    if (!DoubleFromString(ip->name, &val))
       {
       return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE;
       }

    if (val > max || val < min)
       {
       return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE;
       }
    }

 DeleteItemList(rangep);

 return SYNTAX_TYPE_MATCH_OK;
}
// Calculate a value from the 3 other values
// Vref is given by the regulator properties, so
// we can calculate only R1, R2 or Vout
void PCB_CALCULATOR_FRAME::RegulatorsSolve()
{
    int id;
    if( m_rbRegulR1->GetValue() )
        id = 0;     // for R1 calculation
    else if( m_rbRegulR2->GetValue() )
        id = 1;     // for R2 calculation
    else if( m_rbRegulVout->GetValue() )
        id = 2;     // for Vout calculation
    else
    {
        wxMessageBox( wxT("Selection error" ) );
        return;
    }

    double r1, r2, vref, vout;

    wxString txt;

    m_RegulMessage->SetLabel( wxEmptyString);

    // Convert r1 and r2 in ohms
    int r1scale = 1000;
    int r2scale = 1000;

    // Read values from panel:
    txt = m_RegulR1Value->GetValue();
    r1 = DoubleFromString(txt) * r1scale;
    txt = m_RegulR2Value->GetValue();
    r2 = DoubleFromString(txt) * r2scale;
    txt = m_RegulVrefValue->GetValue();
    vref = DoubleFromString(txt);
    txt = m_RegulVoutValue->GetValue();
    vout = DoubleFromString(txt);


    // Some tests:
    if( vout < vref && id != 2)
    {
        m_RegulMessage->SetLabel( _(" Vout must be greater than vref" ) );
        return;
    }

    if( vref == 0.0 )
    {
        m_RegulMessage->SetLabel( _(" Vref set to 0 !" ) );
        return;
    }

    if( (r1 < 0 && id != 0 ) || (r2 <= 0 && id != 1) )
    {
        m_RegulMessage->SetLabel( _("Incorrect value for R1 R2" ) );
        return;
    }

    // Calculate
    if( m_choiceRegType->GetSelection() == 1)
    {
        // 3 terminal regulator
        txt = m_RegulIadjValue->GetValue();
        double iadj = DoubleFromString(txt);
        // iadj is given in micro amp, so convert it in amp.
        iadj /= 1000000;

        switch( id )
        {
            case 0:
                r1 = vref * r2 / ( vout - vref - (r2 * iadj) );
                break;

            case 1:
                r2 = ( vout - vref ) / ( iadj + (vref/r1) );
                break;

            case 2:
                vout = vref * (r1 + r2) / r1;
                vout += r2 * iadj;
                break;
        }
    }
    else
    {   // Standard 4 terminal regulator
        switch( id )
        {
            case 0:
                r1 = ( vout / vref - 1 ) * r2;
                break;

            case 1:
                r2 = r1 / ( vout / vref - 1);
                break;

            case 2:
                vout = vref * (r1 + r2) / r2;
                break;
        }
    }
    // write values to panel:
    txt.Printf(wxT("%g"), r1 / r1scale );
    m_RegulR1Value->SetValue(txt);
    txt.Printf(wxT("%g"), r2 / r2scale);
    m_RegulR2Value->SetValue(txt);
    txt.Printf(wxT("%g"), vref);
    m_RegulVrefValue->SetValue(txt);
    txt.Printf(wxT("%g"), vout);
    m_RegulVoutValue->SetValue(txt);

}
Пример #13
0
void VerifyVarPromise(EvalContext *ctx, const Promise *pp, bool allow_duplicates)
{
    ConvergeVariableOptions opts = CollectConvergeVariableOptions(ctx, pp, allow_duplicates);
    if (!opts.should_converge)
    {
        return;
    }

    char *scope = NULL;
    if (strcmp("meta", pp->parent_promise_type->name) == 0)
    {
        scope = StringConcatenate(2, PromiseGetBundle(pp)->name, "_meta");
    }
    else
    {
        scope = xstrdup(PromiseGetBundle(pp)->name);
    }

    //More consideration needs to be given to using these
    //a.transaction = GetTransactionConstraints(pp);
    Attributes a = { {0} };
    a.classes = GetClassDefinitionConstraints(ctx, pp);

    Rval existing_var_rval;
    DataType existing_var_type = DATA_TYPE_NONE;
    EvalContextVariableGet(ctx, (VarRef) { NULL, scope, pp->promiser }, &existing_var_rval, &existing_var_type);
    Buffer *qualified_scope = BufferNew();
    int result = 0;
    if (strcmp(PromiseGetNamespace(pp), "default") == 0)
    {
        result = BufferSet(qualified_scope, scope, strlen(scope));
        if (result < 0)
        {
            /*
             * Even though there will be no problems with memory allocation, there
             * might be other problems.
             */
            UnexpectedError("Problems writing to buffer");
            free(scope);
            BufferDestroy(&qualified_scope);
            return;
        }
    }
    else
    {
        if (strchr(scope, ':') == NULL)
        {
            result = BufferPrintf(qualified_scope, "%s:%s", PromiseGetNamespace(pp), scope);
            if (result < 0)
            {
                /*
                 * Even though there will be no problems with memory allocation, there
                 * might be other problems.
                 */
                UnexpectedError("Problems writing to buffer");
                free(scope);
                BufferDestroy(&qualified_scope);
                return;
            }
        }
        else
        {
            result = BufferSet(qualified_scope, scope, strlen(scope));
            if (result < 0)
            {
                /*
                 * Even though there will be no problems with memory allocation, there
                 * might be other problems.
                 */
                UnexpectedError("Problems writing to buffer");
                free(scope);
                BufferDestroy(&qualified_scope);
                return;
            }
        }
    }

    PromiseResult promise_result;

    Rval rval = opts.cp_save->rval;

    if (rval.item != NULL)
    {
        FnCall *fp = (FnCall *) rval.item;

        if (opts.cp_save->rval.type == RVAL_TYPE_FNCALL)
        {
            if (existing_var_type != DATA_TYPE_NONE)
            {
                // Already did this
                free(scope);
                BufferDestroy(&qualified_scope);
                return;
            }

            FnCallResult res = FnCallEvaluate(ctx, fp, pp);

            if (res.status == FNCALL_FAILURE)
            {
                /* We do not assign variables to failed fn calls */
                RvalDestroy(res.rval);
                free(scope);
                BufferDestroy(&qualified_scope);
                return;
            }
            else
            {
                rval = res.rval;
            }
        }
        else
        {
            Buffer *conv = BufferNew();

            if (strcmp(opts.cp_save->lval, "int") == 0)
            {
                result = BufferPrintf(conv, "%ld", IntFromString(opts.cp_save->rval.item));
                if (result < 0)
                {
                    /*
                     * Even though there will be no problems with memory allocation, there
                     * might be other problems.
                     */
                    UnexpectedError("Problems writing to buffer");
                    free(scope);
                    BufferDestroy(&qualified_scope);
                    BufferDestroy(&conv);
                    return;
                }
                rval = RvalCopy((Rval) {(char *)BufferData(conv), opts.cp_save->rval.type});
            }
            else if (strcmp(opts.cp_save->lval, "real") == 0)
            {
                double real_value = 0.0;
                if (DoubleFromString(opts.cp_save->rval.item, &real_value))
                {
                    result = BufferPrintf(conv, "%lf", real_value);
                }
                else
                {
                    result = BufferPrintf(conv, "(double conversion error)");
                }

                if (result < 0)
                {
                    /*
                     * Even though there will be no problems with memory allocation, there
                     * might be other problems.
                     */
                    UnexpectedError("Problems writing to buffer");
                    free(scope);
                    BufferDestroy(&conv);
                    BufferDestroy(&qualified_scope);
                    return;
                }
                rval = RvalCopy((Rval) {(char *)BufferData(conv), opts.cp_save->rval.type});
            }
            else
            {
                rval = RvalCopy(opts.cp_save->rval);
            }

            if (rval.type == RVAL_TYPE_LIST)
            {
                Rlist *rval_list = RvalRlistValue(rval);
                RlistFlatten(ctx, &rval_list);
                rval.item = rval_list;
            }

            BufferDestroy(&conv);
        }

        if (Epimenides(ctx, PromiseGetBundle(pp)->name, pp->promiser, rval, 0))
        {
            Log(LOG_LEVEL_ERR, "Variable \"%s\" contains itself indirectly - an unkeepable promise", pp->promiser);
            exit(1);
        }
        else
        {
            /* See if the variable needs recursively expanding again */

            Rval returnval = EvaluateFinalRval(ctx, BufferData(qualified_scope), rval, true, pp);

            RvalDestroy(rval);

            // freed before function exit
            rval = returnval;
        }

        if (existing_var_type != DATA_TYPE_NONE)
        {
            if (opts.ok_redefine)    /* only on second iteration, else we ignore broken promises */
            {
                ScopeDeleteVariable(BufferData(qualified_scope), pp->promiser);
            }
            else if ((THIS_AGENT_TYPE == AGENT_TYPE_COMMON) && (CompareRval(existing_var_rval, rval) == false))
            {
                switch (rval.type)
                {
                case RVAL_TYPE_SCALAR:
                    Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant scalar \"%s\" (was %s now %s)",
                          pp->promiser, RvalScalarValue(existing_var_rval), RvalScalarValue(rval));
                    PromiseRef(LOG_LEVEL_VERBOSE, pp);
                    break;

                case RVAL_TYPE_LIST:
                    {
                        Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant list \"%s\".", pp->promiser);
                        Writer *w = StringWriter();
                        RlistWrite(w, existing_var_rval.item);
                        char *oldstr = StringWriterClose(w);
                        Log(LOG_LEVEL_VERBOSE, "Old value: %s", oldstr);
                        free(oldstr);

                        w = StringWriter();
                        RlistWrite(w, rval.item);
                        char *newstr = StringWriterClose(w);
                        Log(LOG_LEVEL_VERBOSE, " New value: %s", newstr);
                        free(newstr);
                        PromiseRef(LOG_LEVEL_VERBOSE, pp);
                    }
                    break;

                default:
                    break;
                }
            }
        }

        if (IsCf3VarString(pp->promiser))
        {
            // Unexpanded variables, we don't do anything with
            RvalDestroy(rval);
            free(scope);
            BufferDestroy(&qualified_scope);
            return;
        }

        if (!FullTextMatch("[a-zA-Z0-9_\200-\377.]+(\\[.+\\])*", pp->promiser))
        {
            Log(LOG_LEVEL_ERR, "Variable identifier contains illegal characters");
            PromiseRef(LOG_LEVEL_ERR, pp);
            RvalDestroy(rval);
            free(scope);
            BufferDestroy(&qualified_scope);
            return;
        }

        if (opts.drop_undefined && rval.type == RVAL_TYPE_LIST)
        {
            for (Rlist *rp = rval.item; rp != NULL; rp = rp->next)
            {
                if (IsNakedVar(rp->item, '@'))
                {
                    free(rp->item);
                    rp->item = xstrdup(CF_NULL_VALUE);
                }
            }
        }

        if (!EvalContextVariablePut(ctx, (VarRef) { NULL, BufferData(qualified_scope), pp->promiser }, rval, DataTypeFromString(opts.cp_save->lval)))
        {
            Log(LOG_LEVEL_VERBOSE, "Unable to converge %s.%s value (possibly empty or infinite regression)", BufferData(qualified_scope), pp->promiser);
            PromiseRef(LOG_LEVEL_VERBOSE, pp);
            promise_result = PROMISE_RESULT_FAIL;
        }
        else
        {
            promise_result = PROMISE_RESULT_CHANGE;
        }
    }
    else
    {
        Log(LOG_LEVEL_ERR, "Variable %s has no promised value", pp->promiser);
        Log(LOG_LEVEL_ERR, "Rule from %s at/before line %zu", PromiseGetBundle(pp)->source_path, opts.cp_save->offset.line);
        promise_result = PROMISE_RESULT_FAIL;
    }

    /*
     * FIXME: Variable promise are exempt from normal evaluation logic still, so
     * they are not pushed to evaluation stack before being evaluated. Due to
     * this reason, we cannot call cfPS here to set classes, as it will error
     * out with ProgrammingError.
     *
     * In order to support 'classes' body for variables as well, we call
     * ClassAuditLog explicitly.
     */
    ClassAuditLog(ctx, pp, a, promise_result);

    free(scope);
    BufferDestroy(&qualified_scope);
    RvalDestroy(rval);
}
void PCB_CALCULATOR_FRAME::TWDisplayValues( double aCurrent, double aExtWidth,
        double aIntWidth, double aExtThickness, double aIntThickness )
{
    wxString msg;

    // Show the current.
    if( m_TWMode != TW_MASTER_CURRENT )
    {
        msg.Printf( wxT( "%g" ), aCurrent );
        m_TrackCurrentValue->SetValue( msg );
    }

    // Load scale factors to convert into output units.
    double extScale = m_TW_ExtTrackWidth_choiceUnit->GetUnitScale();
    double intScale = m_TW_IntTrackWidth_choiceUnit->GetUnitScale();

    // Display the widths.
    if( m_TWMode != TW_MASTER_EXT_WIDTH )
    {
        msg.Printf( wxT( "%g" ), aExtWidth / extScale );
        m_ExtTrackWidthValue->SetValue( msg );
    }

    if( m_TWMode != TW_MASTER_INT_WIDTH )
    {
        msg.Printf( wxT( "%g" ), aIntWidth / intScale );
        m_IntTrackWidthValue->SetValue( msg );
    }

    // Display cross-sectional areas.
    msg.Printf( wxT( "%g" ), (aExtWidth * aExtThickness) / (extScale * extScale) );
    m_ExtTrackAreaValue->SetLabel( msg );
    msg.Printf( wxT( "%g" ), (aIntWidth * aIntThickness) / (intScale * intScale) );
    m_IntTrackAreaValue->SetLabel( msg );

    // Show area units.
    wxString strunit = m_TW_ExtTrackWidth_choiceUnit->GetUnitName();
    msg = strunit + wxT( " x " ) + strunit;
    m_ExtTrackAreaUnitLabel->SetLabel( msg );
    strunit = m_TW_IntTrackWidth_choiceUnit->GetUnitName();
    msg = strunit + wxT( " x " ) + strunit;
    m_IntTrackAreaUnitLabel->SetLabel( msg );

    // Load resistivity and length of traces.
    double rho      = std::abs( DoubleFromString( m_TWResistivity->GetValue() ) );
    double trackLen = std::abs( DoubleFromString( m_TrackLengthValue->GetValue() ) );
    trackLen *= m_TW_CuLength_choiceUnit->GetUnitScale();

    // Calculate resistance.
    double extResistance = ( rho * trackLen ) / ( aExtWidth * aExtThickness );
    double intResistance = ( rho * trackLen ) / ( aIntWidth * aIntThickness );

    // Display resistance.
    msg.Printf( wxT( "%g" ), extResistance );
    m_ExtTrackResistValue->SetLabel( msg );
    msg.Printf( wxT( "%g" ), intResistance );
    m_IntTrackResistValue->SetLabel( msg );

    // Display voltage drop along trace.
    double extV = extResistance * aCurrent;
    msg.Printf( wxT( "%g" ), extV );
    m_ExtTrackVDropValue->SetLabel( msg );
    double intV = intResistance * aCurrent;
    msg.Printf( wxT( "%g" ), intV );
    m_IntTrackVDropValue->SetLabel( msg );

    // And power loss.
    msg.Printf( wxT( "%g" ), extV * aCurrent );
    m_ExtTrackLossValue->SetLabel( msg );
    msg.Printf( wxT( "%g" ), intV * aCurrent );
    m_IntTrackLossValue->SetLabel( msg );
}
Пример #15
0
static PromiseResult MonExtractValueFromStream(EvalContext *ctx, const char *handle,
                                                Item *stream, Attributes a,
                                                const Promise *pp, double *value_out)
{
 char value[CF_MAXVARSIZE];
 int count = 1, found = false, match_count = 0, done = false;
 double real_val = 0;
 Item *ip, *match = NULL;
 bool ok_conversion = true;
 
 for (ip = stream; ip != NULL; ip = ip->next)
    {
    if (count == a.measure.select_line_number)
       {
       found = true;
       match = ip;
       match_count++;
       }
    
    if (a.measure.select_line_matching && StringMatchFull(a.measure.select_line_matching, ip->name))
       {
       Log(LOG_LEVEL_VERBOSE, " ?? Look for %s regex %s", handle, a.measure.select_line_matching);
       found = true;
       match = ip;
       
       if (a.measure.extraction_regex)
          {
          switch (a.measure.data_type)
             {
             case CF_DATA_TYPE_INT:
             case CF_DATA_TYPE_REAL:
                 
                 strncpy(value, ExtractFirstReference(a.measure.extraction_regex, match->name), CF_MAXVARSIZE - 1);
                 
                 if (strcmp(value, "CF_NOMATCH") == 0)
                    {
                    ok_conversion = false;
                    Log(LOG_LEVEL_VERBOSE, "Was not able to match a value with '%s' on '%s'",
                        a.measure.extraction_regex, match->name);
                    }
                 else
                    {
                    if (ok_conversion)
                       {
                       Log(LOG_LEVEL_VERBOSE, "Found candidate match value of '%s'", value);
                       
                       if (a.measure.policy == MEASURE_POLICY_SUM || a.measure.policy == MEASURE_POLICY_AVERAGE)
                          {
                          double delta = 0;
                          if (DoubleFromString(value, &delta))
                             {
                             real_val += delta;
                             }
                          else
                             {
                             Log(LOG_LEVEL_ERR, "Error in double conversion from string value: %s", value);
                             return false;
                             }
                          }
                       else
                          {
                          if (!DoubleFromString(value, &real_val))
                             {
                             Log(LOG_LEVEL_ERR, "Error in double conversion from string value: %s", value);
                             return false;
                             }
                          }
                       
                       match_count++;
                       
                       if (a.measure.policy == MEASURE_POLICY_FIRST)
                          {
                          done = true;
                          }
                       }
                    }
                 break;
                 
             default:
                 Log(LOG_LEVEL_ERR, "Unexpected data type in data_type attribute: %d", a.measure.data_type);
             }
          }
       }
    
    count++;
    
    if (done)
       {
       break;
       }
    }
 
 if (!found)
    {
    cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, pp, a, "Could not locate the line for promise '%s'", handle);
    *value_out = 0.0;
    return PROMISE_RESULT_FAIL;
    }
 
 switch (a.measure.data_type)
    {
    case CF_DATA_TYPE_COUNTER:
        
        real_val = (double) match_count;
        break;
        
    case CF_DATA_TYPE_INT:
        
        if (match_count > 1)
           {
           Log(LOG_LEVEL_INFO, "Warning: %d lines matched the line_selection \"%s\"- making best average", match_count, a.measure.select_line_matching);
           }
        
        if (match_count > 0 && a.measure.policy == MEASURE_POLICY_AVERAGE) // If not "average" then "sum"
           {
           real_val /= match_count;
           }
        break;
        
    case CF_DATA_TYPE_REAL:
        
        if (match_count > 1)
           {
           Log(LOG_LEVEL_INFO, "Warning: %d lines matched the line_selection \"%s\"- making best average",
               match_count, a.measure.select_line_matching);
           }
        
        if (match_count > 0)
           {
           real_val /= match_count;
           }
        
        break;
        
    default:
        Log(LOG_LEVEL_ERR, "Unexpected data type in data_type attribute: %d", a.measure.data_type);
    }
 
 if (!ok_conversion)
    {
    cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to extract a value from the matched line '%s'", match->name);
    PromiseRef(LOG_LEVEL_INFO, pp);
    *value_out = 0.0;
    return PROMISE_RESULT_FAIL;
    }
 
 Log(LOG_LEVEL_INFO, "Extracted value \"%f\" for promise \"%s\"", real_val, handle);
 *value_out = real_val;
 return PROMISE_RESULT_NOOP;
}