Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/bootable/bootable/deprecated-ota/edify/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 12 kB image not shown  

Quelle  expr.cpp

  Sprache: C
 

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "edify/expr.h"

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include "otautil/error_code.h"

// Functions should:
//
//    - return a malloc()'d string
//    - if Evaluate() on any argument returns nullptr, return nullptr.

static bool BooleanString(const std::string& s) {
    return !s.empty();
}

bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
    if (result == nullptr) {
        return false;
    }

    std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
    if (!v) {
        return false;
    }
    if (v->type != Value::Type::STRING) {
      ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
      return false;
    }

    *result = v->data;
    return true;
}

Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
    return expr->fn(expr->name.c_str(), state, expr->argv);
}

Value* StringValue(const char* str) {
    if (str == nullptr) {
        return nullptr;
    }
    return new Value(Value::Type::STRING, str);
}

Value* StringValue(const std::string& str) {
    return StringValue(str.c_str());
}

Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>&&nbsp;argv) {
    if (argv.empty()) {
        return StringValue("");
    }
    std::string result;
    for (size_t i = 0; i < argv.size(); ++i) {
        std::string str;
        if (!Evaluate(state, argv[i], &str)) {
            return nullptr;
        }
        result += str;
    }

    return StringValue(result);
}

Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>&&nbsp;argv) {
    if (argv.size() != 2 && argv.size() != 3) {
        state->errmsg = "ifelse expects 2 or 3 arguments";
        return nullptr;
    }

    std::string cond;
    if (!Evaluate(state, argv[0], &cond)) {
        return nullptr;
    }

    if (!cond.empty()) {
        return EvaluateValue(state, argv[1]);
    } else if (argv.size() == 3) {
        return EvaluateValue(state, argv[2]);
    }

    return StringValue("");
}

Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& ;argv) {
    std::string msg;
    if (!argv.empty() && Evaluate(state, argv[0], &msg)) {
      state->errmsg += msg;
    } else {
      state->errmsg += "called abort()";
    }
    return nullptr;
}

Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>&&nbsp;argv) {
    for (size_t i = 0; i < argv.size(); ++i) {
        std::string result;
        if (!Evaluate(state, argv[i], &result)) {
            return nullptr;
        }
        if (result.empty()) {
            int len = argv[i]->end - argv[i]->start;
            state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
            return nullptr;
        }
    }
    return StringValue("");
}

Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& ;argv) {
    std::string val;
    if (!Evaluate(state, argv[0], &val)) {
        return nullptr;
    }

    int v;
    if (!android::base::ParseInt(val.c_str(), &v, 0)) {
        return nullptr;
    }
    sleep(v);

    return StringValue(val);
}

Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>&&nbsp;argv) {
    for (size_t i = 0; i < argv.size(); ++i) {
        std::string v;
        if (!Evaluate(state, argv[i], &v)) {
            return nullptr;
        }
        fputs(v.c_str(), stdout);
    }
    return StringValue("");
}

Value* LogicalAndFn(const char* name, State* state,
                    const std::vector<std::unique_ptr<Expr>>& argv) {
    std::string left;
    if (!Evaluate(state, argv[0], &left)) {
        return nullptr;
    }
    if (BooleanString(left)) {
        return EvaluateValue(state, argv[1]);
    } else {
        return StringValue("");
    }
}

Value* LogicalOrFn(const char* name, State* state,
                   const std::vector<std::unique_ptr<Expr>>& argv) {
    std::string left;
    if (!Evaluate(state, argv[0], &left)) {
        return nullptr;
    }
    if (!BooleanString(left)) {
        return EvaluateValue(state, argv[1]);
    } else {
        return StringValue(left);
    }
}

Value* LogicalNotFn(const char* name, State* state,
                    const std::vector<std::unique_ptr<Expr>>& argv) {
    std::string val;
    if (!Evaluate(state, argv[0], &val)) {
        return nullptr;
    }

    return StringValue(BooleanString(val) ? "" : "t");
}

Value* SubstringFn(const char* name, State* state,
                   const std::vector<std::unique_ptr<Expr>>& argv) {
    std::string needle;
    if (!Evaluate(state, argv[0], &needle)) {
        return nullptr;
    }

    std::string haystack;
    if (!Evaluate(state, argv[1], &haystack)) {
        return nullptr;
    }

    std::string result = (haystack.find(needle) != std::string::npos) ? "t" : "";
    return StringValue(result);
}

Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>&&nbsp;argv) {
    std::string left;
    if (!Evaluate(state, argv[0], &left)) {
        return nullptr;
    }
    std::string right;
    if (!Evaluate(state, argv[1], &right)) {
        return nullptr;
    }

    const char* result = (left == right) ? "t" : "";
    return StringValue(result);
}

Value* InequalityFn(const char* name, State* state,
                    const std::vector<std::unique_ptr<Expr>>& argv) {
    std::string left;
    if (!Evaluate(state, argv[0], &left)) {
        return nullptr;
    }
    std::string right;
    if (!Evaluate(state, argv[1], &right)) {
        return nullptr;
    }

    const char* result = (left != right) ? "t" : "";
    return StringValue(result);
}

Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>&&nbsp;argv) {
    std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
    if (!left) {
        return nullptr;
    }
    return EvaluateValue(state, argv[1]);
}

Value* LessThanIntFn(const char* name, State* state,
                     const std::vector<std::unique_ptr<Expr>>& argv) {
    if (argv.size() != 2) {
        state->errmsg = "less_than_int expects 2 arguments";
        return nullptr;
    }

    std::vector<std::string> args;
    if (!ReadArgs(state, argv, &args)) {
        return nullptr;
    }

    // Parse up to at least long long or 64-bit integers.
    int64_t l_int;
    if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
        state->errmsg = "failed to parse int in " + args[0];
        return nullptr;
    }

    int64_t r_int;
    if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
        state->errmsg = "failed to parse int in " + args[1];
        return nullptr;
    }

    return StringValue(l_int < r_int ? "t" : "");
}

Value* GreaterThanIntFn(const char* name, State* state,
                        const std::vector<std::unique_ptr<Expr>>& argv) {
    if (argv.size() != 2) {
        state->errmsg = "greater_than_int expects 2 arguments";
        return nullptr;
    }

    std::vector<std::string> args;
    if (!ReadArgs(state, argv, &args)) {
        return nullptr;
    }

    // Parse up to at least long long or 64-bit integers.
    int64_t l_int;
    if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
        state->errmsg = "failed to parse int in " + args[0];
        return nullptr;
    }

    int64_t r_int;
    if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
        state->errmsg = "failed to parse int in " + args[1];
        return nullptr;
    }

    return StringValue(l_int > r_int ? "t" : "");
}

Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& ;argv) {
    return StringValue(name);
}

// -----------------------------------------------------------------
//   the function table
// -----------------------------------------------------------------

static std::unordered_map<std::string, Function> fn_table;

void RegisterFunction(const std::string& name, Function fn) {
    fn_table[name] = fn;
}

Function FindFunction(const std::string& name) {
    if (fn_table.find(name) == fn_table.end()) {
        return nullptr;
    } else {
        return fn_table[name];
    }
}

void RegisterBuiltins() {
    RegisterFunction("ifelse", IfElseFn);
    RegisterFunction("abort", AbortFn);
    RegisterFunction("assert", AssertFn);
    RegisterFunction("concat", ConcatFn);
    RegisterFunction("is_substring", SubstringFn);
    RegisterFunction("stdout", StdoutFn);
    RegisterFunction("sleep", SleepFn);

    RegisterFunction("less_than_int", LessThanIntFn);
    RegisterFunction("greater_than_int", GreaterThanIntFn);
}


// -----------------------------------------------------------------
//   convenience methods for functions
// -----------------------------------------------------------------

// Evaluate the expressions in argv, and put the results of strings in args. If any expression
// evaluates to nullptr, return false. Return true on success.
bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
              std::vector<std::string>* args) {
    return ReadArgs(state, argv, args, 0, argv.size());
}

bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
              std::vector<std::string>* args, size_t start, size_t len) {
    if (args == nullptr) {
        return false;
    }
    if (start + len > argv.size()) {
        return false;
    }
    for (size_t i = start; i < start + len; ++i) {
        std::string var;
        if (!Evaluate(state, argv[i], &var)) {
            args->clear();
            return false;
        }
        args->push_back(var);
    }
    return true;
}

// Evaluate the expressions in argv, and put the results of Value* in args. If any expression
// evaluate to nullptr, return false. Return true on success.
bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
                   std::vector<std::unique_ptr<Value>>* args) {
    return ReadValueArgs(state, argv, args, 0, argv.size());
}

bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
                   std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) {
    if (args == nullptr) {
        return false;
    }
    if (len == 0 || start + len > argv.size()) {
        return false;
    }
    for (size_t i = start; i < start + len; ++i) {
        std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
        if (!v) {
            args->clear();
            return false;
        }
        args->push_back(std::move(v));
    }
    return true;
}

// Use printf-style arguments to compose an error message to put into
// *state.  Returns nullptr.
Value* ErrorAbort(State* state, const char* format, ...) {
    va_list ap;
    va_start(ap, format);
    android::base::StringAppendV(&state->errmsg, format, ap);
    va_end(ap);
    return nullptr;
}

Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
  std::string err_message;
  va_list ap;
  va_start(ap, format);
  android::base::StringAppendV(&err_message, format, ap);
  va_end(ap);
  // Ensure that there's exactly one line break at the end of the error message.
  state->errmsg = android::base::Trim(err_message) + "\n";
  state->cause_code = cause_code;
  return nullptr;
}

State::State(const std::string& script, UpdaterInterface* interface)
    : script(script), updater(interface), error_code(kNoError), cause_code(kNoCause) {}

Messung V0.5 in Prozent
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-07-01) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.