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