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