2 * Simulator of microcontrollers (cmd.src/newcmdwin32.cc)
\r
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
\r
5 * Copyright (C) 2006, Borut Razem - borut.razem@siol.net
\r
7 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
\r
11 /* This file is part of microcontroller simulator: ucsim.
\r
13 UCSIM is free software; you can redistribute it and/or modify
\r
14 it under the terms of the GNU General Public License as published by
\r
15 the Free Software Foundation; either version 2 of the License, or
\r
16 (at your option) any later version.
\r
18 UCSIM is distributed in the hope that it will be useful,
\r
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
21 GNU General Public License for more details.
\r
23 You should have received a copy of the GNU General Public License
\r
24 along with UCSIM; see the file COPYING. If not, write to the Free
\r
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
\r
29 #include "ddconfig.h"
\r
35 #include <sys/types.h>
\r
36 #include <sys/time.h>
\r
39 #include <windows.h>
\r
41 #include "i_string.h"
\r
43 #include "cmdlexcl.h"
\r
44 #include "cmdpars.h"
\r
47 #include "globals.h"
\r
56 #include "newcmdwin32cl.h"
\r
61 *____________________________________________________________________________
\r
65 cl_channel::set(void)
\r
68 handle = INVALID_HANDLE_VALUE;
\r
73 cl_channel::set(HANDLE _handle, e_handle_type _type)
\r
75 assert(INVALID_HANDLE_VALUE != _handle);
\r
79 type = (_type == CH_UNDEF) ? guess_type() : _type;
\r
83 cl_channel::set(FILE *_fp, e_handle_type _type)
\r
87 handle = (HANDLE)_get_osfhandle(fileno(fp));
\r
88 assert(INVALID_HANDLE_VALUE != handle);
\r
89 type = (_type == CH_UNDEF) ? guess_type() : _type;
\r
93 cl_channel::close(void)
\r
95 assert(INVALID_HANDLE_VALUE != handle);
\r
97 if (CH_SOCKET == type)
\r
99 shutdown((SOCKET)handle, SD_BOTH);
\r
100 closesocket((SOCKET)handle);
\r
104 else if (CH_SOCKET != type)
\r
105 CloseHandle(handle);
\r
108 handle = INVALID_HANDLE_VALUE;
\r
114 *____________________________________________________________________________
\r
117 cl_console::cl_console(char *fin, char *fout, class cl_app *the_app)
\r
124 if (!(f = fopen(fin, "r")))
\r
125 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
\r
126 in.set(f, CH_FILE);
\r
131 if (!(f = fopen(fout, "w")))
\r
132 fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
\r
133 out.set(f, CH_FILE);
\r
139 flags |= CONS_INTERACTIVE;
\r
141 ;//fprintf(stderr, "Warning: non-interactive console\n");
\r
143 lines_printed = new cl_ustrings(100, 100, "console_cache");
\r
146 cl_console::cl_console(FILE *fin, FILE *fout, class cl_app *the_app)
\r
155 flags |= CONS_INTERACTIVE;
\r
157 ;//fprintf(stderr, "Warning: non-interactive console\n");
\r
159 lines_printed = new cl_ustrings(100, 100, "console_cache");
\r
162 cl_console::cl_console(cl_channel _in, cl_channel _out, class cl_app *the_app)
\r
171 flags |= CONS_INTERACTIVE;
\r
173 ;//fprintf(stderr, "Warning: non-interactive console\n");
\r
175 lines_printed= new cl_ustrings(100, 100, "console_cache");
\r
179 cl_console::clone_for_exec(char *fin)
\r
185 if (!(fi = fopen(fin, "r")))
\r
187 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
\r
190 cl_channel ch_in = cl_channel(fi, CH_FILE);
\r
191 class cl_console *con= new cl_sub_console(this, ch_in, out, app);
\r
195 cl_console::~cl_console(void)
\r
197 if (CH_UNDEF != in.get_type())
\r
200 if (CH_UNDEF != out.get_type())
\r
202 if (flags & CONS_PROMPT)
\r
206 delete prompt_option;
\r
207 delete null_prompt_option;
\r
208 delete debug_option;
\r
217 cl_console::redirect(char *fname, char *mode)
\r
219 FILE *fp = fopen(fname, mode);
\r
221 dd_printf("Unable to open file '%s' for %s: %s\n",
\r
222 fname, (mode[0]=='w') ? "write" : "append", strerror(errno));
\r
223 out.set(fp, CH_FILE);
\r
227 cl_console::un_redirect(void)
\r
229 if (CH_UNDEF != rout.get_type())
\r
234 cl_console::cmd_do_print(char *format, va_list ap)
\r
236 FILE *f = get_out()->get_fp();
\r
240 int ret = vfprintf(f, format, ap);
\r
253 cl_console::read_line(void)
\r
255 #define BUF_LEN 1024
\r
257 TRACE("%d-%s\n", get_id(), __PRETTY_FUNCTION__);
\r
260 FILE *fp = in.get_fp();
\r
263 #ifdef HAVE_GETLINE
\r
264 if (getline(&s, 0, fp) < 0)
\r
266 #elif defined HAVE_GETDELIM
\r
267 size_t n = BUF_LEN;
\r
268 s = (char *)malloc(n);
\r
269 if (getdelim(&s, &n, '\n', fp) < 0)
\r
274 #elif defined HAVE_FGETS
\r
275 s = (char *)malloc(BUF_LEN);
\r
276 if (fgets(s, BUF_LEN, fp) == NULL)
\r
282 s[strlen(s)-1]= '\0';
\r
283 if (s[strlen(s)-1] == '\r')
\r
284 s[strlen(s)-1]= '\0';
\r
285 flags&= ~CONS_PROMPT;
\r
291 * This console cl_listen_console on a socket and can accept connection requests
\r
294 cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app)
\r
299 if (INVALID_SOCKET != (sock = make_server_socket(serverport)))
\r
301 if (SOCKET_ERROR == listen(sock, 10))
\r
302 fprintf(stderr, "Can't listen on port %d: %d\n", serverport, WSAGetLastError());
\r
304 in.set((HANDLE)sock, CH_SOCKET);
\r
308 cl_listen_console::proc_input(class cl_cmdset *cmdset)
\r
310 class cl_commander_base *cmd = app->get_commander();
\r
312 struct sockaddr_in sock_addr;
\r
313 ACCEPT_SOCKLEN_T size = sizeof(struct sockaddr);
\r
314 SOCKET newsock = accept((SOCKET)get_in_fd(), (struct sockaddr*)&sock_addr, &size);
\r
316 if (INVALID_SOCKET == newsock)
\r
318 fprintf(stderr, "Can't accept: %d\n", WSAGetLastError());
\r
322 int fh = _open_osfhandle((intptr_t)newsock, _O_TEXT);
\r
325 fprintf(stderr, "Can't _open_osfhandle\n");
\r
327 FILE *fp = fdopen(fh, "r");
\r
329 fprintf(stderr, "Can't open port for input\n");
\r
330 cl_channel ch_in = cl_channel(fp, CH_SOCKET);
\r
332 fh = _open_osfhandle((intptr_t)newsock, _O_TEXT);
\r
335 fprintf(stderr, "Can't _open_osfhandle\n");
\r
337 fp = fdopen(fh, "w");
\r
339 fprintf(stderr, "Can't open port for output\n");
\r
340 cl_channel ch_out = cl_channel(fp, CH_SOCKET);
\r
342 class cl_console_base *c = new cl_console(ch_in, ch_out, app);
\r
343 c->flags |= CONS_INTERACTIVE;
\r
344 cmd->add_console(c);
\r
354 cl_sub_console::cl_sub_console(class cl_console_base *the_parent,
\r
355 cl_channel _in, cl_channel _out, class cl_app *the_app):
\r
356 cl_console(_in, _out, the_app)
\r
358 parent = the_parent;
\r
361 cl_sub_console::~cl_sub_console(void)
\r
363 class cl_commander_base *c = app->get_commander();
\r
367 c->activate_console(parent);
\r
372 cl_sub_console::init(void)
\r
374 class cl_commander_base *c = app->get_commander();
\r
378 c->deactivate_console(parent);
\r
380 cl_console::init();
\r
381 flags |= CONS_ECHO;
\r
387 * Command interpreter
\r
388 *____________________________________________________________________________
\r
392 cl_commander::init(void)
\r
394 TRACE("%s\n", __PRETTY_FUNCTION__);
\r
396 class cl_optref console_on_option(this);
\r
397 class cl_optref config_file_option(this);
\r
398 class cl_optref port_number_option(this);
\r
399 class cl_console_base *con;
\r
401 console_on_option.init();
\r
402 console_on_option.use("console_on");
\r
403 config_file_option.init();
\r
404 config_file_option.use("config_file");
\r
405 port_number_option.init();
\r
408 set_name("Commander");
\r
410 bool need_config = DD_TRUE;
\r
412 if (port_number_option.use("port_number"))
\r
413 add_console(new cl_listen_console(port_number_option.get_value((long)0), app));
\r
415 /* The following code is commented out because it produces gcc warnings
\r
416 * newcmd.cc: In member function `virtual int cl_commander::init()':
\r
417 * newcmd.cc:785: warning: 'Config' might be used uninitialized in this function
\r
418 * newcmd.cc:786: warning: 'cn' might be used uninitialized in this function
\r
421 char *Config= config_file_option.get_value(Config);
\r
422 char *cn= console_on_option.get_value(cn);
\r
424 /* Here shoud probably be something else, but is still better then the former code... */
\r
425 char *Config = config_file_option.get_value("");
\r
426 char *cn = console_on_option.get_value("");
\r
430 add_console(con = new cl_console(cn, cn, app));
\r
431 exec_on(con, Config);
\r
432 need_config = DD_FALSE;
\r
434 if (cons->get_count() == 0)
\r
436 add_console(con = new cl_console(stdin, stdout, app));
\r
437 exec_on(con, Config);
\r
438 need_config = DD_FALSE;
\r
440 if (need_config && Config && *Config)
\r
442 FILE *fc = fopen(Config, "r");
\r
444 fprintf(stderr, "Can't open `%s': %s\n", Config, strerror(errno));
\r
447 con = new cl_console(fc, stderr, app);
\r
448 con->flags |= CONS_NOWELCOME | CONS_ECHO;
\r
456 cl_commander::set_fd_set(void)
\r
458 TRACE("%s\n", __PRETTY_FUNCTION__);
\r
462 FD_ZERO(&read_set);
\r
464 for (i = 0; i < cons->count; i++)
\r
466 class cl_console *c= dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(i)));
\r
468 if (c->input_active() && CH_SOCKET == c->in.get_type())
\r
470 HANDLE fd = c->get_in_fd();
\r
471 assert(INVALID_HANDLE_VALUE != fd);
\r
473 FD_SET((SOCKET)fd, &read_set);
\r
479 cl_commander::console_count(void)
\r
483 for (int j = 0; j < cons->count; j++)
\r
485 class cl_console *c = dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(j)));
\r
487 if (c->input_active())
\r
489 switch (c->in.get_type())
\r
507 cl_commander::console_input_avail(void)
\r
511 FD_ZERO(&console_active_set);
\r
512 for (int j = 0; j < cons->count; j++)
\r
514 class cl_console *c = dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(j)));
\r
516 if (c->input_avail())
\r
518 HANDLE fd = c->get_in_fd();
\r
519 assert(INVALID_HANDLE_VALUE != fd);
\r
521 switch (c->in.get_type())
\r
526 FD_SET((SOCKET)fd, &console_active_set);
\r
540 cl_commander::socket_input_avail(long timeout, bool sleep)
\r
542 active_set = read_set;
\r
544 if (active_set.fd_count)
\r
546 struct timeval tv = {0, 0};
\r
548 struct timeval *tvp = sleep ? NULL : &tv;
\r
550 int i = select(0, &active_set, NULL, NULL, tvp);
\r
551 if (SOCKET_ERROR == i)
\r
553 fprintf(stderr, "Can't select: %d\n", WSAGetLastError());
\r
561 Sleep(timeout / 1000);
\r
567 cl_commander::input_avail_timeout(long timeout)
\r
569 TRACE("%s\n", __PRETTY_FUNCTION__);
\r
572 if (0 != (n = console_input_avail()))
\r
573 FD_ZERO(&active_set);
\r
575 n = socket_input_avail(timeout, false);
\r
580 #define CONSOLE_TIMEOUT 300000
\r
583 cl_commander::wait_input(void)
\r
585 TRACE("%s\n", __PRETTY_FUNCTION__);
\r
589 if (0 < console_count())
\r
593 while (0 == (n = input_avail_timeout(CONSOLE_TIMEOUT)))
\r
600 FD_ZERO(&console_active_set);
\r
601 return socket_input_avail(0, true);
\r
606 cl_commander::proc_input(void)
\r
608 TRACE("%s\n", __PRETTY_FUNCTION__);
\r
610 for (int j = 0; j < cons->count; j++)
\r
612 class cl_console *c = dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(j)));
\r
614 if (c->input_active())
\r
616 HANDLE fd = c->get_in_fd();
\r
617 assert(INVALID_HANDLE_VALUE != fd);
\r
619 if (FD_ISSET(fd, &active_set) || FD_ISSET(fd, &console_active_set))
\r
621 actual_console = c;
\r
622 if (c->proc_input(cmdset))
\r
627 actual_console = 0;
\r
628 return 0 == cons->count;
\r
636 /* End of cmd.src/newcmdwin32.cc */
\r