// 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.

#pragma once

#include <ctime>
#include <fstream>
#include <string>

#include "types.h"

// Interface for syscall generators.
class Generator {
public:
    virtual bool header(std::ofstream& os);
    virtual bool syscall(std::ofstream& os, const Syscall& sc) = 0;
    virtual bool footer(std::ofstream& os);

protected:
    virtual ~Generator() {}
};

// Interface for vDSO wrappers.
class CallWrapper {
public:
    virtual bool applies(const Syscall& sc) const = 0;
    virtual void preCall(std::ofstream& os, const Syscall& sc) const {}
    virtual void postCall(std::ofstream& os, const Syscall& sc, std::string return_var) const {}

protected:
    virtual ~CallWrapper() {}
};

// Generate the vDSO assembly stubs.
class VDsoAsmGenerator : public Generator {
public:
    VDsoAsmGenerator(const std::string& syscall_macro,
                     const std::string& name_prefix,
                     const std::vector<CallWrapper*>& call_wrappers)
        : syscall_macro_(syscall_macro),
          name_prefix_(name_prefix),
          wrappers_(call_wrappers) {}

    bool syscall(std::ofstream& os, const Syscall& sc) override;

private:
    const std::string syscall_macro_;
    const std::string name_prefix_;
    const std::vector<CallWrapper*> wrappers_;
};

// Generate the syscall number definitions.
class SyscallNumbersGenerator : public Generator {
public:
    SyscallNumbersGenerator(const std::string& define_prefix)
        : define_prefix_(define_prefix) {}

    bool syscall(std::ofstream& os, const Syscall& sc) override;
    bool footer(std::ofstream& os) override;

private:
    const std::string define_prefix_;
    int num_calls_ = 0;
};

// Generate debug trace info.
class TraceInfoGenerator : public Generator {
public:
    bool syscall(std::ofstream& os, const Syscall& sc) override;
};

// Generate category list.
class CategoryGenerator : public Generator {
public:
    bool syscall(std::ofstream& os, const Syscall& sc) override;
    bool footer(std::ofstream& os) override;

private:
    std::map<const std::string, std::vector<const std::string*>> category_map_;
};

/* Generates the kernel syscall jump table and accoutrements. */
class KernelBranchGenerator : public Generator {
public:
    bool header(std::ofstream& os) override;
    bool syscall(std::ofstream& os, const Syscall& sc) override;
};

/* Generates the kernel syscall wrappers. */
class KernelWrapperGenerator : public Generator {
public:
    KernelWrapperGenerator(const std::string& syscall_prefix, const std::string& wrapper_prefix,
                           const std::string& define_prefix)
        : syscall_prefix_(syscall_prefix), wrapper_prefix_(wrapper_prefix),
          define_prefix_(define_prefix) {}

    bool header(std::ofstream& os) override;
    bool syscall(std::ofstream& os, const Syscall& sc) override;
    bool footer(std::ofstream& os) override;

private:
    const std::string syscall_prefix_;
    const std::string wrapper_prefix_;
    const std::string define_prefix_;
};

/* Generates the Rust bindings. */
class RustBindingGenerator : public Generator {
public:
    bool header(std::ofstream& os) override;
    bool footer(std::ofstream& os) override;
    bool syscall(std::ofstream& os, const Syscall& sc) override;
};

/* Generates a JSON representation of the syscall list. */
class JsonGenerator : public Generator {
public:
    bool header(std::ofstream& os) override;
    bool footer(std::ofstream& os) override;
    bool syscall(std::ofstream& os, const Syscall& sc) override;

private:
    bool first_syscall_ = true;
};

// Writes the signature of a syscall, up to the end of the args list.
//
// Can wrap pointers with user_ptr.
// Can specify a type to substitute for no args.
// Doesn't write ';', '{}' or attributes.
void write_syscall_signature_line(std::ofstream& os, const Syscall& sc, std::string name_prefix,
                                  std::string before_args, std::string inter_arg,
                                  bool wrap_pointers_with_user_ptr, std::string no_args_type);

// Writes the return variable declaration for a syscall.
//
// Returns the name of the variable (or an empty string if the call was void).
std::string write_syscall_return_var(std::ofstream& os, const Syscall& sc);

// Writes an invocation of a syscall.
//
// Uses the argument names specified in the type description
// Performs no casting or pointer wrapping.
void write_syscall_invocation(std::ofstream& os, const Syscall& sc,
                              const std::string& return_var, const std::string& name_prefix);

void write_argument_annotation(std::ofstream& os, const TypeSpec& arg);
