#definition #tube #script #compiler #rat #free #halo

rat-in-a-tube-definitions

Rat In a Tube 的定义

4 个版本

使用旧的Rust 2015

0.2.3 2023年10月15日
0.2.2 2022年12月16日
0.2.1 2022年11月14日
0.2.0 2022年10月29日

#1859 in 进程宏


2 个库中使用 (通过 rat-in-a-tube)

GPL-3.0-only

37KB
123

Rat In a Tube

RIAT是Halo:Combat Evolved脚本的免费脚本编译器。

要编译,您需要Rust编译器和Cargo。

示例用法

Rat in a Tube 可以在Rust、C和C++中使用。

Rust

RIAT是一个Rust库,因此您可以直接在您的Rust库中使用它。

extern crate rat_in_a_tube;
use rat_in_a_tube::Compiler;

/** Return true if successful. Return false on failure. */
fn compile_scripts_rust(script_file_name: &str, script_data: &[u8]) -> bool {
    // Instantiate our instance
    let mut compiler = Compiler::new(CompileTarget::HaloCEA);

    // Try to compile
    match compiler.read_script_data(script_file_name, script_data) {
        Ok(_) => (),
        Err(e) => {
            let file = e.get_file();
            let message = e.get_message();
            let (line,column) = e.get_position();
            eprintln!("Failed to read script data: {file}:{line}:{column}: {message}");
            return false;
        }
    }
    let script_data = match compiler.digest_tokens() {
        Ok(n) => n,
        Err(e) => {
            let file = e.get_file();
            let message = e.get_message();
            let (line,column) = e.get_position();
            eprintln!("Failed to compile script data: {file}:{line}:{column}: {message}");
            return false;
        }
    };

    // Print information
    println!("Script count: {}", script_data.get_scripts().len());
    println!("Global count: {}", script_data.get_globals().len());
    println!("Node count: {}", script_data.get_nodes().len());

    return true;
}

C

RIAT通过riatc包提供了C绑定。您需要使用您选择的工具链链接riatc库,并将riatc的include目录添加到您的include列表中。

#include <riat/riat.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

/* Return 0 if successful. Return a nonzero value if failed. */
int compile_scripts_c(const char *script_file_name, const uint8_t *script_data, size_t script_data_length) {
    /* Put variables here */
    int result = 0;
    RIATCompiledScriptData *compiled_script_data = NULL;
    RIATScriptC *scripts = NULL;
    RIATGlobalC *globals = NULL;
    RIATScriptNodeC *nodes = NULL;
    size_t script_count, global_count, node_count;

    /* Zero-out error struct. Not required, but calling riat_error_free() on a zeroed out struct is always OK. */
    RIATCompileErrorC error;
    memset(&error, 0, sizeof(error));

    /* Instantiate our instance */
    RIATCompiler *compiler = riat_compiler_new(RIAT_HaloCEA);

    /* Try to compile */
    if(riat_compiler_read_script_data(compiler, script_file_name, script_data, script_data_length, &error) != 0) {
        fprintf(stderr, "Failed to read script data: %s:%zu:%zu: %s\n", error.file, error.line, error.column, error.message);
        result = 1;
        goto CLEANUP;
    }
    if((compiled_script_data = riat_compiler_compile_script_data(compiler, &error)) == NULL) {
        fprintf(stderr, "Failed to compile script data: %s:%zu:%zu: %s\n", error.file, error.line, error.column, error.message);
        result = 1;
        goto CLEANUP;
    }

    /* Get the sizes */
    script_count = riat_script_data_get_scripts(compiled_script_data, NULL);
    global_count = riat_script_data_get_globals(compiled_script_data, NULL);
    node_count = riat_script_data_get_nodes(compiled_script_data, NULL);

    /* Allocate */
    scripts = malloc(sizeof(*scripts) * script_count);
    globals = malloc(sizeof(*globals) * global_count);
    nodes = malloc(sizeof(*nodes) * node_count);

    /* If any of those returned false, we failed */
    if(scripts == NULL || globals == NULL || nodes == NULL) {
        fprintf(stderr, "Allocation error!\n");
        result = 2;
        goto CLEANUP;
    }

    /* Read everything */
    riat_script_data_get_scripts(compiled_script_data, scripts);
    riat_script_data_get_globals(compiled_script_data, globals);
    riat_script_data_get_nodes(compiled_script_data, nodes);

    /* Print information */
    printf("Script count: %zu\n", script_count);
    printf("Global count: %zu\n", global_count);
    printf("Node count %zu\n", node_count);

    /* Cleanup */
    CLEANUP:
    riat_error_free(&error);
    riat_compiler_free(compiler);
    riat_script_data_free(compiled_script_data);
    free(scripts);
    free(globals);
    free(nodes);

    /* Done! */
    return result;
}

C++

rustc包还包含一个C++头文件。您需要使用您选择的工具链编译riatc库,并将riatc的include目录添加到您的include列表中。

虽然您可以使用C头文件与您的C++库一起使用,但C++头文件通过std::vector等容器提供异常、类型安全和自动内存管理。

#include <riat/riat.hpp>
#include <iostream>
#include <cstdint>
#include <vector>

// Return true if successful. Return false on failure.
bool compile_scripts_cpp(const char *script_file_name, const std::vector<std::uint8_t> &script_data) {
    // Instantiate our instance
    RIAT::Compiler instance(RIATCompileTarget::RIAT_HaloCEA);
    RIAT::CompilerScriptResult result;

    // Try to compile
    try {
        instance.read_script_data(script_data.data(), script_data.size(), script_file_name);
        result = instance.compile_scripts();
    }
    catch(std::exception &e) {
        std::cerr << "Error when compiling: " << e.what() << "\n";
        return false;
    }

    // Print information
    auto scripts = result.get_scripts();
    auto globals = result.get_globals();
    auto nodes = result.get_nodes();
    std::cout << "Script count:" << scripts.size() << std::endl;
    std::cout << "Global count:" << globals.size() << std::endl;
    std::cout << "Node count:" << nodes.size() << std::endl;

    // Done!
    return true;
}

依赖项

~0.6–1.4MB
~32K SLoC