3c37a9b82924370d376add04d9dd354a84d8cd73
[fw/sdcc] / sim / ucsim / cmd.src / newcmd.cc
1 /*
2  * Simulator of microcontrollers (newcmd.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
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.
16
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.
21
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
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31 #include <errno.h>
32 #include <stdarg.h>
33 #include <stdlib.h>
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>
39 # include <netdb.h>
40 #endif
41 #include <sys/time.h>
42 #if FD_HEADER_OK
43 # include HEADER_FD
44 #endif
45 #include <unistd.h>
46 #include "i_string.h"
47
48 // prj
49 #include "globals.h"
50
51 // sim
52 #include "simcl.h"
53 #include "argcl.h"
54
55 // local
56 #include "newcmdcl.h"
57 #include "cmdutil.h"
58
59
60 extern "C" int vasprintf();
61 extern "C" int vsnprintf();
62
63 static int
64 cmd_do_print(FILE *f, char *format, va_list ap)
65 {
66   int ret;
67 #ifdef HAVE_VASPRINTF
68   char *msg= NULL;
69   vasprintf(&msg, format, ap);
70   ret= fprintf(f, "%s", msg);
71   free(msg);
72 #else
73 #  ifdef HAVE_VSNPRINTF
74   char msg[80*25];
75   vsnprintf(msg, 80*25, format, ap);
76   ret= fprintf(f, "%s", msg);
77 #  else
78 #    ifdef HAVE_VPRINTF
79   char msg[80*25];
80   vsprintf(msg, format, ap); /* Dangerous */
81   ret= fprintf(f, "%s", msg);
82 #    else
83 #      ifdef HAVE_DOPRNT
84   /* ??? */
85   /*strcpy(msg, "Unimplemented printf has called.\n");*/
86 #      else
87   /*strcpy(msg, "printf can not be implemented, upgrade your libc.\n");*/
88 #      endif
89 #    endif
90 #  endif
91 #endif
92   fflush(f);
93   return(ret);
94 }
95
96
97 /*
98  * Command line
99  *____________________________________________________________________________
100  */
101
102 cl_cmdline::cl_cmdline(char *acmd)
103 {
104   cmd= strdup(acmd);
105   params= new cl_list(2, 2);
106   tokens= new cl_ustrings(2, 2);
107   name= 0;
108 }
109
110 cl_cmdline::~cl_cmdline(void)
111 {
112   if (cmd)
113     free(cmd);
114   if (name)
115     free(name);
116   delete params;
117   delete tokens;
118 }
119
120 int
121 cl_cmdline::init(void)
122 {
123   split();
124   return(0);
125 }
126
127 char *
128 cl_cmdline::skip_delims(char *start)
129 {
130   while (*start &&
131          strchr(" \t\v\r,", *start))
132     start++;
133   return(start);
134 }
135
136 int
137 cl_cmdline::split(void)
138 {
139   char *start= cmd;
140   int i;
141
142   name= 0;
143   if (!cmd ||
144       !*cmd)
145     return(0);
146   start+= strspn(start, " \t\v\r,");
147   if (start &&
148       *start == '\n')
149     {
150       name= (char*)malloc(2);
151       strcpy(name, "\n");
152       return(0);
153     }
154   if (!*start)
155     return(0);
156   i= strcspn(start, " \t\v\r,");
157   if (i)
158     {
159       name= (char*)malloc(i+1);
160       strncpy(name, start, i);
161       name[i]= '\0';
162     }
163   start+= i;
164   start= skip_delims(start);
165   // skip delimiters
166   while (*start)
167     {
168       char *end, *param_str;
169       if (*start == '"')
170         {
171           // string
172           start++;
173           end= start;
174           while (*end &&
175                  *end != '"')
176             end++;
177           if (*end == '"')
178             end--;
179           else
180             simulator->cmd->printf("Unterminated string\n");
181           param_str= (char *)malloc(end-start+2);
182           strncpy(param_str, start, 1+end-start);
183           param_str[1+end-start]= '\0';
184           tokens->add(strdup(param_str));
185           params->add(simulator->mk_cmd_str_arg(param_str));
186           free(param_str);
187           if (*end)
188             end++;
189           if (*end == '"')
190             end++;
191         }
192       else
193         {
194           char *dot;
195           i= strcspn(start, " \t\v\r,");
196           end= start+i;
197           param_str= (char *)malloc(i+1);
198           strncpy(param_str, start, i);
199           param_str[i]= '\0';
200           tokens->add(strdup(param_str));
201           if ((dot= strchr(param_str, '.')) != NULL)
202             {
203               // bit
204               class cl_cmd_arg *sfr, *bit;
205               *dot= '\0';
206               dot++;
207               if (strchr("0123456789", *param_str) != NULL)
208                 sfr= simulator->mk_cmd_int_arg((long long)
209                                                strtol(param_str, 0, 0));
210               else
211                 sfr= simulator->mk_cmd_sym_arg(param_str);
212               if (*dot == '\0')
213                 {
214                   bit= 0;
215                   simulator->cmd->printf("Uncomplete bit address\n");
216                 }
217               else
218                 {
219                   if (strchr("0123456789", *dot) != NULL)
220                     bit= simulator->mk_cmd_int_arg((long long)
221                                                    strtol(dot, 0, 0));
222                   else
223                     bit= simulator->mk_cmd_sym_arg(dot);
224                 }
225               params->add(simulator->mk_cmd_bit_arg(sfr, bit));
226             }
227           else if (strchr("0123456789", *param_str) != NULL)
228             {
229               // number
230               params->add(simulator->mk_cmd_int_arg((long long)
231                                                     strtol(param_str, 0, 0)));
232             }
233           else
234             {
235               // symbol
236               params->add(simulator->mk_cmd_sym_arg(param_str));
237             }
238           free(param_str);
239         }
240       start= end;
241       start= skip_delims(start);
242     }
243   return(0);
244 }
245
246 int
247 cl_cmdline::shift(void)
248 {
249   char *s= skip_delims(cmd);
250
251   free(name);
252   name= NULL;
253   if (s && *s)
254     {
255       while (*s &&
256              strchr(" \t\v\r,", *s) == NULL)
257         s++;
258       s= skip_delims(s);
259       char *p= strdup(s);
260       free(cmd);
261       cmd= p;
262       delete params;
263       params= new cl_list(2, 2);
264       split();
265     }
266   return(name && *name);
267 }
268
269 int
270 cl_cmdline::repeat(void)
271 {
272   return(name &&
273          *name == '\n');
274 }
275
276 class cl_cmd_arg *
277 cl_cmdline::param(int num)
278 {
279   if (num >= params->count)
280     return(0);
281   return((class cl_cmd_arg *)(params->at(num)));
282 }
283
284 void
285 cl_cmdline::insert_param(int pos, class cl_cmd_arg *param)
286 {
287   if (pos >= params->count)
288     params->add(param);
289   else
290     params->add_at(pos, param);
291 }
292
293
294 /*
295  * Command
296  *____________________________________________________________________________
297  */
298
299 cl_cmd::cl_cmd(class cl_sim *asim,
300                char *aname,
301                int can_rep,
302                char *short_hlp,
303                char *long_hlp):
304   cl_base()
305 {
306   sim= asim;
307   names= new cl_strings(1, 1);
308   names->add(aname?strdup(aname):strdup("unknown"));
309   can_repeat= can_rep;
310   short_help= short_hlp?strdup(short_hlp):NULL;
311   long_help= long_hlp?strdup(long_hlp):NULL;
312 }
313
314 /*cl_cmd::cl_cmd(class cl_sim *asim):
315   cl_base()
316 {
317   sim= asim;
318   name= short_help= long_help= 0;
319   can_repeat= 0;
320 }*/
321
322 cl_cmd::~cl_cmd(void)
323 {
324   delete names;
325   if (short_help)
326     free(short_help);
327   if (long_help)
328     free(long_help);
329 }
330
331 void
332 cl_cmd::add_name(char *name)
333 {
334   if (name)
335     names->add(strdup(name));
336 }
337
338 int
339 cl_cmd::name_match(char *aname, int strict)
340 {
341   int i;
342   
343   if (names->count == 0 &&
344       !aname)
345     return(1);
346   if (!aname)
347     return(0);
348   if (strict)
349     {
350       for (i= 0; i < names->count; i++)
351         {
352           char *n= (char*)(names->at(i));
353           if (strcmp(aname, n) == 0)
354             return(1);
355         }
356     }
357   else
358     {
359       for (i= 0; i < names->count; i++)
360         {
361           char *n= (char*)(names->at(i));
362           if (strstr(n, aname) == n)
363             return(1);
364         }
365     }
366   return(0);
367 }
368
369 int
370 cl_cmd::name_match(class cl_cmdline *cmdline, int strict)
371 {
372   return(name_match(cmdline->name, strict));
373 }
374
375 int
376 cl_cmd::syntax_ok(class cl_cmdline *cmdline)
377 {
378   return(1);
379 }
380
381 int
382 cl_cmd::work(class cl_cmdline *cmdline, class cl_console *con)
383 {
384   if (!syntax_ok(cmdline))
385     return(0);
386   return(do_work(cmdline, con));
387 }
388
389 int
390 cl_cmd::do_work(class cl_cmdline *cmdline, class cl_console *con)
391 {
392   con->printf("Command \"%s\" does nothing.\n", (char*)(names->at(0)));
393   return(0);
394 }
395
396
397 /*
398  * Set of commands
399  *____________________________________________________________________________
400  */
401
402 cl_cmdset::cl_cmdset(class cl_sim *asim):
403   cl_list(5, 5)
404 {
405   sim= asim;
406   last_command= 0;
407 }
408
409 class cl_cmd *
410 cl_cmdset::get_cmd(class cl_cmdline *cmdline)
411 {
412   int i;
413
414   if (cmdline->repeat())
415     {
416       if (last_command)
417         return(last_command);
418       else
419         return(0);
420     }
421   // exact match
422   for (i= 0; i < count; i++)
423     {
424       class cl_cmd *c= (class cl_cmd *)at(i);
425       if (c->name_match(cmdline, 1))
426         return(c);
427     }
428   // not exact match
429   class cl_cmd *c_matched= 0;
430   for (i= 0; i < count; i++)
431     {
432       class cl_cmd *c= (class cl_cmd *)at(i);
433       if (c->name_match(cmdline, 0))
434         {
435           if (!c_matched)
436             c_matched= c;
437           else
438             return(0);
439         }
440     }
441   return(c_matched);
442   //return(0);
443 }
444
445 void
446 cl_cmdset::del(char *name)
447 {
448   int i;
449
450   if (!name)
451     return;
452   for (i= 0; i < count; i++)
453     {
454       class cl_cmd *cmd= (class cl_cmd *)(at(i));
455       if (cmd->name_match(name, 1))
456         free_at(i);
457     }
458 }
459
460 void
461 cl_cmdset::replace(char *name, class cl_cmd *cmd)
462 {
463   int i;
464
465   if (!name)
466     return;
467   for (i= 0; i < count; i++)
468     {
469       class cl_cmd *c= (class cl_cmd *)(at(i));
470       if (c->name_match(name, 1))
471         {
472           delete c;
473           put_at(i, cmd);
474         }
475     }
476 }
477
478
479 /*
480  * Composed command: subset of commands
481  *____________________________________________________________________________
482  */
483
484 cl_super_cmd::cl_super_cmd(class cl_sim *asim,
485                            char *aname,
486                            int  can_rep,
487                            char *short_hlp,
488                            char *long_hlp,
489                            class cl_cmdset *acommands):
490   cl_cmd(asim, aname, can_rep, short_hlp, long_hlp)
491 {
492   commands= acommands;
493 }
494
495 cl_super_cmd::~cl_super_cmd(void)
496 {
497   if (commands)
498     delete commands;
499 }
500
501 int
502 cl_super_cmd::work(class cl_cmdline *cmdline, class cl_console *con)
503 {
504   class cl_cmd *cmd;
505
506   if (!commands)
507     return(0);
508   
509   if (!cmdline->shift())
510     {
511       int i;
512       con->printf("\"%s\" must be followed by the name of a subcommand\n"
513                   "List of subcommands:\n", (char*)(names->at(0)));
514       for (i= 0; i < commands->count; i++)
515         {
516           cmd= (class cl_cmd *)(commands->at(i));
517           con->printf("%s\n", cmd->short_help);
518         }
519       return(0);
520     }
521   if ((cmd= commands->get_cmd(cmdline)) == NULL)
522     {
523       con->printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
524                   cmdline->name, (char*)(names->at(0)));
525       return(0);
526     }
527   return(cmd->work(cmdline, con));
528 }
529
530
531 /*
532  * Command console
533  *____________________________________________________________________________
534  */
535
536 cl_console::cl_console(char *fin, char *fout, class cl_sim *asim):
537   cl_base()
538 {
539   FILE *f;
540
541   last_command= NULL;
542   sim= asim;
543   in= stdin;
544   if (fin)
545     if (f= fopen(fin, "r+"), in= f?f:stdin, !f)
546       fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
547   out= stdout;
548   if (fout)
549     if (f= fopen(fout, "w+"), out= f?f:stdout, !f)
550       fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
551   prompt= 0;
552   flags= CONS_NONE;
553 }
554
555 cl_console::cl_console(FILE *fin, FILE *fout, class cl_sim *asim):
556   cl_base()
557 {
558   last_command= NULL;
559   sim= asim;
560   in = fin;
561   out= fout;
562   flags= CONS_NONE;
563 }
564
565 /*
566  * use the port number supplied to connect to localhost for 
567  * (by Sandeep)
568  */
569
570 #ifdef SOCKET_AVAIL
571 static int
572 connect_to_port(int portnum)
573 {
574   int sock= socket(AF_INET,SOCK_STREAM,0);
575   struct sockaddr_in sin;
576
577   sin.sin_family = AF_INET;
578   sin.sin_port = htons(portnum);
579   sin.sin_addr.s_addr = inet_addr("127.0.0.1");
580
581   if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
582     fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
583     return -1;
584   }
585   return sock;
586 }
587
588 cl_console::cl_console(int portnumber, class cl_sim *asim)
589 {
590   int sock= connect_to_port(portnumber);
591
592   last_command= NULL;
593   sim= asim;
594   if (!(in= fdopen(sock, "r+")))
595     fprintf(stderr, "cannot open port for input\n");
596   if (!(out= fdopen(sock, "w+")))
597     fprintf(stderr, "cannot open port for output\n");
598   //fprintf(stderr, "init socket done\n");
599 }
600 #endif
601
602 int
603 cl_console::init(void)
604 {
605   cl_base::init();
606   welcome();
607   flags&= ~CONS_PROMPT;
608   print_prompt();
609   return(0);
610 }
611
612 cl_console::~cl_console(void)
613 {
614   if (in)
615     fclose(in);
616   if (out)
617     {
618       fprintf(out, "\n");
619       fflush(out);
620       fclose(out);
621     }
622 #ifdef SOCKET_AVAIL
623   /*  if (sock)
624     {
625       shutdown(sock, 2);
626       close(sock);
627       }*/
628 #endif
629 }
630
631
632 /*
633  * Output functions
634  */
635
636 void
637 cl_console::welcome(void)
638 {
639   fprintf(out,
640           "ucsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
641           "ucsim comes with ABSOLUTELY NO WARRANTY; for details type "
642           "`show w'.\n"
643           "This is free software, and you are welcome to redistribute it\n"
644           "under certain conditions; type `show c' for details.\n",
645           VERSIONSTR);
646   fflush(out);
647 }
648
649 void
650 cl_console::print_prompt(void)
651 {
652   char *p;
653
654   if (flags & (CONS_PROMPT|CONS_FROZEN))
655     return;
656   flags|= CONS_PROMPT;
657   if (!out)
658     return;
659   if (sim->arg_avail('P'))
660     putc('\0', out);
661   else
662     fprintf(out, "%s", (prompt && prompt[0])?prompt:
663             ((p= sim->get_sarg(0, "prompt"))?p:"> "));
664   fflush(out);
665 }
666
667 int
668 cl_console::printf(char *format, ...)
669 {
670   va_list ap;
671   int ret= 0;
672
673   if (out)
674     {
675       va_start(ap, format);
676       ret= cmd_do_print(out, format, ap);
677       va_end(ap);
678     }
679   return(ret);
680 }
681
682 void
683 cl_console::print_bin(long data, int bits)
684 {
685   long mask= 1;
686
687   if (!out)
688     return;
689   mask= mask << ((bits >= 1)?(bits-1):0);
690   while (bits--)
691     {
692       fprintf(out, "%c", (data&mask)?'1':'0');
693       mask>>= 1;
694     }
695 }
696
697 /*
698  * Input functions
699  */
700
701 int
702 cl_console::match(int fdnum)
703 {
704   if (in &&
705       fileno(in) == fdnum)
706     return(1);
707   return(0);
708 }
709
710 int
711 cl_console::get_in_fd(void)
712 {
713   return(in?fileno(in):-1);
714 }
715
716 int
717 cl_console::input_avail(void)
718 {
719   struct timeval tv;
720   int i;
721   
722   if ((i= get_in_fd()) < 0)
723     return(0);
724   fd_set s;
725   FD_ZERO(&s);
726   FD_SET(i, &s);
727   tv.tv_sec= tv.tv_usec= 0;
728   i= select(i+1, &s, NULL, NULL, &tv);
729   return(i);
730 }
731
732 char *
733 cl_console::read_line(void)
734 {
735   char *s= NULL;
736
737 #ifdef HAVE_GETLINE
738   if (getline(&s, 0, in) < 0)
739     return(0);
740 #else
741
742 # ifdef HAVE_GETDELIM
743   size_t n= 30;
744   s= (char *)malloc(n);
745   if (getdelim(&s, &n, '\n', in) < 0)
746     {
747       free(s);
748       return(0);
749     }
750 # else
751
752 #  ifdef HAVE_FGETS
753   s= (char *)malloc(300);
754   if (fgets(s, 300, in) == NULL)
755     {
756       free(s);
757       return(0);
758     }
759 #  endif
760 # endif
761 #endif
762   s[strlen(s)-1]= '\0';
763   if (s[strlen(s)-1] == '\r')
764     s[strlen(s)-1]= '\0';
765   flags&= ~CONS_PROMPT;
766   return(s);
767 }
768
769 int
770 cl_console::proc_input(void)
771 {
772   int retval;
773
774   if (feof(in))
775     {
776       fprintf(out, "End\n");
777       return(1);
778     }
779   char *cmd= read_line();
780   if (!cmd)
781     return(1);
782   if (flags & CONS_FROZEN)
783     {
784       sim->stop(resUSER);
785       flags&= ~CONS_FROZEN;
786       retval= 0;
787     }
788   else
789     retval= sim->do_cmd(cmd, this);
790   if (!retval)
791     print_prompt();
792   free(cmd);
793   return(retval);
794 }
795
796 /*
797  * Old version, sim->do_cmd() falls into this if it doesn't find a new
798  * command object which can handle enetered command
799  */
800
801 int
802 cl_console::interpret(char *cmd)
803 {
804   fprintf(out, "New interpreter does not known this command\n");
805   return(0);
806 }
807
808
809 /*
810  * This console listen on a socket and can accept connection requests
811  */
812 #ifdef SOCKET_AVAIL
813
814 cl_listen_console::cl_listen_console(int serverport, class cl_sim *asim)
815 {
816   last_command= NULL;
817   sim= asim;
818   if ((sock= make_server_socket(serverport)) >= 0)
819     {
820       if (listen(sock, 10) < 0)
821         fprintf(stderr, "Listen on port %d: %s\n",
822                 serverport, strerror(errno));
823     }
824   in= out= 0;
825 }
826
827 int
828 cl_listen_console::match(int fdnum)
829 {
830   return(sock == fdnum);
831 }
832
833 int
834 cl_listen_console::get_in_fd(void)
835 {
836   return(sock);
837 }
838
839 int
840 cl_listen_console::proc_input(void)
841 {
842   int newsock;
843   SOCKLEN_T size;
844   struct sockaddr_in sock_addr;
845
846   size= sizeof(struct sockaddr); 
847   newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
848   if (newsock < 0)
849     {
850       perror("accept");
851       return(0);
852     }
853   if (!(in= fdopen(newsock, "r+")))
854     fprintf(stderr, "cannot open port for input\n");
855   if (!(out= fdopen(newsock, "w+")))
856     fprintf(stderr, "cannot open port for output\n");
857   sim->cmd->add_console(sim->cmd->mk_console(in, out, sim));
858   in= out= 0;
859   return(0);
860 }
861
862 #endif /* SOCKET_AVAIL */
863
864
865 /*
866  * Command interpreter
867  *____________________________________________________________________________
868  */
869
870 cl_commander::cl_commander(class cl_sim *asim):
871   cl_base()
872 {
873   cons= new cl_list(1, 1); 
874   actual_console= frozen_console= 0;
875   sim= asim;
876 }
877
878 int
879 cl_commander::init(void)
880 {
881   cl_base::init();
882   if (!sim)
883     return(1);
884   if (sim->arg_avail('c'))
885     add_console(mk_console(sim->get_sarg('c', 0),
886                            sim->get_sarg('c', 0), sim));
887 #ifdef SOCKET_AVAIL
888   if (sim->arg_avail('Z'))
889     add_console(mk_console(sim->get_iarg(0, "Zport"), sim));
890   if (sim->arg_avail('r'))
891     add_console(mk_console(sim->get_iarg('r', 0), sim));
892 #endif
893   if (cons->get_count() == 0)
894     add_console(mk_console(stdin, stdout, sim));
895   return(0);
896 }
897
898 cl_commander::~cl_commander(void)
899 {
900   delete cons;
901 }
902
903 class cl_console *
904 cl_commander::mk_console(char *fin, char *fout, class cl_sim *asim)
905 {
906   return(new cl_console(fin, fout, asim));
907 }
908
909 class cl_console *
910 cl_commander::mk_console(FILE *fin, FILE *fout, class cl_sim *asim)
911 {
912   return(new cl_console(fin, fout, asim));
913 }
914
915 #ifdef SOCKET_AVAIL
916 class cl_console *
917 cl_commander::mk_console(int portnumber, class cl_sim *asim)
918 {
919   return(new cl_listen_console(portnumber, asim));
920 }
921 #endif
922
923 void
924 cl_commander::add_console(class cl_console *console)
925 {
926   console->init();
927   cons->add(console);
928   set_fd_set();
929 }
930
931 void
932 cl_commander::del_console(class cl_console *console)
933 {
934   cons->disconn(console);
935   set_fd_set();
936 }
937
938 void
939 cl_commander::set_fd_set(void)
940 {
941   int i;
942   
943   FD_ZERO(&read_set);
944   fd_num= 0;
945   for (i= 0; i < cons->count; i++)
946     {
947       int fd;
948       class cl_console *c= (class cl_console*)(cons->at(i));
949       if ((fd= c->get_in_fd()) >= 0)
950         {
951           if (fd > fd_num)
952             fd_num= fd;
953           FD_SET(fd, &read_set);
954         }
955     }
956   fd_num++;
957 }
958
959
960 /*
961  * Printing to all consoles
962  */
963
964 int
965 cl_commander::all_printf(char *format, ...)
966 {
967   va_list ap;
968   int i, ret= 0;
969   
970   for (i= 0; i < cons->count; i++)
971     {
972       class cl_console *c= (class cl_console*)(cons->at(i));
973       if (c->out)
974         {
975           va_start(ap, format);
976           ret= cmd_do_print(c->out, format, ap);
977           va_end(ap);
978         }
979     }
980   return(ret);
981 }
982
983 int
984 cl_commander::all_print(char *string, int length)
985 {
986   int i;
987   
988   for (i= 0; i < cons->count; i++)
989     {
990       class cl_console *c= (class cl_console*)(cons->at(i));
991       if (c->out)
992         {
993           for (int j= 0; j < length; j++)
994             putc(string[j], c->out);
995         }
996     }
997   return(0);
998 }
999
1000 /*
1001  * Printing to actual_console
1002  */
1003
1004 int
1005 cl_commander::printf(char *format, ...)
1006 {
1007   va_list ap;
1008   int ret= 0;
1009
1010   if (actual_console &&
1011       actual_console->out)
1012     {
1013       va_start(ap, format);
1014       ret= cmd_do_print(actual_console->out, format, ap);
1015       va_end(ap);
1016     }
1017   return(ret);
1018 }
1019
1020 /*
1021  * Printing to consoles which have CONS_DEBUG flag set
1022  */
1023
1024 int
1025 cl_commander::debug(char *format, ...)
1026 {
1027   va_list ap;
1028   int i, ret= 0;
1029
1030   for (i= 0; i < cons->count; i++)
1031     {
1032       class cl_console *c= (class cl_console*)(cons->at(i));
1033       if (c->out &&
1034           c->flags & CONS_DEBUG)
1035         {
1036           va_start(ap, format);
1037           ret= cmd_do_print(c->out, format, ap);
1038           va_end(ap);
1039         }
1040     }
1041   return(ret);
1042 }
1043
1044 int
1045 cl_commander::flag_printf(int iflags, char *format, ...)
1046 {
1047   va_list ap;
1048   int i, ret= 0;
1049
1050   for (i= 0; i < cons->count; i++)
1051     {
1052       class cl_console *c= (class cl_console*)(cons->at(i));
1053       if (c->out &&
1054           (c->flags & iflags) == iflags)
1055         {
1056           va_start(ap, format);
1057           ret= cmd_do_print(c->out, format, ap);
1058           va_end(ap);
1059         }
1060     }
1061   return(ret);
1062 }
1063
1064 int
1065 cl_commander::input_avail(void)
1066 {
1067   struct timeval tv;
1068   int i;
1069
1070   tv.tv_sec= tv.tv_usec= 0;
1071   active_set= read_set;
1072   i= select(fd_num/*FD_SETSIZE*/, &active_set, NULL, NULL, &tv);
1073   return(i);
1074 }
1075
1076 int
1077 cl_commander::input_avail_on_frozen(void)
1078 {
1079   if (!frozen_console)
1080     return(0);
1081   return(frozen_console->input_avail());
1082 }
1083
1084 int
1085 cl_commander::wait_input(void)
1086 {
1087   int i;
1088
1089   active_set= read_set;
1090   i= select(fd_num/*FD_SETSIZE*/, &active_set, NULL, NULL, NULL);
1091   return(i);
1092 }
1093
1094 int
1095 cl_commander::proc_input(void)
1096 {
1097   int i;
1098
1099   for (i= 0; i < fd_num/*FD_SETSIZE*/; i++)
1100     if (FD_ISSET(i, &active_set))
1101       {
1102         class cl_console *c;
1103         int j;
1104         for (j= 0; j < cons->count; j++)
1105           {
1106             c= (class cl_console*)(cons->at(j));
1107             if (c->match(i))
1108               {
1109                 actual_console= c;
1110                 int retval= c->proc_input();
1111                 if (retval)
1112                   {
1113                     del_console(c);
1114                     delete c;
1115                   }
1116                 actual_console= 0;
1117                 return(cons->count == 0);
1118               }
1119           }
1120       }
1121   return(0);
1122 }
1123
1124
1125 /* End of newcmd.cc */