awa5_rs 0.1.13

An AWA5.0 CLI tool written in Rust (btw)
Documentation
extern crate clap;

use awa5_rs::*;

use clap::{Arg, Command};
use std::collections::HashSet;
use std::fs;
use std::path::Path;

fn main() {
    let mut cmd = Command::new("awa5_rs")
        .version("1.0")
        .about("An AWA5.0 CLI tool written in Rust (btw)")
        .arg(
            Arg::new("input")
                .index(1)
                .help("File to interpret or convert")
                .num_args(1),
        )
        .arg(
            Arg::new("output")
                .short('o')
                .long("output")
                .help("Output to file with new format .awasm .awa .o")
                .num_args(1),
        )
        .arg(
            Arg::new("string")
                .short('s')
                .long("string")
                .help("String to interpret or convert")
                .num_args(1),
        )
        .arg(
            Arg::new("awasm")
                .long("awasm")
                .help("Parse string as awasm")
                .num_args(0),
        )
        .arg(
            Arg::new("awa")
                .long("awa")
                .help("Parse string as awatalk")
                .num_args(0),
        )
        .arg(
            Arg::new("path")
                .short('p')
                .long("path")
                .help("Search paths separated by ';' for shared libraries")
                .num_args(1),
        )
        .arg(
            Arg::new("include")
                .short('i')
                .long("include")
                .help("Include paths separated by ';' for source files")
                .num_args(1),
        );

    let matches = cmd.clone().get_matches();

    if matches.contains_id("input") && matches.contains_id("string") {
        eprintln!(
            "Warning: Both file input and 'string' flag are given. Please provide only one.\n"
        );
        cmd.print_help().unwrap();
        std::process::exit(1);
    }

    let mut path = "/usr/local/lib";
    let mut include_paths = "";

    if matches.contains_id("path") {
        path = matches.get_one::<String>("path").unwrap();
    }

    if matches.contains_id("include") {
        include_paths = matches.get_one::<String>("include").unwrap();
    }

    if matches.contains_id("input") {
        let input_file = matches.get_one::<String>("input").unwrap();

        let file_type = detect_file_format(input_file);

        match file_type {
            "awasm" => {
                let lines = read_lines(input_file).unwrap();

                let mut macro_table = parser::awasm::MacroTable::new();
                let mut already_included: HashSet<String> = HashSet::new();
                let instructions = parser::awasm::parse_lines(
                    &mut macro_table,
                    &mut already_included,
                    include_paths,
                    "",
                    lines,
                );

                let object_vec = assembler::make_object_vec(&instructions);

                if matches.contains_id("output") {
                    let output_file = matches.get_one::<String>("output").unwrap();

                    match Path::new(output_file)
                        .extension()
                        .and_then(|ext| ext.to_str())
                        .unwrap()
                    {
                        "awasm" => {
                            let _ = fs::copy(input_file, output_file);
                        }
                        "awa" => {
                            let result = assembler::object_to_awa(&object_vec);
                            let _ = write_string_file(output_file, &result);
                        }
                        "o" => {
                            let _ = write_object_file(output_file, object_vec);
                        }
                        _ => {}
                    }
                } else {
                    interpet_object(object_vec, path);
                }
            }
            "awa" => {
                let content = fs::read_to_string(input_file).unwrap();

                let instructions = parser::awatalk::parse_string(&content);

                let object_vec = assembler::make_object_vec(&instructions);

                if matches.contains_id("output") {
                    let output_file = matches.get_one::<String>("output").unwrap();

                    match Path::new(output_file)
                        .extension()
                        .and_then(|ext| ext.to_str())
                        .unwrap()
                    {
                        "awasm" => {
                            let result = assembler::object_to_awasm(&object_vec);
                            let _ = write_string_file(output_file, &result);
                        }
                        "awa" => {
                            let _ = fs::copy(input_file, output_file);
                        }
                        "o" => {
                            let _ = write_object_file(output_file, object_vec);
                        }
                        _ => {}
                    }
                } else {
                    interpet_object(object_vec, path);
                }
            }
            "o" => match read_binary_file(input_file) {
                Ok(binary_data) => {
                    if matches.contains_id("output") {
                        let output_file = matches.get_one::<String>("output").unwrap();

                        match Path::new(output_file)
                            .extension()
                            .and_then(|ext| ext.to_str())
                            .unwrap()
                        {
                            "awasm" => {
                                let result = assembler::object_to_awasm(&binary_data);
                                let _ = write_string_file(output_file, &result);
                            }
                            "awa" => {
                                let result = assembler::object_to_awa(&binary_data);
                                let _ = write_string_file(output_file, &result);
                            }
                            "o" => {
                                let _ = fs::copy(input_file, output_file);
                            }
                            _ => {}
                        }
                    } else {
                        interpet_object(binary_data, path);
                    }
                }
                Err(err) => {
                    eprintln!("Error reading file: {}", err);
                }
            },
            _ => panic!("Could not autodetect file type"),
        }
    } else {
        let mut input_string = String::new();
        if matches.contains_id("string") {
            input_string = matches.get_one::<String>("string").unwrap().clone();
        } else {
            let _ = std::io::stdin().read_line(&mut input_string);
        }

        if matches.get_flag("awasm") && matches.get_flag("awa") {
            eprintln!(
                "Warning: Both 'awasm' and 'awa' flags are given. Please provide only one.\n"
            );
            cmd.print_help().unwrap();
            std::process::exit(1);
        }

        if !matches.get_flag("awasm") && !matches.get_flag("awa") {
            eprintln!("Warning: Neither 'awasm' and 'awa' flags are given. Please provide at least one.\n");
            cmd.print_help().unwrap();
            std::process::exit(1);
        }

        if matches.get_flag("awasm") {
            let lines = input_string.lines().map(|line| line.to_string());

            let mut macro_table = parser::awasm::MacroTable::new();
            let mut already_included: HashSet<String> = HashSet::new();
            let instructions = parser::awasm::parse_lines(
                &mut macro_table,
                &mut already_included,
                include_paths,
                "",
                lines,
            );

            let object_vec = assembler::make_object_vec(&instructions);

            if matches.contains_id("output") {
                let output_file = matches.get_one::<String>("output").unwrap();

                match Path::new(output_file)
                    .extension()
                    .and_then(|ext| ext.to_str())
                    .unwrap()
                {
                    "awasm" => {
                        let result = assembler::object_to_awasm(&object_vec);
                        let _ = write_string_file(output_file, &result);
                    }
                    "awa" => {
                        let result = assembler::object_to_awa(&object_vec);
                        let _ = write_string_file(output_file, &result);
                    }
                    "o" => {
                        let _ = write_object_file(output_file, object_vec);
                    }
                    _ => {}
                }
            } else {
                interpet_object(object_vec, path);
            }
        }

        if matches.get_flag("awa") {
            let instructions = parser::awatalk::parse_string(&input_string);

            let object_vec = assembler::make_object_vec(&instructions);

            if matches.contains_id("output") {
                let output_file = matches.get_one::<String>("output").unwrap();

                match Path::new(output_file)
                    .extension()
                    .and_then(|ext| ext.to_str())
                    .unwrap()
                {
                    "awasm" => {
                        let result = assembler::object_to_awasm(&object_vec);
                        let _ = write_string_file(output_file, &result);
                    }
                    "awa" => {
                        let result = assembler::object_to_awa(&object_vec);
                        let _ = write_string_file(output_file, &result);
                    }
                    "o" => {
                        let _ = write_object_file(output_file, object_vec);
                    }
                    _ => {}
                }
            } else {
                interpet_object(object_vec, path);
            }
        }
    }
}