Redesigned option handling, start of libtool introduction
[fw/sdcc] / sim / ucsim / cmd.src / command.cc
1 /*
2  * Simulator of microcontrollers (cmd.src/command.cc)
3  *
4  * Copyright (C) 2002,02 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 <stdlib.h>
31 #include "i_string.h"
32
33 // prj
34
35 // local, cmd
36 #include "commandcl.h"
37
38
39 /*
40  * Command line
41  *____________________________________________________________________________
42  */
43
44 cl_cmdline::cl_cmdline(class cl_app *the_app,
45                        char *acmd, class cl_console *acon):
46   cl_base()
47 {
48   app= the_app;
49   cmd= strdup(acmd);
50   params= new cl_list(2, 2);
51   tokens= new cl_ustrings(2, 2);
52   set_name(0);
53   matched_syntax= 0;
54   con= acon;
55 }
56
57 cl_cmdline::~cl_cmdline(void)
58 {
59   if (cmd)
60     free(cmd);
61   delete params;
62   delete tokens;
63 }
64
65 int
66 cl_cmdline::init(void)
67 {
68   split();
69   return(0);
70 }
71
72 char *
73 cl_cmdline::skip_delims(char *start)
74 {
75   while (*start &&
76          strchr(" \t\v\r,", *start))
77     start++;
78   return(start);
79 }
80
81 int
82 cl_cmdline::split(void)
83 {
84   //class cl_sim *sim;
85   char *start= cmd;
86   int i;
87   class cl_cmd_arg *arg;
88
89   //sim= app->get_sim();
90   set_name(0);
91   if (!cmd ||
92       !*cmd)
93     return(0);
94   start+= strspn(start, " \t\v\r,");
95   if (start &&
96       *start == '\n')
97     {
98       char *n= (char*)malloc(2);
99       strcpy(n, "\n");
100       set_name(n);
101       return(0);
102     }
103   if (!*start)
104     return(0);
105   i= strcspn(start, " \t\v\r,");
106   if (i)
107     {
108       char *n= (char*)malloc(i+1);
109       strncpy(n, start, i);
110       n[i]= '\0';
111       set_name(n);
112     }
113   start+= i;
114   start= skip_delims(start);
115   // skip delimiters
116   while (*start)
117     {
118       char *end, *param_str;
119       if (*start == '"')
120         {
121           // string
122           start++;
123           end= start;
124           while (*end &&
125                  *end != '"')
126             {
127               if (*end == '\\')
128                 {
129                   end++;
130                   if (*end)
131                     end++;
132                 }
133               else
134                 end++;
135             }
136           if (*end == '"')
137             end--;
138           else
139             con->dd_printf("Unterminated string\n");
140           param_str= (char *)malloc(end-start+2);
141           strncpy(param_str, start, 1+end-start);
142           param_str[1+end-start]= '\0';
143           tokens->add(strdup(param_str));
144           params->add(arg= new cl_cmd_str_arg(param_str));
145           arg->init();
146           free(param_str);
147           if (*end)
148             end++;
149           if (*end == '"')
150             end++;
151         }
152       else
153         {
154           char *dot;
155           i= strcspn(start, " \t\v\r,");
156           end= start+i;
157           param_str= (char *)malloc(i+1);
158           strncpy(param_str, start, i);
159           param_str[i]= '\0';
160           if (strchr(">", *start))
161             {
162               char *fn, mode[3]= "w\0";
163               switch (*start)
164                 {
165                 case '>':
166                   if (i == 1 ||
167                       (i == 2 &&
168                        start[1] == '>')) {
169                     con->dd_printf("Unspecified redirection\n");
170                     break;
171                   }
172                   fn= start+1;
173                   if (*fn == '>') {
174                     fn++;
175                     mode[0]= 'a';
176                   }
177                   con->redirect(fn, mode);
178                   break;
179                 default:
180                   break;
181                 }
182               free(param_str);
183               start= end;
184               start= skip_delims(start);
185               continue;
186             }
187           tokens->add(strdup(param_str));
188           if ((dot= strchr(param_str, '.')) != NULL)
189             {
190               // bit
191               class cl_cmd_arg *sfr, *bit;
192               *dot= '\0';
193               dot++;
194               if (strchr("0123456789", *param_str) != NULL)
195                 {
196                   sfr= new cl_cmd_int_arg((long)strtol(param_str, 0, 0));
197                   sfr->init();
198                 }
199               else
200                 {
201                   sfr= new cl_cmd_sym_arg(param_str);
202                   sfr->init();
203                 }
204               if (*dot == '\0')
205                 {
206                   bit= 0;
207                   con->dd_printf("Uncomplete bit address\n");
208                   delete sfr;
209                 }
210               else
211                 {
212                   if (strchr("0123456789", *dot) != NULL)
213                     {
214                       bit= new cl_cmd_int_arg((long)strtol(dot, 0, 0));
215                       bit->init();
216                     }
217                   else
218                     {
219                       bit= new cl_cmd_sym_arg(dot);
220                       bit->init();
221                     }
222                   params->add(arg= new cl_cmd_bit_arg(sfr, bit));
223                   arg->init();
224                 }
225             }
226           else if ((dot= strchr(param_str, '[')) != NULL)
227             {
228               // array
229               class cl_cmd_arg *aname, *aindex;
230               *dot= '\0';
231               dot++;
232               if (strchr("0123456789", *param_str) != NULL)
233                 {
234                   aname= new cl_cmd_int_arg((long)strtol(param_str, 0, 0));
235                   aname->init();
236                 }
237               else
238                 {
239                   aname= new cl_cmd_sym_arg(param_str);
240                   aname->init();
241                 }
242               if (*dot == '\0')
243                 {
244                   aname= 0;
245                   con->dd_printf("Uncomplete array\n");
246                 }
247               else
248                 {
249                   char *p;
250                   p= dot + strlen(dot) - 1;
251                   while (p > dot &&
252                          *p != ']')
253                     {
254                       *p= '\0';
255                       p--;
256                     }
257                   if (*p == ']')
258                     *p= '\0';
259                   if (strlen(dot) == 0)
260                     {
261                       con->dd_printf("Uncomplete array index\n");
262                       delete aname;
263                     }
264                   else    
265                     {
266                       if (strchr("0123456789", *dot) != NULL)
267                         {
268                           aindex= new cl_cmd_int_arg((long)strtol(dot, 0, 0));
269                           aindex->init();
270                         }
271                       else
272                         {
273                           aindex= new cl_cmd_sym_arg(dot);
274                           aindex->init();
275                         }
276                       params->add(arg= new cl_cmd_array_arg(aname, aindex));
277                       arg->init();
278                     }
279                 }
280             }
281           else if (strchr("0123456789", *param_str) != NULL)
282             {
283               // number
284               params->add(arg= new cl_cmd_int_arg((long)
285                                                   strtol(param_str, 0, 0)));
286               arg->init();
287             }
288           else
289             {
290               // symbol
291               params->add(arg= new cl_cmd_sym_arg(param_str));
292               arg->init();
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   set_name(0);
308   if (s && *s)
309     {
310       while (*s &&
311              strchr(" \t\v\r,", *s) == NULL)
312         s++;
313       s= skip_delims(s);
314       char *p= strdup(s);
315       free(cmd);
316       cmd= p;
317       delete params;
318       params= new cl_list(2, 2);
319       split();
320     }
321   return(have_real_name());
322 }
323
324 int
325 cl_cmdline::repeat(void)
326 {
327   char *n;
328   return((n= get_name()) &&
329          *n == '\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_uc *uc, 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       if (uc)
371         switch (*p)
372           {
373           case SY_ADDR:
374             if (!parm->as_address(uc))
375               return(DD_FALSE);
376             //printf("ADDRESS match %lx\n",parm->value.address);
377             break;
378           case SY_MEMORY:
379             if (!parm->as_memory(uc))
380               return(DD_FALSE);
381             //printf("MEMORY match %s\n",parm->value.memory->class_name);
382             break;
383           case SY_BIT:
384             if (!parm->as_bit(uc))
385               return(DD_FALSE);
386             break;
387           }
388       switch (*p)
389         {
390         case SY_NUMBER:
391           if (!parm->as_number())
392             return(DD_FALSE);
393           break;
394         case SY_DATA:
395           if (!parm->as_data())
396             return(DD_FALSE);
397           break;
398         case SY_HW:
399           if (!parm->as_hw(uc))
400             return(DD_FALSE);
401           break;
402         case SY_STRING:
403           if (!parm->as_string())
404             return(DD_FALSE);
405           break;
406         case SY_DATALIST:
407           if (!set_data_list(parm, &iparam))
408             return(DD_FALSE);
409           break;
410         default:
411           return(DD_FALSE);
412         }
413       p++;
414       iparam++;
415       if (iparam < params->count)
416         parm= (class cl_cmd_arg *)(params->at(iparam));
417       else
418         parm= 0;
419     }
420   if (!*p &&
421       !parm)
422     {
423       matched_syntax= syntax;
424       return(DD_TRUE);
425     }
426   return(DD_FALSE);
427 }
428
429 bool
430 cl_cmdline::set_data_list(class cl_cmd_arg *parm, int *iparm)
431 {
432   class cl_cmd_arg *next_parm;
433   int len, i, j;
434   t_mem *array;
435
436   len= 0;
437   array= 0;
438   for (i= *iparm, next_parm= param(i); next_parm; i++, next_parm= param(i))
439     {
440       if (next_parm->is_string())
441         {
442           int l;
443           char *s;
444           //s= proc_escape(next_parm->get_svalue(), &l);
445           if (!next_parm->as_string())
446             continue;
447           s= next_parm->value.string.string;
448           l= next_parm->value.string.len;
449           if (!array)
450             array= (t_mem*)malloc(sizeof(t_mem)*l);
451           else
452             array= (t_mem*)realloc(array, sizeof(t_mem)*(l+len));
453           for (j= 0; j < l; j++)
454             {
455               array[len]= s[j];
456               len++;
457             }
458           //if (s)
459           //free(s);
460         }
461       else
462         {
463           if (!next_parm->as_data())
464             {
465               if (array)
466                 free(array);
467               return(DD_FALSE);
468             }
469           if (!array)
470             array= (t_mem*)malloc(sizeof(t_mem));
471           else
472             array= (t_mem*)realloc(array, sizeof(t_mem)*(1+len));
473           array[len]= next_parm->value.data;
474           len++;
475         }
476     }
477   *iparm= i;
478   parm->value.data_list.array= array;
479   parm->value.data_list.len= len;
480   return(DD_TRUE);
481 }
482
483
484 /*
485  * Command
486  *____________________________________________________________________________
487  */
488
489 cl_cmd::cl_cmd(enum cmd_operate_on op_on,
490                char *aname,
491                int can_rep,
492                char *short_hlp,
493                char *long_hlp):
494   cl_base()
495 {
496   operate_on= op_on;
497   names= new cl_strings(1, 1);
498   names->add(aname?strdup(aname):strdup("unknown"));
499   can_repeat= can_rep;
500   short_help= short_hlp?strdup(short_hlp):NULL;
501   long_help= long_hlp?strdup(long_hlp):NULL;
502 }
503
504 /*cl_cmd::cl_cmd(class cl_sim *asim):
505   cl_base()
506 {
507   sim= asim;
508   name= short_help= long_help= 0;
509   can_repeat= 0;
510 }*/
511
512 cl_cmd::~cl_cmd(void)
513 {
514   delete names;
515   if (short_help)
516     free(short_help);
517   if (long_help)
518     free(long_help);
519 }
520
521 void
522 cl_cmd::add_name(char *nam)
523 {
524   if (nam)
525     names->add(strdup(nam));
526 }
527
528 int
529 cl_cmd::name_match(char *aname, int strict)
530 {
531   int i;
532   
533   if (names->count == 0 &&
534       !aname)
535     return(1);
536   if (!aname)
537     return(0);
538   if (strict)
539     {
540       for (i= 0; i < names->count; i++)
541         {
542           char *n= (char*)(names->at(i));
543           if (strcmp(aname, n) == 0)
544             return(1);
545         }
546     }
547   else
548     {
549       for (i= 0; i < names->count; i++)
550         {
551           char *n= (char*)(names->at(i));
552           if (strstr(n, aname) == n)
553             return(1);
554         }
555     }
556   return(0);
557 }
558
559 int
560 cl_cmd::name_match(class cl_cmdline *cmdline, int strict)
561 {
562   return(name_match(cmdline->get_name(), strict));
563 }
564
565 int
566 cl_cmd::syntax_ok(class cl_cmdline *cmdline)
567 {
568   return(1);
569 }
570
571 int
572 cl_cmd::work(class cl_app *app,
573              class cl_cmdline *cmdline, class cl_console *con)
574 {
575   if (!syntax_ok(cmdline))
576     return(0);
577   class cl_sim *sim= app->get_sim();
578   class cl_uc *uc= 0;
579   if (sim)
580     uc= sim->uc;
581   switch (operate_on)
582     {
583     case operate_on_app:
584       if (!app)
585         {
586           con->dd_printf("There is no application to work on!\n");
587           return(DD_TRUE);
588         }
589       return(do_work(app, cmdline, con));
590     case operate_on_sim:
591       if (!sim)
592         {
593           con->dd_printf("There is no simulator to work on!\n");
594           return(DD_TRUE);
595         }
596       return(do_work(sim, cmdline, con));
597     case operate_on_uc:
598       if (!sim)
599         {
600           con->dd_printf("There is no microcontroller to work on!\n");
601           return(DD_TRUE);
602         }
603       return(do_work(uc, cmdline, con));
604     default:
605       return(do_work(cmdline, con));
606     }
607 }
608
609 int
610 cl_cmd::do_work(class cl_cmdline *cmdline, class cl_console *con)
611 {
612   con->dd_printf("Command \"%s\" does nothing.\n",
613                  (char*)(names->at(0)));
614   return(0);
615 }
616
617 int
618 cl_cmd::do_work(class cl_app *app,
619                 class cl_cmdline *cmdline, class cl_console *con)
620 {
621   con->dd_printf("Command \"%s\" does nothing on application.\n",
622                  (char*)(names->at(0)));
623   return(0);
624 }
625
626 int
627 cl_cmd::do_work(class cl_sim *sim,
628                 class cl_cmdline *cmdline, class cl_console *con)
629 {
630   con->dd_printf("Command \"%s\" does nothing on simulator.\n",
631                  (char*)(names->at(0)));
632   return(0);
633 }
634
635 int
636 cl_cmd::do_work(class cl_uc *uc,
637                 class cl_cmdline *cmdline, class cl_console *con)
638 {
639   con->dd_printf("Command \"%s\" does nothing on microcontroller.\n",
640                  (char*)(names->at(0)));
641   return(0);
642 }
643
644
645 /*
646  * Set of commands
647  *____________________________________________________________________________
648  */
649
650 cl_cmdset::cl_cmdset(void):
651   cl_list(5, 5)
652 {
653   //sim= 0;
654   last_command= 0;
655 }
656
657 /*cl_cmdset::cl_cmdset(class cl_sim *asim):
658   cl_list(5, 5)
659 {
660   sim= asim;
661   last_command= 0;
662 }*/
663
664 class cl_cmd *
665 cl_cmdset::get_cmd(class cl_cmdline *cmdline)
666 {
667   int i;
668
669   if (cmdline->repeat())
670     {
671       if (last_command)
672         return(last_command);
673       else
674         return(0);
675     }
676   // exact match
677   for (i= 0; i < count; i++)
678     {
679       class cl_cmd *c= (class cl_cmd *)at(i);
680       if (c->name_match(cmdline, 1))
681         return(c);
682     }
683   // not exact match
684   class cl_cmd *c_matched= 0;
685   for (i= 0; i < count; i++)
686     {
687       class cl_cmd *c= (class cl_cmd *)at(i);
688       if (c->name_match(cmdline, 0))
689         {
690           if (!c_matched)
691             c_matched= c;
692           else
693             return(0);
694         }
695     }
696   return(c_matched);
697   //return(0);
698 }
699
700 class cl_cmd *
701 cl_cmdset::get_cmd(char *cmd_name)
702 {
703   int i;
704
705   for (i= 0; i < count; i++)
706     {
707       class cl_cmd *c= (class cl_cmd *)at(i);
708       if (c->name_match(cmd_name, 1))
709         return(c);
710     }
711   return(0);
712 }
713
714 void
715 cl_cmdset::del(char *nam)
716 {
717   int i;
718
719   if (!nam)
720     return;
721   for (i= 0; i < count; i++)
722     {
723       class cl_cmd *cmd= (class cl_cmd *)(at(i));
724       if (cmd->name_match(nam, 1))
725         free_at(i);
726     }
727 }
728
729 void
730 cl_cmdset::replace(char *nam, class cl_cmd *cmd)
731 {
732   int i;
733
734   if (!nam)
735     return;
736   for (i= 0; i < count; i++)
737     {
738       class cl_cmd *c= (class cl_cmd *)(at(i));
739       if (c->name_match(nam, 1))
740         {
741           delete c;
742           put_at(i, cmd);
743         }
744     }
745 }
746
747
748 /*
749  * Composed command: subset of commands
750  *____________________________________________________________________________
751  */
752
753 cl_super_cmd::cl_super_cmd(char *aname,
754                            int  can_rep,
755                            char *short_hlp,
756                            char *long_hlp,
757                            class cl_cmdset *acommands):
758   cl_cmd(operate_on_none, aname, can_rep, short_hlp, long_hlp)
759 {
760   commands= acommands;
761 }
762
763 cl_super_cmd::~cl_super_cmd(void)
764 {
765   if (commands)
766     delete commands;
767 }
768
769 int
770 cl_super_cmd::work(class cl_app *app,
771                    class cl_cmdline *cmdline, class cl_console *con)
772 {
773   class cl_cmd *cmd= 0;
774
775   if (!commands)
776     return(0);
777   
778   if (!cmdline->shift())
779     {
780       if ((cmd= commands->get_cmd("_no_parameters_")) != 0)
781         return(cmd->work(app, cmdline, con));
782       int i;
783       con->dd_printf("\"%s\" must be followed by the name of a subcommand\n"
784                      "List of subcommands:\n", (char*)(names->at(0)));
785       for (i= 0; i < commands->count; i++)
786         {
787           cmd= (class cl_cmd *)(commands->at(i));
788           con->dd_printf("%s\n", cmd->short_help);
789         }
790       return(0);
791     }
792   if ((cmd= commands->get_cmd(cmdline)) == NULL)
793     {
794       con->dd_printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
795                      cmdline->get_name(), (char*)(names->at(0)));
796       return(0);
797     }
798   return(cmd->work(app, cmdline, con));
799 }
800
801
802 /* End of cmd.src/command.cc */