/* Copyright Yann Weber This file is part of asmsh. asmsh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. asmsh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with asmsh. If not, see . */ #include "shell.h" int asmsh_init(asmsh_t *sh, const char *child_path) { bzero(sh, sizeof(asmsh_t)); if(!(sh->env = asmsh_env(child_path))) { asmsh_log_fatal("Unable to start child env"); goto err; } if(!(sh->cctx = asmsh_asmc_ctx_default())) { asmsh_log_fatal("Unable to start compilation context"); asmsh_env_free(sh->env); goto err; } sh->child_path = strdup(child_path); // TODO check error return 0; err: bzero(sh, sizeof(asmsh_t)); return -1; } void asmsh_cleanup(asmsh_t *sh) { if(!sh){ return; } if(sh->cctx) { asmsh_asmc_ctx_free(sh->cctx); } if(sh->env) { asmsh_env_free(sh->env); } if(sh->child_path) { free(sh->child_path); } if(sh->last_instr) { free(sh->last_instr); } bzero(sh, sizeof(asmsh_t)); } /** Attempt to compile and step if sucess */ static int _compile_step(asmsh_t *sh, const char *cmd); /** Attempt to handle given shell internal command (starting with '.') */ static int _handle_command(asmsh_t *sh, const char *cmd); int asmsh_exec(asmsh_t *sh, const char *cmd) { if(!cmd) { errno=EINVAL; return -1; } int clen, ret; //lstrip whitespace for(cmd; *cmd && (*cmd == ' ' || *cmd == '\t'); cmd++); if(!*cmd) { return 0; } switch(*cmd) { case '.': ret = _handle_command(sh, cmd); break; default: ret = _compile_step(sh, cmd); break; } return ret; } static int _compile_step(asmsh_t *sh, const char *cmd) { int ret, status; asmsh_bytecode_t bcode; if(asmsh_asmc_compile(sh->cctx, cmd, &bcode) < 0) { return -1; } if(!bcode.size) { asmsh_log_error("No bytecode returned..."); return -1; } sh->last_bcode = bcode; if(sh->last_instr) { free(sh->last_instr); } sh->last_instr = strdup(cmd); char buf[256]; int _ret; _ret = snprintf(buf, 255, "'%s' = 0x", cmd); for(int _i=0; _ienv, &bcode)) { return -1; } status=0; ret = asmsh_env_step(sh->env, &status); if(ret < 0) { perror("Unable to step"); asmsh_log_fatal("Error will child step"); return -1; } else if(ret > 0) { asmsh_log_fatal("Child exited with non-zero status"); return 1+WEXITSTATUS(status); } return 0; } static int _handle_command(asmsh_t *sh, const char *cmd) { const int clen = strlen(cmd); const asmsh_cmd_t *match; int ret; asmsh_cmd_args_t *args; args = asmsh_cmd_parse(cmd); if(!args) { asmsh_log_error("Parse error"); // TODO better error return -1; } match = asmsh_cmd_match(args->cmd, strlen(args->cmd)); if(!match) { asmsh_log_error("Unknow command"); return -1; } ret = match->cmd(sh, args); asmsh_cmd_args_free(args); return ret; }