fixed bug #490097
[fw/sdcc] / debugger / mcs51 / cmd.c
1 /*-------------------------------------------------------------------------
2     cmd.c - source  file for debugger command execution
3
4               Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19    
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!  
23 -------------------------------------------------------------------------*/
24
25 #include "sdcdb.h"
26 #include "symtab.h"
27 #include "simi.h"
28 #include "break.h"
29 #include "cmd.h"
30
31 int listLines = 10;
32 EXTERN_STACK_DCL(callStack,function *,1024);
33
34 #if defined(__APPLE__) && defined(__MACH__)
35 static char *copying=
36 {" GNU GENERAL PUBLIC LICENSE Version 2"};
37 static char *warranty=
38 {" NO WARRANTY"};
39 #else
40 static char *copying=
41 "                   GNU GENERAL PUBLIC LICENSE
42                        Version 2, June 1991
43
44  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
45  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
46  Everyone is permitted to copy and distribute verbatim copies
47  of this license document, but changing it is not allowed.
48
49                             Preamble
50
51   The licenses for most software are designed to take away your
52 freedom to share and change it.  By contrast, the GNU General Public
53 License is intended to guarantee your freedom to share and change free
54 software--to make sure the software is free for all its users.  This
55 General Public License applies to most of the Free Software
56 Foundation's software and to any other program whose authors commit to
57 using it.  (Some other Free Software Foundation software is covered by
58 the GNU Library General Public License instead.)  You can apply it to
59 your programs, too.
60
61   When we speak of free software, we are referring to freedom, not
62 price.  Our General Public Licenses are designed to make sure that you
63 have the freedom to distribute copies of free software (and charge for
64 this service if you wish), that you receive source code or can get it
65 if you want it, that you can change the software or use pieces of it
66 in new free programs; and that you know you can do these things.
67
68   To protect your rights, we need to make restrictions that forbid
69 anyone to deny you these rights or to ask you to surrender the rights.
70 These restrictions translate to certain responsibilities for you if you
71 distribute copies of the software, or if you modify it.
72
73   For example, if you distribute copies of such a program, whether
74 gratis or for a fee, you must give the recipients all the rights that
75 you have.  You must make sure that they, too, receive or can get the
76 source code.  And you must show them these terms so they know their
77 rights.
78
79   We protect your rights with two steps: (1) copyright the software, and
80 (2) offer you this license which gives you legal permission to copy,
81 distribute and/or modify the software.
82
83   Also, for each author's protection and ours, we want to make certain
84 that everyone understands that there is no warranty for this free
85 software.  If the software is modified by someone else and passed on, we
86 want its recipients to know that what they have is not the original, so
87 that any problems introduced by others will not reflect on the original
88 authors' reputations.
89
90   Finally, any free program is threatened constantly by software
91 patents.  We wish to avoid the danger that redistributors of a free
92 program will individually obtain patent licenses, in effect making the
93 program proprietary.  To prevent this, we have made it clear that any
94 patent must be licensed for everyone's free use or not licensed at all.
95
96   The precise terms and conditions for copying, distribution and
97 modification follow.
98 ^L
99                     GNU GENERAL PUBLIC LICENSE
100    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
101
102   0. This License applies to any program or other work which contains
103 a notice placed by the copyright holder saying it may be distributed
104 under the terms of this General Public License.  The \"Program\", below,
105 refers to any such program or work, and a \"work based on the Program\"
106 means either the Program or any derivative work under copyright law:
107 that is to say, a work containing the Program or a portion of it,
108 either verbatim or with modifications and/or translated into another
109 language.  (Hereinafter, translation is included without limitation in
110 the term \"modification\".)  Each licensee is addressed as \"you\".
111
112 Activities other than copying, distribution and modification are not
113 covered by this License; they are outside its scope.  The act of
114 running the Program is not restricted, and the output from the Program
115 is covered only if its contents constitute a work based on the
116 Program (independent of having been made by running the Program).
117 Whether that is true depends on what the Program does.
118
119   1. You may copy and distribute verbatim copies of the Program's
120 source code as you receive it, in any medium, provided that you
121 conspicuously and appropriately publish on each copy an appropriate
122 copyright notice and disclaimer of warranty; keep intact all the
123 notices that refer to this License and to the absence of any warranty;
124 and give any other recipients of the Program a copy of this License
125 along with the Program.
126
127 You may charge a fee for the physical act of transferring a copy, and
128 you may at your option offer warranty protection in exchange for a fee.
129
130   2. You may modify your copy or copies of the Program or any portion
131 of it, thus forming a work based on the Program, and copy and
132 distribute such modifications or work under the terms of Section 1
133 above, provided that you also meet all of these conditions:
134
135     a) You must cause the modified files to carry prominent notices
136     stating that you changed the files and the date of any change.
137
138     b) You must cause any work that you distribute or publish, that in
139     whole or in part contains or is derived from the Program or any
140     part thereof, to be licensed as a whole at no charge to all third
141     parties under the terms of this License.
142
143     c) If the modified program normally reads commands interactively
144     when run, you must cause it, when started running for such
145     interactive use in the most ordinary way, to print or display an
146     announcement including an appropriate copyright notice and a
147     notice that there is no warranty (or else, saying that you provide
148     a warranty) and that users may redistribute the program under
149     these conditions, and telling the user how to view a copy of this
150     License.  (Exception: if the Program itself is interactive but
151     does not normally print such an announcement, your work based on
152     the Program is not required to print an announcement.)
153
154 These requirements apply to the modified work as a whole.  If
155 identifiable sections of that work are not derived from the Program,
156 and can be reasonably considered independent and separate works in
157 themselves, then this License, and its terms, do not apply to those
158 sections when you distribute them as separate works.  But when you
159 distribute the same sections as part of a whole which is a work based
160 on the Program, the distribution of the whole must be on the terms of
161 this License, whose permissions for other licensees extend to the
162 entire whole, and thus to each and every part regardless of who wrote it.
163
164 Thus, it is not the intent of this section to claim rights or contest
165 your rights to work written entirely by you; rather, the intent is to
166 exercise the right to control the distribution of derivative or
167 collective works based on the Program.
168
169 In addition, mere aggregation of another work not based on the Program
170 with the Program (or with a work based on the Program) on a volume of
171 a storage or distribution medium does not bring the other work under
172 the scope of this License.
173
174   3. You may copy and distribute the Program (or a work based on it,
175 under Section 2) in object code or executable form under the terms of
176 Sections 1 and 2 above provided that you also do one of the following:
177
178     a) Accompany it with the complete corresponding machine-readable
179     source code, which must be distributed under the terms of Sections
180     1 and 2 above on a medium customarily used for software interchange; or,
181
182     b) Accompany it with a written offer, valid for at least three
183     years, to give any third party, for a charge no more than your
184     cost of physically performing source distribution, a complete
185     machine-readable copy of the corresponding source code, to be
186     distributed under the terms of Sections 1 and 2 above on a medium
187     customarily used for software interchange; or,
188
189     c) Accompany it with the information you received as to the offer
190     to distribute corresponding source code.  (This alternative is
191     allowed only for noncommercial distribution and only if you
192     received the program in object code or executable form with such
193     an offer, in accord with Subsection b above.)
194
195 The source code for a work means the preferred form of the work for
196 making modifications to it.  For an executable work, complete source
197 code means all the source code for all modules it contains, plus any
198 associated interface definition files, plus the scripts used to
199 control compilation and installation of the executable.  However, as a
200 special exception, the source code distributed need not include
201 anything that is normally distributed (in either source or binary
202 form) with the major components (compiler, kernel, and so on) of the
203 operating system on which the executable runs, unless that component
204 itself accompanies the executable.
205
206 If distribution of executable or object code is made by offering
207 access to copy from a designated place, then offering equivalent
208 access to copy the source code from the same place counts as
209 distribution of the source code, even though third parties are not
210 compelled to copy the source along with the object code.
211 ^L
212   4. You may not copy, modify, sublicense, or distribute the Program
213 except as expressly provided under this License.  Any attempt
214 otherwise to copy, modify, sublicense or distribute the Program is
215 void, and will automatically terminate your rights under this License.
216 However, parties who have received copies, or rights, from you under
217 this License will not have their licenses terminated so long as such
218 parties remain in full compliance.
219
220   5. You are not required to accept this License, since you have not
221 signed it.  However, nothing else grants you permission to modify or
222 distribute the Program or its derivative works.  These actions are
223 prohibited by law if you do not accept this License.  Therefore, by
224 modifying or distributing the Program (or any work based on the
225 Program), you indicate your acceptance of this License to do so, and
226 all its terms and conditions for copying, distributing or modifying
227 the Program or works based on it.
228
229   6. Each time you redistribute the Program (or any work based on the
230 Program), the recipient automatically receives a license from the
231 original licensor to copy, distribute or modify the Program subject to
232 these terms and conditions.  You may not impose any further
233 restrictions on the recipients' exercise of the rights granted herein.
234 You are not responsible for enforcing compliance by third parties to
235 this License.
236
237   7. If, as a consequence of a court judgment or allegation of patent
238 infringement or for any other reason (not limited to patent issues),
239 conditions are imposed on you (whether by court order, agreement or
240 otherwise) that contradict the conditions of this License, they do not
241 excuse you from the conditions of this License.  If you cannot
242 distribute so as to satisfy simultaneously your obligations under this
243 License and any other pertinent obligations, then as a consequence you
244 may not distribute the Program at all.  For example, if a patent
245 license would not permit royalty-free redistribution of the Program by
246 all those who receive copies directly or indirectly through you, then
247 the only way you could satisfy both it and this License would be to
248 refrain entirely from distribution of the Program.
249
250 If any portion of this section is held invalid or unenforceable under
251 any particular circumstance, the balance of the section is intended to
252 apply and the section as a whole is intended to apply in other
253 circumstances.
254
255 It is not the purpose of this section to induce you to infringe any
256 patents or other property right claims or to contest validity of any
257 such claims; this section has the sole purpose of protecting the
258 integrity of the free software distribution system, which is
259 implemented by public license practices.  Many people have made
260 generous contributions to the wide range of software distributed
261 through that system in reliance on consistent application of that
262 system; it is up to the author/donor to decide if he or she is willing
263 to distribute software through any other system and a licensee cannot
264 impose that choice.
265
266 This section is intended to make thoroughly clear what is believed to
267 be a consequence of the rest of this License.
268
269   8. If the distribution and/or use of the Program is restricted in
270 certain countries either by patents or by copyrighted interfaces, the
271 original copyright holder who places the Program under this License
272 may add an explicit geographical distribution limitation excluding
273 those countries, so that distribution is permitted only in or among
274 countries not thus excluded.  In such case, this License incorporates
275 the limitation as if written in the body of this License.
276
277   9. The Free Software Foundation may publish revised and/or new versions
278 of the General Public License from time to time.  Such new versions will
279 be similar in spirit to the present version, but may differ in detail to
280 address new problems or concerns.
281
282 Each version is given a distinguishing version number.  If the Program
283 specifies a version number of this License which applies to it and \"any
284 later version\", you have the option of following the terms and conditions
285 either of that version or of any later version published by the Free
286 Software Foundation.  If the Program does not specify a version number of
287 this License, you may choose any version ever published by the Free Software
288 Foundation.
289
290   10. If you wish to incorporate parts of the Program into other free
291 programs whose distribution conditions are different, write to the author
292 to ask for permission.  For software which is copyrighted by the Free
293 Software Foundation, write to the Free Software Foundation; we sometimes
294 make exceptions for this.  Our decision will be guided by the two goals
295 of preserving the free status of all derivatives of our free software and
296 of promoting the sharing and reuse of software generally.
297 ";
298 static char *warranty=
299 "                            NO WARRANTY
300
301   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
302 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
303 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
304 PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
305 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
306 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
307 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
308 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
309 REPAIR OR CORRECTION.
310
311   12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
312 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
313 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
314 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
315 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
316 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
317 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
318 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
319 POSSIBILITY OF SUCH DAMAGES.
320 ";
321 #endif
322
323 static void printTypeInfo(link *);
324 static void printValAggregates (symbol *,link *,char,unsigned int);
325
326 int srcMode = SRC_CMODE ;
327
328 /*-----------------------------------------------------------------*/
329 /* funcWithName - returns function with name                       */
330 /*-----------------------------------------------------------------*/
331 DEFSETFUNC(funcWithName)
332 {
333     function *func = item;
334     V_ARG(char *,name);
335     V_ARG(function **,funcp);
336
337     if (*funcp)
338         return 0;
339
340     if (strcmp(func->sym->name,name) == 0) {
341         *funcp = func;
342         return 1;
343     }
344     
345     return 0;
346 }
347
348 /*-----------------------------------------------------------------*/
349 /* setBPatModLine - set break point at the line specified for the  */
350 /*-----------------------------------------------------------------*/
351 static void setBPatModLine (module *mod, int line)
352 {
353     /* look for the first executable line after the line
354        specified & get the break point there */    
355     if (srcMode == SRC_CMODE && line > mod->ncLines) {
356         fprintf(stderr,"No line %d in file \"%s\".\n",
357                 line,mod->c_name);
358         return ;
359     }
360     
361     if (srcMode == SRC_AMODE && line > mod->nasmLines) {
362         fprintf(stderr,"No line %d in file \"%s\".\n",
363                 line,mod->asm_name);
364         return ;
365     }
366
367     for ( ; line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ; 
368           line++ ) {
369         if (srcMode == SRC_CMODE) {
370             if (mod->cLines[line]->addr) {
371                 setBreakPoint (mod->cLines[line]->addr, CODE, USER, 
372                                userBpCB, mod->c_name, line);
373                 break;
374             }
375         }
376         else {
377            if (mod->asmLines[line]->addr) {
378                setBreakPoint (mod->asmLines[line]->addr, CODE, USER, 
379                               userBpCB, mod->asm_name, line);
380                break;
381            } 
382         }
383     }
384
385     return;
386 }
387
388 /*-----------------------------------------------------------------*/
389 /* clearBPatModLine - clr break point at the line specified        */
390 /*-----------------------------------------------------------------*/
391 static void clearBPatModLine (module *mod, int line)
392 {
393     /* look for the first executable line after the line
394        specified & get the break point there */
395     if (srcMode == SRC_CMODE && line > mod->ncLines) {
396         fprintf(stderr,"No line %d in file \"%s\".\n",
397                 line,mod->c_name);
398         return ;
399     }
400     
401     if (srcMode == SRC_AMODE && line > mod->ncLines) {
402         fprintf(stderr,"No line %d in file \"%s\".\n",
403                 line,mod->c_name);
404         return ;
405     }    
406     
407     for ( ; line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ; 
408           line++ ) {
409         if (srcMode == SRC_CMODE) 
410             if (mod->cLines[line]->addr) {
411                 clearUSERbp (mod->cLines[line]->addr);                    
412                 break;
413             }
414         else
415             if (mod->asmLines[line]->addr) {
416                 clearUSERbp (mod->asmLines[line]->addr);                          
417                 break;
418             }
419     }
420
421     return;
422 }
423
424 /*-----------------------------------------------------------------*/
425 /* funcWithNameModule - returns functions with a name module combo */
426 /*-----------------------------------------------------------------*/
427 DEFSETFUNC(funcWithNameModule) 
428 {
429     function *func = item;
430     V_ARG(char *,fname);
431     V_ARG(char *,mname);
432     V_ARG(function **,funcp);
433
434     if (*funcp)
435         return 0;
436
437     if (strcmp(func->sym->name,fname) == 0 &&
438         strcmp(func->mod->c_name,mname) == 0) {
439         *funcp = func;
440         return 1;
441     }
442
443     return 0;
444 }
445
446 /*-----------------------------------------------------------------*/
447 /* funcInAddr - given an address returns the function              */
448 /*-----------------------------------------------------------------*/
449 DEFSETFUNC(funcInAddr)
450 {
451     function *func = item;
452     V_ARG(unsigned int,addr);
453     V_ARG(function **,funcp);
454
455     if (*funcp)
456         return 0;
457
458     /* in the address range */
459     if (func->sym->addr <= addr &&
460         func->sym->eaddr >= addr) {
461         
462         *funcp = func;
463         return 1;
464     }
465
466     return 0;       
467 }
468
469 /*-----------------------------------------------------------------*/
470 /* setStepBp - will set STEP Bp @ function entry points            */
471 /*-----------------------------------------------------------------*/
472 DEFSETFUNC(setStepBp)
473 {
474     function *func = item;
475     
476     if (func->sym && func->sym->addr ) {
477         
478         /* set the entry break point */
479         setBreakPoint (func->sym->addr , CODE , STEP , 
480                        stepBpCB ,func->mod->c_name , func->entryline);
481
482         return 1;
483     }
484
485     return 0;
486 }
487
488 /*-----------------------------------------------------------------*/
489 /* setStepEPBp - sets a given type of bp @ the execution point     */
490 /*-----------------------------------------------------------------*/
491 DEFSETFUNC(setStepEPBp)
492 {
493     exePoint *ep = item;
494     V_ARG(int,bptype);
495     V_ARG(char *,mname);
496    
497     setBreakPoint (ep->addr, CODE, bptype, 
498                    stepBpCB, mname, ep->line);
499     return 1;
500 }
501
502 /*-----------------------------------------------------------------*/
503 /* setNextEPBp - sets a given type of bp @ the execution point     */
504 /*-----------------------------------------------------------------*/
505 DEFSETFUNC(setNextEPBp)
506 {
507     exePoint *ep = item;
508     V_ARG(int,bptype);
509     V_ARG(char *,mname);
510    
511     setBreakPoint (ep->addr, CODE, bptype, 
512                    nextBpCB, mname, ep->line);
513     return 1;
514 }
515
516 /*-----------------------------------------------------------------*/
517 /* lineAtAddr - for execution points returns the one with addr     */
518 /*-----------------------------------------------------------------*/
519 DEFSETFUNC(lineAtAddr)
520 {
521     exePoint *ep = item;
522     V_ARG(unsigned int,addr);
523     V_ARG(int *,line);
524     V_ARG(int *,block);
525     V_ARG(int *,level);
526
527     /* address must be an exact match */
528     if (ep->addr == addr) {
529         *line = ep->line;
530         if (block)
531             *block = ep->block ;
532         if (level)
533             *level = ep->level ;
534         return 1;
535     }
536
537     return 0;
538     
539 }
540
541 /*-----------------------------------------------------------------*/
542 /* discoverContext - find out the current context of the bp        */
543 /*-----------------------------------------------------------------*/
544 context *discoverContext (unsigned addr)
545 {
546     function *func = NULL;
547     int line = 0;
548
549     /* find the function we are in */
550     if (!applyToSet(functions,funcInAddr,addr,&func)) {
551       fprintf(stderr, "Error?:discoverContext: cannot apply to set!\n");
552         return NULL;
553     }
554
555     currCtxt->func = func;
556     currCtxt->addr = func->laddr = addr;
557     currCtxt->modName = func->modName;
558     
559     /* find the c line number */
560     if(applyToSet(func->cfpoints,lineAtAddr,addr,
561                   &line,&currCtxt->block,&currCtxt->level)) 
562         currCtxt->cline = func->lline = line;
563     else
564         currCtxt->cline = func->exitline;
565     
566     /* find the asm line number */
567     line = 0;
568     if (applyToSet(func->afpoints,lineAtAddr,addr,
569                    &line,NULL,NULL))
570         currCtxt->asmline = line;       
571     else
572         currCtxt->asmline = -1;
573         
574     return currCtxt ;
575 }
576
577
578 /*-----------------------------------------------------------------*/
579 /* simGo - send 'go' cmd to simulator and wait till a break occurs */
580 /*-----------------------------------------------------------------*/
581 void simGo (unsigned int gaddr)
582 {   
583     unsigned int addr ;
584     context *ctxt;
585     int rv;
586     static int initial_break_flag = 0;
587
588  top:    
589     addr = simGoTillBp (gaddr);
590
591     /* got the pc for the break point now first
592        discover the program context i.e. module, function 
593        linenumber of the source etc, etc etc */
594     ctxt = discoverContext (addr);
595     
596     /* dispatch all the break point call back functions */
597     rv = dispatchCB (addr,ctxt);    
598
599  ret:    
600
601     /* the dispatch call back function will return
602        non-zero if an user break point has been hit
603        if not then we continue with the execution 
604        of the program */
605     if (!rv) {
606       if (!initial_break_flag) {
607         initial_break_flag = 1;  // kludge to stop only at first run
608         fprintf(stdout, "Stopping at entry.  You can now list and set breakpoints\n");
609       }
610       else {
611         gaddr = -1;
612         goto top ;
613       }
614
615 // notes: kpb
616 // I took this out, after running "run" it would just keep re-running
617 // even after a lot of break points hit.  For some reason above code
618 // not triggering(dispatchCB).  This seems to be by design, startup adds
619 // a bunch of breakpoints-but they are not USER breakpoints.  Perhaps the
620 // debugger changed with its implementation of "go"("run").  It seems we
621 // need to add a "next" or "step" followed by a "run"...
622 // I added a "step" in simi.c when we want a resume function, this seems
623 // to work.
624
625 // still there is question of how do we stop it initially, since
626 // it must be started before it can get a context.  If so, we would
627 // want it to just run up to an initial entry point you'd think...
628 // I don't see why we can't set breakpoints before an initial run,
629 // this does not seem right to me.
630
631 // line #'s are a bit off too.
632
633 #if 0
634         gaddr = -1;
635         goto top ;
636 #endif
637     }
638     
639 }
640
641 /*-----------------------------------------------------------------*/
642 /* cmdSetUserBp - set break point at the user specified location   */
643 /*-----------------------------------------------------------------*/
644 int cmdSetUserBp (char *s, context *cctxt)
645 {
646     char *bp ;
647     function *func = NULL;
648         
649     /* user break point location specification can be of the following
650        forms
651        a) <nothing>        - break point at current location
652        b) lineno           - number of the current module
653        c) filename:lineno  - line number of the given file
654        e) filename:function- function X in file Y (useful for static functions)
655        f) function         - function entry point
656     */
657
658     if (!cctxt) {
659         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
660         return 0;
661     }
662     /* white space skip */
663     while (*s && isspace(*s)) s++;
664     
665     /* null terminate it after stripping trailing blanks*/
666     bp = s + strlen(s);
667     while (bp != s && isspace(*bp)) bp--;
668     *bp = '\0';
669
670     /* case a) nothing */
671     /* if nothing given then current location : we know
672        the current execution location from the currentContext */
673     if (! *s ) {
674
675         /* if current context is known */
676         if (cctxt->func) {
677             if (srcMode == SRC_CMODE)
678                 /* set the break point */
679                 setBreakPoint ( cctxt->addr , CODE , USER , userBpCB ,
680                                 cctxt->func->mod->c_name, cctxt->cline);
681             else
682                 setBreakPoint ( cctxt->addr , CODE , USER , userBpCB ,
683                                 cctxt->func->mod->asm_name, cctxt->asmline);
684                 
685         }
686         else
687             fprintf(stderr,"No default breakpoint address now.\n");
688                         
689         goto ret ;
690     }
691
692     /* case b) lineno */
693     /* check if line number */
694     if (isdigit(*s)) {
695         /* get the lineno */
696         int line = atoi(s);
697
698         /* if current context not present then we must get the module
699            which has main & set the break point @ line number provided
700            of that module : if current context known then set the bp 
701            at the line number given for the current module 
702         */
703         if (cctxt->func) {
704             if (!cctxt->func->mod) {
705                 if (!applyToSet(functions,funcWithName,"main"))
706                     fprintf(stderr,"Function \"main\" not defined.\n");
707                 else 
708                     setBPatModLine(func->mod,line);
709             } else 
710                 setBPatModLine(cctxt->func->mod,line);                  
711         } else {
712                 fprintf(stdout,"No symbol information currently\n");
713         }
714         
715         goto ret;
716     }
717
718     if ((bp = strchr(s,':'))) {
719         
720         module *mod = NULL;
721         *bp = '\0';
722         
723         if (srcMode == SRC_CMODE) {
724             if (!applyToSet(modules,moduleWithCName,s,&mod)) {
725                 fprintf (stderr,"No source file named %s.\n",s);
726                 goto ret;
727             }
728         } else {
729             if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
730                 fprintf (stderr,"No source file named %s.\n",s);
731                 goto ret;
732             }
733         }
734                 
735         /* case c) filename:lineno */
736         if (isdigit(*(bp +1))) {                    
737          
738             setBPatModLine (mod,atoi(bp+1));        
739             goto ret;
740             
741         }
742         /* case d) filename:function */
743         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
744             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
745         else        
746             setBPatModLine (mod,
747                             (srcMode == SRC_CMODE ? 
748                              func->entryline :
749                              func->aentryline));
750         
751         goto ret;
752     }
753             
754     /* case e) function */
755     if (!applyToSet(functions,funcWithName,s,&func))
756         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
757     else
758         setBPatModLine(func->mod,
759                        (srcMode == SRC_CMODE ?
760                         func->entryline :
761                         func->aentryline));
762
763  ret:    
764     return 0;
765 }
766
767 /*-----------------------------------------------------------------*/
768 /* cmdListAsm - list assembler source code                         */
769 /*-----------------------------------------------------------------*/
770 int cmdListAsm (char *s, context *cctxt)
771 {
772     fprintf(stderr,"'listasm' command not yet implemented\n");
773     return 0;
774 }
775
776 /*-----------------------------------------------------------------*/
777 /* cmdSetOption - set debugger options                             */
778 /*-----------------------------------------------------------------*/
779 int cmdSetOption (char *s, context *cctxt)
780 {
781     while (*s && isspace(*s)) s++;
782     if (strncmp(s,"srcmode",7) == 0 ) {
783         if (srcMode == SRC_CMODE)
784             srcMode = SRC_AMODE;
785         else
786             srcMode = SRC_CMODE;
787         fprintf(stderr,"source mode set to '%s'\n", 
788                 (srcMode == SRC_CMODE ? "C" : "asm"));
789         return 0;
790     }
791     
792     fprintf(stderr,"'set %s' command not yet implemented\n",s);
793     return 0;
794 }
795
796 /*-----------------------------------------------------------------*/
797 /* cmdContinue - continue till next break point                    */
798 /*-----------------------------------------------------------------*/
799 int cmdContinue (char *s, context *cctxt)
800 {
801     if (!cctxt || !cctxt->func) {
802         fprintf(stdout,"The program is not being run.\n");
803         return 0;
804     }
805
806     fprintf(stdout,"Continuing.\n");
807     simGo(-1);
808     return 0;
809 }
810
811 /*-----------------------------------------------------------------*/
812 /* cmdDelUserBp - delete user break point                          */
813 /*-----------------------------------------------------------------*/
814 int cmdDelUserBp (char *s, context *cctxt)
815 {
816     int bpnum ;
817     while (isspace(*s)) s++;
818     
819     if (!*s ) {
820         if (userBpPresent) {
821             char buffer[10];
822             fprintf (stdout,"Delete all breakpoints? (y or n) ");
823             fflush(stdout);
824             fgets(buffer,sizeof(buffer),stdin);
825             if (toupper(buffer[0]) == 'Y')
826                 deleteUSERbp(-1);          
827         }
828         return 0;
829     }
830     
831     /* determine the break point number */
832     if (sscanf(s,"%d",&bpnum) == 1)
833         deleteUSERbp(bpnum);
834
835     return 0;
836 }
837
838 /*-----------------------------------------------------------------*/
839 /* cmdStep - single step thru C source file                        */
840 /*-----------------------------------------------------------------*/
841 int cmdStep (char *s, context *cctxt)
842 {
843     function *func = NULL;
844
845     if (!cctxt || !cctxt->func || !cctxt->func->mod) 
846         fprintf(stdout,"The program is not being run.\n");
847     else {
848         /* if we are @ the end of a function then set
849            break points at execution points of the
850            function in the call stack... */
851         if (cctxt->addr == cctxt->func->sym->eaddr) {
852             if ((func = STACK_PEEK(callStack))) {
853                 if (srcMode == SRC_CMODE)
854                     applyToSet (func->cfpoints,setStepEPBp,STEP,
855                                 func->mod->c_name);     
856                 else
857                     applyToSet (func->afpoints,setStepEPBp,STEP,
858                                 func->mod->asm_name);
859             }
860         } else {
861             /* set breakpoints at all function entry points
862                and all exepoints of this functions & for
863                all functions one up in the call stack */
864             
865             /* all function entry points */
866             applyToSet(functions,setStepBp); 
867             
868             if (srcMode == SRC_CMODE) {
869                 /* for all execution points in this function */
870                 applyToSet(cctxt->func->cfpoints,setStepEPBp,STEP,
871                            cctxt->func->mod->c_name);
872                 
873                 /* set a break point @ the current function's
874                    exit */
875                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
876                                stepBpCB, cctxt->func->mod->c_name, 
877                                cctxt->func->exitline);
878                 
879                 /* now break point @ callers execution points */
880                 if ((func = STACK_PPEEK(callStack))) {
881                     applyToSet (func->cfpoints,setStepEPBp,STEP,
882                                 func->mod->c_name);     
883                     /* set bp @ callers exit point */
884                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
885                                    stepBpCB, func->mod->c_name, 
886                                    func->exitline);
887                 }
888             } else {
889                 /* for all execution points in this function */
890                 applyToSet(cctxt->func->afpoints,setStepEPBp,STEP,
891                            cctxt->func->mod->asm_name);
892                 
893                 /* set a break point @ the current function's
894                    exit */
895                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
896                                stepBpCB, cctxt->func->mod->asm_name, 
897                                cctxt->func->aexitline);
898                 
899                 /* now break point @ callers execution points */
900                 if ((func = STACK_PPEEK(callStack))) {
901                     
902                     applyToSet (func->afpoints,setStepEPBp,STEP,
903                                 func->mod->asm_name);   
904                     
905                     /* set bp @ callers exit point */
906                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
907                                    stepBpCB, func->mod->asm_name, 
908                                    func->aexitline);
909                 }
910             }
911         }
912
913         simGo(-1);
914     }
915     return 0;
916 }
917
918 /*-----------------------------------------------------------------*/
919 /* cmdNext - next executable C statement file                      */
920 /*-----------------------------------------------------------------*/
921 int cmdNext (char *s, context *cctxt)
922 {
923     function *func = NULL;
924     /* next is almost the same as step except we don't
925        we don't set break point for all function entry
926        points */
927     if (!cctxt || !cctxt->func || !cctxt->func->mod) 
928         fprintf(stdout,"The program is not being run.\n");
929     else {
930         
931         /* if we are @ the end of a function then set
932            break points at execution points of the
933            function in the call stack... */
934         if (cctxt->addr == cctxt->func->sym->eaddr) {
935             if ((func = STACK_PEEK(callStack))) {
936                 if (srcMode == SRC_CMODE)
937                     applyToSet (func->cfpoints,setStepEPBp,STEP,
938                                 func->mod->c_name);     
939                 else
940                     applyToSet (func->afpoints,setStepEPBp,STEP,
941                                func->mod->asm_name);
942             }
943         } else {
944             if (srcMode == SRC_CMODE) {
945                 /* for all execution points in this function */
946                 applyToSet(cctxt->func->cfpoints,setNextEPBp,NEXT,
947                            cctxt->func->mod->c_name);
948                 /* set a break point @ the current function's
949                    exit */
950                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
951                                nextBpCB, cctxt->func->mod->c_name, 
952                                cctxt->func->exitline);
953                 
954                 /* now break point @ callers execution points */        
955                 if ((func = STACK_PPEEK(callStack))) {
956                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
957                                 func->mod->c_name);     
958                     /* set bp @ callers exit point */
959                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
960                                    stepBpCB, func->mod->c_name, 
961                                    func->exitline);
962                 }
963             } else {
964                 /* for all execution points in this function */
965                 applyToSet(cctxt->func->afpoints,setNextEPBp,NEXT,
966                            cctxt->func->mod->asm_name);
967                 /* set a break point @ the current function's
968                    exit */
969                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
970                                nextBpCB, cctxt->func->mod->asm_name, 
971                                cctxt->func->aexitline);
972                 
973                 /* now break point @ callers execution points */        
974                 if ((func = STACK_PPEEK(callStack))) {
975                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
976                                 func->mod->asm_name);   
977                     /* set bp @ callers exit point */
978                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
979                                    stepBpCB, func->mod->asm_name, 
980                                    func->aexitline);
981                 }
982             }
983             simGo(-1);  
984         }
985     }    
986     return 0;
987 }
988
989 /*-----------------------------------------------------------------*/
990 /* cmdRun  - run till next break point                             */
991 /*-----------------------------------------------------------------*/
992 int cmdRun (char *s, context *cctxt)
993 {
994     char buff[10];
995     if (!cctxt || !cctxt->func || !cctxt->func->mod) {
996         fprintf(stdout,"Starting program\n");
997         simGo(0);
998     } else {
999         
1000         fprintf(stdout,
1001                 "The program being debugged has been started already.\n");
1002         fprintf(stdout,"Start it from the beginning? (y or n) ");
1003         fflush(stdout);
1004
1005         fgets(buff,sizeof(buff),stdin);
1006         if (toupper(buff[0]) == 'Y') {
1007             simReset();
1008             simGo(0);
1009         }
1010     }
1011
1012     return 0;
1013 }
1014
1015 /*-----------------------------------------------------------------*/
1016 /* infoStack - print call stack information                        */
1017 /*-----------------------------------------------------------------*/
1018 static void infoStack(context *ctxt)
1019 {
1020     function *func ;
1021     int i = 0 ;
1022
1023     STACK_STARTWALK(callStack) ;
1024     while ((func = STACK_WALK(callStack))) {
1025
1026         fprintf(stdout,"#%d 0x%04x %s () at %s:%d\n",i++,
1027                 func->laddr,func->sym->name,
1028                 func->mod->c_name,func->lline);
1029     }
1030
1031 }
1032
1033 /*-----------------------------------------------------------------*/
1034 /* cmdInfo - info command                                          */
1035 /*-----------------------------------------------------------------*/
1036 int cmdInfo (char *s, context *cctxt)
1037 {
1038     while (isspace(*s)) s++;
1039
1040     /* list all break points */
1041     if (strcmp(s,"break") == 0) {
1042         listUSERbp();
1043         return 0;
1044     }
1045
1046     /* info frame same as frame */
1047     if (strcmp(s,"frame") == 0) {
1048         cmdFrame (s,cctxt);
1049         return 0;
1050     }
1051
1052     /* info stack display call stack */
1053     if (strcmp(s,"stack") == 0) {
1054         infoStack(cctxt);
1055         return 0;
1056     }
1057
1058     /* info stack display call stack */
1059     if (strcmp(s,"registers") == 0) {
1060         fprintf(stdout,"%s",simRegs());
1061         return 0;
1062     }
1063
1064     fprintf(stdout,"Undefined info command: \"%s\".  Try \"help\n",s);
1065     return 0;
1066
1067 }
1068
1069 /*-----------------------------------------------------------------*/
1070 /* cmdQuit  - quit debugging                                       */
1071 /*-----------------------------------------------------------------*/
1072 int cmdQuit (char *s, context *cctxt)
1073 {   
1074     if (simactive)
1075         closeSimulator();
1076     return 1;
1077 }
1078
1079 /*-----------------------------------------------------------------*/
1080 /* cmdListSrc  - list src                                          */
1081 /*-----------------------------------------------------------------*/
1082 int cmdListSrc (char *s, context *cctxt)
1083 {   
1084     static int currline = 0;
1085     int i =0 ;
1086     int pline = 0;
1087     static module *mod = NULL;
1088     int llines = listLines;
1089
1090     while (*s && isspace(*s)) s++;
1091     
1092     /* if the user has spcified line numer then the line number
1093        can be of the following formats
1094        LINE          - just line number
1095        FILE:LINE     - filename line number
1096        FUNCTION      - list a function
1097        FILE:FUNCTION - function in file */
1098     if (!cctxt || !cctxt->func || !cctxt->func->mod) {
1099         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
1100         return 0;
1101     }
1102     if (*s) {
1103         /* case a) LINE */
1104         if (isdigit(*s)) {
1105             sscanf(s,"%d",&pline);
1106             mod = cctxt->func->mod;
1107         }
1108         else {
1109             char *bp;
1110             function *func = NULL;
1111             
1112             /* if ':' present then FILE:LINE || FILE:FUNCTION */
1113             if ((bp = strchr(s,':'))) {
1114                 *bp = '\0';
1115                 bp ++;
1116                 if (isdigit(*bp)) {
1117                     /* FILE:LINE */
1118                     if (srcMode == SRC_CMODE) {
1119                         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1120                             fprintf (stderr,"No source file named %s.\n",s);
1121                             return 0;
1122                         }
1123                     } else {
1124                         if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
1125                             fprintf (stderr,"No source file named %s.\n",s);
1126                             return 0;
1127                         }
1128                     }
1129                     sscanf(bp,"%d",&pline);                         
1130                 } else {
1131                     /* FILE:FUCTION */
1132                     if (!applyToSet(functions,funcWithNameModule,bp,s,&func)) {
1133                         fprintf(stdout,"Function \"%s\" not defined.\n",bp);
1134                         return 0;
1135                     }
1136                     mod = func->mod;
1137                     if (srcMode == SRC_CMODE) {
1138                         pline = func->entryline;
1139                         llines = func->exitline - func->entryline + 1;
1140                     } else {
1141                         pline = func->aentryline;
1142                         llines = func->aexitline - func->aentryline + 1;
1143                     }
1144                 }
1145             }
1146             else {
1147                 /* FUNCTION */
1148                 if (!applyToSet(functions,funcWithName,s,&func)) {
1149                     fprintf(stderr,"Function \"%s\" not defined.\n",s); 
1150                     return 0;
1151                 }
1152                 else {
1153                     mod = func->mod;
1154                     if (srcMode == SRC_CMODE) {
1155                         pline = func->entryline;
1156                         llines = func->exitline - func->entryline + 1; 
1157                     } else {
1158                         pline = func->aentryline;
1159                         llines = func->aexitline - func->aentryline + 1; 
1160                     }
1161                 }
1162             }               
1163         }
1164     } else {
1165         /* if no line specified & we had listed
1166            before then continue from that listing */
1167         if (currline)
1168             pline = currline ;
1169         else {
1170             mod = cctxt->func->mod;
1171             if (srcMode == SRC_CMODE)
1172                 pline = cctxt->cline;
1173             else
1174                 pline = cctxt->asmline;
1175         }
1176     }
1177     
1178     for ( i = 0 ; i < llines ; i++ ) {
1179         if (srcMode == SRC_CMODE) {
1180             if ( (pline + i) >= mod->ncLines )
1181                 break;
1182             fprintf(stdout,"%d\t%s",pline + i,
1183                     mod->cLines[pline +i]->src);
1184         } else {
1185             if ( (pline + i) >= mod->nasmLines )
1186                 break;
1187             fprintf(stdout,"%d\t%s",pline + i,
1188                     mod->asmLines[pline +i]->src);
1189         }
1190     }
1191     currline = pline + i ;
1192     return 0;
1193 }
1194
1195 /*-----------------------------------------------------------------*/
1196 /* printValBasic - print value of basic types                      */
1197 /*-----------------------------------------------------------------*/
1198 static void printValBasic(symbol *sym,unsigned addr,char mem, int size)
1199 {
1200     union {     
1201         float f;     
1202         unsigned long val;
1203         long         sval;
1204         struct {
1205             short    lo;
1206             short    hi;
1207         } i;
1208         unsigned char b[4];
1209     }v;
1210     union {
1211         unsigned char b[4];
1212     }v1;
1213     
1214     v.val = simGetValue(addr,mem,size);
1215     /* if this a floating point number then */
1216     if (IS_FLOAT(sym->type))    
1217         fprintf(stdout,"%f",v.f);    
1218     else
1219         if (IS_PTR(sym->type))
1220             fprintf(stdout,"0x%x",v.val);
1221         else
1222             if (IS_SPEC(sym->type) && IS_INTEGRAL(sym->type)) {
1223                 if (IS_CHAR(sym->etype)) 
1224                     fprintf(stdout,"'%c' %d 0x%x",v.val,v.val,v.val);
1225                 else
1226                     if (IS_INT(sym->etype)) 
1227                         if (IS_LONG(sym->etype))
1228                             if (SPEC_USIGN(sym->etype))
1229                                 fprintf(stdout,"%d 0x%x",v.val,v.val);
1230                             else
1231                                 fprintf(stdout,"%d 0x%x",v.sval,v.sval);
1232                         else
1233                             fprintf(stdout,"%d 0x%x",v.i.lo,v.i.lo);
1234                     else
1235                         fprintf(stdout,"0x%x",v.val);
1236             } else
1237                 fprintf(stdout,"0x%x",v.val);
1238                 
1239     
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* printValFunc  - prints function values                          */
1244 /*-----------------------------------------------------------------*/
1245 static void printValFunc (symbol *sym)
1246 {
1247     fprintf(stdout,"print function not yet implemented\n");
1248 }
1249
1250 /*-----------------------------------------------------------------*/
1251 /* printArrayValue - will print the values of array elements       */
1252 /*-----------------------------------------------------------------*/
1253 static void printArrayValue (symbol *sym, char space, unsigned int addr)
1254 {
1255         link *elem_type = sym->type->next;
1256         int i;
1257         
1258         fprintf(stdout," { ");
1259         for (i = 0 ; i < DCL_ELEM(sym->type) ; i++) {           
1260                 if (IS_AGGREGATE(elem_type)) {
1261                         printValAggregates(sym,elem_type,space,addr);                  
1262                 } else {
1263                         printValBasic(sym,addr,space,getSize(elem_type));
1264                 }
1265                 addr += getSize(elem_type);
1266                 if (i != DCL_ELEM(sym->type) -1)
1267                         fprintf(stdout,",");
1268         }
1269
1270         fprintf(stdout,"}\n");          
1271 }
1272
1273 /*-----------------------------------------------------------------*/
1274 /* printStructValue - prints structures elements                   */
1275 /*-----------------------------------------------------------------*/
1276 static void printStructValue (symbol *sym,link *type, char space, unsigned int addr) 
1277 {
1278         symbol *fields = SPEC_STRUCT(type)->fields;
1279
1280         fprintf(stdout," { ");
1281         while (fields) {
1282                 fprintf(stdout,"%s = ",fields->name);
1283                 if (IS_AGGREGATE(fields->type)) {
1284                         printValAggregates(fields,fields->type,space, addr);
1285                 } else {
1286                         printValBasic(fields,addr,space,getSize(fields->type));
1287                 }
1288                 addr += getSize(fields->type);
1289                 fields = fields->next;
1290         }
1291         fprintf(stdout,"}\n");
1292 }
1293
1294 /*-----------------------------------------------------------------*/
1295 /* printValAggregates - print value of aggregates                  */
1296 /*-----------------------------------------------------------------*/
1297 static void printValAggregates (symbol *sym, link *type,char space,unsigned int addr)
1298 {
1299
1300         if (IS_ARRAY(type)) {
1301                 printArrayValue(sym, space, addr);
1302                 return ;
1303         }
1304
1305         if (IS_STRUCT(type)) { 
1306                 printStructValue(sym,sym->type,space, addr); 
1307                 return; 
1308         } 
1309 }
1310
1311 /*-----------------------------------------------------------------*/
1312 /* printSymValue - print value of a symbol                         */
1313 /*-----------------------------------------------------------------*/
1314 static void printSymValue (symbol *sym, context *cctxt)
1315 {
1316     static int stack = 1;
1317     unsigned long val;
1318     /* if it is on stack then compute address & fall thru */
1319     if (sym->isonstack) {
1320         symbol *bp = symLookup("bp",cctxt);
1321         if (!bp) {
1322             fprintf(stdout,"cannot determine stack frame\n");
1323             return ;
1324         }
1325
1326         sym->addr = simGetValue(bp->addr,bp->addrspace,bp->size)
1327           + sym->offset ;      
1328     }
1329     
1330     /* get the value from the simulator and
1331        print it */
1332     fprintf(stdout,"$%d = ",stack++);
1333     /* arrays & structures first */
1334     if (IS_AGGREGATE(sym->type))
1335         printValAggregates(sym,sym->type,sym->addrspace,sym->addr);
1336     else
1337         /* functions */
1338         if (IS_FUNC(sym->type))
1339             printValFunc(sym);
1340         else {
1341             printValBasic(sym,sym->addr,sym->addrspace,sym->size);
1342             fprintf(stdout,"\n");
1343         }
1344 }
1345
1346 /*-----------------------------------------------------------------*/
1347 /* printStructInfo - print out structure information               */
1348 /*-----------------------------------------------------------------*/
1349 static void printStructInfo (structdef *sdef)
1350 {
1351     symbol *field = sdef->fields ;
1352     int i = 0 ;
1353     
1354     while (field) {
1355         i += field->offset;
1356         field = field->next;
1357     }
1358
1359     fprintf(stdout,"%s %s {\n",(i ? "struct" : "union" ), sdef->tag);
1360     field = sdef->fields;
1361     while (field) {
1362         printTypeInfo (field->type);
1363         fprintf(stdout," %s ;\n",field->name);
1364         field = field->next ;
1365     }
1366
1367     fprintf(stdout,"}\n");
1368
1369 }
1370
1371 /*-----------------------------------------------------------------*/
1372 /* printTypeInfo - print out the type information                  */
1373 /*-----------------------------------------------------------------*/
1374 static void printTypeInfo(link *p)
1375 {
1376     if (!p)
1377         return ;
1378
1379     if (IS_DECL(p)) {
1380         switch (DCL_TYPE(p))  {
1381         case FUNCTION:
1382             printTypeInfo (p->next);
1383             fprintf(stdout,"()");
1384             break;
1385         case ARRAY:
1386             printTypeInfo (p->next);
1387             fprintf(stdout,"[%d]",DCL_ELEM(p));
1388             break;
1389         
1390         case IPOINTER:
1391         case PPOINTER:
1392         case POINTER:
1393             printTypeInfo (p->next);
1394             fprintf(stdout,"(_near *)");
1395             break;
1396
1397         case FPOINTER:
1398             printTypeInfo (p->next);
1399             fprintf(stdout,"(_xdata *)");
1400             break;
1401
1402         case CPOINTER:
1403             printTypeInfo( p->next);
1404             fprintf(stdout,"(_code *)");
1405             break;
1406             
1407         case GPOINTER:
1408             printTypeInfo( p->next);
1409             fprintf(stdout,"(_generic *)");
1410             break;                   
1411         }
1412     } else {
1413         switch (SPEC_NOUN(p)) { /* depending on the specifier type */
1414         case V_INT:
1415             (IS_LONG(p) ? fputs("long ",stdout) : 
1416              ( IS_SHORT(p) ? fputs("short ",stdout) : 
1417                fputs("int ",stdout))) ;
1418             break;
1419         case V_FLOAT:
1420              fputs("float ",stdout);
1421              break;
1422
1423         case V_CHAR:
1424             fputs ("char ",stdout);
1425             break;
1426
1427         case V_VOID:
1428             fputs("void ",stdout);
1429             break;
1430
1431         case V_STRUCT:
1432             printStructInfo (SPEC_STRUCT(p));
1433             break;
1434
1435         case V_SBIT:
1436             fputs("sbit ",stdout);
1437             break;
1438
1439         case V_BIT:
1440             fprintf(stdout,": %d" ,SPEC_BLEN(p));       
1441             break;
1442         }
1443     }
1444 }
1445
1446 /*-----------------------------------------------------------------*/
1447 /* cmdPrint - print value of variable                              */
1448 /*-----------------------------------------------------------------*/
1449 int cmdPrint (char *s, context *cctxt)
1450 {   
1451     symbol *sym ;
1452     char *bp = s+strlen(s) -1;
1453
1454     while (isspace(*s)) s++;
1455     if (!*s) return 0;
1456     while (isspace(*bp)) bp--;
1457     bp++ ;
1458     *bp = '\0';
1459
1460     if (!cctxt || !cctxt->func) {
1461         fprintf(stdout,"No symbol \"%s\" in current context.\n",
1462                 s);
1463         return 0;
1464     }
1465     if ((sym = symLookup(s,cctxt))) {
1466         printSymValue(sym,cctxt);
1467     } else {
1468         fprintf(stdout,
1469                 "No symbol \"%s\" in current context.\n",              
1470                 s);
1471     }
1472     return 0;
1473 }
1474
1475 /*-----------------------------------------------------------------*/
1476 /* cmdPrintType - print type of a variable                         */
1477 /*-----------------------------------------------------------------*/
1478 int cmdPrintType (char *s, context *cctxt)
1479 {   
1480         symbol *sym ;
1481     char *bp = s+strlen(s) -1;
1482
1483     while (isspace(*s)) s++;
1484     if (!*s) return 0;
1485     while (isspace(*bp)) bp--;
1486     bp++ ;
1487     *bp = '\0';
1488
1489     if (!cctxt || !cctxt->func) {
1490         fprintf(stdout,"No symbol \"%s\" in current context.\n",
1491                 s);
1492         return 0;
1493     }
1494
1495     if ((sym = symLookup(s,cctxt))) {
1496         printTypeInfo(sym->type);
1497         fprintf(stdout,"\n");
1498     } else {
1499         fprintf(stdout,
1500                 "No symbol \"%s\" in current context.\n",              
1501                 s);
1502     }
1503     return 0;   
1504 }
1505
1506 /*-----------------------------------------------------------------*/
1507 /* cmdClrUserBp - clear user break point                           */
1508 /*-----------------------------------------------------------------*/
1509 int cmdClrUserBp (char *s, context *cctxt)
1510 {   
1511     char *bp ;    
1512     function *func = NULL;
1513         
1514     /* clear break point location specification can be of the following
1515        forms
1516        a) <nothing>        - break point at current location
1517        b) lineno           - number of the current module
1518        c) filename:lineno  - line number of the given file
1519        e) filename:function- function X in file Y (useful for static functions)
1520        f) function         - function entry point
1521     */
1522
1523     if (!cctxt) {
1524         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
1525         return 0;
1526     }
1527
1528     /* white space skip */
1529     while (*s && isspace(*s)) s++;
1530     
1531     /* null terminate it after stripping trailing blanks*/
1532     bp = s + strlen(s);
1533     while (bp != s && isspace(*bp)) bp--;
1534     *bp = '\0';
1535
1536     /* case a) nothing */
1537     /* if nothing given then current location : we know
1538        the current execution location from the currentContext */
1539     if (! *s ) {
1540
1541         /* if current context is known */
1542         if (cctxt->func) 
1543             /* clear the break point @ current location */
1544             clearUSERbp (cctxt->addr);
1545         else
1546             fprintf(stderr,"No default breakpoint address now.\n");
1547                         
1548         goto ret ;
1549     }
1550
1551     /* case b) lineno */
1552     /* check if line number */
1553     if (isdigit(*s)) {
1554         /* get the lineno */
1555         int line = atoi(s);
1556
1557         /* if current context not present then we must get the module
1558            which has main & set the break point @ line number provided
1559            of that module : if current context known then set the bp 
1560            at the line number given for the current module 
1561         */
1562         if (cctxt->func) {
1563             if (!cctxt->func->mod) {
1564                 if (!applyToSet(functions,funcWithName,"main"))
1565                     fprintf(stderr,"Function \"main\" not defined.\n");
1566                 else 
1567                     clearBPatModLine(func->mod,line);
1568             } else 
1569                 clearBPatModLine(cctxt->func->mod,line);                        
1570         }
1571         
1572         goto ret;
1573     }
1574
1575     if ((bp = strchr(s,':'))) {
1576         
1577         module *mod = NULL;
1578         *bp = '\0';
1579         
1580         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1581             fprintf (stderr,"No source file named %s.\n",s);
1582             goto ret;
1583         }
1584
1585         /* case c) filename:lineno */
1586         if (isdigit(*(bp +1))) {                    
1587          
1588             clearBPatModLine (mod,atoi(bp+1));      
1589             goto ret;
1590             
1591         }
1592         /* case d) filename:function */
1593         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
1594             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
1595         else
1596             clearBPatModLine (mod,func->entryline);
1597         
1598         goto ret;
1599     }
1600             
1601     /* case e) function */
1602     if (!applyToSet(functions,funcWithName,s,&func))
1603         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
1604     else
1605         clearBPatModLine(func->mod,func->entryline);
1606
1607  ret:    
1608     return 0;        
1609 }
1610
1611
1612 /*-----------------------------------------------------------------*/
1613 /* cmdSimulator - send command to simulator                        */
1614 /*-----------------------------------------------------------------*/
1615 int cmdSimulator (char *s, context *cctxt)
1616 {   
1617   char tmpstr[82];
1618
1619     if (strlen(s) > 80) {
1620       printf("error 3A\n");
1621       exit(1);
1622     }
1623     strcpy(tmpstr, s);
1624     strcat(tmpstr, "\n");
1625     sendSim(tmpstr);
1626     waitForSim();
1627     fprintf(stdout,"%s",simResponse());
1628     return 0;
1629 }
1630
1631 /*-----------------------------------------------------------------*/
1632 /* cmdFrame - Frame command                                        */
1633 /*-----------------------------------------------------------------*/
1634 int cmdFrame (char *s, context *cctxt)
1635 {   
1636     function *func ;
1637
1638     if ((func = STACK_PEEK(callStack))) {
1639         fprintf(stdout,"#0  %s () at %s:%d\n",
1640                 func->sym->name,func->mod->c_name,cctxt->cline);
1641
1642         if (cctxt->cline < func->mod->ncLines)      
1643             fprintf(stdout,"%d\t%s",
1644                     cctxt->cline,
1645                     func->mod->cLines[cctxt->cline]->src);
1646     } else
1647         fprintf(stdout,"No stack.\n");
1648     return 0;
1649 }
1650
1651 /*-----------------------------------------------------------------*/
1652 /* cmdFinish - exec till end of current function                   */
1653 /*-----------------------------------------------------------------*/
1654 int cmdFinish (char *s, context *ctxt)
1655 {
1656     if (!ctxt || ! ctxt->func) {
1657         fprintf(stdout,"The program is not running.\n");
1658         return 0;
1659     }
1660
1661     if (srcMode == SRC_CMODE) {
1662         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
1663                        stepBpCB, ctxt->func->mod->c_name, 
1664                        ctxt->func->exitline);
1665     } else {
1666         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
1667                        stepBpCB, ctxt->func->mod->asm_name, 
1668                        ctxt->func->aexitline);
1669     }
1670
1671     simGo(-1);
1672     return 0;
1673     
1674 }
1675
1676
1677 /*-----------------------------------------------------------------*/
1678 /* cmdShow - show command                                          */
1679 /*-----------------------------------------------------------------*/
1680 int cmdShow (char *s, context *cctxt)
1681 {
1682     /* skip white space */
1683     while (*s && isspace(*s)) s++ ;
1684
1685     if (strcmp(s,"copying") == 0) {
1686         fputs(copying,stdout);
1687         return 0;
1688     }
1689     
1690     if (strcmp(s,"warranty") == 0) {
1691         fputs(warranty,stdout);
1692         return 0;
1693     }
1694
1695     return 0;
1696 }
1697