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