2 * Simulator of microcontrollers (cmd.src/newcmd.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
10 /* This file is part of microcontroller simulator: ucsim.
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
34 #include <sys/types.h>
36 # include <winsock2.h>
38 #elif defined HAVE_SYS_SOCKET_H
39 # include <sys/socket.h>
40 # include <netinet/in.h>
41 # include <arpa/inet.h>
70 extern "C" int vasprintf(char **strp, const char *format, va_list ap);
71 extern "C" int vsnprintf(char *str, size_t size,const char *format,va_list ap);
78 cl_prompt_option::cl_prompt_option(class cl_console *console):
85 cl_prompt_option::init(void)
88 help= format_string("Prompt string of console%d", con->get_id());
89 create(con, string_opt, "prompt", help);
90 //fprintf(stderr," **new prompt option %p\"%s\", value=%p str=%p\n",option,object_name(option),option->get_value(),option->get_value()->sval);
92 default_option("prompt");
93 //fprintf(stderr,"opt=%p\"%s\" value after default set=%p str=%p\n",option,object_name(option),option->get_value(),option->get_value()->sval);
98 cl_prompt_option::option_changed(void)
103 option->get_value(&s);
108 cl_debug_option::cl_debug_option(class cl_console *console):
109 cl_prompt_option(console)
113 cl_debug_option::init(void)
116 help= format_string("Debug messages to console%d", con->get_id());
117 create(con, bool_opt, "debug", help);
119 default_option("debug");
124 cl_debug_option::option_changed(void)
129 option->get_value(&b);
131 con->flags|= CONS_DEBUG;
133 con->flags&= ~CONS_DEBUG;
139 *____________________________________________________________________________
142 cl_console::cl_console(char *fin, char *fout, class cl_app *the_app):
150 if (f= fopen(fin, "r"), in= f, !f)
151 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
154 if (f= fopen(fout, "w"), out= f, !f)
155 fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
160 flags|= CONS_INTERACTIVE;
162 ;//fprintf(stderr, "Warning: non-interactive console\n");
165 lines_printed= new cl_ustrings(100, 100, "console_cache");
168 cl_console::cl_console(FILE *fin, FILE *fout, class cl_app *the_app):
178 flags|= CONS_INTERACTIVE;
180 ;//fprintf(stderr, "Warning: non-interactive console\n");
183 lines_printed= new cl_ustrings(100, 100, "console_cache");
187 * use the port number supplied to connect to localhost for
193 connect_to_port(int portnum)
195 int sock= socket(AF_INET,SOCK_STREAM,0);
196 struct sockaddr_in sin;
198 sin.sin_family = AF_INET;
199 sin.sin_port = htons(portnum);
200 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
202 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
203 fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
209 cl_console::cl_console(int portnumber, class cl_app *the_app)
211 int sock= connect_to_port(portnumber);
214 if (!(in= fdopen(sock, "r")))
215 fprintf(stderr, "cannot open port for input\n");
216 if (!(out= fdopen(sock, "w")))
217 fprintf(stderr, "cannot open port for output\n");
218 //fprintf(stderr, "init socket done\n");
220 lines_printed= new cl_ustrings(1, 1, "console_cache");
225 cl_console::clone_for_exec(char *fin)
231 if (fi= fopen(fin, "r"), !fi)
233 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
236 if ((fo= fdopen(dup(fileno(out)), "a")) == 0)
239 fprintf(stderr, "Can't re-open output file: %s\n", strerror(errno));
242 class cl_console *con= new cl_sub_console(this, fi, fo, app);
247 cl_console::init(void)
250 prompt_option= new cl_prompt_option(this);
251 prompt_option->init();
252 null_prompt_option= new cl_optref(this);
253 null_prompt_option->init();
254 null_prompt_option->use("null_prompt");
255 debug_option= new cl_debug_option(this);
256 debug_option->init();
258 flags&= ~CONS_PROMPT;
265 cl_console::~cl_console(void)
272 if (flags & CONS_PROMPT)
277 delete prompt_option;
278 delete null_prompt_option;
291 cl_console::accept_last(void)
295 if (isatty(fileno(in)))
306 cl_console::welcome(void)
308 FILE *Out= rout?rout:out;
311 (flags & CONS_NOWELCOME))
313 fprintf(Out, "uCsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
314 "uCsim comes with ABSOLUTELY NO WARRANTY; for details type "
316 "This is free software, and you are welcome to redistribute it\n"
317 "under certain conditions; type `show c' for details.\n",
323 cl_console::redirect(char *fname, char *mode)
325 if ((rout= fopen(fname, mode)) == NULL)
326 dd_printf("Unable to open file '%s' for %s: %s\n",
327 fname, (mode[0]=='w')?"write":"append", strerror(errno));
331 cl_console::un_redirect(void)
341 cl_console::cmd_do_print(FILE *f, char *format, va_list ap)
344 #ifdef HAVE_VASPRINTF
346 vasprintf(&msg, format, ap);
347 ret= fprintf(f, "%s", msg);
350 # ifdef HAVE_VSNPRINTF
352 vsnprintf(msg, 80*25, format, ap);
353 ret= fprintf(f, "%s", msg);
357 vsprintf(msg, format, ap); /* Dangerous */
358 ret= fprintf(f, "%s", msg);
362 /*strcpy(msg, "Unimplemented printf has called.\n");*/
364 /*strcpy(msg, "printf can not be implemented, upgrade your libc.\n");*/
374 cl_console::print_prompt(void)
377 FILE *Out= rout?rout:out;
379 if (flags & (CONS_PROMPT|CONS_FROZEN|CONS_INACTIVE))
384 if (/*app->args->arg_avail('P')*/null_prompt_option->get_value(bool(0)))
388 fprintf(Out, "%d", id);
389 fprintf(Out, "%s", (prompt && prompt[0])?prompt:"> ");
390 // ((p= app->args->get_sarg(0, "prompt"))?p:"> "));
396 cl_console::dd_printf(char *format, ...)
400 FILE *Out= rout?rout:out;
404 va_start(ap, format);
405 ret= cmd_do_print(Out, format, ap);
412 cl_console::debug(char *format, ...)
414 if ((flags & CONS_DEBUG) == 0)
419 FILE *Out= rout?rout:out;
423 va_start(ap, format);
424 ret= cmd_do_print(Out, format, ap);
431 cl_console::print_bin(long data, int bits)
434 FILE *Out= rout?rout:out;
438 mask= mask << ((bits >= 1)?(bits-1):0);
441 fprintf(Out, "%c", (data&mask)?'1':'0');
447 cl_console::print_char_octal(char c)
449 FILE *Out= rout?rout:out;
452 ::print_char_octal(c, Out);
461 cl_console::match(int fdnum)
470 cl_console::get_in_fd(void)
472 if (flags & CONS_INACTIVE)
474 return(in?fileno(in):-1);
478 cl_console::input_avail(void)
483 if ((i= get_in_fd()) < 0)
488 tv.tv_sec= tv.tv_usec= 0;
489 i= select(i+1, &s, NULL, NULL, &tv);
494 cl_console::read_line(void)
499 if (getline(&s, 0, in) < 0)
503 # ifdef HAVE_GETDELIM
505 s= (char *)malloc(n);
506 if (getdelim(&s, &n, '\n', in) < 0)
514 s= (char *)malloc(300);
515 if (fgets(s, 300, in) == NULL)
523 s[strlen(s)-1]= '\0';
524 if (s[strlen(s)-1] == '\r')
525 s[strlen(s)-1]= '\0';
526 flags&= ~CONS_PROMPT;
531 cl_console::proc_input(class cl_cmdset *cmdset)
538 fprintf(out, "End\n");
541 char *cmdstr= read_line();
544 if (flags & CONS_FROZEN)
546 app->get_sim()->stop(resUSER);
547 flags&= ~CONS_FROZEN;
557 class cl_cmdline *cmdline= 0;
559 if (flags & CONS_ECHO)
560 dd_printf("%s\n", cmdstr);
561 cmdline= new cl_cmdline(app, cmdstr, this);
563 if (cmdline->repeat() &&
569 cmdline= last_cmdline;
573 cm= cmdset->get_cmd(cmdline, accept_last());
583 retval= cm->work(app, cmdline, this);
587 last_cmdline= cmdline;
594 class YY_cl_ucsim_parser_CLASS *pars;
595 class cl_ucsim_lexer *lexer;
596 lexer= new cl_ucsim_lexer(cmdstr);
597 pars= new YY_cl_ucsim_parser_CLASS(lexer);
603 retval= interpret(cmdstr);*/
606 //retval= sim->do_cmd(cmd, this);
615 * Old version, sim->do_cmd() falls into this if it doesn't find a new
616 * command object which can handle entered command
620 cl_console::interpret(char *cmd)
622 FILE *Out= rout?rout:out;
624 fprintf(Out, "Unknown command\n");
629 cl_console::set_id(int new_id)
634 set_name(s= format_string("console%d", id));
639 cl_console::set_prompt(char *p)
652 * This console listen on a socket and can accept connection requests
656 cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app)
659 if ((sock= make_server_socket(serverport)) >= 0)
661 if (listen(sock, 10) < 0)
662 fprintf(stderr, "Listen on port %d: %s\n",
663 serverport, strerror(errno));
669 cl_listen_console::match(int fdnum)
671 return(sock == fdnum);
675 cl_listen_console::get_in_fd(void)
681 cl_listen_console::proc_input(class cl_cmdset *cmdset)
684 ACCEPT_SOCKLEN_T size;
685 struct sockaddr_in sock_addr;
686 class cl_commander *cmd;
688 cmd= app->get_commander();
689 size= sizeof(struct sockaddr);
690 newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
696 if (!(in= fdopen(newsock, "r+")))
697 fprintf(stderr, "cannot open port for input\n");
698 if (!(out= fdopen(newsock, "w+")))
699 fprintf(stderr, "cannot open port for output\n");
700 class cl_console *c= cmd->mk_console(in, out);
701 c->flags|= CONS_INTERACTIVE;
707 #endif /* SOCKET_AVAIL */
714 cl_sub_console::cl_sub_console(class cl_console *the_parent,
715 FILE *fin, FILE *fout, class cl_app *the_app):
716 cl_console(fin, fout, the_app)
721 cl_sub_console::~cl_sub_console(void)
723 class cl_commander *c= app->get_commander();
727 c->activate_console(parent);
732 cl_sub_console::init(void)
734 class cl_commander *c= app->get_commander();
738 c->deactivate_console(parent);
747 * Command interpreter
748 *____________________________________________________________________________
751 cl_commander::cl_commander(class cl_app *the_app, class cl_cmdset *acmdset
752 /*, class cl_sim *asim*/):
756 cons= new cl_list(1, 1, "consoles");
757 actual_console= frozen_console= 0;
762 cl_commander::init(void)
764 class cl_optref console_on_option(this);
765 class cl_optref config_file_option(this);
766 class cl_optref port_number_option(this);
767 class cl_console *con;
769 console_on_option.init();
770 console_on_option.use("console_on");
771 config_file_option.init();
772 config_file_option.use("config_file");
773 port_number_option.init();
776 set_name("Commander");
778 bool need_config= DD_TRUE;
781 if (port_number_option.use("port_number"))
782 add_console(mk_console(port_number_option.get_value((long)0)));
785 /* The following code is commented out because it produces gcc warnings
786 * newcmd.cc: In member function `virtual int cl_commander::init()':
787 * newcmd.cc:785: warning: 'Config' might be used uninitialized in this function
788 * newcmd.cc:786: warning: 'cn' might be used uninitialized in this function
791 char *Config= config_file_option.get_value(Config);
792 char *cn= console_on_option.get_value(cn);
794 /* Here shoud probably be something else, but is still better then the former code... */
795 char *Config= config_file_option.get_value("");
796 char *cn= console_on_option.get_value("");
800 add_console(con= mk_console(cn, cn));
801 exec_on(con, Config);
802 need_config= DD_FALSE;
804 if (cons->get_count() == 0)
806 add_console(con= mk_console(stdin, stdout));
807 exec_on(con, Config);
808 need_config= DD_FALSE;
814 FILE *fc= fopen(Config, "r");
816 fprintf(stderr, "Can't open `%s': %s\n", Config, strerror(errno));
819 con= mk_console(fc, stderr);
820 con->flags|= CONS_NOWELCOME|CONS_ECHO;
827 cl_commander::~cl_commander(void)
834 cl_commander::mk_console(char *fin, char *fout)
836 return(new cl_console(fin, fout, app));
840 cl_commander::mk_console(FILE *fin, FILE *fout)
842 return(new cl_console(fin, fout, app));
847 cl_commander::mk_console(int portnumber)
849 return(new cl_listen_console(portnumber, app));
854 cl_commander::add_console(class cl_console *console)
858 int i=cons->add(console);
865 cl_commander::del_console(class cl_console *console)
867 cons->disconn(console);
872 cl_commander::activate_console(class cl_console *console)
874 console->flags&= ~CONS_INACTIVE;
875 //console->print_prompt();
880 cl_commander::deactivate_console(class cl_console *console)
882 console->flags|= CONS_INACTIVE;
887 cl_commander::set_fd_set(void)
891 //fprintf(stderr, "** Setting fd set\n");
894 for (i= 0; i < cons->count; i++)
897 class cl_console *c= (class cl_console*)(cons->at(i));
898 if ((fd= c->get_in_fd()) >= 0)
900 if ((c->flags & CONS_FROZEN) == 0 ||
901 (c->flags & CONS_INTERACTIVE) != 0)
903 FD_SET(fd, &read_set);
909 ;//fprintf(stderr, "** Skipping console %p\n",c);
916 * Printing to all consoles
920 cl_commander::all_printf(char *format, ...)
925 for (i= 0; i < cons->count; i++)
927 class cl_console *c= (class cl_console*)(cons->at(i));
928 FILE *Out= c->get_out();
931 va_start(ap, format);
932 ret= c->cmd_do_print(Out, format, ap);
940 cl_commander::prompt(void)
944 for (i= 0; i < cons->count; i++)
946 class cl_console *c= (class cl_console*)(cons->at(i));
952 cl_commander::all_print(char *string, int length)
956 for (i= 0; i < cons->count; i++)
958 class cl_console *c= (class cl_console*)(cons->at(i));
959 FILE *Out= c->get_out();
962 for (int j= 0; j < length; j++)
963 putc(string[j], Out);
970 * Printing to actual_console
974 cl_commander::get_out(void)
977 return(actual_console->get_out());
978 else if (frozen_console)
979 return(frozen_console->get_out());
984 cl_commander::dd_printf(char *format, ...)
989 class cl_console *con;
993 f= actual_console->get_out();
996 else if (frozen_console)
998 f= frozen_console->get_out();
1006 if (/*actual_console &&
1007 actual_console->out*/f &&
1010 va_start(ap, format);
1011 ret= con->cmd_do_print(f/*actual_console->out*/, format, ap);
1018 cl_commander::dd_printf(char *format, va_list ap)
1022 class cl_console *con;
1026 f= actual_console->get_out();
1027 con= actual_console;
1029 else if (frozen_console)
1031 f= frozen_console->get_out();
1032 con= frozen_console;
1039 if (/*actual_console &&
1040 actual_console->out*/f &&
1043 ret= con->cmd_do_print(f/*actual_console->out*/, format, ap);
1049 * Printing to consoles which have CONS_DEBUG flag set
1053 cl_commander::debug(char *format, ...)
1058 for (i= 0; i < cons->count; i++)
1060 class cl_console *c= (class cl_console*)(cons->at(i));
1061 FILE *Out= c->get_out();
1063 c->flags & CONS_DEBUG)
1065 va_start(ap, format);
1066 ret= c->cmd_do_print(Out, format, ap);
1074 cl_commander::debug(char *format, va_list ap)
1078 for (i= 0; i < cons->count; i++)
1080 class cl_console *c= (class cl_console*)(cons->at(i));
1081 FILE *Out= c->get_out();
1083 c->flags & CONS_DEBUG)
1085 ret= c->cmd_do_print(Out, format, ap);
1092 cl_commander::flag_printf(int iflags, char *format, ...)
1097 for (i= 0; i < cons->count; i++)
1099 class cl_console *c= (class cl_console*)(cons->at(i));
1100 FILE *Out= c->get_out();
1102 (c->flags & iflags) == iflags)
1104 va_start(ap, format);
1105 ret= c->cmd_do_print(Out, format, ap);
1113 cl_commander::input_avail(void)
1118 tv.tv_sec= tv.tv_usec= 0;
1119 active_set= read_set;
1120 i= select(fd_num, &active_set, NULL, NULL, &tv);
1125 cl_commander::input_avail_on_frozen(void)
1129 if (!frozen_console)
1131 if ((fd= frozen_console->get_in_fd()) >= 0 &&
1134 return(frozen_console->input_avail());
1138 cl_commander::wait_input(void)
1142 active_set= read_set;
1144 i= select(fd_num, &active_set, NULL, NULL, NULL);
1149 cl_commander::proc_input(void)
1153 for (i= 0; i < fd_num; i++)
1154 if (FD_ISSET(i, &active_set))
1156 class cl_console *c;
1158 for (j= 0; j < cons->count; j++)
1160 c= (class cl_console*)(cons->at(j));
1164 int retval= c->proc_input(cmdset);
1171 return(cons->count == 0);
1179 cl_commander::exec_on(class cl_console *cons, char *file_name)
1181 FILE *fi= fopen(file_name, "r");
1186 class cl_console *subcon= cons->clone_for_exec(file_name);
1187 subcon->flags|= CONS_NOWELCOME;
1188 add_console(subcon);
1192 /* End of cmd.src/newcmd.cc */