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>
60 extern "C" int vasprintf(char **strp, const char *format, va_list ap);
61 extern "C" int vsnprintf(char *str, size_t size,const char *format,va_list ap);
64 cmd_do_print(FILE *f, char *format, va_list ap)
69 vasprintf(&msg, format, ap);
70 ret= fprintf(f, "%s", msg);
73 # ifdef HAVE_VSNPRINTF
75 vsnprintf(msg, 80*25, format, ap);
76 ret= fprintf(f, "%s", msg);
80 vsprintf(msg, format, ap); /* Dangerous */
81 ret= fprintf(f, "%s", msg);
85 /*strcpy(msg, "Unimplemented printf has called.\n");*/
87 /*strcpy(msg, "printf can not be implemented, upgrade your libc.\n");*/
99 *____________________________________________________________________________
102 cl_cmdline::cl_cmdline(char *acmd, class cl_console *acon)
105 params= new cl_list(2, 2);
106 tokens= new cl_ustrings(2, 2);
112 cl_cmdline::~cl_cmdline(void)
123 cl_cmdline::init(void)
130 cl_cmdline::skip_delims(char *start)
133 strchr(" \t\v\r,", *start))
139 cl_cmdline::split(void)
148 start+= strspn(start, " \t\v\r,");
152 name= (char*)malloc(2);
158 i= strcspn(start, " \t\v\r,");
161 name= (char*)malloc(i+1);
162 strncpy(name, start, i);
166 start= skip_delims(start);
170 char *end, *param_str;
191 con->printf("Unterminated string\n");
192 param_str= (char *)malloc(end-start+2);
193 strncpy(param_str, start, 1+end-start);
194 param_str[1+end-start]= '\0';
195 tokens->add(strdup(param_str));
196 params->add(con->sim->mk_cmd_str_arg(param_str));
206 i= strcspn(start, " \t\v\r,");
208 param_str= (char *)malloc(i+1);
209 strncpy(param_str, start, i);
211 tokens->add(strdup(param_str));
212 if ((dot= strchr(param_str, '.')) != NULL)
215 class cl_cmd_arg *sfr, *bit;
218 if (strchr("0123456789", *param_str) != NULL)
219 sfr= con->sim->mk_cmd_int_arg((long long)
220 strtol(param_str, 0, 0));
222 sfr= con->sim->mk_cmd_sym_arg(param_str);
226 con->printf("Uncomplete bit address\n");
231 if (strchr("0123456789", *dot) != NULL)
232 bit= con->sim->mk_cmd_int_arg((long long)
235 bit= con->sim->mk_cmd_sym_arg(dot);
236 params->add(con->sim->mk_cmd_bit_arg(sfr, bit));
239 else if ((dot= strchr(param_str, '[')) != NULL)
242 class cl_cmd_arg *aname, *aindex;
245 if (strchr("0123456789", *param_str) != NULL)
246 aname= con->sim->mk_cmd_int_arg((long long)
247 strtol(param_str, 0, 0));
249 aname= con->sim->mk_cmd_sym_arg(param_str);
253 con->printf("Uncomplete array\n");
258 p= dot + strlen(dot) - 1;
267 if (strlen(dot) == 0)
269 con->printf("Uncomplete array index\n");
274 if (strchr("0123456789", *dot) != NULL)
275 aindex= con->sim->mk_cmd_int_arg((long long)
278 aindex= con->sim->mk_cmd_sym_arg(dot);
279 params->add(con->sim->mk_cmd_array_arg(aname, aindex));
283 else if (strchr("0123456789", *param_str) != NULL)
286 params->add(con->sim->mk_cmd_int_arg((long long)
287 strtol(param_str, 0, 0)));
292 params->add(con->sim->mk_cmd_sym_arg(param_str));
297 start= skip_delims(start);
303 cl_cmdline::shift(void)
305 char *s= skip_delims(cmd);
312 strchr(" \t\v\r,", *s) == NULL)
319 params= new cl_list(2, 2);
322 return(name && *name);
326 cl_cmdline::repeat(void)
333 cl_cmdline::param(int num)
335 if (num >= params->count)
337 return((class cl_cmd_arg *)(params->at(num)));
341 cl_cmdline::insert_param(int pos, class cl_cmd_arg *param)
343 if (pos >= params->count)
346 params->add_at(pos, param);
350 cl_cmdline::syntax_match(class cl_sim *sim, char *syntax)
357 matched_syntax= syntax;
362 //printf("syntax %s?\n",syntax);
365 class cl_cmd_arg *parm= (class cl_cmd_arg *)(params->at(iparam));
369 //printf("Checking %s as %c\n",parm->get_svalue(),*p);
373 if (!parm->as_address())
375 //printf("ADDRESS match %lx\n",parm->value.address);
378 if (!parm->as_number())
382 if (!parm->as_data())
386 if (!parm->as_memory())
388 //printf("MEMORY match %s\n",parm->value.memory->class_name);
391 if (!parm->as_hw(sim->uc))
395 if (!parm->as_string())
399 if (!set_data_list(parm, &iparam))
403 if (!parm->as_bit(sim->uc))
411 if (iparam < params->count)
412 parm= (class cl_cmd_arg *)(params->at(iparam));
419 matched_syntax= syntax;
426 cl_cmdline::set_data_list(class cl_cmd_arg *parm, int *iparm)
428 class cl_cmd_arg *next_parm;
434 for (i= *iparm, next_parm= param(i); next_parm; i++, next_parm= param(i))
436 if (next_parm->is_string())
440 //s= proc_escape(next_parm->get_svalue(), &l);
441 if (!next_parm->as_string())
443 s= next_parm->value.string.string;
444 l= next_parm->value.string.len;
446 array= (t_mem*)malloc(sizeof(t_mem)*l);
448 array= (t_mem*)realloc(array, sizeof(t_mem)*(l+len));
449 for (j= 0; j < l; j++)
459 if (!next_parm->as_data())
466 array= (t_mem*)malloc(sizeof(t_mem));
468 array= (t_mem*)realloc(array, sizeof(t_mem)*(1+len));
469 array[len]= next_parm->value.data;
474 parm->value.data_list.array= array;
475 parm->value.data_list.len= len;
482 *____________________________________________________________________________
485 cl_cmd::cl_cmd(//class cl_sim *asim,
493 names= new cl_strings(1, 1);
494 names->add(aname?strdup(aname):strdup("unknown"));
496 short_help= short_hlp?strdup(short_hlp):NULL;
497 long_help= long_hlp?strdup(long_hlp):NULL;
500 /*cl_cmd::cl_cmd(class cl_sim *asim):
504 name= short_help= long_help= 0;
508 cl_cmd::~cl_cmd(void)
518 cl_cmd::add_name(char *name)
521 names->add(strdup(name));
525 cl_cmd::name_match(char *aname, int strict)
529 if (names->count == 0 &&
536 for (i= 0; i < names->count; i++)
538 char *n= (char*)(names->at(i));
539 if (strcmp(aname, n) == 0)
545 for (i= 0; i < names->count; i++)
547 char *n= (char*)(names->at(i));
548 if (strstr(n, aname) == n)
556 cl_cmd::name_match(class cl_cmdline *cmdline, int strict)
558 return(name_match(cmdline->name, strict));
562 cl_cmd::syntax_ok(class cl_cmdline *cmdline)
568 cl_cmd::work(class cl_sim *sim,
569 class cl_cmdline *cmdline, class cl_console *con)
571 if (!syntax_ok(cmdline))
573 return(do_work(sim, cmdline, con));
577 cl_cmd::do_work(class cl_sim *sim,
578 class cl_cmdline *cmdline, class cl_console *con)
580 con->printf("Command \"%s\" does nothing.\n", (char*)(names->at(0)));
587 *____________________________________________________________________________
590 cl_cmdset::cl_cmdset(class cl_sim *asim):
598 cl_cmdset::get_cmd(class cl_cmdline *cmdline)
602 if (cmdline->repeat())
605 return(last_command);
610 for (i= 0; i < count; i++)
612 class cl_cmd *c= (class cl_cmd *)at(i);
613 if (c->name_match(cmdline, 1))
617 class cl_cmd *c_matched= 0;
618 for (i= 0; i < count; i++)
620 class cl_cmd *c= (class cl_cmd *)at(i);
621 if (c->name_match(cmdline, 0))
634 cl_cmdset::get_cmd(char *cmd_name)
638 for (i= 0; i < count; i++)
640 class cl_cmd *c= (class cl_cmd *)at(i);
641 if (c->name_match(cmd_name, 1))
648 cl_cmdset::del(char *name)
654 for (i= 0; i < count; i++)
656 class cl_cmd *cmd= (class cl_cmd *)(at(i));
657 if (cmd->name_match(name, 1))
663 cl_cmdset::replace(char *name, class cl_cmd *cmd)
669 for (i= 0; i < count; i++)
671 class cl_cmd *c= (class cl_cmd *)(at(i));
672 if (c->name_match(name, 1))
682 * Composed command: subset of commands
683 *____________________________________________________________________________
686 cl_super_cmd::cl_super_cmd(//class cl_sim *asim,
691 class cl_cmdset *acommands):
692 cl_cmd(aname, can_rep, short_hlp, long_hlp)
697 cl_super_cmd::~cl_super_cmd(void)
704 cl_super_cmd::work(class cl_sim *sim,
705 class cl_cmdline *cmdline, class cl_console *con)
707 class cl_cmd *cmd= 0;
712 if (!cmdline->shift())
714 if ((cmd= commands->get_cmd("_no_parameters_")) != 0)
715 return(cmd->work(sim, cmdline, con));
717 con->printf("\"%s\" must be followed by the name of a subcommand\n"
718 "List of subcommands:\n", (char*)(names->at(0)));
719 for (i= 0; i < commands->count; i++)
721 cmd= (class cl_cmd *)(commands->at(i));
722 con->printf("%s\n", cmd->short_help);
726 if ((cmd= commands->get_cmd(cmdline)) == NULL)
728 con->printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
729 cmdline->name, (char*)(names->at(0)));
732 return(cmd->work(sim, cmdline, con));
738 *____________________________________________________________________________
741 cl_console::cl_console(char *fin, char *fout, class cl_sim *asim):
750 if (f= fopen(fin, "r+"), in= f, !f)
751 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
754 if (f= fopen(fout, "w+"), out= f, !f)
755 fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
760 flags|= CONS_INTERACTIVE;
762 printf("Warning: non-interactive console\n");
765 cl_console::cl_console(FILE *fin, FILE *fout, class cl_sim *asim):
776 flags|= CONS_INTERACTIVE;
778 printf("Warning: non-interactive console\n");
782 * use the port number supplied to connect to localhost for
788 connect_to_port(int portnum)
790 int sock= socket(AF_INET,SOCK_STREAM,0);
791 struct sockaddr_in sin;
793 sin.sin_family = AF_INET;
794 sin.sin_port = htons(portnum);
795 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
797 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
798 fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
804 cl_console::cl_console(int portnumber, class cl_sim *asim)
806 int sock= connect_to_port(portnumber);
810 if (!(in= fdopen(sock, "r+")))
811 fprintf(stderr, "cannot open port for input\n");
812 if (!(out= fdopen(sock, "w+")))
813 fprintf(stderr, "cannot open port for output\n");
814 //fprintf(stderr, "init socket done\n");
819 cl_console::init(void)
823 flags&= ~CONS_PROMPT;
828 cl_console::~cl_console(void)
853 cl_console::welcome(void)
857 fprintf(out, "ucsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
858 "ucsim comes with ABSOLUTELY NO WARRANTY; for details type "
860 "This is free software, and you are welcome to redistribute it\n"
861 "under certain conditions; type `show c' for details.\n",
867 cl_console::print_prompt(void)
871 if (flags & (CONS_PROMPT|CONS_FROZEN))
876 if (sim->arg_avail('P'))
879 fprintf(out, "%s", (prompt && prompt[0])?prompt:
880 ((p= sim->get_sarg(0, "prompt"))?p:"> "));
885 cl_console::printf(char *format, ...)
892 va_start(ap, format);
893 ret= cmd_do_print(out, format, ap);
900 cl_console::print_bin(long data, int bits)
906 mask= mask << ((bits >= 1)?(bits-1):0);
909 fprintf(out, "%c", (data&mask)?'1':'0');
919 cl_console::match(int fdnum)
928 cl_console::get_in_fd(void)
930 return(in?fileno(in):-1);
934 cl_console::input_avail(void)
939 if ((i= get_in_fd()) < 0)
944 tv.tv_sec= tv.tv_usec= 0;
945 i= select(i+1, &s, NULL, NULL, &tv);
950 cl_console::read_line(void)
955 if (getline(&s, 0, in) < 0)
959 # ifdef HAVE_GETDELIM
961 s= (char *)malloc(n);
962 if (getdelim(&s, &n, '\n', in) < 0)
970 s= (char *)malloc(300);
971 if (fgets(s, 300, in) == NULL)
979 s[strlen(s)-1]= '\0';
980 if (s[strlen(s)-1] == '\r')
981 s[strlen(s)-1]= '\0';
982 flags&= ~CONS_PROMPT;
987 cl_console::proc_input(class cl_cmdset *cmdset)
993 fprintf(out, "End\n");
996 char *cmdstr= read_line();
999 if (flags & CONS_FROZEN)
1002 flags&= ~CONS_FROZEN;
1007 class cl_cmdline *cmdline;
1009 cmdline= new cl_cmdline(cmdstr, this);
1011 cm= cmdset->get_cmd(cmdline);
1013 retval= cm->work(sim, cmdline, this);
1016 retval= interpret(cmdstr);
1018 //retval= sim->do_cmd(cmd, this);
1026 * Old version, sim->do_cmd() falls into this if it doesn't find a new
1027 * command object which can handle entered command
1031 cl_console::interpret(char *cmd)
1033 fprintf(out, "New interpreter does not known this command\n");
1039 * This console listen on a socket and can accept connection requests
1043 cl_listen_console::cl_listen_console(int serverport, class cl_sim *asim)
1047 if ((sock= make_server_socket(serverport)) >= 0)
1049 if (listen(sock, 10) < 0)
1050 fprintf(stderr, "Listen on port %d: %s\n",
1051 serverport, strerror(errno));
1057 cl_listen_console::match(int fdnum)
1059 return(sock == fdnum);
1063 cl_listen_console::get_in_fd(void)
1069 cl_listen_console::proc_input(class cl_cmdset *cmdset)
1072 ACCEPT_SOCKLEN_T size;
1073 struct sockaddr_in sock_addr;
1075 size= sizeof(struct sockaddr);
1076 newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
1082 if (!(in= fdopen(newsock, "r+")))
1083 fprintf(stderr, "cannot open port for input\n");
1084 if (!(out= fdopen(newsock, "w+")))
1085 fprintf(stderr, "cannot open port for output\n");
1086 class cl_console *c= sim->cmd->mk_console(in, out, sim);
1087 c->flags|= CONS_INTERACTIVE;
1089 sim->cmd->add_console(c);
1094 #endif /* SOCKET_AVAIL */
1098 * Command interpreter
1099 *____________________________________________________________________________
1102 cl_commander::cl_commander(class cl_cmdset *acmdset, class cl_sim *asim):
1105 cons= new cl_list(1, 1);
1106 actual_console= frozen_console= 0;
1112 cl_commander::init(void)
1117 if (sim->arg_avail('c'))
1118 add_console(mk_console(sim->get_sarg('c', 0),
1119 sim->get_sarg('c', 0), sim));
1121 if (sim->arg_avail('Z'))
1122 add_console(mk_console(sim->get_iarg(0, "Zport"), sim));
1123 if (sim->arg_avail('r'))
1124 add_console(mk_console(sim->get_iarg('r', 0), sim));
1126 if (cons->get_count() == 0)
1127 add_console(mk_console(stdin, stdout, sim));
1131 cl_commander::~cl_commander(void)
1138 cl_commander::mk_console(char *fin, char *fout, class cl_sim *asim)
1140 return(new cl_console(fin, fout, asim));
1144 cl_commander::mk_console(FILE *fin, FILE *fout, class cl_sim *asim)
1146 return(new cl_console(fin, fout, asim));
1151 cl_commander::mk_console(int portnumber, class cl_sim *asim)
1153 return(new cl_listen_console(portnumber, asim));
1158 cl_commander::add_console(class cl_console *console)
1166 cl_commander::del_console(class cl_console *console)
1168 cons->disconn(console);
1173 cl_commander::set_fd_set(void)
1177 //fprintf(stderr, "** Setting fd set\n");
1180 for (i= 0; i < cons->count; i++)
1183 class cl_console *c= (class cl_console*)(cons->at(i));
1184 if ((fd= c->get_in_fd()) >= 0)
1186 if ((c->flags & CONS_FROZEN) == 0 ||
1187 (c->flags & CONS_INTERACTIVE) != 0)
1189 FD_SET(fd, &read_set);
1195 ;//fprintf(stderr, "** Skipping console %p\n",c);
1202 * Printing to all consoles
1206 cl_commander::all_printf(char *format, ...)
1211 for (i= 0; i < cons->count; i++)
1213 class cl_console *c= (class cl_console*)(cons->at(i));
1216 va_start(ap, format);
1217 ret= cmd_do_print(c->out, format, ap);
1225 cl_commander::all_print(char *string, int length)
1229 for (i= 0; i < cons->count; i++)
1231 class cl_console *c= (class cl_console*)(cons->at(i));
1234 for (int j= 0; j < length; j++)
1235 putc(string[j], c->out);
1242 * Printing to actual_console
1246 cl_commander::printf(char *format, ...)
1251 if (actual_console &&
1252 actual_console->out)
1254 va_start(ap, format);
1255 ret= cmd_do_print(actual_console->out, format, ap);
1262 * Printing to consoles which have CONS_DEBUG flag set
1266 cl_commander::debug(char *format, ...)
1271 for (i= 0; i < cons->count; i++)
1273 class cl_console *c= (class cl_console*)(cons->at(i));
1275 c->flags & CONS_DEBUG)
1277 va_start(ap, format);
1278 ret= cmd_do_print(c->out, format, ap);
1286 cl_commander::flag_printf(int iflags, char *format, ...)
1291 for (i= 0; i < cons->count; i++)
1293 class cl_console *c= (class cl_console*)(cons->at(i));
1295 (c->flags & iflags) == iflags)
1297 va_start(ap, format);
1298 ret= cmd_do_print(c->out, format, ap);
1306 cl_commander::input_avail(void)
1311 tv.tv_sec= tv.tv_usec= 0;
1312 active_set= read_set;
1313 i= select(fd_num, &active_set, NULL, NULL, &tv);
1318 cl_commander::input_avail_on_frozen(void)
1322 if (!frozen_console)
1324 if ((fd= frozen_console->get_in_fd()) >= 0 &&
1327 return(frozen_console->input_avail());
1331 cl_commander::wait_input(void)
1335 active_set= read_set;
1336 i= select(fd_num, &active_set, NULL, NULL, NULL);
1341 cl_commander::proc_input(void)
1345 for (i= 0; i < fd_num; i++)
1346 if (FD_ISSET(i, &active_set))
1348 class cl_console *c;
1350 for (j= 0; j < cons->count; j++)
1352 c= (class cl_console*)(cons->at(j));
1356 int retval= c->proc_input(cmdset);
1363 return(cons->count == 0);
1371 /* End of cmd.src/newcmd.cc */