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>
35 #ifdef HAVE_SYS_SOCKET_H
36 # include <sys/socket.h>
37 # include <netinet/in.h>
38 # include <arpa/inet.h>
62 extern "C" int vasprintf(char **strp, const char *format, va_list ap);
63 extern "C" int vsnprintf(char *str, size_t size,const char *format,va_list ap);
66 cmd_do_print(FILE *f, char *format, va_list ap)
71 vasprintf(&msg, format, ap);
72 ret= fprintf(f, "%s", msg);
75 # ifdef HAVE_VSNPRINTF
77 vsnprintf(msg, 80*25, format, ap);
78 ret= fprintf(f, "%s", msg);
82 vsprintf(msg, format, ap); /* Dangerous */
83 ret= fprintf(f, "%s", msg);
87 /*strcpy(msg, "Unimplemented printf has called.\n");*/
89 /*strcpy(msg, "printf can not be implemented, upgrade your libc.\n");*/
103 cl_prompt_option::cl_prompt_option(class cl_console *console):
110 cl_prompt_option::init(void)
113 help= format_string("Prompt string of console%d", con->get_id());
114 create(con, string_opt, "prompt", help);
115 //fprintf(stderr," **new prompt option %p\"%s\", value=%p str=%p\n",option,object_name(option),option->get_value(),option->get_value()->sval);
117 default_option("prompt");
118 //fprintf(stderr,"opt=%p\"%s\" value after default set=%p str=%p\n",option,object_name(option),option->get_value(),option->get_value()->sval);
123 cl_prompt_option::option_changed(void)
128 option->get_value(&s);
133 cl_debug_option::cl_debug_option(class cl_console *console):
134 cl_prompt_option(console)
138 cl_debug_option::init(void)
141 help= format_string("Debug messages to console%d", con->get_id());
142 create(con, bool_opt, "debug", help);
144 default_option("debug");
149 cl_debug_option::option_changed(void)
154 option->get_value(&b);
156 con->flags|= CONS_DEBUG;
158 con->flags&= ~CONS_DEBUG;
164 *____________________________________________________________________________
167 cl_console::cl_console(char *fin, char *fout, class cl_app *the_app):
176 if (f= fopen(fin, "r"), in= f, !f)
177 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
180 if (f= fopen(fout, "w"), out= f, !f)
181 fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
186 flags|= CONS_INTERACTIVE;
188 ;//fprintf(stderr, "Warning: non-interactive console\n");
192 cl_console::cl_console(FILE *fin, FILE *fout, class cl_app *the_app):
203 flags|= CONS_INTERACTIVE;
205 ;//fprintf(stderr, "Warning: non-interactive console\n");
210 * use the port number supplied to connect to localhost for
216 connect_to_port(int portnum)
218 int sock= socket(AF_INET,SOCK_STREAM,0);
219 struct sockaddr_in sin;
221 sin.sin_family = AF_INET;
222 sin.sin_port = htons(portnum);
223 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
225 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
226 fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
232 cl_console::cl_console(int portnumber, class cl_app *the_app)
234 int sock= connect_to_port(portnumber);
238 if (!(in= fdopen(sock, "r")))
239 fprintf(stderr, "cannot open port for input\n");
240 if (!(out= fdopen(sock, "w")))
241 fprintf(stderr, "cannot open port for output\n");
242 //fprintf(stderr, "init socket done\n");
248 cl_console::clone_for_exec(char *fin)
253 if (fi= fopen(fin, "r"), !fi)
255 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
258 if ((fo= fdopen(dup(fileno(out)), "a")) == 0)
261 fprintf(stderr, "Can't re-open output file: %s\n", strerror(errno));
264 class cl_console *con= new cl_sub_console(this, fi, fo, app);
269 cl_console::init(void)
272 prompt_option= new cl_prompt_option(this);
273 prompt_option->init();
274 null_prompt_option= new cl_optref(this);
275 null_prompt_option->init();
276 null_prompt_option->use("null_prompt");
277 debug_option= new cl_debug_option(this);
278 debug_option->init();
280 flags&= ~CONS_PROMPT;
285 cl_console::~cl_console(void)
292 if (flags & CONS_PROMPT)
297 delete prompt_option;
298 delete null_prompt_option;
315 cl_console::welcome(void)
317 FILE *Out= rout?rout:out;
320 (flags & CONS_NOWELCOME))
322 fprintf(Out, "uCsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
323 "uCsim comes with ABSOLUTELY NO WARRANTY; for details type "
325 "This is free software, and you are welcome to redistribute it\n"
326 "under certain conditions; type `show c' for details.\n",
332 cl_console::redirect(char *fname, char *mode)
334 if ((rout= fopen(fname, mode)) == NULL)
335 dd_printf("Unable to open file '%s' for %s: %s\n",
336 fname, (mode[0]=='w')?"write":"append", strerror(errno));
340 cl_console::un_redirect(void)
349 cl_console::print_prompt(void)
352 FILE *Out= rout?rout:out;
354 if (flags & (CONS_PROMPT|CONS_FROZEN|CONS_INACTIVE))
359 if (/*app->args->arg_avail('P')*/null_prompt_option->get_value(bool(0)))
363 fprintf(Out, "%d", id);
364 fprintf(Out, "%s", (prompt && prompt[0])?prompt:"> ");
365 // ((p= app->args->get_sarg(0, "prompt"))?p:"> "));
371 cl_console::dd_printf(char *format, ...)
375 FILE *Out= rout?rout:out;
379 va_start(ap, format);
380 ret= cmd_do_print(Out, format, ap);
387 cl_console::print_bin(long data, int bits)
390 FILE *Out= rout?rout:out;
394 mask= mask << ((bits >= 1)?(bits-1):0);
397 fprintf(Out, "%c", (data&mask)?'1':'0');
403 cl_console::print_char_octal(char c)
405 FILE *Out= rout?rout:out;
408 ::print_char_octal(c, Out);
417 cl_console::match(int fdnum)
426 cl_console::get_in_fd(void)
428 if (flags & CONS_INACTIVE)
430 return(in?fileno(in):-1);
434 cl_console::input_avail(void)
439 if ((i= get_in_fd()) < 0)
444 tv.tv_sec= tv.tv_usec= 0;
445 i= select(i+1, &s, NULL, NULL, &tv);
450 cl_console::read_line(void)
455 if (getline(&s, 0, in) < 0)
459 # ifdef HAVE_GETDELIM
461 s= (char *)malloc(n);
462 if (getdelim(&s, &n, '\n', in) < 0)
470 s= (char *)malloc(300);
471 if (fgets(s, 300, in) == NULL)
479 s[strlen(s)-1]= '\0';
480 if (s[strlen(s)-1] == '\r')
481 s[strlen(s)-1]= '\0';
482 flags&= ~CONS_PROMPT;
487 cl_console::proc_input(class cl_cmdset *cmdset)
494 fprintf(out, "End\n");
497 char *cmdstr= read_line();
500 if (flags & CONS_FROZEN)
502 app->get_sim()->stop(resUSER);
503 flags&= ~CONS_FROZEN;
513 class cl_cmdline *cmdline;
515 if (flags & CONS_ECHO)
516 dd_printf("%s\n", cmdstr);
517 cmdline= new cl_cmdline(app, cmdstr, this);
519 cm= cmdset->get_cmd(cmdline);
521 retval= cm->work(app, cmdline, this);
524 retval= interpret(cmdstr);
527 //retval= sim->do_cmd(cmd, this);
536 * Old version, sim->do_cmd() falls into this if it doesn't find a new
537 * command object which can handle entered command
541 cl_console::interpret(char *cmd)
543 FILE *Out= rout?rout:out;
545 fprintf(Out, "Unknown command\n");
550 cl_console::set_id(int new_id)
555 set_name(s= format_string("console%d", id));
560 cl_console::set_prompt(char *p)
573 * This console listen on a socket and can accept connection requests
577 cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app)
581 if ((sock= make_server_socket(serverport)) >= 0)
583 if (listen(sock, 10) < 0)
584 fprintf(stderr, "Listen on port %d: %s\n",
585 serverport, strerror(errno));
591 cl_listen_console::match(int fdnum)
593 return(sock == fdnum);
597 cl_listen_console::get_in_fd(void)
603 cl_listen_console::proc_input(class cl_cmdset *cmdset)
606 ACCEPT_SOCKLEN_T size;
607 struct sockaddr_in sock_addr;
608 class cl_commander *cmd;
610 cmd= app->get_commander();
611 size= sizeof(struct sockaddr);
612 newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
618 if (!(in= fdopen(newsock, "r+")))
619 fprintf(stderr, "cannot open port for input\n");
620 if (!(out= fdopen(newsock, "w+")))
621 fprintf(stderr, "cannot open port for output\n");
622 class cl_console *c= cmd->mk_console(in, out);
623 c->flags|= CONS_INTERACTIVE;
629 #endif /* SOCKET_AVAIL */
636 cl_sub_console::cl_sub_console(class cl_console *the_parent,
637 FILE *fin, FILE *fout, class cl_app *the_app):
638 cl_console(fin, fout, the_app)
643 cl_sub_console::~cl_sub_console(void)
645 class cl_commander *c= app->get_commander();
649 c->activate_console(parent);
654 cl_sub_console::init(void)
656 class cl_commander *c= app->get_commander();
660 c->deactivate_console(parent);
669 * Command interpreter
670 *____________________________________________________________________________
673 cl_commander::cl_commander(class cl_app *the_app, class cl_cmdset *acmdset
674 /*, class cl_sim *asim*/):
678 cons= new cl_list(1, 1);
679 actual_console= frozen_console= 0;
684 cl_commander::init(void)
686 class cl_optref console_on_option(this);
688 console_on_option.init();
689 console_on_option.use("console_on");
692 set_name("Commander");
694 char *Config= app->args->get_sarg(0, "Config");
697 class cl_console *con= mk_console(0/*"/dev/tty"*/);
701 //if (app->args->arg_avail('c'))
703 char *cn= console_on_option.get_value(cn);
705 add_console(mk_console(cn, cn));
708 if (app->args->arg_avail('Z'))
709 add_console(mk_console(app->args->get_iarg(0, "Zport")));
710 if (app->args->arg_avail('r'))
711 add_console(mk_console(app->args->get_iarg('r', 0)));
713 if (cons->get_count() == 0)
714 add_console(mk_console(stdin, stdout));
718 cl_commander::~cl_commander(void)
725 cl_commander::mk_console(char *fin, char *fout)
727 return(new cl_console(fin, fout, app));
731 cl_commander::mk_console(FILE *fin, FILE *fout)
733 return(new cl_console(fin, fout, app));
738 cl_commander::mk_console(int portnumber)
740 return(new cl_listen_console(portnumber, app));
745 cl_commander::add_console(class cl_console *console)
749 int i=cons->add(console);
756 cl_commander::del_console(class cl_console *console)
758 cons->disconn(console);
763 cl_commander::activate_console(class cl_console *console)
765 console->flags&= ~CONS_INACTIVE;
766 //console->print_prompt();
771 cl_commander::deactivate_console(class cl_console *console)
773 console->flags|= CONS_INACTIVE;
778 cl_commander::set_fd_set(void)
782 //fprintf(stderr, "** Setting fd set\n");
785 for (i= 0; i < cons->count; i++)
788 class cl_console *c= (class cl_console*)(cons->at(i));
789 if ((fd= c->get_in_fd()) >= 0)
791 if ((c->flags & CONS_FROZEN) == 0 ||
792 (c->flags & CONS_INTERACTIVE) != 0)
794 FD_SET(fd, &read_set);
800 ;//fprintf(stderr, "** Skipping console %p\n",c);
807 * Printing to all consoles
811 cl_commander::all_printf(char *format, ...)
816 for (i= 0; i < cons->count; i++)
818 class cl_console *c= (class cl_console*)(cons->at(i));
819 FILE *Out= c->get_out();
822 va_start(ap, format);
823 ret= cmd_do_print(Out, format, ap);
831 cl_commander::prompt(void)
835 for (i= 0; i < cons->count; i++)
837 class cl_console *c= (class cl_console*)(cons->at(i));
843 cl_commander::all_print(char *string, int length)
847 for (i= 0; i < cons->count; i++)
849 class cl_console *c= (class cl_console*)(cons->at(i));
850 FILE *Out= c->get_out();
853 for (int j= 0; j < length; j++)
854 putc(string[j], Out);
861 * Printing to actual_console
865 cl_commander::dd_printf(char *format, ...)
872 f= actual_console->get_out();
873 else if (frozen_console)
874 f= frozen_console->get_out();
877 if (/*actual_console &&
878 actual_console->out*/f)
880 va_start(ap, format);
881 ret= cmd_do_print(f/*actual_console->out*/, format, ap);
888 * Printing to consoles which have CONS_DEBUG flag set
892 cl_commander::debug(char *format, ...)
897 for (i= 0; i < cons->count; i++)
899 class cl_console *c= (class cl_console*)(cons->at(i));
900 FILE *Out= c->get_out();
902 c->flags & CONS_DEBUG)
904 va_start(ap, format);
905 ret= cmd_do_print(Out, format, ap);
913 cl_commander::flag_printf(int iflags, char *format, ...)
918 for (i= 0; i < cons->count; i++)
920 class cl_console *c= (class cl_console*)(cons->at(i));
921 FILE *Out= c->get_out();
923 (c->flags & iflags) == iflags)
925 va_start(ap, format);
926 ret= cmd_do_print(Out, format, ap);
934 cl_commander::input_avail(void)
939 tv.tv_sec= tv.tv_usec= 0;
940 active_set= read_set;
941 i= select(fd_num, &active_set, NULL, NULL, &tv);
946 cl_commander::input_avail_on_frozen(void)
952 if ((fd= frozen_console->get_in_fd()) >= 0 &&
955 return(frozen_console->input_avail());
959 cl_commander::wait_input(void)
963 active_set= read_set;
965 i= select(fd_num, &active_set, NULL, NULL, NULL);
970 cl_commander::proc_input(void)
974 for (i= 0; i < fd_num; i++)
975 if (FD_ISSET(i, &active_set))
979 for (j= 0; j < cons->count; j++)
981 c= (class cl_console*)(cons->at(j));
985 int retval= c->proc_input(cmdset);
992 return(cons->count == 0);
1000 /* End of cmd.src/newcmd.cc */