/* * Simulator of microcontrollers (cmd.src/newcmdposix.cc) * * Copyright (C) 1999,99 Drotos Daniel, Talker Bt. * Copyright (C) 2006, Borut Razem - borut.razem@siol.net * * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * */ /* This file is part of microcontroller simulator: ucsim. UCSIM 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 2 of the License, or (at your option) any later version. UCSIM 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 UCSIM; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*@1@*/ #include "ddconfig.h" #include #include #include #include #include #include #include "i_string.h" // prj #include "globals.h" #include "utils.h" // sim #include "simcl.h" #include "argcl.h" #include "appcl.h" // local #include "newcmdposixcl.h" /* * Command console *____________________________________________________________________________ */ cl_console::cl_console(const char *_fin, const char *_fout, class cl_app *the_app) { app= the_app; fin= 0; if (_fin) { fin= mk_io(_fin, cchars("r")); } fout= 0; if (_fout) { fout= mk_io(_fout, cchars("w")); } prompt= 0; set_flag(~CONS_NONE, false); if ((fin && fin->tty) && (fout && fout->tty)) { set_interactive(true); fin->echo(fout); fin->cooked(); } else ; frout= 0; id= 0; lines_printed= new cl_ustrings(100, 100, "console_cache"); } cl_console::cl_console(cl_f *_fin, cl_f *_fout, class cl_app *the_app) { app= the_app; fin= _fin; fout= _fout; prompt= 0; set_flag(~CONS_NONE, false); if ((fin && fin->tty) && (fout && fout->tty)) { set_interactive(true); fin->echo(fout); fin->cooked(); } else ; frout= 0; id= 0; lines_printed= new cl_ustrings(100, 100, "console_cache"); } class cl_console * cl_console::clone_for_exec(char *_fin) { class cl_f *fi= 0, *fo= 0; if (!_fin) return(0); if (fi= mk_io(_fin, "r"), !fi) { fprintf(stderr, "Can't open `%s': %s\n", _fin, strerror(errno)); return(0); } if ((fo= fout->copy("a")) == 0) { delete fi; fprintf(stderr, "Can't re-open output file: %s\n", strerror(errno)); return(0); } class cl_console *con= new cl_sub_console(this, fi, fo, app); return(con); } void cl_console::drop_files(void) // do not close, just ignore { fin= 0; fout= 0; frout= 0; application->get_commander()->update_active(); } void cl_console::close_files(bool close_in, bool close_out) { if (frout) delete frout; if (close_out) { if (fout) { if (fout->tty) tu_reset(); delete fout; } fout= 0; } if (close_in) { if (fin) delete fin; fin= 0; application->get_commander()->update_active(); } //drop_files(); } void cl_console::replace_files(bool close_old, cl_f *new_in, cl_f *new_out) { if (frout) delete frout; frout= 0; if (close_old) close_files(fin != new_in, fout != new_out); fin= new_in; fout= new_out; application->get_commander()->update_active(); } /* void cl_console::set_id(int new_id) { char *s; id= new_id; set_name(s= format_string("console%d fin=%s,%d fout=%s,%d", id, fin?fin->get_file_name():"", fin?fin->file_id:-1, fout?fout->get_file_name():"", fout?fout->file_id:-1)); free(s); } */ cl_console::~cl_console(void) { un_redirect(); if (fout) { //if (flags & CONS_PROMPT) //fout->write_str("\n"); //fout->flush(); if (fout->tty) tu_reset(); delete fout; } if (fin) { delete fin; } } /* * Output functions */ void cl_console::redirect(char *fname, char *mode) { frout= mk_io(fname, mode); set_flag(CONS_REDIRECTED, true); } void cl_console::un_redirect(void) { set_flag(CONS_REDIRECTED, false); if (!frout) return; delete frout; frout= 0; } /* * Input functions */ bool cl_console::input_avail(void) { bool ret= false; if (startup_command.nempty()) return true; if (input_active()) { ret= fin->input_avail(); if (ret) ; } return ret; } bool cl_console::need_check(void) { return fin && (fin->type == F_CONSOLE); } bool cl_console::set_cooked(bool new_val) { if (!fin) return false; if (new_val) { if (!fin->get_cooking()) fin->interactive(fout); } else { // raw fin->raw(); } return fin->get_cooking(); } /* Return -1 if EOF (and buffer is empty) or ^C found 0 buffer is not ready yet 1 buffer filled (EOL detected) */ int cl_console::read_line(void) { int i= 0; int b[2]= { 0, 0 }; do { if (startup_command.nempty()) { char *s= startup_command; b[0]= s[0]; startup_command= &s[1]; i= 1; } else { i= fin->read(b, 1); } if (i < -1) { return -1; } if (i == 0) { // EOF if (lbuf.len() == 0) return -1; // execute last line, assuming \n return 1; } if (i > 0) { // Got a char if (b[0] == 3) // ^C, drop and close return -1; if ((b[0] == '\n') || (b[0] == '\r')) { if (nl && (nl != b[0])) { nl= 0; continue; } nl= b[0]; /* if (lbuf.len() != 0) { b[0]= '\n'; lbuf+= b; } */ return 1; } { char s[2]; s[0]= b[0]; s[1]= b[1]; lbuf+= s; } } } while (i > 0); return 0; } /* * This console listen on a socket and can accept connection requests */ //#ifdef SOCKET_AVAIL cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app) { app= the_app; fin= mk_srv(serverport); fout= frout= 0; } /* void cl_listen_console::set_id(int new_id) { char *s; id= new_id; set_name(s= format_string("listen_console%d port=%d", id, fin?fin->server_port:-1)); free(s); } */ int cl_listen_console::proc_input(class cl_cmdset *cmdset) { //int newsock; class cl_commander_base *cmd; cl_f *in, *out; cmd= app->get_commander(); srv_accept(fin, &in, &out); class cl_console_base *c= new cl_console(in, out, app); c->set_flag(CONS_INTERACTIVE, true); in->interactive(out); cmd->add_console(c); return(0); } //#endif /* SOCKET_AVAIL */ /* * Sub-console */ /* cl_sub_console::cl_sub_console(class cl_console_base *the_parent, FILE *fin, FILE *fout, class cl_app *the_app): cl_console(fin, fout, the_app) { parent= the_parent; } */ cl_sub_console::cl_sub_console(class cl_console_base *the_parent, class cl_f *fin, class cl_f *fout, class cl_app *the_app): cl_console(fin, fout, the_app) { parent= the_parent; } cl_sub_console::~cl_sub_console(void) { class cl_commander_base *c= app->get_commander(); if (parent && c) { c->activate_console(parent); } } int cl_sub_console::init(void) { class cl_commander_base *c= app->get_commander(); if (parent && c) { c->deactivate_console(parent); } cl_console::init(); set_flag(CONS_ECHO, true); return(0); } /* void cl_sub_console::set_id(int new_id) { char *s; id= new_id; set_name(s= format_string("sub_console%d (of %d) fin=%s,%d fout=%s,%d", id, parent?parent->get_id():-1, fin?fin->get_file_name():"", fin?fin->file_id:-1, fout?fout->get_file_name():"", fout?fout->file_id:-1)); free(s); } */ /* * Command interpreter *____________________________________________________________________________ */ int cl_commander::init(void) { class cl_optref console_on_option(this); class cl_optref config_file_option(this); class cl_optref port_number_option(this); class cl_console_base *con; int ccnt= 0; cl_console_base *c; console_on_option.init(); console_on_option.use("console_on"); config_file_option.init(); config_file_option.use("config_file"); port_number_option.init(); cl_base::init(); set_name("Commander"); active_inputs= new cl_list(10, 5, "active_inputs"); check_list= new cl_list(10, 5, "check_list"); bool need_config= true; if (port_number_option.use("port_number")) { add_console(c= new cl_listen_console(port_number_option.get_value((long)0), app)); } /* else { c= new cl_listen_console(5559, app); add_console(c); c->prev_quit= 0; ccnt= 1; } */ char *Config= config_file_option.get_value(""); char *cn= console_on_option.get_value(""); if (cn) { if (strcmp(cn, "-") == 0) { class cl_f *in, *out; in= cp_io(fileno(stdin), cchars("r")); out= cp_io(fileno(stdout), cchars("w")); in->interactive(out); add_console(con= new cl_console(in, out, app)); config_console= exec_on(con, Config); if (config_console) config_console->set_startup(app->startup_command); else con->set_startup(app->startup_command); need_config= false; if (in->tty) con->set_flag(CONS_INTERACTIVE, true); } else { add_console(con= new cl_console(cn, cn, app)); config_console= exec_on(con, Config); need_config= false; } } if (cons->get_count() == ccnt) { class cl_f *in, *out; in= cp_io(fileno(stdin), cchars("r")); out= cp_io(fileno(stdout), cchars("w")); in->interactive(out); add_console(con= new cl_console(in, out, app)); config_console= exec_on(con, Config); if (config_console) config_console->set_startup(app->startup_command); else con->set_startup(app->startup_command); need_config= false; if (in->tty) con->set_flag(CONS_INTERACTIVE, true); } if ( need_config && ( (Config && *Config) || app->startup_command.nempty() ) ) { class cl_f *i= NULL, *o; if (Config && *Config) i= mk_io(Config, "r"); o= cp_io(fileno(stderr), "w"); con= new cl_console(/*fc*/i, /*stderr*/o, app); con->set_flag(CONS_NOWELCOME|CONS_ECHO, true); //exec_on(con, Config); config_console= con; con->set_startup(app->startup_command); add_console(con); } return(0); } void cl_commander::update_active(void) { int i; active_inputs->disconn_all(); check_list->disconn_all(); if (config_console) { if (!cons->index_of(config_console, NULL)) config_console= 0; } //printf("List of active cons: "); for (i= 0; i < cons->count; i++) { class cl_console *c= (class cl_console *)cons->at(i); class cl_f *f= c->get_fin(); if (config_console && (config_console != c)) continue; if (f && (f->file_id < 0)) continue; if (c->input_active() && f) { active_inputs->add(f); //printf("%d,",c->get_id()); } if (c->need_check() && f) check_list->add(f); } //printf("\n"); //printf("List of check cons: "); /*for (i= 0; i < check_list->count; i++) { class cl_console *c= (class cl_console *)cons->at(i); printf("%d,", c->get_id()); }*/ //printf("\n"); } int cl_commander::input_avail(void) { class cl_list *avail= new cl_list(10,5,"avail"); bool ret= check_inputs(active_inputs, avail); avail->disconn_all(); delete avail; if (!ret) for (int j = 0; j < cons->count; j++) { class cl_console *c = dynamic_cast((class cl_console_base*)(cons->at(j))); chars *s= c->get_startup(); if (s->nempty()) { return true; } } return ret; } int cl_commander::wait_input(void) { while (!input_avail()) loop_delay(); return 0; } int cl_commander::proc_input(void) { if (config_console) { if (!cons->index_of(config_console, NULL)) config_console= 0; } for (int j = 0; j < cons->count; j++) { class cl_console *c = dynamic_cast((class cl_console_base*)(cons->at(j))); class cl_f *f= c->get_fin(); if (config_console && (config_console != c)) continue; if (c->input_active() && (f || c->has_startup())) { if (c->input_avail()) { actual_console = c; int retval = c->proc_input(cmdset); if (retval) { del_console(c); //delete c; } actual_console = 0; int i= consoles_prevent_quit(); return(i == 0); } } } return 0; } void cl_commander::check(void) { int i; for (i= 0; i < check_list->count; i++) { class cl_f *f= (class cl_f *)check_list->at(i); f->check(); } } /* End of cmd.src/newcmdposix.cc */