Version 0.3.0
[fw/sdcc] / sim / ucsim / cmd.src / newcmd.cc
1 /*
2  * Simulator of microcontrollers (cmd.src/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 #include "appcl.h"
55
56 // local
57 #include "newcmdcl.h"
58 #include "cmdutil.h"
59
60
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);
63
64 static int
65 cmd_do_print(FILE *f, char *format, va_list ap)
66 {
67   int ret;
68 #ifdef HAVE_VASPRINTF
69   char *msg= NULL;
70   vasprintf(&msg, format, ap);
71   ret= fprintf(f, "%s", msg);
72   free(msg);
73 #else
74 #  ifdef HAVE_VSNPRINTF
75   char msg[80*25];
76   vsnprintf(msg, 80*25, format, ap);
77   ret= fprintf(f, "%s", msg);
78 #  else
79 #    ifdef HAVE_VPRINTF
80   char msg[80*25];
81   vsprintf(msg, format, ap); /* Dangerous */
82   ret= fprintf(f, "%s", msg);
83 #    else
84 #      ifdef HAVE_DOPRNT
85   /* ??? */
86   /*strcpy(msg, "Unimplemented printf has called.\n");*/
87 #      else
88   /*strcpy(msg, "printf can not be implemented, upgrade your libc.\n");*/
89 #      endif
90 #    endif
91 #  endif
92 #endif
93   fflush(f);
94   return(ret);
95 }
96
97
98 /*
99  * Command line
100  *____________________________________________________________________________
101  */
102
103 cl_cmdline::cl_cmdline(char *acmd, class cl_console *acon)
104 {
105   cmd= strdup(acmd);
106   params= new cl_list(2, 2);
107   tokens= new cl_ustrings(2, 2);
108   name= 0;
109   matched_syntax= 0;
110   con= acon;
111 }
112
113 cl_cmdline::~cl_cmdline(void)
114 {
115   if (cmd)
116     free(cmd);
117   if (name)
118     free(name);
119   delete params;
120   delete tokens;
121 }
122
123 int
124 cl_cmdline::init(void)
125 {
126   split();
127   return(0);
128 }
129
130 char *
131 cl_cmdline::skip_delims(char *start)
132 {
133   while (*start &&
134          strchr(" \t\v\r,", *start))
135     start++;
136   return(start);
137 }
138
139 int
140 cl_cmdline::split(void)
141 {
142   char *start= cmd;
143   int i;
144
145   name= 0;
146   if (!cmd ||
147       !*cmd)
148     return(0);
149   start+= strspn(start, " \t\v\r,");
150   if (start &&
151       *start == '\n')
152     {
153       name= (char*)malloc(2);
154       strcpy(name, "\n");
155       return(0);
156     }
157   if (!*start)
158     return(0);
159   i= strcspn(start, " \t\v\r,");
160   if (i)
161     {
162       name= (char*)malloc(i+1);
163       strncpy(name, start, i);
164       name[i]= '\0';
165     }
166   start+= i;
167   start= skip_delims(start);
168   // skip delimiters
169   while (*start)
170     {
171       char *end, *param_str;
172       if (*start == '"')
173         {
174           // string
175           start++;
176           end= start;
177           while (*end &&
178                  *end != '"')
179             {
180               if (*end == '\\')
181                 {
182                   end++;
183                   if (*end)
184                     end++;
185                 }
186               else
187                 end++;
188             }
189           if (*end == '"')
190             end--;
191           else
192             con->printf("Unterminated string\n");
193           param_str= (char *)malloc(end-start+2);
194           strncpy(param_str, start, 1+end-start);
195           param_str[1+end-start]= '\0';
196           tokens->add(strdup(param_str));
197           params->add(con->sim->mk_cmd_str_arg(param_str));
198           free(param_str);
199           if (*end)
200             end++;
201           if (*end == '"')
202             end++;
203         }
204       else
205         {
206           char *dot;
207           i= strcspn(start, " \t\v\r,");
208           end= start+i;
209           param_str= (char *)malloc(i+1);
210           strncpy(param_str, start, i);
211           param_str[i]= '\0';
212           tokens->add(strdup(param_str));
213           if ((dot= strchr(param_str, '.')) != NULL)
214             {
215               // bit
216               class cl_cmd_arg *sfr, *bit;
217               *dot= '\0';
218               dot++;
219               if (strchr("0123456789", *param_str) != NULL)
220                 sfr= con->sim->mk_cmd_int_arg((long long)
221                                                strtol(param_str, 0, 0));
222               else
223                 sfr= con->sim->mk_cmd_sym_arg(param_str);
224               if (*dot == '\0')
225                 {
226                   bit= 0;
227                   con->printf("Uncomplete bit address\n");
228                   delete sfr;
229                 }
230               else
231                 {
232                   if (strchr("0123456789", *dot) != NULL)
233                     bit= con->sim->mk_cmd_int_arg((long long)
234                                                    strtol(dot, 0, 0));
235                   else
236                     bit= con->sim->mk_cmd_sym_arg(dot);
237                   params->add(con->sim->mk_cmd_bit_arg(sfr, bit));
238                 }
239             }
240           else if ((dot= strchr(param_str, '[')) != NULL)
241             {
242               // array
243               class cl_cmd_arg *aname, *aindex;
244               *dot= '\0';
245               dot++;
246               if (strchr("0123456789", *param_str) != NULL)
247                 aname= con->sim->mk_cmd_int_arg((long long)
248                                                  strtol(param_str, 0, 0));
249               else
250                 aname= con->sim->mk_cmd_sym_arg(param_str);
251               if (*dot == '\0')
252                 {
253                   aname= 0;
254                   con->printf("Uncomplete array\n");
255                 }
256               else
257                 {
258                   char *p;
259                   p= dot + strlen(dot) - 1;
260                   while (p > dot &&
261                          *p != ']')
262                     {
263                       *p= '\0';
264                       p--;
265                     }
266                   if (*p == ']')
267                     *p= '\0';
268                   if (strlen(dot) == 0)
269                     {
270                       con->printf("Uncomplete array index\n");
271                       delete aname;
272                     }
273                   else    
274                     {
275                       if (strchr("0123456789", *dot) != NULL)
276                         aindex= con->sim->mk_cmd_int_arg((long long)
277                                                           strtol(dot, 0, 0));
278                       else
279                         aindex= con->sim->mk_cmd_sym_arg(dot);
280                       params->add(con->sim->mk_cmd_array_arg(aname, aindex));
281                     }
282                 }
283             }
284           else if (strchr("0123456789", *param_str) != NULL)
285             {
286               // number
287               params->add(con->sim->mk_cmd_int_arg((long long)
288                                                     strtol(param_str, 0, 0)));
289             }
290           else
291             {
292               // symbol
293               params->add(con->sim->mk_cmd_sym_arg(param_str));
294             }
295           free(param_str);
296         }
297       start= end;
298       start= skip_delims(start);
299     }
300   return(0);
301 }
302
303 int
304 cl_cmdline::shift(void)
305 {
306   char *s= skip_delims(cmd);
307
308   free(name);
309   name= NULL;
310   if (s && *s)
311     {
312       while (*s &&
313              strchr(" \t\v\r,", *s) == NULL)
314         s++;
315       s= skip_delims(s);
316       char *p= strdup(s);
317       free(cmd);
318       cmd= p;
319       delete params;
320       params= new cl_list(2, 2);
321       split();
322     }
323   return(name && *name);
324 }
325
326 int
327 cl_cmdline::repeat(void)
328 {
329   return(name &&
330          *name == '\n');
331 }
332
333 class cl_cmd_arg *
334 cl_cmdline::param(int num)
335 {
336   if (num >= params->count)
337     return(0);
338   return((class cl_cmd_arg *)(params->at(num)));
339 }
340
341 void
342 cl_cmdline::insert_param(int pos, class cl_cmd_arg *param)
343 {
344   if (pos >= params->count)
345     params->add(param);
346   else
347     params->add_at(pos, param);
348 }
349
350 bool
351 cl_cmdline::syntax_match(class cl_sim *sim, char *syntax)
352 {
353   if (!syntax)
354     return(DD_FALSE);
355   if (!*syntax &&
356       !params->count)
357     {
358       matched_syntax= syntax;
359       return(DD_TRUE);
360     }
361   if (!params->count)
362     return(DD_FALSE);
363   //printf("syntax %s?\n",syntax);
364   char *p= syntax;
365   int iparam= 0;
366   class cl_cmd_arg *parm= (class cl_cmd_arg *)(params->at(iparam));
367   while (*p &&
368          parm)
369     {
370       //printf("Checking %s as %c\n",parm->get_svalue(),*p);
371       switch (*p)
372         {
373         case SY_ADDR:
374           if (!parm->as_address())
375             return(DD_FALSE);
376           //printf("ADDRESS match %lx\n",parm->value.address);
377           break;
378         case SY_NUMBER:
379           if (!parm->as_number())
380             return(DD_FALSE);
381           break;
382         case SY_DATA:
383           if (!parm->as_data())
384             return(DD_FALSE);
385           break;
386         case SY_MEMORY:
387           if (!parm->as_memory())
388             return(DD_FALSE);
389           //printf("MEMORY match %s\n",parm->value.memory->class_name);
390           break;
391         case SY_HW:
392           if (!parm->as_hw(sim->uc))
393             return(DD_FALSE);
394           break;
395         case SY_STRING:
396           if (!parm->as_string())
397             return(DD_FALSE);
398           break;
399         case SY_DATALIST:
400           if (!set_data_list(parm, &iparam))
401             return(DD_FALSE);
402           break;
403         case SY_BIT:
404           if (!parm->as_bit(sim->uc))
405             return(DD_FALSE);
406           break;
407         default:
408           return(DD_FALSE);
409         }
410       p++;
411       iparam++;
412       if (iparam < params->count)
413         parm= (class cl_cmd_arg *)(params->at(iparam));
414       else
415         parm= 0;
416     }
417   if (!*p &&
418       !parm)
419     {
420       matched_syntax= syntax;
421       return(DD_TRUE);
422     }
423   return(DD_FALSE);
424 }
425
426 bool
427 cl_cmdline::set_data_list(class cl_cmd_arg *parm, int *iparm)
428 {
429   class cl_cmd_arg *next_parm;
430   int len, i, j;
431   t_mem *array;
432
433   len= 0;
434   array= 0;
435   for (i= *iparm, next_parm= param(i); next_parm; i++, next_parm= param(i))
436     {
437       if (next_parm->is_string())
438         {
439           int l;
440           char *s;
441           //s= proc_escape(next_parm->get_svalue(), &l);
442           if (!next_parm->as_string())
443             continue;
444           s= next_parm->value.string.string;
445           l= next_parm->value.string.len;
446           if (!array)
447             array= (t_mem*)malloc(sizeof(t_mem)*l);
448           else
449             array= (t_mem*)realloc(array, sizeof(t_mem)*(l+len));
450           for (j= 0; j < l; j++)
451             {
452               array[len]= s[j];
453               len++;
454             }
455           //if (s)
456           //free(s);
457         }
458       else
459         {
460           if (!next_parm->as_data())
461             {
462               if (array)
463                 free(array);
464               return(DD_FALSE);
465             }
466           if (!array)
467             array= (t_mem*)malloc(sizeof(t_mem));
468           else
469             array= (t_mem*)realloc(array, sizeof(t_mem)*(1+len));
470           array[len]= next_parm->value.data;
471           len++;
472         }
473     }
474   *iparm= i;
475   parm->value.data_list.array= array;
476   parm->value.data_list.len= len;
477   return(DD_TRUE);
478 }
479
480
481 /*
482  * Command
483  *____________________________________________________________________________
484  */
485
486 cl_cmd::cl_cmd(//class cl_sim *asim,
487                char *aname,
488                int can_rep,
489                char *short_hlp,
490                char *long_hlp):
491   cl_base()
492 {
493   //sim= asim;
494   names= new cl_strings(1, 1);
495   names->add(aname?strdup(aname):strdup("unknown"));
496   can_repeat= can_rep;
497   short_help= short_hlp?strdup(short_hlp):NULL;
498   long_help= long_hlp?strdup(long_hlp):NULL;
499 }
500
501 /*cl_cmd::cl_cmd(class cl_sim *asim):
502   cl_base()
503 {
504   sim= asim;
505   name= short_help= long_help= 0;
506   can_repeat= 0;
507 }*/
508
509 cl_cmd::~cl_cmd(void)
510 {
511   delete names;
512   if (short_help)
513     free(short_help);
514   if (long_help)
515     free(long_help);
516 }
517
518 void
519 cl_cmd::add_name(char *name)
520 {
521   if (name)
522     names->add(strdup(name));
523 }
524
525 int
526 cl_cmd::name_match(char *aname, int strict)
527 {
528   int i;
529   
530   if (names->count == 0 &&
531       !aname)
532     return(1);
533   if (!aname)
534     return(0);
535   if (strict)
536     {
537       for (i= 0; i < names->count; i++)
538         {
539           char *n= (char*)(names->at(i));
540           if (strcmp(aname, n) == 0)
541             return(1);
542         }
543     }
544   else
545     {
546       for (i= 0; i < names->count; i++)
547         {
548           char *n= (char*)(names->at(i));
549           if (strstr(n, aname) == n)
550             return(1);
551         }
552     }
553   return(0);
554 }
555
556 int
557 cl_cmd::name_match(class cl_cmdline *cmdline, int strict)
558 {
559   return(name_match(cmdline->name, strict));
560 }
561
562 int
563 cl_cmd::syntax_ok(class cl_cmdline *cmdline)
564 {
565   return(1);
566 }
567
568 int
569 cl_cmd::work(class cl_sim *sim,
570              class cl_cmdline *cmdline, class cl_console *con)
571 {
572   if (!syntax_ok(cmdline))
573     return(0);
574   return(do_work(sim, cmdline, con));
575 }
576
577 int
578 cl_cmd::do_work(class cl_sim *sim,
579                 class cl_cmdline *cmdline, class cl_console *con)
580 {
581   con->printf("Command \"%s\" does nothing.\n", (char*)(names->at(0)));
582   return(0);
583 }
584
585
586 /*
587  * Set of commands
588  *____________________________________________________________________________
589  */
590
591 cl_cmdset::cl_cmdset(class cl_sim *asim):
592   cl_list(5, 5)
593 {
594   sim= asim;
595   last_command= 0;
596 }
597
598 class cl_cmd *
599 cl_cmdset::get_cmd(class cl_cmdline *cmdline)
600 {
601   int i;
602
603   if (cmdline->repeat())
604     {
605       if (last_command)
606         return(last_command);
607       else
608         return(0);
609     }
610   // exact match
611   for (i= 0; i < count; i++)
612     {
613       class cl_cmd *c= (class cl_cmd *)at(i);
614       if (c->name_match(cmdline, 1))
615         return(c);
616     }
617   // not exact match
618   class cl_cmd *c_matched= 0;
619   for (i= 0; i < count; i++)
620     {
621       class cl_cmd *c= (class cl_cmd *)at(i);
622       if (c->name_match(cmdline, 0))
623         {
624           if (!c_matched)
625             c_matched= c;
626           else
627             return(0);
628         }
629     }
630   return(c_matched);
631   //return(0);
632 }
633
634 class cl_cmd *
635 cl_cmdset::get_cmd(char *cmd_name)
636 {
637   int i;
638
639   for (i= 0; i < count; i++)
640     {
641       class cl_cmd *c= (class cl_cmd *)at(i);
642       if (c->name_match(cmd_name, 1))
643         return(c);
644     }
645   return(0);
646 }
647
648 void
649 cl_cmdset::del(char *name)
650 {
651   int i;
652
653   if (!name)
654     return;
655   for (i= 0; i < count; i++)
656     {
657       class cl_cmd *cmd= (class cl_cmd *)(at(i));
658       if (cmd->name_match(name, 1))
659         free_at(i);
660     }
661 }
662
663 void
664 cl_cmdset::replace(char *name, class cl_cmd *cmd)
665 {
666   int i;
667
668   if (!name)
669     return;
670   for (i= 0; i < count; i++)
671     {
672       class cl_cmd *c= (class cl_cmd *)(at(i));
673       if (c->name_match(name, 1))
674         {
675           delete c;
676           put_at(i, cmd);
677         }
678     }
679 }
680
681
682 /*
683  * Composed command: subset of commands
684  *____________________________________________________________________________
685  */
686
687 cl_super_cmd::cl_super_cmd(//class cl_sim *asim,
688                            char *aname,
689                            int  can_rep,
690                            char *short_hlp,
691                            char *long_hlp,
692                            class cl_cmdset *acommands):
693   cl_cmd(aname, can_rep, short_hlp, long_hlp)
694 {
695   commands= acommands;
696 }
697
698 cl_super_cmd::~cl_super_cmd(void)
699 {
700   if (commands)
701     delete commands;
702 }
703
704 int
705 cl_super_cmd::work(class cl_sim *sim,
706                    class cl_cmdline *cmdline, class cl_console *con)
707 {
708   class cl_cmd *cmd= 0;
709
710   if (!commands)
711     return(0);
712   
713   if (!cmdline->shift())
714     {
715       if ((cmd= commands->get_cmd("_no_parameters_")) != 0)
716         return(cmd->work(sim, cmdline, con));
717       int i;
718       con->printf("\"%s\" must be followed by the name of a subcommand\n"
719                   "List of subcommands:\n", (char*)(names->at(0)));
720       for (i= 0; i < commands->count; i++)
721         {
722           cmd= (class cl_cmd *)(commands->at(i));
723           con->printf("%s\n", cmd->short_help);
724         }
725       return(0);
726     }
727   if ((cmd= commands->get_cmd(cmdline)) == NULL)
728     {
729       con->printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
730                   cmdline->name, (char*)(names->at(0)));
731       return(0);
732     }
733   return(cmd->work(sim, cmdline, con));
734 }
735
736
737 /*
738  * Command console
739  *____________________________________________________________________________
740  */
741
742 cl_console::cl_console(char *fin, char *fout, class cl_sim *asim):
743   cl_base()
744 {
745   FILE *f;
746
747   last_command= NULL;
748   sim= asim;
749   in= 0;
750   if (fin)
751     if (f= fopen(fin, "r+"), in= f, !f)
752       fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
753   out= 0;
754   if (fout)
755     if (f= fopen(fout, "w+"), out= f, !f)
756       fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
757   prompt= 0;
758   flags= CONS_NONE;
759   if (in &&
760       isatty(fileno(in)))
761     flags|= CONS_INTERACTIVE;
762   else
763     printf("Warning: non-interactive console\n");
764 }
765
766 cl_console::cl_console(FILE *fin, FILE *fout, class cl_sim *asim):
767   cl_base()
768 {
769   last_command= NULL;
770   sim= asim;
771   in = fin;
772   out= fout;
773   prompt= 0;
774   flags= CONS_NONE;
775   if (in &&
776       isatty(fileno(in)))
777     flags|= CONS_INTERACTIVE;
778   else
779     printf("Warning: non-interactive console\n");
780 }
781
782 /*
783  * use the port number supplied to connect to localhost for 
784  * (by Sandeep)
785  */
786
787 #ifdef SOCKET_AVAIL
788 static int
789 connect_to_port(int portnum)
790 {
791   int sock= socket(AF_INET,SOCK_STREAM,0);
792   struct sockaddr_in sin;
793
794   sin.sin_family = AF_INET;
795   sin.sin_port = htons(portnum);
796   sin.sin_addr.s_addr = inet_addr("127.0.0.1");
797
798   if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
799     fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
800     return -1;
801   }
802   return sock;
803 }
804
805 cl_console::cl_console(int portnumber, class cl_sim *asim)
806 {
807   int sock= connect_to_port(portnumber);
808
809   last_command= NULL;
810   sim= asim;
811   if (!(in= fdopen(sock, "r+")))
812     fprintf(stderr, "cannot open port for input\n");
813   if (!(out= fdopen(sock, "w+")))
814     fprintf(stderr, "cannot open port for output\n");
815   //fprintf(stderr, "init socket done\n");
816 }
817 #endif
818
819 int
820 cl_console::init(void)
821 {
822   cl_base::init();
823   welcome();
824   flags&= ~CONS_PROMPT;
825   print_prompt();
826   return(0);
827 }
828
829 cl_console::~cl_console(void)
830 {
831   if (in)
832     fclose(in);
833   if (out)
834     {
835       fprintf(out, "\n");
836       fflush(out);
837       fclose(out);
838     }
839 #ifdef SOCKET_AVAIL
840   /*  if (sock)
841     {
842       shutdown(sock, 2);
843       close(sock);
844       }*/
845 #endif
846 }
847
848
849 /*
850  * Output functions
851  */
852
853 void
854 cl_console::welcome(void)
855 {
856   if (!out)
857     return;
858   fprintf(out, "ucsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
859           "ucsim comes with ABSOLUTELY NO WARRANTY; for details type "
860           "`show w'.\n"
861           "This is free software, and you are welcome to redistribute it\n"
862           "under certain conditions; type `show c' for details.\n",
863           VERSIONSTR);
864   fflush(out);
865 }
866
867 void
868 cl_console::print_prompt(void)
869 {
870   char *p;
871
872   if (flags & (CONS_PROMPT|CONS_FROZEN))
873     return;
874   flags|= CONS_PROMPT;
875   if (!out)
876     return;
877   if (sim->arg_avail('P'))
878     putc('\0', out);
879   else
880     fprintf(out, "%s", (prompt && prompt[0])?prompt:
881             ((p= sim->get_sarg(0, "prompt"))?p:"> "));
882   fflush(out);
883 }
884
885 int
886 cl_console::printf(char *format, ...)
887 {
888   va_list ap;
889   int ret= 0;
890
891   if (out)
892     {
893       va_start(ap, format);
894       ret= cmd_do_print(out, format, ap);
895       va_end(ap);
896     }
897   return(ret);
898 }
899
900 void
901 cl_console::print_bin(long data, int bits)
902 {
903   long mask= 1;
904
905   if (!out)
906     return;
907   mask= mask << ((bits >= 1)?(bits-1):0);
908   while (bits--)
909     {
910       fprintf(out, "%c", (data&mask)?'1':'0');
911       mask>>= 1;
912     }
913 }
914
915 /*
916  * Input functions
917  */
918
919 int
920 cl_console::match(int fdnum)
921 {
922   if (in &&
923       fileno(in) == fdnum)
924     return(1);
925   return(0);
926 }
927
928 int
929 cl_console::get_in_fd(void)
930 {
931   return(in?fileno(in):-1);
932 }
933
934 int
935 cl_console::input_avail(void)
936 {
937   struct timeval tv;
938   int i;
939   
940   if ((i= get_in_fd()) < 0)
941     return(0);
942   fd_set s;
943   FD_ZERO(&s);
944   FD_SET(i, &s);
945   tv.tv_sec= tv.tv_usec= 0;
946   i= select(i+1, &s, NULL, NULL, &tv);
947   return(i);
948 }
949
950 char *
951 cl_console::read_line(void)
952 {
953   char *s= NULL;
954
955 #ifdef HAVE_GETLINE
956   if (getline(&s, 0, in) < 0)
957     return(0);
958 #else
959
960 # ifdef HAVE_GETDELIM
961   size_t n= 30;
962   s= (char *)malloc(n);
963   if (getdelim(&s, &n, '\n', in) < 0)
964     {
965       free(s);
966       return(0);
967     }
968 # else
969
970 #  ifdef HAVE_FGETS
971   s= (char *)malloc(300);
972   if (fgets(s, 300, in) == NULL)
973     {
974       free(s);
975       return(0);
976     }
977 #  endif
978 # endif
979 #endif
980   s[strlen(s)-1]= '\0';
981   if (s[strlen(s)-1] == '\r')
982     s[strlen(s)-1]= '\0';
983   flags&= ~CONS_PROMPT;
984   return(s);
985 }
986
987 int
988 cl_console::proc_input(class cl_app *app, class cl_cmdset *cmdset)
989 {
990   int retval= 0;
991
992   if (feof(in))
993     {
994       fprintf(out, "End\n");
995       return(1);
996     }
997   char *cmdstr= read_line();
998   if (!cmdstr)
999     return(1);
1000   if (flags & CONS_FROZEN)
1001     {
1002       sim->stop(resUSER);
1003       flags&= ~CONS_FROZEN;
1004       retval= 0;
1005     }
1006   else
1007     {
1008       class cl_cmdline *cmdline;
1009       class cl_cmd *cm;
1010       cmdline= new cl_cmdline(cmdstr, this);
1011       cmdline->init();
1012       cm= 0;
1013       if (app)
1014         cm= app->get_cmd(cmdline);
1015       if (cm == 0 &&
1016           cmdset)
1017         cm= cmdset->get_cmd(cmdline);
1018       if (cm)
1019         retval= cm->work(sim, cmdline, this);
1020       delete cmdline;
1021       if (!cm)
1022         retval= interpret(cmdstr);
1023     }
1024   //retval= sim->do_cmd(cmd, this);
1025   if (!retval)
1026     print_prompt();
1027   free(cmdstr);
1028   return(retval);
1029 }
1030
1031 /*
1032  * Old version, sim->do_cmd() falls into this if it doesn't find a new
1033  * command object which can handle entered command
1034  */
1035
1036 int
1037 cl_console::interpret(char *cmd)
1038 {
1039   fprintf(out, "New interpreter does not known this command\n");
1040   return(0);
1041 }
1042
1043
1044 /*
1045  * This console listen on a socket and can accept connection requests
1046  */
1047 #ifdef SOCKET_AVAIL
1048
1049 cl_listen_console::cl_listen_console(int serverport, class cl_sim *asim)
1050 {
1051   last_command= NULL;
1052   sim= asim;
1053   if ((sock= make_server_socket(serverport)) >= 0)
1054     {
1055       if (listen(sock, 10) < 0)
1056         fprintf(stderr, "Listen on port %d: %s\n",
1057                 serverport, strerror(errno));
1058     }
1059   in= out= 0;
1060 }
1061
1062 int
1063 cl_listen_console::match(int fdnum)
1064 {
1065   return(sock == fdnum);
1066 }
1067
1068 int
1069 cl_listen_console::get_in_fd(void)
1070 {
1071   return(sock);
1072 }
1073
1074 int
1075 cl_listen_console::proc_input(class cl_cmdset *cmdset)
1076 {
1077   int newsock;
1078   ACCEPT_SOCKLEN_T size;
1079   struct sockaddr_in sock_addr;
1080
1081   size= sizeof(struct sockaddr); 
1082   newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
1083   if (newsock < 0)
1084     {
1085       perror("accept");
1086       return(0);
1087     }
1088   if (!(in= fdopen(newsock, "r+")))
1089     fprintf(stderr, "cannot open port for input\n");
1090   if (!(out= fdopen(newsock, "w+")))
1091     fprintf(stderr, "cannot open port for output\n");
1092   class cl_console *c= sim->cmd->mk_console(in, out, sim);
1093   c->flags|= CONS_INTERACTIVE;
1094   c->init();
1095   sim->cmd->add_console(c);
1096   in= out= 0;
1097   return(0);
1098 }
1099
1100 #endif /* SOCKET_AVAIL */
1101
1102
1103 /*
1104  * Command interpreter
1105  *____________________________________________________________________________
1106  */
1107
1108 cl_commander::cl_commander(class cl_app *the_app,
1109                            class cl_cmdset *acmdset, class cl_sim *asim):
1110   cl_base()
1111 {
1112   app= the_app;
1113   cons= new cl_list(1, 1); 
1114   actual_console= frozen_console= 0;
1115   cmdset= acmdset;
1116   sim= asim;
1117 }
1118
1119 int
1120 cl_commander::init(void)
1121 {
1122   cl_base::init();
1123   if (!sim)
1124     return(1);
1125   if (sim->arg_avail('c'))
1126     add_console(mk_console(sim->get_sarg('c', 0),
1127                            sim->get_sarg('c', 0), sim));
1128 #ifdef SOCKET_AVAIL
1129   if (sim->arg_avail('Z'))
1130     add_console(mk_console(sim->get_iarg(0, "Zport"), sim));
1131   if (sim->arg_avail('r'))
1132     add_console(mk_console(sim->get_iarg('r', 0), sim));
1133 #endif
1134   if (cons->get_count() == 0)
1135     add_console(mk_console(stdin, stdout, sim));
1136   return(0);
1137 }
1138
1139 cl_commander::~cl_commander(void)
1140 {
1141   delete cons;
1142   delete cmdset;
1143 }
1144
1145 class cl_console *
1146 cl_commander::mk_console(char *fin, char *fout, class cl_sim *asim)
1147 {
1148   return(new cl_console(fin, fout, asim));
1149 }
1150
1151 class cl_console *
1152 cl_commander::mk_console(FILE *fin, FILE *fout, class cl_sim *asim)
1153 {
1154   return(new cl_console(fin, fout, asim));
1155 }
1156
1157 #ifdef SOCKET_AVAIL
1158 class cl_console *
1159 cl_commander::mk_console(int portnumber, class cl_sim *asim)
1160 {
1161   return(new cl_listen_console(portnumber, asim));
1162 }
1163 #endif
1164
1165 void
1166 cl_commander::add_console(class cl_console *console)
1167 {
1168   console->init();
1169   cons->add(console);
1170   set_fd_set();
1171 }
1172
1173 void
1174 cl_commander::del_console(class cl_console *console)
1175 {
1176   cons->disconn(console);
1177   set_fd_set();
1178 }
1179
1180 void
1181 cl_commander::set_fd_set(void)
1182 {
1183   int i;
1184
1185   //fprintf(stderr, "** Setting fd set\n");  
1186   FD_ZERO(&read_set);
1187   fd_num= 0;
1188   for (i= 0; i < cons->count; i++)
1189     {
1190       int fd;
1191       class cl_console *c= (class cl_console*)(cons->at(i));
1192       if ((fd= c->get_in_fd()) >= 0)
1193         {
1194           if ((c->flags & CONS_FROZEN) == 0 ||
1195               (c->flags & CONS_INTERACTIVE) != 0)
1196             {
1197               FD_SET(fd, &read_set);
1198               if (fd > fd_num)
1199                 fd_num= fd;
1200             }
1201         }
1202       else
1203         ;//fprintf(stderr, "** Skipping console %p\n",c);
1204     }
1205   fd_num++;
1206 }
1207
1208
1209 /*
1210  * Printing to all consoles
1211  */
1212
1213 int
1214 cl_commander::all_printf(char *format, ...)
1215 {
1216   va_list ap;
1217   int i, ret= 0;
1218   
1219   for (i= 0; i < cons->count; i++)
1220     {
1221       class cl_console *c= (class cl_console*)(cons->at(i));
1222       if (c->out)
1223         {
1224           va_start(ap, format);
1225           ret= cmd_do_print(c->out, format, ap);
1226           va_end(ap);
1227         }
1228     }
1229   return(ret);
1230 }
1231
1232 int
1233 cl_commander::all_print(char *string, int length)
1234 {
1235   int i;
1236   
1237   for (i= 0; i < cons->count; i++)
1238     {
1239       class cl_console *c= (class cl_console*)(cons->at(i));
1240       if (c->out)
1241         {
1242           for (int j= 0; j < length; j++)
1243             putc(string[j], c->out);
1244         }
1245     }
1246   return(0);
1247 }
1248
1249 /*
1250  * Printing to actual_console
1251  */
1252
1253 int
1254 cl_commander::printf(char *format, ...)
1255 {
1256   va_list ap;
1257   int ret= 0;
1258
1259   if (actual_console &&
1260       actual_console->out)
1261     {
1262       va_start(ap, format);
1263       ret= cmd_do_print(actual_console->out, format, ap);
1264       va_end(ap);
1265     }
1266   return(ret);
1267 }
1268
1269 /*
1270  * Printing to consoles which have CONS_DEBUG flag set
1271  */
1272
1273 int
1274 cl_commander::debug(char *format, ...)
1275 {
1276   va_list ap;
1277   int i, ret= 0;
1278
1279   for (i= 0; i < cons->count; i++)
1280     {
1281       class cl_console *c= (class cl_console*)(cons->at(i));
1282       if (c->out &&
1283           c->flags & CONS_DEBUG)
1284         {
1285           va_start(ap, format);
1286           ret= cmd_do_print(c->out, format, ap);
1287           va_end(ap);
1288         }
1289     }
1290   return(ret);
1291 }
1292
1293 int
1294 cl_commander::flag_printf(int iflags, char *format, ...)
1295 {
1296   va_list ap;
1297   int i, ret= 0;
1298
1299   for (i= 0; i < cons->count; i++)
1300     {
1301       class cl_console *c= (class cl_console*)(cons->at(i));
1302       if (c->out &&
1303           (c->flags & iflags) == iflags)
1304         {
1305           va_start(ap, format);
1306           ret= cmd_do_print(c->out, format, ap);
1307           va_end(ap);
1308         }
1309     }
1310   return(ret);
1311 }
1312
1313 int
1314 cl_commander::input_avail(void)
1315 {
1316   struct timeval tv;
1317   int i;
1318
1319   tv.tv_sec= tv.tv_usec= 0;
1320   active_set= read_set;
1321   i= select(fd_num, &active_set, NULL, NULL, &tv);
1322   return(i);
1323 }
1324
1325 int
1326 cl_commander::input_avail_on_frozen(void)
1327 {
1328   int fd;
1329
1330   if (!frozen_console)
1331     return(0);
1332   if ((fd= frozen_console->get_in_fd()) >= 0 &&
1333       !isatty(fd))
1334     return(0);
1335   return(frozen_console->input_avail());
1336 }
1337
1338 int
1339 cl_commander::wait_input(void)
1340 {
1341   int i;
1342
1343   active_set= read_set;
1344   i= select(fd_num, &active_set, NULL, NULL, NULL);
1345   return(i);
1346 }
1347
1348 int
1349 cl_commander::proc_input(void)
1350 {
1351   int i;
1352
1353   for (i= 0; i < fd_num; i++)
1354     if (FD_ISSET(i, &active_set))
1355       {
1356         class cl_console *c;
1357         int j;
1358         for (j= 0; j < cons->count; j++)
1359           {
1360             c= (class cl_console*)(cons->at(j));
1361             if (c->match(i))
1362               {
1363                 actual_console= c;
1364                 int retval= c->proc_input(app, cmdset);
1365                 if (retval)
1366                   {
1367                     del_console(c);
1368                     delete c;
1369                   }
1370                 actual_console= 0;
1371                 return(cons->count == 0);
1372               }
1373           }
1374       }
1375   return(0);
1376 }
1377
1378
1379 /* End of cmd.src/newcmd.cc */