// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "vdso_wrapper_generator.h"

#include <algorithm>

using std::ofstream;
using std::string;
using std::vector;

static const string in = "    ";
static const string inin = in + in;

static bool none_apply(const Syscall& sc, const std::vector<CallWrapper*> wrappers) {
    for (const CallWrapper* wrapper : wrappers) {
        if (wrapper->applies(sc)) {
            return false;
        }
    }
    return true;
}

bool VdsoWrapperGenerator::syscall(ofstream& os, const Syscall& sc) {
    if (sc.is_vdso() || none_apply(sc, wrappers_)) {
        // Skip all calls implemented in the VDSO. They're on their own.
        return os.good();
    }

    // Writing the wrapper.
    write_syscall_signature_line(os, sc, wrapper_prefix_, "", " ", false, "");
    os << " {\n"
       << in;
    std::string return_var = write_syscall_return_var(os, sc);
    pre_call(os, sc);
    os << inin;
    // Invoke the actuall syscall.
    write_syscall_invocation(os, sc, return_var, call_prefix_);
    post_call(os, sc, return_var);

    if (!return_var.empty()) {
        os << in << "return " << return_var << ";\n";
    }
    os << "}\n\n";

    // Now put the wrapper into the public interface.
    os << "VDSO_INTERFACE_FUNCTION(zx_" << sc.name << ");\n\n";

    return os.good();
}

void VdsoWrapperGenerator::pre_call(ofstream& os, const Syscall& sc) const {
    std::for_each(wrappers_.begin(), wrappers_.end(), [&os, &sc](const CallWrapper* wrapper) {
        if (wrapper->applies(sc)) {
            wrapper->preCall(os, sc);
        }
    });
}

void VdsoWrapperGenerator::post_call(ofstream& os, const Syscall& sc, string return_var) const {
    std::for_each(wrappers_.rbegin(), wrappers_.rend(), [&os, &sc, &return_var](
                                                            const CallWrapper* wrapper) {
        if (wrapper->applies(sc)) {
            wrapper->postCall(os, sc, return_var);
        }
    });
}

bool TestWrapper::applies(const Syscall& sc) const {
    return sc.name == "syscall_test_wrapper";
}

void TestWrapper::preCall(ofstream& os, const Syscall& sc) const {
    os << in << "if (a < 0 || b < 0 || c < 0) return ZX_ERR_INVALID_ARGS;\n";
}

void TestWrapper::postCall(ofstream& os, const Syscall& sc, string return_var) const {
    os << in << "if (" << return_var << " > 50) return ZX_ERR_OUT_OF_RANGE;\n";
}

bool BlockingRetryWrapper::applies(const Syscall& sc) const {
    return sc.is_blocking();
}

void BlockingRetryWrapper::preCall(ofstream& os, const Syscall& sc) const {
    os << in << "do {\n";
}

void BlockingRetryWrapper::postCall(
    ofstream& os, const Syscall& sc, string return_var) const {
    os << in << "} while (unlikely(" << return_var << " == ZX_ERR_INTERNAL_INTR_RETRY));\n";
}
