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(class cl_app *the_app,
104 char *acmd, class cl_console *acon):
109 params= new cl_list(2, 2);
110 tokens= new cl_ustrings(2, 2);
116 cl_cmdline::~cl_cmdline(void)
127 cl_cmdline::init(void)
134 cl_cmdline::skip_delims(char *start)
137 strchr(" \t\v\r,", *start))
143 cl_cmdline::split(void)
148 class cl_cmd_arg *arg;
150 //sim= app->get_sim();
155 start+= strspn(start, " \t\v\r,");
159 name= (char*)malloc(2);
165 i= strcspn(start, " \t\v\r,");
168 name= (char*)malloc(i+1);
169 strncpy(name, start, i);
173 start= skip_delims(start);
177 char *end, *param_str;
198 con->dd_printf("Unterminated string\n");
199 param_str= (char *)malloc(end-start+2);
200 strncpy(param_str, start, 1+end-start);
201 param_str[1+end-start]= '\0';
202 tokens->add(strdup(param_str));
203 params->add(arg= new cl_cmd_str_arg(param_str));
214 i= strcspn(start, " \t\v\r,");
216 param_str= (char *)malloc(i+1);
217 strncpy(param_str, start, i);
219 tokens->add(strdup(param_str));
220 if ((dot= strchr(param_str, '.')) != NULL)
223 class cl_cmd_arg *sfr, *bit;
226 if (strchr("0123456789", *param_str) != NULL)
228 sfr= new cl_cmd_int_arg((long)strtol(param_str, 0, 0));
233 sfr= new cl_cmd_sym_arg(param_str);
239 con->dd_printf("Uncomplete bit address\n");
244 if (strchr("0123456789", *dot) != NULL)
246 bit= new cl_cmd_int_arg((long)strtol(dot, 0, 0));
251 bit= new cl_cmd_sym_arg(dot);
254 params->add(arg= new cl_cmd_bit_arg(sfr, bit));
258 else if ((dot= strchr(param_str, '[')) != NULL)
261 class cl_cmd_arg *aname, *aindex;
264 if (strchr("0123456789", *param_str) != NULL)
266 aname= new cl_cmd_int_arg((long)strtol(param_str, 0, 0));
271 aname= new cl_cmd_sym_arg(param_str);
277 con->dd_printf("Uncomplete array\n");
282 p= dot + strlen(dot) - 1;
291 if (strlen(dot) == 0)
293 con->dd_printf("Uncomplete array index\n");
298 if (strchr("0123456789", *dot) != NULL)
300 aindex= new cl_cmd_int_arg((long)strtol(dot, 0, 0));
305 aindex= new cl_cmd_sym_arg(dot);
308 params->add(arg= new cl_cmd_array_arg(aname, aindex));
313 else if (strchr("0123456789", *param_str) != NULL)
316 params->add(arg= new cl_cmd_int_arg((long)
317 strtol(param_str, 0, 0)));
323 params->add(arg= new cl_cmd_sym_arg(param_str));
329 start= skip_delims(start);
335 cl_cmdline::shift(void)
337 char *s= skip_delims(cmd);
344 strchr(" \t\v\r,", *s) == NULL)
351 params= new cl_list(2, 2);
354 return(name && *name);
358 cl_cmdline::repeat(void)
365 cl_cmdline::param(int num)
367 if (num >= params->count)
369 return((class cl_cmd_arg *)(params->at(num)));
373 cl_cmdline::insert_param(int pos, class cl_cmd_arg *param)
375 if (pos >= params->count)
378 params->add_at(pos, param);
382 cl_cmdline::syntax_match(class cl_uc *uc, char *syntax)
389 matched_syntax= syntax;
394 //printf("syntax %s?\n",syntax);
397 class cl_cmd_arg *parm= (class cl_cmd_arg *)(params->at(iparam));
401 //printf("Checking %s as %c\n",parm->get_svalue(),*p);
405 if (!parm->as_address(uc))
407 //printf("ADDRESS match %lx\n",parm->value.address);
410 if (!parm->as_number())
414 if (!parm->as_data())
418 if (!parm->as_memory(uc))
420 //printf("MEMORY match %s\n",parm->value.memory->class_name);
423 if (!parm->as_hw(uc))
427 if (!parm->as_string())
431 if (!set_data_list(parm, &iparam))
435 if (!parm->as_bit(uc))
443 if (iparam < params->count)
444 parm= (class cl_cmd_arg *)(params->at(iparam));
451 matched_syntax= syntax;
458 cl_cmdline::set_data_list(class cl_cmd_arg *parm, int *iparm)
460 class cl_cmd_arg *next_parm;
466 for (i= *iparm, next_parm= param(i); next_parm; i++, next_parm= param(i))
468 if (next_parm->is_string())
472 //s= proc_escape(next_parm->get_svalue(), &l);
473 if (!next_parm->as_string())
475 s= next_parm->value.string.string;
476 l= next_parm->value.string.len;
478 array= (t_mem*)malloc(sizeof(t_mem)*l);
480 array= (t_mem*)realloc(array, sizeof(t_mem)*(l+len));
481 for (j= 0; j < l; j++)
491 if (!next_parm->as_data())
498 array= (t_mem*)malloc(sizeof(t_mem));
500 array= (t_mem*)realloc(array, sizeof(t_mem)*(1+len));
501 array[len]= next_parm->value.data;
506 parm->value.data_list.array= array;
507 parm->value.data_list.len= len;
514 *____________________________________________________________________________
517 cl_cmd::cl_cmd(enum cmd_operate_on op_on,
525 names= new cl_strings(1, 1);
526 names->add(aname?strdup(aname):strdup("unknown"));
528 short_help= short_hlp?strdup(short_hlp):NULL;
529 long_help= long_hlp?strdup(long_hlp):NULL;
532 /*cl_cmd::cl_cmd(class cl_sim *asim):
536 name= short_help= long_help= 0;
540 cl_cmd::~cl_cmd(void)
550 cl_cmd::add_name(char *name)
553 names->add(strdup(name));
557 cl_cmd::name_match(char *aname, int strict)
561 if (names->count == 0 &&
568 for (i= 0; i < names->count; i++)
570 char *n= (char*)(names->at(i));
571 if (strcmp(aname, n) == 0)
577 for (i= 0; i < names->count; i++)
579 char *n= (char*)(names->at(i));
580 if (strstr(n, aname) == n)
588 cl_cmd::name_match(class cl_cmdline *cmdline, int strict)
590 return(name_match(cmdline->name, strict));
594 cl_cmd::syntax_ok(class cl_cmdline *cmdline)
600 cl_cmd::work(class cl_app *app,
601 class cl_cmdline *cmdline, class cl_console *con)
603 if (!syntax_ok(cmdline))
605 class cl_sim *sim= app->get_sim();
614 con->dd_printf("There is no application to work on!\n");
617 return(do_work(app, cmdline, con));
621 con->dd_printf("There is no simulator to work on!\n");
624 return(do_work(sim, cmdline, con));
628 con->dd_printf("There is no microcontroller to work on!\n");
631 return(do_work(uc, cmdline, con));
633 return(do_work(cmdline, con));
638 cl_cmd::do_work(class cl_cmdline *cmdline, class cl_console *con)
640 con->dd_printf("Command \"%s\" does nothing.\n",
641 (char*)(names->at(0)));
646 cl_cmd::do_work(class cl_app *app,
647 class cl_cmdline *cmdline, class cl_console *con)
649 con->dd_printf("Command \"%s\" does nothing on application.\n",
650 (char*)(names->at(0)));
655 cl_cmd::do_work(class cl_sim *sim,
656 class cl_cmdline *cmdline, class cl_console *con)
658 con->dd_printf("Command \"%s\" does nothing on simulator.\n",
659 (char*)(names->at(0)));
664 cl_cmd::do_work(class cl_uc *uc,
665 class cl_cmdline *cmdline, class cl_console *con)
667 con->dd_printf("Command \"%s\" does nothing on microcontroller.\n",
668 (char*)(names->at(0)));
675 *____________________________________________________________________________
678 cl_cmdset::cl_cmdset(void):
685 /*cl_cmdset::cl_cmdset(class cl_sim *asim):
693 cl_cmdset::get_cmd(class cl_cmdline *cmdline)
697 if (cmdline->repeat())
700 return(last_command);
705 for (i= 0; i < count; i++)
707 class cl_cmd *c= (class cl_cmd *)at(i);
708 if (c->name_match(cmdline, 1))
712 class cl_cmd *c_matched= 0;
713 for (i= 0; i < count; i++)
715 class cl_cmd *c= (class cl_cmd *)at(i);
716 if (c->name_match(cmdline, 0))
729 cl_cmdset::get_cmd(char *cmd_name)
733 for (i= 0; i < count; i++)
735 class cl_cmd *c= (class cl_cmd *)at(i);
736 if (c->name_match(cmd_name, 1))
743 cl_cmdset::del(char *name)
749 for (i= 0; i < count; i++)
751 class cl_cmd *cmd= (class cl_cmd *)(at(i));
752 if (cmd->name_match(name, 1))
758 cl_cmdset::replace(char *name, class cl_cmd *cmd)
764 for (i= 0; i < count; i++)
766 class cl_cmd *c= (class cl_cmd *)(at(i));
767 if (c->name_match(name, 1))
777 * Composed command: subset of commands
778 *____________________________________________________________________________
781 cl_super_cmd::cl_super_cmd(char *aname,
785 class cl_cmdset *acommands):
786 cl_cmd(operate_on_none, aname, can_rep, short_hlp, long_hlp)
791 cl_super_cmd::~cl_super_cmd(void)
798 cl_super_cmd::work(class cl_app *app,
799 class cl_cmdline *cmdline, class cl_console *con)
801 class cl_cmd *cmd= 0;
806 if (!cmdline->shift())
808 if ((cmd= commands->get_cmd("_no_parameters_")) != 0)
809 return(cmd->work(app, cmdline, con));
811 con->dd_printf("\"%s\" must be followed by the name of a subcommand\n"
812 "List of subcommands:\n", (char*)(names->at(0)));
813 for (i= 0; i < commands->count; i++)
815 cmd= (class cl_cmd *)(commands->at(i));
816 con->dd_printf("%s\n", cmd->short_help);
820 if ((cmd= commands->get_cmd(cmdline)) == NULL)
822 con->dd_printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
823 cmdline->name, (char*)(names->at(0)));
826 return(cmd->work(app, cmdline, con));
832 *____________________________________________________________________________
835 cl_console::cl_console(char *fin, char *fout, class cl_app *the_app):
844 if (f= fopen(fin, "r+"), in= f, !f)
845 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
848 if (f= fopen(fout, "w+"), out= f, !f)
849 fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
854 flags|= CONS_INTERACTIVE;
856 dd_printf("Warning: non-interactive console\n");
859 cl_console::cl_console(FILE *fin, FILE *fout, class cl_app *the_app):
870 flags|= CONS_INTERACTIVE;
872 dd_printf("Warning: non-interactive console\n");
876 * use the port number supplied to connect to localhost for
882 connect_to_port(int portnum)
884 int sock= socket(AF_INET,SOCK_STREAM,0);
885 struct sockaddr_in sin;
887 sin.sin_family = AF_INET;
888 sin.sin_port = htons(portnum);
889 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
891 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
892 fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
898 cl_console::cl_console(int portnumber, class cl_app *the_app)
900 int sock= connect_to_port(portnumber);
904 if (!(in= fdopen(sock, "r+")))
905 fprintf(stderr, "cannot open port for input\n");
906 if (!(out= fdopen(sock, "w+")))
907 fprintf(stderr, "cannot open port for output\n");
908 //fprintf(stderr, "init socket done\n");
913 cl_console::init(void)
917 flags&= ~CONS_PROMPT;
922 cl_console::~cl_console(void)
947 cl_console::welcome(void)
951 fprintf(out, "uCsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
952 "uCsim comes with ABSOLUTELY NO WARRANTY; for details type "
954 "This is free software, and you are welcome to redistribute it\n"
955 "under certain conditions; type `show c' for details.\n",
961 cl_console::print_prompt(void)
965 if (flags & (CONS_PROMPT|CONS_FROZEN))
970 if (app->args->arg_avail('P'))
973 fprintf(out, "%s", (prompt && prompt[0])?prompt:
974 ((p= app->args->get_sarg(0, "prompt"))?p:"> "));
979 cl_console::dd_printf(char *format, ...)
986 va_start(ap, format);
987 ret= cmd_do_print(out, format, ap);
994 cl_console::print_bin(long data, int bits)
1000 mask= mask << ((bits >= 1)?(bits-1):0);
1003 fprintf(out, "%c", (data&mask)?'1':'0');
1013 cl_console::match(int fdnum)
1016 fileno(in) == fdnum)
1022 cl_console::get_in_fd(void)
1024 return(in?fileno(in):-1);
1028 cl_console::input_avail(void)
1033 if ((i= get_in_fd()) < 0)
1038 tv.tv_sec= tv.tv_usec= 0;
1039 i= select(i+1, &s, NULL, NULL, &tv);
1044 cl_console::read_line(void)
1049 if (getline(&s, 0, in) < 0)
1053 # ifdef HAVE_GETDELIM
1055 s= (char *)malloc(n);
1056 if (getdelim(&s, &n, '\n', in) < 0)
1064 s= (char *)malloc(300);
1065 if (fgets(s, 300, in) == NULL)
1073 s[strlen(s)-1]= '\0';
1074 if (s[strlen(s)-1] == '\r')
1075 s[strlen(s)-1]= '\0';
1076 flags&= ~CONS_PROMPT;
1081 cl_console::proc_input(class cl_cmdset *cmdset)
1087 fprintf(out, "End\n");
1090 char *cmdstr= read_line();
1093 if (flags & CONS_FROZEN)
1095 app->get_sim()->stop(resUSER);
1096 flags&= ~CONS_FROZEN;
1101 class cl_cmdline *cmdline;
1103 cmdline= new cl_cmdline(app, cmdstr, this);
1105 cm= cmdset->get_cmd(cmdline);
1107 retval= cm->work(app, cmdline, this);
1110 retval= interpret(cmdstr);
1112 //retval= sim->do_cmd(cmd, this);
1120 * Old version, sim->do_cmd() falls into this if it doesn't find a new
1121 * command object which can handle entered command
1125 cl_console::interpret(char *cmd)
1127 fprintf(out, "Unknown command\n");
1133 * This console listen on a socket and can accept connection requests
1137 cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app)
1141 if ((sock= make_server_socket(serverport)) >= 0)
1143 if (listen(sock, 10) < 0)
1144 fprintf(stderr, "Listen on port %d: %s\n",
1145 serverport, strerror(errno));
1151 cl_listen_console::match(int fdnum)
1153 return(sock == fdnum);
1157 cl_listen_console::get_in_fd(void)
1163 cl_listen_console::proc_input(class cl_cmdset *cmdset)
1166 ACCEPT_SOCKLEN_T size;
1167 struct sockaddr_in sock_addr;
1168 class cl_commander *cmd;
1170 cmd= app->get_commander();
1171 size= sizeof(struct sockaddr);
1172 newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
1178 if (!(in= fdopen(newsock, "r+")))
1179 fprintf(stderr, "cannot open port for input\n");
1180 if (!(out= fdopen(newsock, "w+")))
1181 fprintf(stderr, "cannot open port for output\n");
1182 class cl_console *c= cmd->mk_console(in, out);
1183 c->flags|= CONS_INTERACTIVE;
1184 cmd->add_console(c);
1189 #endif /* SOCKET_AVAIL */
1193 * Command interpreter
1194 *____________________________________________________________________________
1197 cl_commander::cl_commander(class cl_app *the_app, class cl_cmdset *acmdset
1198 /*, class cl_sim *asim*/):
1202 cons= new cl_list(1, 1);
1203 actual_console= frozen_console= 0;
1208 cl_commander::init(void)
1212 char *Config= app->args->get_sarg(0, "Config");
1215 class cl_console *con= mk_console(0/*"/dev/tty"*/);
1219 if (app->args->arg_avail('c'))
1220 add_console(mk_console(app->args->get_sarg('c', 0),
1221 app->args->get_sarg('c', 0)));
1223 if (app->args->arg_avail('Z'))
1224 add_console(mk_console(app->args->get_iarg(0, "Zport")));
1225 if (app->args->arg_avail('r'))
1226 add_console(mk_console(app->args->get_iarg('r', 0)));
1228 if (cons->get_count() == 0)
1229 add_console(mk_console(stdin, stdout));
1233 cl_commander::~cl_commander(void)
1240 cl_commander::mk_console(char *fin, char *fout)
1242 return(new cl_console(fin, fout, app));
1246 cl_commander::mk_console(FILE *fin, FILE *fout)
1248 return(new cl_console(fin, fout, app));
1253 cl_commander::mk_console(int portnumber)
1255 return(new cl_listen_console(portnumber, app));
1260 cl_commander::add_console(class cl_console *console)
1268 cl_commander::del_console(class cl_console *console)
1270 cons->disconn(console);
1275 cl_commander::set_fd_set(void)
1279 //fprintf(stderr, "** Setting fd set\n");
1282 for (i= 0; i < cons->count; i++)
1285 class cl_console *c= (class cl_console*)(cons->at(i));
1286 if ((fd= c->get_in_fd()) >= 0)
1288 if ((c->flags & CONS_FROZEN) == 0 ||
1289 (c->flags & CONS_INTERACTIVE) != 0)
1291 FD_SET(fd, &read_set);
1297 ;//fprintf(stderr, "** Skipping console %p\n",c);
1304 * Printing to all consoles
1308 cl_commander::all_printf(char *format, ...)
1313 for (i= 0; i < cons->count; i++)
1315 class cl_console *c= (class cl_console*)(cons->at(i));
1318 va_start(ap, format);
1319 ret= cmd_do_print(c->out, format, ap);
1327 cl_commander::all_print(char *string, int length)
1331 for (i= 0; i < cons->count; i++)
1333 class cl_console *c= (class cl_console*)(cons->at(i));
1336 for (int j= 0; j < length; j++)
1337 putc(string[j], c->out);
1344 * Printing to actual_console
1348 cl_commander::dd_printf(char *format, ...)
1353 if (actual_console &&
1354 actual_console->out)
1356 va_start(ap, format);
1357 ret= cmd_do_print(actual_console->out, format, ap);
1364 * Printing to consoles which have CONS_DEBUG flag set
1368 cl_commander::debug(char *format, ...)
1373 for (i= 0; i < cons->count; i++)
1375 class cl_console *c= (class cl_console*)(cons->at(i));
1377 c->flags & CONS_DEBUG)
1379 va_start(ap, format);
1380 ret= cmd_do_print(c->out, format, ap);
1388 cl_commander::flag_printf(int iflags, char *format, ...)
1393 for (i= 0; i < cons->count; i++)
1395 class cl_console *c= (class cl_console*)(cons->at(i));
1397 (c->flags & iflags) == iflags)
1399 va_start(ap, format);
1400 ret= cmd_do_print(c->out, format, ap);
1408 cl_commander::input_avail(void)
1413 tv.tv_sec= tv.tv_usec= 0;
1414 active_set= read_set;
1415 i= select(fd_num, &active_set, NULL, NULL, &tv);
1420 cl_commander::input_avail_on_frozen(void)
1424 if (!frozen_console)
1426 if ((fd= frozen_console->get_in_fd()) >= 0 &&
1429 return(frozen_console->input_avail());
1433 cl_commander::wait_input(void)
1437 active_set= read_set;
1438 i= select(fd_num, &active_set, NULL, NULL, NULL);
1443 cl_commander::proc_input(void)
1447 for (i= 0; i < fd_num; i++)
1448 if (FD_ISSET(i, &active_set))
1450 class cl_console *c;
1452 for (j= 0; j < cons->count; j++)
1454 c= (class cl_console*)(cons->at(j));
1458 int retval= c->proc_input(cmdset);
1465 return(cons->count == 0);
1473 /* End of cmd.src/newcmd.cc */