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