was stopping on every entry/exit point
[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       fprintf(stderr, "Error?:discoverContext: cannot apply to set!\n");
545         return NULL;
546     }
547
548     currCtxt->func = func;
549     currCtxt->addr = func->laddr = addr;
550     currCtxt->modName = func->modName;
551     
552     /* find the c line number */
553     if(applyToSet(func->cfpoints,lineAtAddr,addr,
554                   &line,&currCtxt->block,&currCtxt->level)) 
555         currCtxt->cline = func->lline = line;
556     else
557         currCtxt->cline = func->exitline;
558     
559     /* find the asm line number */
560     line = 0;
561     if (applyToSet(func->afpoints,lineAtAddr,addr,
562                    &line,NULL,NULL))
563         currCtxt->asmline = line;       
564     else
565         currCtxt->asmline = -1;
566         
567     return currCtxt ;
568 }
569
570
571 /*-----------------------------------------------------------------*/
572 /* simGo - send 'go' cmd to simulator and wait till a break occurs */
573 /*-----------------------------------------------------------------*/
574 void simGo (unsigned int gaddr)
575 {   
576     unsigned int addr ;
577     context *ctxt;
578     int rv;
579     static int initial_break_flag = 0;
580
581  top:    
582     addr = simGoTillBp (gaddr);
583
584     /* got the pc for the break point now first
585        discover the program context i.e. module, function 
586        linenumber of the source etc, etc etc */
587     ctxt = discoverContext (addr);
588     
589     /* dispatch all the break point call back functions */
590     rv = dispatchCB (addr,ctxt);    
591
592  ret:    
593
594     /* the dispatch call back function will return
595        non-zero if an user break point has been hit
596        if not then we continue with the execution 
597        of the program */
598     if (!rv) {
599       if (!initial_break_flag) {
600         initial_break_flag = 1;  // kludge to stop only at first run
601         fprintf(stdout, "Stopping at entry.  You can now list and set breakpoints\n");
602       }
603       else {
604         gaddr = -1;
605         goto top ;
606       }
607
608 // notes: kpb
609 // I took this out, after running "run" it would just keep re-running
610 // even after a lot of break points hit.  For some reason above code
611 // not triggering(dispatchCB).  This seems to be by design, startup adds
612 // a bunch of breakpoints-but they are not USER breakpoints.  Perhaps the
613 // debugger changed with its implementation of "go"("run").  It seems we
614 // need to add a "next" or "step" followed by a "run"...
615 // I added a "step" in simi.c when we want a resume function, this seems
616 // to work.
617
618 // still there is question of how do we stop it initially, since
619 // it must be started before it can get a context.  If so, we would
620 // want it to just run up to an initial entry point you'd think...
621 // I don't see why we can't set breakpoints before an initial run,
622 // this does not seem right to me.
623
624 // line #'s are a bit off too.
625
626 #if 0
627         gaddr = -1;
628         goto top ;
629 #endif
630     }
631     
632 }
633
634 /*-----------------------------------------------------------------*/
635 /* cmdSetUserBp - set break point at the user specified location   */
636 /*-----------------------------------------------------------------*/
637 int cmdSetUserBp (char *s, context *cctxt)
638 {
639     char *bp ;
640     function *func = NULL;
641         
642     /* user break point location specification can be of the following
643        forms
644        a) <nothing>        - break point at current location
645        b) lineno           - number of the current module
646        c) filename:lineno  - line number of the given file
647        e) filename:function- function X in file Y (useful for static functions)
648        f) function         - function entry point
649     */
650
651     if (!cctxt) {
652         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
653         return 0;
654     }
655     /* white space skip */
656     while (*s && isspace(*s)) s++;
657     
658     /* null terminate it after stripping trailing blanks*/
659     bp = s + strlen(s);
660     while (bp != s && isspace(*bp)) bp--;
661     *bp = '\0';
662
663     /* case a) nothing */
664     /* if nothing given then current location : we know
665        the current execution location from the currentContext */
666     if (! *s ) {
667
668         /* if current context is known */
669         if (cctxt->func) {
670             if (srcMode == SRC_CMODE)
671                 /* set the break point */
672                 setBreakPoint ( cctxt->addr , CODE , USER , userBpCB ,
673                                 cctxt->func->mod->c_name, cctxt->cline);
674             else
675                 setBreakPoint ( cctxt->addr , CODE , USER , userBpCB ,
676                                 cctxt->func->mod->asm_name, cctxt->asmline);
677                 
678         }
679         else
680             fprintf(stderr,"No default breakpoint address now.\n");
681                         
682         goto ret ;
683     }
684
685     /* case b) lineno */
686     /* check if line number */
687     if (isdigit(*s)) {
688         /* get the lineno */
689         int line = atoi(s);
690
691         /* if current context not present then we must get the module
692            which has main & set the break point @ line number provided
693            of that module : if current context known then set the bp 
694            at the line number given for the current module 
695         */
696         if (cctxt->func) {
697             if (!cctxt->func->mod) {
698                 if (!applyToSet(functions,funcWithName,"main"))
699                     fprintf(stderr,"Function \"main\" not defined.\n");
700                 else 
701                     setBPatModLine(func->mod,line);
702             } else 
703                 setBPatModLine(cctxt->func->mod,line);                  
704         } else {
705                 fprintf(stdout,"No symbol information currently\n");
706         }
707         
708         goto ret;
709     }
710
711     if ((bp = strchr(s,':'))) {
712         
713         module *mod = NULL;
714         *bp = '\0';
715         
716         if (srcMode == SRC_CMODE) {
717             if (!applyToSet(modules,moduleWithCName,s,&mod)) {
718                 fprintf (stderr,"No source file named %s.\n",s);
719                 goto ret;
720             }
721         } else {
722             if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
723                 fprintf (stderr,"No source file named %s.\n",s);
724                 goto ret;
725             }
726         }
727                 
728         /* case c) filename:lineno */
729         if (isdigit(*(bp +1))) {                    
730          
731             setBPatModLine (mod,atoi(bp+1));        
732             goto ret;
733             
734         }
735         /* case d) filename:function */
736         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
737             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
738         else        
739             setBPatModLine (mod,
740                             (srcMode == SRC_CMODE ? 
741                              func->entryline :
742                              func->aentryline));
743         
744         goto ret;
745     }
746             
747     /* case e) function */
748     if (!applyToSet(functions,funcWithName,s,&func))
749         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
750     else
751         setBPatModLine(func->mod,
752                        (srcMode == SRC_CMODE ?
753                         func->entryline :
754                         func->aentryline));
755
756  ret:    
757     return 0;
758 }
759
760 /*-----------------------------------------------------------------*/
761 /* cmdListAsm - list assembler source code                         */
762 /*-----------------------------------------------------------------*/
763 int cmdListAsm (char *s, context *cctxt)
764 {
765     fprintf(stderr,"'listasm' command not yet implemented\n");
766     return 0;
767 }
768
769 /*-----------------------------------------------------------------*/
770 /* cmdSetOption - set debugger options                             */
771 /*-----------------------------------------------------------------*/
772 int cmdSetOption (char *s, context *cctxt)
773 {
774     while (*s && isspace(*s)) s++;
775     if (strncmp(s,"srcmode",7) == 0 ) {
776         if (srcMode == SRC_CMODE)
777             srcMode = SRC_AMODE;
778         else
779             srcMode = SRC_CMODE;
780         fprintf(stderr,"source mode set to '%s'\n", 
781                 (srcMode == SRC_CMODE ? "C" : "asm"));
782         return 0;
783     }
784     
785     fprintf(stderr,"'set %s' command not yet implemented\n",s);
786     return 0;
787 }
788
789 /*-----------------------------------------------------------------*/
790 /* cmdContinue - continue till next break point                    */
791 /*-----------------------------------------------------------------*/
792 int cmdContinue (char *s, context *cctxt)
793 {
794     if (!cctxt || !cctxt->func) {
795         fprintf(stdout,"The program is not being run.\n");
796         return 0;
797     }
798
799     fprintf(stdout,"Continuing.\n");
800     simGo(-1);
801     return 0;
802 }
803
804 /*-----------------------------------------------------------------*/
805 /* cmdDelUserBp - delete user break point                          */
806 /*-----------------------------------------------------------------*/
807 int cmdDelUserBp (char *s, context *cctxt)
808 {
809     int bpnum ;
810     while (isspace(*s)) s++;
811     
812     if (!*s ) {
813         if (userBpPresent) {
814             char buffer[10];
815             fprintf (stdout,"Delete all breakpoints? (y or n) ");
816             fflush(stdout);
817             fgets(buffer,sizeof(buffer),stdin);
818             if (toupper(buffer[0]) == 'Y')
819                 deleteUSERbp(-1);          
820         }
821         return 0;
822     }
823     
824     /* determine the break point number */
825     if (sscanf(s,"%d",&bpnum) == 1)
826         deleteUSERbp(bpnum);
827
828     return 0;
829 }
830
831 /*-----------------------------------------------------------------*/
832 /* cmdStep - single step thru C source file                        */
833 /*-----------------------------------------------------------------*/
834 int cmdStep (char *s, context *cctxt)
835 {
836     function *func = NULL;
837
838     if (!cctxt || !cctxt->func || !cctxt->func->mod) 
839         fprintf(stdout,"The program is not being run.\n");
840     else {
841         /* if we are @ the end of a function then set
842            break points at execution points of the
843            function in the call stack... */
844         if (cctxt->addr == cctxt->func->sym->eaddr) {
845             if ((func = STACK_PEEK(callStack))) {
846                 if (srcMode == SRC_CMODE)
847                     applyToSet (func->cfpoints,setStepEPBp,STEP,
848                                 func->mod->c_name);     
849                 else
850                     applyToSet (func->afpoints,setStepEPBp,STEP,
851                                 func->mod->asm_name);
852             }
853         } else {
854             /* set breakpoints at all function entry points
855                and all exepoints of this functions & for
856                all functions one up in the call stack */
857             
858             /* all function entry points */
859             applyToSet(functions,setStepBp); 
860             
861             if (srcMode == SRC_CMODE) {
862                 /* for all execution points in this function */
863                 applyToSet(cctxt->func->cfpoints,setStepEPBp,STEP,
864                            cctxt->func->mod->c_name);
865                 
866                 /* set a break point @ the current function's
867                    exit */
868                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
869                                stepBpCB, cctxt->func->mod->c_name, 
870                                cctxt->func->exitline);
871                 
872                 /* now break point @ callers execution points */
873                 if ((func = STACK_PPEEK(callStack))) {
874                     applyToSet (func->cfpoints,setStepEPBp,STEP,
875                                 func->mod->c_name);     
876                     /* set bp @ callers exit point */
877                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
878                                    stepBpCB, func->mod->c_name, 
879                                    func->exitline);
880                 }
881             } else {
882                 /* for all execution points in this function */
883                 applyToSet(cctxt->func->afpoints,setStepEPBp,STEP,
884                            cctxt->func->mod->asm_name);
885                 
886                 /* set a break point @ the current function's
887                    exit */
888                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
889                                stepBpCB, cctxt->func->mod->asm_name, 
890                                cctxt->func->aexitline);
891                 
892                 /* now break point @ callers execution points */
893                 if ((func = STACK_PPEEK(callStack))) {
894                     
895                     applyToSet (func->afpoints,setStepEPBp,STEP,
896                                 func->mod->asm_name);   
897                     
898                     /* set bp @ callers exit point */
899                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
900                                    stepBpCB, func->mod->asm_name, 
901                                    func->aexitline);
902                 }
903             }
904         }
905
906         simGo(-1);
907     }
908     return 0;
909 }
910
911 /*-----------------------------------------------------------------*/
912 /* cmdNext - next executable C statement file                      */
913 /*-----------------------------------------------------------------*/
914 int cmdNext (char *s, context *cctxt)
915 {
916     function *func = NULL;
917     /* next is almost the same as step except we don't
918        we don't set break point for all function entry
919        points */
920     if (!cctxt || !cctxt->func || !cctxt->func->mod) 
921         fprintf(stdout,"The program is not being run.\n");
922     else {
923         
924         /* if we are @ the end of a function then set
925            break points at execution points of the
926            function in the call stack... */
927         if (cctxt->addr == cctxt->func->sym->eaddr) {
928             if ((func = STACK_PEEK(callStack))) {
929                 if (srcMode == SRC_CMODE)
930                     applyToSet (func->cfpoints,setStepEPBp,STEP,
931                                 func->mod->c_name);     
932                 else
933                     applyToSet (func->afpoints,setStepEPBp,STEP,
934                                func->mod->asm_name);
935             }
936         } else {
937             if (srcMode == SRC_CMODE) {
938                 /* for all execution points in this function */
939                 applyToSet(cctxt->func->cfpoints,setNextEPBp,NEXT,
940                            cctxt->func->mod->c_name);
941                 /* set a break point @ the current function's
942                    exit */
943                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
944                                nextBpCB, cctxt->func->mod->c_name, 
945                                cctxt->func->exitline);
946                 
947                 /* now break point @ callers execution points */        
948                 if ((func = STACK_PPEEK(callStack))) {
949                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
950                                 func->mod->c_name);     
951                     /* set bp @ callers exit point */
952                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
953                                    stepBpCB, func->mod->c_name, 
954                                    func->exitline);
955                 }
956             } else {
957                 /* for all execution points in this function */
958                 applyToSet(cctxt->func->afpoints,setNextEPBp,NEXT,
959                            cctxt->func->mod->asm_name);
960                 /* set a break point @ the current function's
961                    exit */
962                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
963                                nextBpCB, cctxt->func->mod->asm_name, 
964                                cctxt->func->aexitline);
965                 
966                 /* now break point @ callers execution points */        
967                 if ((func = STACK_PPEEK(callStack))) {
968                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
969                                 func->mod->asm_name);   
970                     /* set bp @ callers exit point */
971                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
972                                    stepBpCB, func->mod->asm_name, 
973                                    func->aexitline);
974                 }
975             }
976             simGo(-1);  
977         }
978     }    
979     return 0;
980 }
981
982 /*-----------------------------------------------------------------*/
983 /* cmdRun  - run till next break point                             */
984 /*-----------------------------------------------------------------*/
985 int cmdRun (char *s, context *cctxt)
986 {
987     char buff[10];
988     if (!cctxt || !cctxt->func || !cctxt->func->mod) {
989         fprintf(stdout,"Starting program\n");
990         simGo(0);
991     } else {
992         
993         fprintf(stdout,
994                 "The program being debugged has been started already.\n");
995         fprintf(stdout,"Start it from the beginning? (y or n) ");
996         fflush(stdout);
997
998         fgets(buff,sizeof(buff),stdin);
999         if (toupper(buff[0]) == 'Y') {
1000             simReset();
1001             simGo(0);
1002         }
1003     }
1004
1005     return 0;
1006 }
1007
1008 /*-----------------------------------------------------------------*/
1009 /* infoStack - print call stack information                        */
1010 /*-----------------------------------------------------------------*/
1011 static void infoStack(context *ctxt)
1012 {
1013     function *func ;
1014     int i = 0 ;
1015
1016     STACK_STARTWALK(callStack) ;
1017     while ((func = STACK_WALK(callStack))) {
1018
1019         fprintf(stdout,"#%d 0x%04x %s () at %s:%d\n",i++,
1020                 func->laddr,func->sym->name,
1021                 func->mod->c_name,func->lline);
1022     }
1023
1024 }
1025
1026 /*-----------------------------------------------------------------*/
1027 /* cmdInfo - info command                                          */
1028 /*-----------------------------------------------------------------*/
1029 int cmdInfo (char *s, context *cctxt)
1030 {
1031     while (isspace(*s)) s++;
1032
1033     /* list all break points */
1034     if (strcmp(s,"break") == 0) {
1035         listUSERbp();
1036         return 0;
1037     }
1038
1039     /* info frame same as frame */
1040     if (strcmp(s,"frame") == 0) {
1041         cmdFrame (s,cctxt);
1042         return 0;
1043     }
1044
1045     /* info stack display call stack */
1046     if (strcmp(s,"stack") == 0) {
1047         infoStack(cctxt);
1048         return 0;
1049     }
1050
1051     /* info stack display call stack */
1052     if (strcmp(s,"registers") == 0) {
1053         fprintf(stdout,"%s",simRegs());
1054         return 0;
1055     }
1056
1057     fprintf(stdout,"Undefined info command: \"%s\".  Try \"help\n",s);
1058     return 0;
1059
1060 }
1061
1062 /*-----------------------------------------------------------------*/
1063 /* cmdQuit  - quit debugging                                       */
1064 /*-----------------------------------------------------------------*/
1065 int cmdQuit (char *s, context *cctxt)
1066 {   
1067     if (simactive)
1068         closeSimulator();
1069     return 1;
1070 }
1071
1072 /*-----------------------------------------------------------------*/
1073 /* cmdListSrc  - list src                                          */
1074 /*-----------------------------------------------------------------*/
1075 int cmdListSrc (char *s, context *cctxt)
1076 {   
1077     static int currline = 0;
1078     int i =0 ;
1079     int pline = 0;
1080     static module *mod = NULL;
1081     int llines = listLines;
1082
1083     while (*s && isspace(*s)) s++;
1084     
1085     /* if the user has spcified line numer then the line number
1086        can be of the following formats
1087        LINE          - just line number
1088        FILE:LINE     - filename line number
1089        FUNCTION      - list a function
1090        FILE:FUNCTION - function in file */
1091     if (!cctxt || !cctxt->func || !cctxt->func->mod) {
1092         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
1093         return 0;
1094     }
1095     if (*s) {
1096         /* case a) LINE */
1097         if (isdigit(*s)) {
1098             sscanf(s,"%d",&pline);
1099             mod = cctxt->func->mod;
1100         }
1101         else {
1102             char *bp;
1103             function *func = NULL;
1104             
1105             /* if ':' present then FILE:LINE || FILE:FUNCTION */
1106             if ((bp = strchr(s,':'))) {
1107                 *bp = '\0';
1108                 bp ++;
1109                 if (isdigit(*bp)) {
1110                     /* FILE:LINE */
1111                     if (srcMode == SRC_CMODE) {
1112                         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1113                             fprintf (stderr,"No source file named %s.\n",s);
1114                             return 0;
1115                         }
1116                     } else {
1117                         if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
1118                             fprintf (stderr,"No source file named %s.\n",s);
1119                             return 0;
1120                         }
1121                     }
1122                     sscanf(bp,"%d",&pline);                         
1123                 } else {
1124                     /* FILE:FUCTION */
1125                     if (!applyToSet(functions,funcWithNameModule,bp,s,&func)) {
1126                         fprintf(stdout,"Function \"%s\" not defined.\n",bp);
1127                         return 0;
1128                     }
1129                     mod = func->mod;
1130                     if (srcMode == SRC_CMODE) {
1131                         pline = func->entryline;
1132                         llines = func->exitline - func->entryline + 1;
1133                     } else {
1134                         pline = func->aentryline;
1135                         llines = func->aexitline - func->aentryline + 1;
1136                     }
1137                 }
1138             }
1139             else {
1140                 /* FUNCTION */
1141                 if (!applyToSet(functions,funcWithName,s,&func)) {
1142                     fprintf(stderr,"Function \"%s\" not defined.\n",s); 
1143                     return 0;
1144                 }
1145                 else {
1146                     mod = func->mod;
1147                     if (srcMode == SRC_CMODE) {
1148                         pline = func->entryline;
1149                         llines = func->exitline - func->entryline + 1; 
1150                     } else {
1151                         pline = func->aentryline;
1152                         llines = func->aexitline - func->aentryline + 1; 
1153                     }
1154                 }
1155             }               
1156         }
1157     } else {
1158         /* if no line specified & we had listed
1159            before then continue from that listing */
1160         if (currline)
1161             pline = currline ;
1162         else {
1163             mod = cctxt->func->mod;
1164             if (srcMode == SRC_CMODE)
1165                 pline = cctxt->cline;
1166             else
1167                 pline = cctxt->asmline;
1168         }
1169     }
1170     
1171     for ( i = 0 ; i < llines ; i++ ) {
1172         if (srcMode == SRC_CMODE) {
1173             if ( (pline + i) >= mod->ncLines )
1174                 break;
1175             fprintf(stdout,"%d\t%s",pline + i,
1176                     mod->cLines[pline +i]->src);
1177         } else {
1178             if ( (pline + i) >= mod->nasmLines )
1179                 break;
1180             fprintf(stdout,"%d\t%s",pline + i,
1181                     mod->asmLines[pline +i]->src);
1182         }
1183     }
1184     currline = pline + i ;
1185     return 0;
1186 }
1187
1188 /*-----------------------------------------------------------------*/
1189 /* printValBasic - print value of basic types                      */
1190 /*-----------------------------------------------------------------*/
1191 static void printValBasic(symbol *sym,unsigned addr,char mem, int size)
1192 {
1193     union {     
1194         float f;     
1195         unsigned long val;
1196         long         sval;
1197         struct {
1198             short    lo;
1199             short    hi;
1200         } i;
1201         unsigned char b[4];
1202     }v;
1203     union {
1204         unsigned char b[4];
1205     }v1;
1206     
1207     v.val = simGetValue(addr,mem,size);
1208     /* if this a floating point number then */
1209     if (IS_FLOAT(sym->type))    
1210         fprintf(stdout,"%f",v.f);    
1211     else
1212         if (IS_PTR(sym->type))
1213             fprintf(stdout,"0x%x",v.val);
1214         else
1215             if (IS_SPEC(sym->type) && IS_INTEGRAL(sym->type)) {
1216                 if (IS_CHAR(sym->etype)) 
1217                     fprintf(stdout,"'%c' %d 0x%x",v.val,v.val,v.val);
1218                 else
1219                     if (IS_INT(sym->etype)) 
1220                         if (IS_LONG(sym->etype))
1221                             if (SPEC_USIGN(sym->etype))
1222                                 fprintf(stdout,"%d 0x%x",v.val,v.val);
1223                             else
1224                                 fprintf(stdout,"%d 0x%x",v.sval,v.sval);
1225                         else
1226                             fprintf(stdout,"%d 0x%x",v.i.lo,v.i.lo);
1227                     else
1228                         fprintf(stdout,"0x%x",v.val);
1229             } else
1230                 fprintf(stdout,"0x%x",v.val);
1231                 
1232     
1233 }
1234
1235 /*-----------------------------------------------------------------*/
1236 /* printValFunc  - prints function values                          */
1237 /*-----------------------------------------------------------------*/
1238 static void printValFunc (symbol *sym)
1239 {
1240     fprintf(stdout,"print function not yet implemented\n");
1241 }
1242
1243 /*-----------------------------------------------------------------*/
1244 /* printArrayValue - will print the values of array elements       */
1245 /*-----------------------------------------------------------------*/
1246 static void printArrayValue (symbol *sym, char space, unsigned int addr)
1247 {
1248         link *elem_type = sym->type->next;
1249         int i;
1250         
1251         fprintf(stdout," { ");
1252         for (i = 0 ; i < DCL_ELEM(sym->type) ; i++) {           
1253                 if (IS_AGGREGATE(elem_type)) {
1254                         printValAggregates(sym,elem_type,space,addr);                  
1255                 } else {
1256                         printValBasic(sym,addr,space,getSize(elem_type));
1257                 }
1258                 addr += getSize(elem_type);
1259                 if (i != DCL_ELEM(sym->type) -1)
1260                         fprintf(stdout,",");
1261         }
1262
1263         fprintf(stdout,"}\n");          
1264 }
1265
1266 /*-----------------------------------------------------------------*/
1267 /* printStructValue - prints structures elements                   */
1268 /*-----------------------------------------------------------------*/
1269 static void printStructValue (symbol *sym,link *type, char space, unsigned int addr) 
1270 {
1271         symbol *fields = SPEC_STRUCT(type)->fields;
1272
1273         fprintf(stdout," { ");
1274         while (fields) {
1275                 fprintf(stdout,"%s = ",fields->name);
1276                 if (IS_AGGREGATE(fields->type)) {
1277                         printValAggregates(fields,fields->type,space, addr);
1278                 } else {
1279                         printValBasic(fields,addr,space,getSize(fields->type));
1280                 }
1281                 addr += getSize(fields->type);
1282                 fields = fields->next;
1283         }
1284         fprintf(stdout,"}\n");
1285 }
1286
1287 /*-----------------------------------------------------------------*/
1288 /* printValAggregates - print value of aggregates                  */
1289 /*-----------------------------------------------------------------*/
1290 static void printValAggregates (symbol *sym, link *type,char space,unsigned int addr)
1291 {
1292
1293         if (IS_ARRAY(type)) {
1294                 printArrayValue(sym, space, addr);
1295                 return ;
1296         }
1297
1298         if (IS_STRUCT(type)) { 
1299                 printStructValue(sym,sym->type,space, addr); 
1300                 return; 
1301         } 
1302 }
1303
1304 /*-----------------------------------------------------------------*/
1305 /* printSymValue - print value of a symbol                         */
1306 /*-----------------------------------------------------------------*/
1307 static void printSymValue (symbol *sym, context *cctxt)
1308 {
1309     static int stack = 1;
1310     unsigned long val;
1311     /* if it is on stack then compute address & fall thru */
1312     if (sym->isonstack) {
1313         symbol *bp = symLookup("bp",cctxt);
1314         if (!bp) {
1315             fprintf(stdout,"cannot determine stack frame\n");
1316             return ;
1317         }
1318
1319         sym->addr = simGetValue(bp->addr,bp->addrspace,bp->size)
1320           + sym->offset ;      
1321     }
1322     
1323     /* get the value from the simulator and
1324        print it */
1325     fprintf(stdout,"$%d = ",stack++);
1326     /* arrays & structures first */
1327     if (IS_AGGREGATE(sym->type))
1328         printValAggregates(sym,sym->type,sym->addrspace,sym->addr);
1329     else
1330         /* functions */
1331         if (IS_FUNC(sym->type))
1332             printValFunc(sym);
1333         else {
1334             printValBasic(sym,sym->addr,sym->addrspace,sym->size);
1335             fprintf(stdout,"\n");
1336         }
1337 }
1338
1339 /*-----------------------------------------------------------------*/
1340 /* printStructInfo - print out structure information               */
1341 /*-----------------------------------------------------------------*/
1342 static void printStructInfo (structdef *sdef)
1343 {
1344     symbol *field = sdef->fields ;
1345     int i = 0 ;
1346     
1347     while (field) {
1348         i += field->offset;
1349         field = field->next;
1350     }
1351
1352     fprintf(stdout,"%s %s {\n",(i ? "struct" : "union" ), sdef->tag);
1353     field = sdef->fields;
1354     while (field) {
1355         printTypeInfo (field->type);
1356         fprintf(stdout," %s ;\n",field->name);
1357         field = field->next ;
1358     }
1359
1360     fprintf(stdout,"}\n");
1361
1362 }
1363
1364 /*-----------------------------------------------------------------*/
1365 /* printTypeInfo - print out the type information                  */
1366 /*-----------------------------------------------------------------*/
1367 static void printTypeInfo(link *p)
1368 {
1369     if (!p)
1370         return ;
1371
1372     if (IS_DECL(p)) {
1373         switch (DCL_TYPE(p))  {
1374         case FUNCTION:
1375             printTypeInfo (p->next);
1376             fprintf(stdout,"()");
1377             break;
1378         case ARRAY:
1379             printTypeInfo (p->next);
1380             fprintf(stdout,"[%d]",DCL_ELEM(p));
1381             break;
1382         
1383         case IPOINTER:
1384         case PPOINTER:
1385         case POINTER:
1386             printTypeInfo (p->next);
1387             fprintf(stdout,"(_near *)");
1388             break;
1389
1390         case FPOINTER:
1391             printTypeInfo (p->next);
1392             fprintf(stdout,"(_xdata *)");
1393             break;
1394
1395         case CPOINTER:
1396             printTypeInfo( p->next);
1397             fprintf(stdout,"(_code *)");
1398             break;
1399             
1400         case GPOINTER:
1401             printTypeInfo( p->next);
1402             fprintf(stdout,"(_generic *)");
1403             break;                   
1404         }
1405     } else {
1406         switch (SPEC_NOUN(p)) { /* depending on the specifier type */
1407         case V_INT:
1408             (IS_LONG(p) ? fputs("long ",stdout) : 
1409              ( IS_SHORT(p) ? fputs("short ",stdout) : 
1410                fputs("int ",stdout))) ;
1411             break;
1412         case V_FLOAT:
1413              fputs("float ",stdout);
1414              break;
1415
1416         case V_CHAR:
1417             fputs ("char ",stdout);
1418             break;
1419
1420         case V_VOID:
1421             fputs("void ",stdout);
1422             break;
1423
1424         case V_STRUCT:
1425             printStructInfo (SPEC_STRUCT(p));
1426             break;
1427
1428         case V_SBIT:
1429             fputs("sbit ",stdout);
1430             break;
1431
1432         case V_BIT:
1433             fprintf(stdout,": %d" ,SPEC_BLEN(p));       
1434             break;
1435         }
1436     }
1437 }
1438
1439 /*-----------------------------------------------------------------*/
1440 /* cmdPrint - print value of variable                              */
1441 /*-----------------------------------------------------------------*/
1442 int cmdPrint (char *s, context *cctxt)
1443 {   
1444     symbol *sym ;
1445     char *bp = s+strlen(s) -1;
1446
1447     while (isspace(*s)) s++;
1448     if (!*s) return 0;
1449     while (isspace(*bp)) bp--;
1450     bp++ ;
1451     *bp = '\0';
1452
1453     if (!cctxt || !cctxt->func) {
1454         fprintf(stdout,"No symbol \"%s\" in current context.\n",
1455                 s);
1456         return 0;
1457     }
1458     if ((sym = symLookup(s,cctxt))) {
1459         printSymValue(sym,cctxt);
1460     } else {
1461         fprintf(stdout,
1462                 "No symbol \"%s\" in current context.\n",              
1463                 s);
1464     }
1465     return 0;
1466 }
1467
1468 /*-----------------------------------------------------------------*/
1469 /* cmdPrintType - print type of a variable                         */
1470 /*-----------------------------------------------------------------*/
1471 int cmdPrintType (char *s, context *cctxt)
1472 {   
1473         symbol *sym ;
1474     char *bp = s+strlen(s) -1;
1475
1476     while (isspace(*s)) s++;
1477     if (!*s) return 0;
1478     while (isspace(*bp)) bp--;
1479     bp++ ;
1480     *bp = '\0';
1481
1482     if (!cctxt || !cctxt->func) {
1483         fprintf(stdout,"No symbol \"%s\" in current context.\n",
1484                 s);
1485         return 0;
1486     }
1487
1488     if ((sym = symLookup(s,cctxt))) {
1489         printTypeInfo(sym->type);
1490         fprintf(stdout,"\n");
1491     } else {
1492         fprintf(stdout,
1493                 "No symbol \"%s\" in current context.\n",              
1494                 s);
1495     }
1496     return 0;   
1497 }
1498
1499 /*-----------------------------------------------------------------*/
1500 /* cmdClrUserBp - clear user break point                           */
1501 /*-----------------------------------------------------------------*/
1502 int cmdClrUserBp (char *s, context *cctxt)
1503 {   
1504     char *bp ;    
1505     function *func = NULL;
1506         
1507     /* clear break point location specification can be of the following
1508        forms
1509        a) <nothing>        - break point at current location
1510        b) lineno           - number of the current module
1511        c) filename:lineno  - line number of the given file
1512        e) filename:function- function X in file Y (useful for static functions)
1513        f) function         - function entry point
1514     */
1515
1516     if (!cctxt) {
1517         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
1518         return 0;
1519     }
1520
1521     /* white space skip */
1522     while (*s && isspace(*s)) s++;
1523     
1524     /* null terminate it after stripping trailing blanks*/
1525     bp = s + strlen(s);
1526     while (bp != s && isspace(*bp)) bp--;
1527     *bp = '\0';
1528
1529     /* case a) nothing */
1530     /* if nothing given then current location : we know
1531        the current execution location from the currentContext */
1532     if (! *s ) {
1533
1534         /* if current context is known */
1535         if (cctxt->func) 
1536             /* clear the break point @ current location */
1537             clearUSERbp (cctxt->addr);
1538         else
1539             fprintf(stderr,"No default breakpoint address now.\n");
1540                         
1541         goto ret ;
1542     }
1543
1544     /* case b) lineno */
1545     /* check if line number */
1546     if (isdigit(*s)) {
1547         /* get the lineno */
1548         int line = atoi(s);
1549
1550         /* if current context not present then we must get the module
1551            which has main & set the break point @ line number provided
1552            of that module : if current context known then set the bp 
1553            at the line number given for the current module 
1554         */
1555         if (cctxt->func) {
1556             if (!cctxt->func->mod) {
1557                 if (!applyToSet(functions,funcWithName,"main"))
1558                     fprintf(stderr,"Function \"main\" not defined.\n");
1559                 else 
1560                     clearBPatModLine(func->mod,line);
1561             } else 
1562                 clearBPatModLine(cctxt->func->mod,line);                        
1563         }
1564         
1565         goto ret;
1566     }
1567
1568     if ((bp = strchr(s,':'))) {
1569         
1570         module *mod = NULL;
1571         *bp = '\0';
1572         
1573         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1574             fprintf (stderr,"No source file named %s.\n",s);
1575             goto ret;
1576         }
1577
1578         /* case c) filename:lineno */
1579         if (isdigit(*(bp +1))) {                    
1580          
1581             clearBPatModLine (mod,atoi(bp+1));      
1582             goto ret;
1583             
1584         }
1585         /* case d) filename:function */
1586         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
1587             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
1588         else
1589             clearBPatModLine (mod,func->entryline);
1590         
1591         goto ret;
1592     }
1593             
1594     /* case e) function */
1595     if (!applyToSet(functions,funcWithName,s,&func))
1596         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
1597     else
1598         clearBPatModLine(func->mod,func->entryline);
1599
1600  ret:    
1601     return 0;        
1602 }
1603
1604
1605 /*-----------------------------------------------------------------*/
1606 /* cmdSimulator - send command to simulator                        */
1607 /*-----------------------------------------------------------------*/
1608 int cmdSimulator (char *s, context *cctxt)
1609 {   
1610   char tmpstr[82];
1611
1612     if (strlen(s) > 80) {
1613       printf("error 3A\n");
1614       exit(1);
1615     }
1616     strcpy(tmpstr, s);
1617     strcat(tmpstr, "\n");
1618     sendSim(tmpstr);
1619     waitForSim();
1620     fprintf(stdout,"%s",simResponse());
1621     return 0;
1622 }
1623
1624 /*-----------------------------------------------------------------*/
1625 /* cmdFrame - Frame command                                        */
1626 /*-----------------------------------------------------------------*/
1627 int cmdFrame (char *s, context *cctxt)
1628 {   
1629     function *func ;
1630
1631     if ((func = STACK_PEEK(callStack))) {
1632         fprintf(stdout,"#0  %s () at %s:%d\n",
1633                 func->sym->name,func->mod->c_name,cctxt->cline);
1634
1635         if (cctxt->cline < func->mod->ncLines)      
1636             fprintf(stdout,"%d\t%s",
1637                     cctxt->cline,
1638                     func->mod->cLines[cctxt->cline]->src);
1639     } else
1640         fprintf(stdout,"No stack.\n");
1641     return 0;
1642 }
1643
1644 /*-----------------------------------------------------------------*/
1645 /* cmdFinish - exec till end of current function                   */
1646 /*-----------------------------------------------------------------*/
1647 int cmdFinish (char *s, context *ctxt)
1648 {
1649     if (!ctxt || ! ctxt->func) {
1650         fprintf(stdout,"The program is not running.\n");
1651         return 0;
1652     }
1653
1654     if (srcMode == SRC_CMODE) {
1655         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
1656                        stepBpCB, ctxt->func->mod->c_name, 
1657                        ctxt->func->exitline);
1658     } else {
1659         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
1660                        stepBpCB, ctxt->func->mod->asm_name, 
1661                        ctxt->func->aexitline);
1662     }
1663
1664     simGo(-1);
1665     return 0;
1666     
1667 }
1668
1669
1670 /*-----------------------------------------------------------------*/
1671 /* cmdShow - show command                                          */
1672 /*-----------------------------------------------------------------*/
1673 int cmdShow (char *s, context *cctxt)
1674 {
1675     /* skip white space */
1676     while (*s && isspace(*s)) s++ ;
1677
1678     if (strcmp(s,"copying") == 0) {
1679         fputs(copying,stdout);
1680         return 0;
1681     }
1682     
1683     if (strcmp(s,"warranty") == 0) {
1684         fputs(warranty,stdout);
1685         return 0;
1686     }
1687
1688     return 0;
1689 }
1690