PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/sim/ucsim/cmd.src/newcmdwin32.cc

http://github.com/darconeous/sdcc
C++ | 633 lines | 465 code | 104 blank | 64 comment | 86 complexity | 3a1e52cbd3d4024b1fe1176b4c76c620 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-2.0
  1. /*
  2. * Simulator of microcontrollers (cmd.src/newcmdwin32.cc)
  3. *
  4. * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
  5. * Copyright (C) 2006, Borut Razem - borut.razem@siol.net
  6. *
  7. * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
  8. *
  9. */
  10. /* This file is part of microcontroller simulator: ucsim.
  11. UCSIM is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2 of the License, or
  14. (at your option) any later version.
  15. UCSIM is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with UCSIM; see the file COPYING. If not, write to the Free
  21. Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  22. 02111-1307, USA. */
  23. /*@1@*/
  24. #include "ddconfig.h"
  25. #include <stdio.h>
  26. #include <errno.h>
  27. #include <stdarg.h>
  28. #include <stdlib.h>
  29. #include <sys/types.h>
  30. #include <sys/time.h>
  31. #include <assert.h>
  32. #include <fcntl.h>
  33. #include <windows.h>
  34. #include "i_string.h"
  35. // prj
  36. #include "globals.h"
  37. #include "utils.h"
  38. // sim
  39. #include "simcl.h"
  40. #include "argcl.h"
  41. #include "appcl.h"
  42. // local
  43. #include "newcmdwin32cl.h"
  44. /*
  45. * Channel
  46. *____________________________________________________________________________
  47. */
  48. inline void
  49. cl_channel::set(void)
  50. {
  51. fp = 0;
  52. handle = INVALID_HANDLE_VALUE;
  53. type = CH_UNDEF;
  54. }
  55. inline void
  56. cl_channel::set(HANDLE _handle, e_handle_type _type)
  57. {
  58. assert(INVALID_HANDLE_VALUE != _handle);
  59. fp = 0;
  60. handle = _handle;
  61. type = (_type == CH_UNDEF) ? guess_type() : _type;
  62. }
  63. inline void
  64. cl_channel::set(FILE *_fp, e_handle_type _type)
  65. {
  66. assert(_fp);
  67. fp = _fp;
  68. handle = (HANDLE)_get_osfhandle(fileno(fp));
  69. assert(INVALID_HANDLE_VALUE != handle);
  70. type = (_type == CH_UNDEF) ? guess_type() : _type;
  71. }
  72. void
  73. cl_channel::close(void)
  74. {
  75. assert(INVALID_HANDLE_VALUE != handle);
  76. if (CH_SOCKET == type)
  77. {
  78. shutdown((SOCKET)handle, SD_BOTH);
  79. closesocket((SOCKET)handle);
  80. }
  81. if (fp)
  82. fclose(fp);
  83. else if (CH_SOCKET != type)
  84. CloseHandle(handle);
  85. fp = 0;
  86. handle = INVALID_HANDLE_VALUE;
  87. type = CH_UNDEF;
  88. }
  89. /*
  90. * Command console
  91. *____________________________________________________________________________
  92. */
  93. cl_console::cl_console(const char *fin, const char *fout, class cl_app *the_app)
  94. {
  95. FILE *f;
  96. app = the_app;
  97. if (fin)
  98. {
  99. if (!(f = fopen(fin, "r")))
  100. fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
  101. in.set(f, CH_FILE);
  102. }
  103. if (fout)
  104. {
  105. if (!(f = fopen(fout, "w")))
  106. fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
  107. out.set(f, CH_FILE);
  108. }
  109. prompt = 0;
  110. flags = CONS_NONE;
  111. if (in.is_tty())
  112. flags |= CONS_INTERACTIVE;
  113. else
  114. ;//fprintf(stderr, "Warning: non-interactive console\n");
  115. id = 0;
  116. lines_printed = new cl_ustrings(100, 100, "console_cache");
  117. }
  118. cl_console::cl_console(FILE *fin, FILE *fout, class cl_app *the_app)
  119. {
  120. app = the_app;
  121. in.set(fin);
  122. out.set(fout);
  123. prompt = 0;
  124. flags = CONS_NONE;
  125. if (in.is_tty())
  126. flags |= CONS_INTERACTIVE;
  127. else
  128. ;//fprintf(stderr, "Warning: non-interactive console\n");
  129. id = 0;
  130. lines_printed = new cl_ustrings(100, 100, "console_cache");
  131. }
  132. cl_console::cl_console(cl_channel _in, cl_channel _out, class cl_app *the_app)
  133. {
  134. app = the_app;
  135. in = _in;
  136. out = _out;
  137. prompt = 0;
  138. flags = CONS_NONE;
  139. if (in.is_tty())
  140. flags |= CONS_INTERACTIVE;
  141. else
  142. ;//fprintf(stderr, "Warning: non-interactive console\n");
  143. id = 0;
  144. lines_printed= new cl_ustrings(100, 100, "console_cache");
  145. }
  146. class cl_console *
  147. cl_console::clone_for_exec(char *fin)
  148. {
  149. FILE *fi;
  150. if (!fin)
  151. return 0;
  152. if (!(fi = fopen(fin, "r")))
  153. {
  154. fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
  155. return 0;
  156. }
  157. cl_channel ch_in = cl_channel(fi, CH_FILE);
  158. class cl_console *con= new cl_sub_console(this, ch_in, out, app);
  159. return con;
  160. }
  161. cl_console::~cl_console(void)
  162. {
  163. if (CH_UNDEF != in.get_type())
  164. in.close();
  165. un_redirect();
  166. if (CH_UNDEF != out.get_type())
  167. {
  168. if (flags & CONS_PROMPT)
  169. dd_printf("\n");
  170. out.close();
  171. }
  172. delete prompt_option;
  173. delete null_prompt_option;
  174. delete debug_option;
  175. }
  176. /*
  177. * Output functions
  178. */
  179. void
  180. cl_console::redirect(char *fname, char *mode)
  181. {
  182. FILE *fp = fopen(fname, mode);
  183. if (!fp)
  184. dd_printf("Unable to open file '%s' for %s: %s\n",
  185. fname, (mode[0]=='w') ? "write" : "append", strerror(errno));
  186. out.set(fp, CH_FILE);
  187. }
  188. void
  189. cl_console::un_redirect(void)
  190. {
  191. if (CH_UNDEF != rout.get_type())
  192. out.close();
  193. }
  194. int
  195. cl_console::cmd_do_print(const char *format, va_list ap)
  196. {
  197. FILE *f = get_out()->get_fp();
  198. if (f)
  199. {
  200. int ret = vfprintf(f, format, ap);
  201. fflush(f);
  202. return ret;
  203. }
  204. else
  205. return 0;
  206. }
  207. /*
  208. * Input functions
  209. */
  210. char *
  211. cl_console::read_line(void)
  212. {
  213. #define BUF_LEN 1024
  214. TRACE("%d-%s\n", get_id(), __PRETTY_FUNCTION__);
  215. char *s = NULL;
  216. FILE *fp = in.get_fp();
  217. assert(fp);
  218. #ifdef HAVE_GETLINE
  219. if (getline(&s, 0, fp) < 0)
  220. return(0);
  221. #elif defined HAVE_GETDELIM
  222. size_t n = BUF_LEN;
  223. s = (char *)malloc(n);
  224. if (getdelim(&s, &n, '\n', fp) < 0)
  225. {
  226. free(s);
  227. return(0);
  228. }
  229. #elif defined HAVE_FGETS
  230. s = (char *)malloc(BUF_LEN);
  231. if (fgets(s, BUF_LEN, fp) == NULL)
  232. {
  233. free(s);
  234. return(0);
  235. }
  236. #endif
  237. s[strlen(s)-1]= '\0';
  238. if (s[strlen(s)-1] == '\r')
  239. s[strlen(s)-1]= '\0';
  240. flags&= ~CONS_PROMPT;
  241. return(s);
  242. }
  243. /*
  244. * This console cl_listen_console on a socket and can accept connection requests
  245. */
  246. cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app)
  247. {
  248. SOCKET sock;
  249. app = the_app;
  250. if (INVALID_SOCKET != (sock = make_server_socket(serverport)))
  251. {
  252. if (SOCKET_ERROR == listen(sock, 10))
  253. fprintf(stderr, "Can't listen on port %d: %d\n", serverport, WSAGetLastError());
  254. }
  255. in.set((HANDLE)sock, CH_SOCKET);
  256. }
  257. int
  258. cl_listen_console::proc_input(class cl_cmdset *cmdset)
  259. {
  260. class cl_commander_base *cmd = app->get_commander();
  261. struct sockaddr_in sock_addr;
  262. ACCEPT_SOCKLEN_T size = sizeof(struct sockaddr);
  263. SOCKET newsock = accept((SOCKET)get_in_fd(), (struct sockaddr*)&sock_addr, &size);
  264. if (INVALID_SOCKET == newsock)
  265. {
  266. fprintf(stderr, "Can't accept: %d\n", WSAGetLastError());
  267. return(0);
  268. }
  269. int fh = _open_osfhandle((intptr_t)newsock, _O_TEXT);
  270. if (-1 == fh)
  271. {
  272. fprintf(stderr, "Can't _open_osfhandle\n");
  273. }
  274. FILE *fp = fdopen(fh, "r");
  275. if (!fp)
  276. fprintf(stderr, "Can't open port for input\n");
  277. cl_channel ch_in = cl_channel(fp, CH_SOCKET);
  278. fh = _open_osfhandle((intptr_t)newsock, _O_TEXT);
  279. if (-1 == fh)
  280. {
  281. fprintf(stderr, "Can't _open_osfhandle\n");
  282. }
  283. fp = fdopen(fh, "w");
  284. if (!fp)
  285. fprintf(stderr, "Can't open port for output\n");
  286. cl_channel ch_out = cl_channel(fp, CH_SOCKET);
  287. class cl_console_base *c = new cl_console(ch_in, ch_out, app);
  288. c->flags |= CONS_INTERACTIVE;
  289. cmd->add_console(c);
  290. return 0;
  291. }
  292. /*
  293. * Sub-console
  294. */
  295. cl_sub_console::cl_sub_console(class cl_console_base *the_parent,
  296. cl_channel _in, cl_channel _out, class cl_app *the_app):
  297. cl_console(_in, _out, the_app)
  298. {
  299. parent = the_parent;
  300. }
  301. cl_sub_console::~cl_sub_console(void)
  302. {
  303. class cl_commander_base *c = app->get_commander();
  304. if (parent && c)
  305. {
  306. c->activate_console(parent);
  307. }
  308. }
  309. int
  310. cl_sub_console::init(void)
  311. {
  312. class cl_commander_base *c = app->get_commander();
  313. if (parent && c)
  314. {
  315. c->deactivate_console(parent);
  316. }
  317. cl_console::init();
  318. flags |= CONS_ECHO;
  319. return 0;
  320. }
  321. /*
  322. * Command interpreter
  323. *____________________________________________________________________________
  324. */
  325. int
  326. cl_commander::init(void)
  327. {
  328. TRACE("%s\n", __PRETTY_FUNCTION__);
  329. class cl_optref console_on_option(this);
  330. class cl_optref config_file_option(this);
  331. class cl_optref port_number_option(this);
  332. class cl_console_base *con;
  333. console_on_option.init();
  334. console_on_option.use("console_on");
  335. config_file_option.init();
  336. config_file_option.use("config_file");
  337. port_number_option.init();
  338. cl_base::init();
  339. set_name("Commander");
  340. bool need_config = DD_TRUE;
  341. if (port_number_option.use("port_number"))
  342. add_console(new cl_listen_console(port_number_option.get_value((long)0), app));
  343. /* The following code is commented out because it produces gcc warnings
  344. * newcmd.cc: In member function `virtual int cl_commander::init()':
  345. * newcmd.cc:785: warning: 'Config' might be used uninitialized in this function
  346. * newcmd.cc:786: warning: 'cn' might be used uninitialized in this function
  347. */
  348. /*
  349. char *Config= config_file_option.get_value(Config);
  350. char *cn= console_on_option.get_value(cn);
  351. */
  352. /* Here shoud probably be something else, but is still better then the former code... */
  353. char *Config = config_file_option.get_value("");
  354. char *cn = console_on_option.get_value("");
  355. if (cn)
  356. {
  357. add_console(con = new cl_console(cn, cn, app));
  358. exec_on(con, Config);
  359. need_config = DD_FALSE;
  360. }
  361. if (cons->get_count() == 0)
  362. {
  363. add_console(con = new cl_console(stdin, stdout, app));
  364. exec_on(con, Config);
  365. need_config = DD_FALSE;
  366. }
  367. if (need_config && Config && *Config)
  368. {
  369. FILE *fc = fopen(Config, "r");
  370. if (!fc)
  371. fprintf(stderr, "Can't open `%s': %s\n", Config, strerror(errno));
  372. else
  373. {
  374. con = new cl_console(fc, stderr, app);
  375. con->flags |= CONS_NOWELCOME | CONS_ECHO;
  376. add_console(con);
  377. }
  378. }
  379. return(0);
  380. }
  381. void
  382. cl_commander::set_fd_set(void)
  383. {
  384. TRACE("%s\n", __PRETTY_FUNCTION__);
  385. int i;
  386. FD_ZERO(&read_set);
  387. for (i = 0; i < cons->count; i++)
  388. {
  389. class cl_console *c= dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(i)));
  390. if (c->input_active() && CH_SOCKET == c->in.get_type())
  391. {
  392. HANDLE fd = c->get_in_fd();
  393. assert(INVALID_HANDLE_VALUE != fd);
  394. FD_SET((SOCKET)fd, &read_set);
  395. }
  396. }
  397. }
  398. int
  399. cl_commander::console_count(void)
  400. {
  401. int i = 0;
  402. for (int j = 0; j < cons->count; j++)
  403. {
  404. class cl_console *c = dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(j)));
  405. if (c->input_active())
  406. {
  407. switch (c->in.get_type())
  408. {
  409. case CH_CONSOLE:
  410. case CH_FILE:
  411. case CH_SERIAL:
  412. ++i;
  413. break;
  414. default:
  415. break;
  416. }
  417. }
  418. }
  419. return i;
  420. }
  421. int
  422. cl_commander::console_input_avail(void)
  423. {
  424. int i = 0;
  425. FD_ZERO(&console_active_set);
  426. for (int j = 0; j < cons->count; j++)
  427. {
  428. class cl_console *c = dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(j)));
  429. if (c->input_avail())
  430. {
  431. HANDLE fd = c->get_in_fd();
  432. assert(INVALID_HANDLE_VALUE != fd);
  433. switch (c->in.get_type())
  434. {
  435. case CH_CONSOLE:
  436. case CH_FILE:
  437. case CH_SERIAL:
  438. FD_SET((SOCKET)fd, &console_active_set);
  439. ++i;
  440. break;
  441. default:
  442. break;
  443. }
  444. }
  445. }
  446. return i;
  447. }
  448. int
  449. cl_commander::socket_input_avail(long timeout, bool sleep)
  450. {
  451. active_set = read_set;
  452. if (active_set.fd_count)
  453. {
  454. struct timeval tv = {0, 0};
  455. struct timeval *tvp = sleep ? NULL : &tv;
  456. int i = select(0, &active_set, NULL, NULL, tvp);
  457. if (SOCKET_ERROR == i)
  458. {
  459. fprintf(stderr, "Can't select: %d\n", WSAGetLastError());
  460. return 0;
  461. }
  462. return i;
  463. }
  464. else
  465. {
  466. Sleep(timeout / 1000);
  467. return 0;
  468. }
  469. }
  470. int
  471. cl_commander::input_avail_timeout(long timeout)
  472. {
  473. TRACE("%s\n", __PRETTY_FUNCTION__);
  474. int n;
  475. if (0 != (n = console_input_avail()))
  476. FD_ZERO(&active_set);
  477. else
  478. n = socket_input_avail(timeout, false);
  479. return n;
  480. }
  481. #define CONSOLE_TIMEOUT 300000
  482. int
  483. cl_commander::wait_input(void)
  484. {
  485. TRACE("%s\n", __PRETTY_FUNCTION__);
  486. prompt();
  487. if (0 < console_count())
  488. {
  489. int n;
  490. while (0 == (n = input_avail_timeout(CONSOLE_TIMEOUT)))
  491. ;
  492. return n;
  493. }
  494. else
  495. {
  496. FD_ZERO(&console_active_set);
  497. return socket_input_avail(0, true);
  498. }
  499. }
  500. int
  501. cl_commander::proc_input(void)
  502. {
  503. TRACE("%s\n", __PRETTY_FUNCTION__);
  504. for (int j = 0; j < cons->count; j++)
  505. {
  506. class cl_console *c = dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(j)));
  507. if (c->input_active())
  508. {
  509. HANDLE fd = c->get_in_fd();
  510. assert(INVALID_HANDLE_VALUE != fd);
  511. if (FD_ISSET(fd, &active_set) || FD_ISSET(fd, &console_active_set))
  512. {
  513. actual_console = c;
  514. if (c->proc_input(cmdset))
  515. {
  516. del_console(c);
  517. delete c;
  518. }
  519. actual_console = 0;
  520. return 0 == cons->count;
  521. }
  522. }
  523. }
  524. return 0;
  525. }
  526. /* End of cmd.src/newcmdwin32.cc */