#include #include #include #include #include #include "util.hpp" #include "struc.hpp" #include "parse.hpp" #include "options.hpp" #include "recursive.hpp" #include "minimize.hpp" #include "resolve.hpp" #include "processing.hpp" #include "debashify.hpp" #include "version.h" #include "g_version.h" void oneshot_opt_process(const char* arg0) { if(options['h']) { print_help(arg0); exit(0); } else if(options["version"]) { printf("%s %s%s\n", arg0, VERSION_STRING, VERSION_SUFFIX); printf("%s\n", VERSION_SHA); exit(0); } else if(options["help-commands"]) { print_include_help(); printf("\n\n"); print_resolve_help(); exit(0); } } int main(int argc, char* argv[]) { std::vector args; int ret=0; try { args=options.process(argc, argv, false, true); } catch(std::exception& e) { std::cerr << e.what() << std::endl; return 1; } oneshot_opt_process(argv[0]); // resolve input std::string file; if(args.size() > 0) // argument provided { if(args[0] == "-" || args[0] == "/dev/stdin") //stdin { file = "/dev/stdin"; } else { file=args[0]; } } else { if(isatty(fileno(stdin))) // stdin is interactive { print_help(argv[0]); return 1; } else // is piped { file = "/dev/stdin"; args.push_back("/dev/stdin"); } } // parsing shmain* sh = new shmain(new list); shmain* tsh = nullptr; try { bool is_exec = false; bool first_run = true; // do parsing for(uint32_t i=0 ; i 1) // not exec: parse options on args { args=options.process(args); } oneshot_opt_process(argv[0]); get_opts(); } // parse g_origin=file; if(!add_include(file)) continue; tsh = parse_text(filecontents, file); if(shebang_is_bin) // resolve lxsh shebang to sh tsh->shebang="#!/bin/sh"; /* mid processing */ // resolve/include if(g_include || g_resolve) { resolve(tsh); } // concatenate to main sh->concat(tsh); delete tsh; tsh = nullptr; // is exec: break and exec if(is_exec) break; } // end of argument parse if(options["debashify"]) { debashify(sh); } // processing before output // minimize if(options['m']) opt_minimize=true; if(options["remove-unused"]) delete_unused( sh, re_var_exclude, re_fct_exclude ); if(options["minimize-var"]) minimize_var( sh, re_var_exclude ); if(options["minimize-fct"]) minimize_fct( sh, re_fct_exclude ); // other processing if(options["unset-var"]) add_unset_variables( sh, re_var_exclude ); // list outputs if(options["list-var"]) list_vars(sh, re_var_exclude); else if(options["list-var-def"]) list_var_defs(sh, re_var_exclude); else if(options["list-var-call"]) list_var_calls(sh, re_var_exclude); else if(options["list-fct"]) list_fcts(sh, re_fct_exclude); else if(options["list-cmd"]) list_cmds(sh, regex_null); // execute else if(is_exec) { ret = execute(sh, args); } // output else if(options['o']) // file output { std::string destfile=options['o']; // resolve - to stdout if(destfile == "-") destfile = "/dev/stdout"; // output std::ofstream(destfile) << sh->generate(g_shebang, 0); // don't chmod on /dev/ if(destfile.substr(0,5) != "/dev/") ztd::exec("chmod", "+x", destfile); } else // to console { std::cout << sh->generate(g_shebang, 0); } } #ifndef NO_PARSE_CATCH catch(ztd::format_error& e) { if(tsh != nullptr) delete tsh; delete sh; printFormatError(e); return 100; } #endif catch(std::runtime_error& e) { if(tsh != nullptr) delete tsh; delete sh; std::cerr << e.what() << std::endl; return 2; } delete sh; return ret; }