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>
61 extern "C" int vasprintf(char **strp, const char *format, va_list ap);
62 extern "C" int vsnprintf(char *str, size_t size,const char *format,va_list ap);
65 cmd_do_print(FILE *f, char *format, va_list ap)
70 vasprintf(&msg, format, ap);
71 ret= fprintf(f, "%s", msg);
74 # ifdef HAVE_VSNPRINTF
76 vsnprintf(msg, 80*25, format, ap);
77 ret= fprintf(f, "%s", msg);
81 vsprintf(msg, format, ap); /* Dangerous */
82 ret= fprintf(f, "%s", msg);
86 /*strcpy(msg, "Unimplemented printf has called.\n");*/
88 /*strcpy(msg, "printf can not be implemented, upgrade your libc.\n");*/
100 *____________________________________________________________________________
103 cl_cmdline::cl_cmdline(char *acmd, class cl_console *acon)
106 params= new cl_list(2, 2);
107 tokens= new cl_ustrings(2, 2);
113 cl_cmdline::~cl_cmdline(void)
124 cl_cmdline::init(void)
131 cl_cmdline::skip_delims(char *start)
134 strchr(" \t\v\r,", *start))
140 cl_cmdline::split(void)
149 start+= strspn(start, " \t\v\r,");
153 name= (char*)malloc(2);
159 i= strcspn(start, " \t\v\r,");
162 name= (char*)malloc(i+1);
163 strncpy(name, start, i);
167 start= skip_delims(start);
171 char *end, *param_str;
192 con->printf("Unterminated string\n");
193 param_str= (char *)malloc(end-start+2);
194 strncpy(param_str, start, 1+end-start);
195 param_str[1+end-start]= '\0';
196 tokens->add(strdup(param_str));
197 params->add(con->sim->mk_cmd_str_arg(param_str));
207 i= strcspn(start, " \t\v\r,");
209 param_str= (char *)malloc(i+1);
210 strncpy(param_str, start, i);
212 tokens->add(strdup(param_str));
213 if ((dot= strchr(param_str, '.')) != NULL)
216 class cl_cmd_arg *sfr, *bit;
219 if (strchr("0123456789", *param_str) != NULL)
220 sfr= con->sim->mk_cmd_int_arg((long long)
221 strtol(param_str, 0, 0));
223 sfr= con->sim->mk_cmd_sym_arg(param_str);
227 con->printf("Uncomplete bit address\n");
232 if (strchr("0123456789", *dot) != NULL)
233 bit= con->sim->mk_cmd_int_arg((long long)
236 bit= con->sim->mk_cmd_sym_arg(dot);
237 params->add(con->sim->mk_cmd_bit_arg(sfr, bit));
240 else if ((dot= strchr(param_str, '[')) != NULL)
243 class cl_cmd_arg *aname, *aindex;
246 if (strchr("0123456789", *param_str) != NULL)
247 aname= con->sim->mk_cmd_int_arg((long long)
248 strtol(param_str, 0, 0));
250 aname= con->sim->mk_cmd_sym_arg(param_str);
254 con->printf("Uncomplete array\n");
259 p= dot + strlen(dot) - 1;
268 if (strlen(dot) == 0)
270 con->printf("Uncomplete array index\n");
275 if (strchr("0123456789", *dot) != NULL)
276 aindex= con->sim->mk_cmd_int_arg((long long)
279 aindex= con->sim->mk_cmd_sym_arg(dot);
280 params->add(con->sim->mk_cmd_array_arg(aname, aindex));
284 else if (strchr("0123456789", *param_str) != NULL)
287 params->add(con->sim->mk_cmd_int_arg((long long)
288 strtol(param_str, 0, 0)));
293 params->add(con->sim->mk_cmd_sym_arg(param_str));
298 start= skip_delims(start);
304 cl_cmdline::shift(void)
306 char *s= skip_delims(cmd);
313 strchr(" \t\v\r,", *s) == NULL)
320 params= new cl_list(2, 2);
323 return(name && *name);
327 cl_cmdline::repeat(void)
334 cl_cmdline::param(int num)
336 if (num >= params->count)
338 return((class cl_cmd_arg *)(params->at(num)));
342 cl_cmdline::insert_param(int pos, class cl_cmd_arg *param)
344 if (pos >= params->count)
347 params->add_at(pos, param);
351 cl_cmdline::syntax_match(class cl_sim *sim, char *syntax)
358 matched_syntax= syntax;
363 //printf("syntax %s?\n",syntax);
366 class cl_cmd_arg *parm= (class cl_cmd_arg *)(params->at(iparam));
370 //printf("Checking %s as %c\n",parm->get_svalue(),*p);
374 if (!parm->as_address())
376 //printf("ADDRESS match %lx\n",parm->value.address);
379 if (!parm->as_number())
383 if (!parm->as_data())
387 if (!parm->as_memory())
389 //printf("MEMORY match %s\n",parm->value.memory->class_name);
392 if (!parm->as_hw(sim->uc))
396 if (!parm->as_string())
400 if (!set_data_list(parm, &iparam))
404 if (!parm->as_bit(sim->uc))
412 if (iparam < params->count)
413 parm= (class cl_cmd_arg *)(params->at(iparam));
420 matched_syntax= syntax;
427 cl_cmdline::set_data_list(class cl_cmd_arg *parm, int *iparm)
429 class cl_cmd_arg *next_parm;
435 for (i= *iparm, next_parm= param(i); next_parm; i++, next_parm= param(i))
437 if (next_parm->is_string())
441 //s= proc_escape(next_parm->get_svalue(), &l);
442 if (!next_parm->as_string())
444 s= next_parm->value.string.string;
445 l= next_parm->value.string.len;
447 array= (t_mem*)malloc(sizeof(t_mem)*l);
449 array= (t_mem*)realloc(array, sizeof(t_mem)*(l+len));
450 for (j= 0; j < l; j++)
460 if (!next_parm->as_data())
467 array= (t_mem*)malloc(sizeof(t_mem));
469 array= (t_mem*)realloc(array, sizeof(t_mem)*(1+len));
470 array[len]= next_parm->value.data;
475 parm->value.data_list.array= array;
476 parm->value.data_list.len= len;
483 *____________________________________________________________________________
486 cl_cmd::cl_cmd(//class cl_sim *asim,
494 names= new cl_strings(1, 1);
495 names->add(aname?strdup(aname):strdup("unknown"));
497 short_help= short_hlp?strdup(short_hlp):NULL;
498 long_help= long_hlp?strdup(long_hlp):NULL;
501 /*cl_cmd::cl_cmd(class cl_sim *asim):
505 name= short_help= long_help= 0;
509 cl_cmd::~cl_cmd(void)
519 cl_cmd::add_name(char *name)
522 names->add(strdup(name));
526 cl_cmd::name_match(char *aname, int strict)
530 if (names->count == 0 &&
537 for (i= 0; i < names->count; i++)
539 char *n= (char*)(names->at(i));
540 if (strcmp(aname, n) == 0)
546 for (i= 0; i < names->count; i++)
548 char *n= (char*)(names->at(i));
549 if (strstr(n, aname) == n)
557 cl_cmd::name_match(class cl_cmdline *cmdline, int strict)
559 return(name_match(cmdline->name, strict));
563 cl_cmd::syntax_ok(class cl_cmdline *cmdline)
569 cl_cmd::work(class cl_sim *sim,
570 class cl_cmdline *cmdline, class cl_console *con)
572 if (!syntax_ok(cmdline))
574 return(do_work(sim, cmdline, con));
578 cl_cmd::do_work(class cl_sim *sim,
579 class cl_cmdline *cmdline, class cl_console *con)
581 con->printf("Command \"%s\" does nothing.\n", (char*)(names->at(0)));
588 *____________________________________________________________________________
591 cl_cmdset::cl_cmdset(class cl_sim *asim):
599 cl_cmdset::get_cmd(class cl_cmdline *cmdline)
603 if (cmdline->repeat())
606 return(last_command);
611 for (i= 0; i < count; i++)
613 class cl_cmd *c= (class cl_cmd *)at(i);
614 if (c->name_match(cmdline, 1))
618 class cl_cmd *c_matched= 0;
619 for (i= 0; i < count; i++)
621 class cl_cmd *c= (class cl_cmd *)at(i);
622 if (c->name_match(cmdline, 0))
635 cl_cmdset::get_cmd(char *cmd_name)
639 for (i= 0; i < count; i++)
641 class cl_cmd *c= (class cl_cmd *)at(i);
642 if (c->name_match(cmd_name, 1))
649 cl_cmdset::del(char *name)
655 for (i= 0; i < count; i++)
657 class cl_cmd *cmd= (class cl_cmd *)(at(i));
658 if (cmd->name_match(name, 1))
664 cl_cmdset::replace(char *name, class cl_cmd *cmd)
670 for (i= 0; i < count; i++)
672 class cl_cmd *c= (class cl_cmd *)(at(i));
673 if (c->name_match(name, 1))
683 * Composed command: subset of commands
684 *____________________________________________________________________________
687 cl_super_cmd::cl_super_cmd(//class cl_sim *asim,
692 class cl_cmdset *acommands):
693 cl_cmd(aname, can_rep, short_hlp, long_hlp)
698 cl_super_cmd::~cl_super_cmd(void)
705 cl_super_cmd::work(class cl_sim *sim,
706 class cl_cmdline *cmdline, class cl_console *con)
708 class cl_cmd *cmd= 0;
713 if (!cmdline->shift())
715 if ((cmd= commands->get_cmd("_no_parameters_")) != 0)
716 return(cmd->work(sim, cmdline, con));
718 con->printf("\"%s\" must be followed by the name of a subcommand\n"
719 "List of subcommands:\n", (char*)(names->at(0)));
720 for (i= 0; i < commands->count; i++)
722 cmd= (class cl_cmd *)(commands->at(i));
723 con->printf("%s\n", cmd->short_help);
727 if ((cmd= commands->get_cmd(cmdline)) == NULL)
729 con->printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
730 cmdline->name, (char*)(names->at(0)));
733 return(cmd->work(sim, cmdline, con));
739 *____________________________________________________________________________
742 cl_console::cl_console(char *fin, char *fout, class cl_sim *asim):
751 if (f= fopen(fin, "r+"), in= f, !f)
752 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
755 if (f= fopen(fout, "w+"), out= f, !f)
756 fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
761 flags|= CONS_INTERACTIVE;
763 printf("Warning: non-interactive console\n");
766 cl_console::cl_console(FILE *fin, FILE *fout, class cl_sim *asim):
777 flags|= CONS_INTERACTIVE;
779 printf("Warning: non-interactive console\n");
783 * use the port number supplied to connect to localhost for
789 connect_to_port(int portnum)
791 int sock= socket(AF_INET,SOCK_STREAM,0);
792 struct sockaddr_in sin;
794 sin.sin_family = AF_INET;
795 sin.sin_port = htons(portnum);
796 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
798 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
799 fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
805 cl_console::cl_console(int portnumber, class cl_sim *asim)
807 int sock= connect_to_port(portnumber);
811 if (!(in= fdopen(sock, "r+")))
812 fprintf(stderr, "cannot open port for input\n");
813 if (!(out= fdopen(sock, "w+")))
814 fprintf(stderr, "cannot open port for output\n");
815 //fprintf(stderr, "init socket done\n");
820 cl_console::init(void)
824 flags&= ~CONS_PROMPT;
829 cl_console::~cl_console(void)
854 cl_console::welcome(void)
858 fprintf(out, "ucsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
859 "ucsim comes with ABSOLUTELY NO WARRANTY; for details type "
861 "This is free software, and you are welcome to redistribute it\n"
862 "under certain conditions; type `show c' for details.\n",
868 cl_console::print_prompt(void)
872 if (flags & (CONS_PROMPT|CONS_FROZEN))
877 if (sim->arg_avail('P'))
880 fprintf(out, "%s", (prompt && prompt[0])?prompt:
881 ((p= sim->get_sarg(0, "prompt"))?p:"> "));
886 cl_console::printf(char *format, ...)
893 va_start(ap, format);
894 ret= cmd_do_print(out, format, ap);
901 cl_console::print_bin(long data, int bits)
907 mask= mask << ((bits >= 1)?(bits-1):0);
910 fprintf(out, "%c", (data&mask)?'1':'0');
920 cl_console::match(int fdnum)
929 cl_console::get_in_fd(void)
931 return(in?fileno(in):-1);
935 cl_console::input_avail(void)
940 if ((i= get_in_fd()) < 0)
945 tv.tv_sec= tv.tv_usec= 0;
946 i= select(i+1, &s, NULL, NULL, &tv);
951 cl_console::read_line(void)
956 if (getline(&s, 0, in) < 0)
960 # ifdef HAVE_GETDELIM
962 s= (char *)malloc(n);
963 if (getdelim(&s, &n, '\n', in) < 0)
971 s= (char *)malloc(300);
972 if (fgets(s, 300, in) == NULL)
980 s[strlen(s)-1]= '\0';
981 if (s[strlen(s)-1] == '\r')
982 s[strlen(s)-1]= '\0';
983 flags&= ~CONS_PROMPT;
988 cl_console::proc_input(class cl_app *app, class cl_cmdset *cmdset)
994 fprintf(out, "End\n");
997 char *cmdstr= read_line();
1000 if (flags & CONS_FROZEN)
1003 flags&= ~CONS_FROZEN;
1008 class cl_cmdline *cmdline;
1010 cmdline= new cl_cmdline(cmdstr, this);
1014 cm= app->get_cmd(cmdline);
1017 cm= cmdset->get_cmd(cmdline);
1019 retval= cm->work(sim, cmdline, this);
1022 retval= interpret(cmdstr);
1024 //retval= sim->do_cmd(cmd, this);
1032 * Old version, sim->do_cmd() falls into this if it doesn't find a new
1033 * command object which can handle entered command
1037 cl_console::interpret(char *cmd)
1039 fprintf(out, "New interpreter does not known this command\n");
1045 * This console listen on a socket and can accept connection requests
1049 cl_listen_console::cl_listen_console(int serverport, class cl_sim *asim)
1053 if ((sock= make_server_socket(serverport)) >= 0)
1055 if (listen(sock, 10) < 0)
1056 fprintf(stderr, "Listen on port %d: %s\n",
1057 serverport, strerror(errno));
1063 cl_listen_console::match(int fdnum)
1065 return(sock == fdnum);
1069 cl_listen_console::get_in_fd(void)
1075 cl_listen_console::proc_input(class cl_cmdset *cmdset)
1078 ACCEPT_SOCKLEN_T size;
1079 struct sockaddr_in sock_addr;
1081 size= sizeof(struct sockaddr);
1082 newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
1088 if (!(in= fdopen(newsock, "r+")))
1089 fprintf(stderr, "cannot open port for input\n");
1090 if (!(out= fdopen(newsock, "w+")))
1091 fprintf(stderr, "cannot open port for output\n");
1092 class cl_console *c= sim->cmd->mk_console(in, out, sim);
1093 c->flags|= CONS_INTERACTIVE;
1095 sim->cmd->add_console(c);
1100 #endif /* SOCKET_AVAIL */
1104 * Command interpreter
1105 *____________________________________________________________________________
1108 cl_commander::cl_commander(class cl_app *the_app,
1109 class cl_cmdset *acmdset, class cl_sim *asim):
1113 cons= new cl_list(1, 1);
1114 actual_console= frozen_console= 0;
1120 cl_commander::init(void)
1125 if (sim->arg_avail('c'))
1126 add_console(mk_console(sim->get_sarg('c', 0),
1127 sim->get_sarg('c', 0), sim));
1129 if (sim->arg_avail('Z'))
1130 add_console(mk_console(sim->get_iarg(0, "Zport"), sim));
1131 if (sim->arg_avail('r'))
1132 add_console(mk_console(sim->get_iarg('r', 0), sim));
1134 if (cons->get_count() == 0)
1135 add_console(mk_console(stdin, stdout, sim));
1139 cl_commander::~cl_commander(void)
1146 cl_commander::mk_console(char *fin, char *fout, class cl_sim *asim)
1148 return(new cl_console(fin, fout, asim));
1152 cl_commander::mk_console(FILE *fin, FILE *fout, class cl_sim *asim)
1154 return(new cl_console(fin, fout, asim));
1159 cl_commander::mk_console(int portnumber, class cl_sim *asim)
1161 return(new cl_listen_console(portnumber, asim));
1166 cl_commander::add_console(class cl_console *console)
1174 cl_commander::del_console(class cl_console *console)
1176 cons->disconn(console);
1181 cl_commander::set_fd_set(void)
1185 //fprintf(stderr, "** Setting fd set\n");
1188 for (i= 0; i < cons->count; i++)
1191 class cl_console *c= (class cl_console*)(cons->at(i));
1192 if ((fd= c->get_in_fd()) >= 0)
1194 if ((c->flags & CONS_FROZEN) == 0 ||
1195 (c->flags & CONS_INTERACTIVE) != 0)
1197 FD_SET(fd, &read_set);
1203 ;//fprintf(stderr, "** Skipping console %p\n",c);
1210 * Printing to all consoles
1214 cl_commander::all_printf(char *format, ...)
1219 for (i= 0; i < cons->count; i++)
1221 class cl_console *c= (class cl_console*)(cons->at(i));
1224 va_start(ap, format);
1225 ret= cmd_do_print(c->out, format, ap);
1233 cl_commander::all_print(char *string, int length)
1237 for (i= 0; i < cons->count; i++)
1239 class cl_console *c= (class cl_console*)(cons->at(i));
1242 for (int j= 0; j < length; j++)
1243 putc(string[j], c->out);
1250 * Printing to actual_console
1254 cl_commander::printf(char *format, ...)
1259 if (actual_console &&
1260 actual_console->out)
1262 va_start(ap, format);
1263 ret= cmd_do_print(actual_console->out, format, ap);
1270 * Printing to consoles which have CONS_DEBUG flag set
1274 cl_commander::debug(char *format, ...)
1279 for (i= 0; i < cons->count; i++)
1281 class cl_console *c= (class cl_console*)(cons->at(i));
1283 c->flags & CONS_DEBUG)
1285 va_start(ap, format);
1286 ret= cmd_do_print(c->out, format, ap);
1294 cl_commander::flag_printf(int iflags, char *format, ...)
1299 for (i= 0; i < cons->count; i++)
1301 class cl_console *c= (class cl_console*)(cons->at(i));
1303 (c->flags & iflags) == iflags)
1305 va_start(ap, format);
1306 ret= cmd_do_print(c->out, format, ap);
1314 cl_commander::input_avail(void)
1319 tv.tv_sec= tv.tv_usec= 0;
1320 active_set= read_set;
1321 i= select(fd_num, &active_set, NULL, NULL, &tv);
1326 cl_commander::input_avail_on_frozen(void)
1330 if (!frozen_console)
1332 if ((fd= frozen_console->get_in_fd()) >= 0 &&
1335 return(frozen_console->input_avail());
1339 cl_commander::wait_input(void)
1343 active_set= read_set;
1344 i= select(fd_num, &active_set, NULL, NULL, NULL);
1349 cl_commander::proc_input(void)
1353 for (i= 0; i < fd_num; i++)
1354 if (FD_ISSET(i, &active_set))
1356 class cl_console *c;
1358 for (j= 0; j < cons->count; j++)
1360 c= (class cl_console*)(cons->at(j));
1364 int retval= c->proc_input(app, cmdset);
1371 return(cons->count == 0);
1379 /* End of cmd.src/newcmd.cc */