Martins patches
[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 #include "newalloc.h"
31
32 /* default number of lines to list out */
33 #define LISTLINES 10
34 static int listlines = LISTLINES;
35
36 /* mainly used to retain a reference to the active module being
37    listed.  May be used as a general context for other commands if
38    no better context is available */
39 static module *list_mod = NULL;
40
41 EXTERN_STACK_DCL(callStack,function *,1024);
42
43 #if defined(__APPLE__) && defined(__MACH__)
44 static char *copying=
45 {" GNU GENERAL PUBLIC LICENSE Version 2"};
46 static char *warranty=
47 {" NO WARRANTY"};
48 #else
49 static char *copying=
50 "                   GNU GENERAL PUBLIC LICENSE\n"
51 "                       Version 2, June 1991\n"
52 "\n"
53 " Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n"
54 " 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
55 " Everyone is permitted to copy and distribute verbatim copies\n"
56 " of this license document, but changing it is not allowed.\n"
57 "\n"
58 "                            Preamble\n"
59 "\n"
60 "  The licenses for most software are designed to take away your\n"
61 "freedom to share and change it.  By contrast, the GNU General Public\n"
62 "License is intended to guarantee your freedom to share and change free\n"
63 "software--to make sure the software is free for all its users.  This\n"
64 "General Public License applies to most of the Free Software\n"
65 "Foundation's software and to any other program whose authors commit to\n"
66 "using it.  (Some other Free Software Foundation software is covered by\n"
67 "the GNU Library General Public License instead.)  You can apply it to\n"
68 "your programs, too.\n"
69 "\n"
70 "  When we speak of free software, we are referring to freedom, not\n"
71 "price.  Our General Public Licenses are designed to make sure that you\n"
72 "have the freedom to distribute copies of free software (and charge for\n"
73 "this service if you wish), that you receive source code or can get it\n"
74 "if you want it, that you can change the software or use pieces of it\n"
75 "in new free programs; and that you know you can do these things.\n"
76 "\n"
77 "  To protect your rights, we need to make restrictions that forbid\n"
78 "anyone to deny you these rights or to ask you to surrender the rights.\n"
79 "These restrictions translate to certain responsibilities for you if you\n"
80 "distribute copies of the software, or if you modify it.\n"
81 "\n"
82 "  For example, if you distribute copies of such a program, whether\n"
83 "gratis or for a fee, you must give the recipients all the rights that\n"
84 "you have.  You must make sure that they, too, receive or can get the\n"
85 "source code.  And you must show them these terms so they know their\n"
86 "rights.\n"
87 "\n"
88 "  We protect your rights with two steps: (1) copyright the software, and\n"
89 "(2) offer you this license which gives you legal permission to copy,\n"
90 "distribute and/or modify the software.\n"
91 "\n"
92 "  Also, for each author's protection and ours, we want to make certain\n"
93 "that everyone understands that there is no warranty for this free\n"
94 "software.  If the software is modified by someone else and passed on, we\n"
95 "want its recipients to know that what they have is not the original, so\n"
96 "that any problems introduced by others will not reflect on the original\n"
97 "authors' reputations.\n"
98 "\n"
99 "  Finally, any free program is threatened constantly by software\n"
100 "patents.  We wish to avoid the danger that redistributors of a free\n"
101 "program will individually obtain patent licenses, in effect making the\n"
102 "program proprietary.  To prevent this, we have made it clear that any\n"
103 "patent must be licensed for everyone's free use or not licensed at all.\n"
104 "\n"
105 "  The precise terms and conditions for copying, distribution and\n"
106 "modification follow.\n"
107 "^L\n"
108 "                    GNU GENERAL PUBLIC LICENSE\n"
109 "   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n"
110 "\n"
111 "  0. This License applies to any program or other work which contains\n"
112 "a notice placed by the copyright holder saying it may be distributed\n"
113 "under the terms of this General Public License.  The \"Program\", below,\n"
114 "refers to any such program or work, and a \"work based on the Program\"\n"
115 "means either the Program or any derivative work under copyright law:\n"
116 "that is to say, a work containing the Program or a portion of it,\n"
117 "either verbatim or with modifications and/or translated into another\n"
118 "language.  (Hereinafter, translation is included without limitation in\n"
119 "the term \"modification\".)  Each licensee is addressed as \"you\".\n"
120 "\n"
121 "Activities other than copying, distribution and modification are not\n"
122 "covered by this License; they are outside its scope.  The act of\n"
123 "running the Program is not restricted, and the output from the Program\n"
124 "is covered only if its contents constitute a work based on the\n"
125 "Program (independent of having been made by running the Program).\n"
126 "Whether that is true depends on what the Program does.\n"
127 "\n"
128 "  1. You may copy and distribute verbatim copies of the Program's\n"
129 "source code as you receive it, in any medium, provided that you\n"
130 "conspicuously and appropriately publish on each copy an appropriate\n"
131 "copyright notice and disclaimer of warranty; keep intact all the\n"
132 "notices that refer to this License and to the absence of any warranty;\n"
133 "and give any other recipients of the Program a copy of this License\n"
134 "along with the Program.\n"
135 "\n"
136 "You may charge a fee for the physical act of transferring a copy, and\n"
137 "you may at your option offer warranty protection in exchange for a fee.\n"
138 "\n"
139 "  2. You may modify your copy or copies of the Program or any portion\n"
140 "of it, thus forming a work based on the Program, and copy and\n"
141 "distribute such modifications or work under the terms of Section 1\n"
142 "above, provided that you also meet all of these conditions:\n"
143 "\n"
144 "    a) You must cause the modified files to carry prominent notices\n"
145 "    stating that you changed the files and the date of any change.\n"
146 "\n"
147 "    b) You must cause any work that you distribute or publish, that in\n"
148 "    whole or in part contains or is derived from the Program or any\n"
149 "    part thereof, to be licensed as a whole at no charge to all third\n"
150 "    parties under the terms of this License.\n"
151 "\n"
152 "    c) If the modified program normally reads commands interactively\n"
153 "    when run, you must cause it, when started running for such\n"
154 "    interactive use in the most ordinary way, to print or display an\n"
155 "    announcement including an appropriate copyright notice and a\n"
156 "    notice that there is no warranty (or else, saying that you provide\n"
157 "    a warranty) and that users may redistribute the program under\n"
158 "    these conditions, and telling the user how to view a copy of this\n"
159 "    License.  (Exception: if the Program itself is interactive but\n"
160 "    does not normally print such an announcement, your work based on\n"
161 "    the Program is not required to print an announcement.)\n"
162 "\n"
163 "These requirements apply to the modified work as a whole.  If\n"
164 "identifiable sections of that work are not derived from the Program,\n"
165 "and can be reasonably considered independent and separate works in\n"
166 "themselves, then this License, and its terms, do not apply to those\n"
167 "sections when you distribute them as separate works.  But when you\n"
168 "distribute the same sections as part of a whole which is a work based\n"
169 "on the Program, the distribution of the whole must be on the terms of\n"
170 "this License, whose permissions for other licensees extend to the\n"
171 "entire whole, and thus to each and every part regardless of who wrote it.\n"
172 "\n"
173 "Thus, it is not the intent of this section to claim rights or contest\n"
174 "your rights to work written entirely by you; rather, the intent is to\n"
175 "exercise the right to control the distribution of derivative or\n"
176 "collective works based on the Program.\n"
177 "\n"
178 "In addition, mere aggregation of another work not based on the Program\n"
179 "with the Program (or with a work based on the Program) on a volume of\n"
180 "a storage or distribution medium does not bring the other work under\n"
181 "the scope of this License.\n"
182 "\n"
183 "  3. You may copy and distribute the Program (or a work based on it,\n"
184 "under Section 2) in object code or executable form under the terms of\n"
185 "Sections 1 and 2 above provided that you also do one of the following:\n"
186 "\n"
187 "    a) Accompany it with the complete corresponding machine-readable\n"
188 "    source code, which must be distributed under the terms of Sections\n"
189 "    1 and 2 above on a medium customarily used for software interchange; or,\n"
190 "\n"
191 "    b) Accompany it with a written offer, valid for at least three\n"
192 "    years, to give any third party, for a charge no more than your\n"
193 "    cost of physically performing source distribution, a complete\n"
194 "    machine-readable copy of the corresponding source code, to be\n"
195 "    distributed under the terms of Sections 1 and 2 above on a medium\n"
196 "    customarily used for software interchange; or,\n"
197 "\n"
198 "    c) Accompany it with the information you received as to the offer\n"
199 "    to distribute corresponding source code.  (This alternative is\n"
200 "    allowed only for noncommercial distribution and only if you\n"
201 "    received the program in object code or executable form with such\n"
202 "    an offer, in accord with Subsection b above.)\n"
203 "\n"
204 "The source code for a work means the preferred form of the work for\n"
205 "making modifications to it.  For an executable work, complete source\n"
206 "code means all the source code for all modules it contains, plus any\n"
207 "associated interface definition files, plus the scripts used to\n"
208 "control compilation and installation of the executable.  However, as a\n"
209 "special exception, the source code distributed need not include\n"
210 "anything that is normally distributed (in either source or binary\n"
211 "form) with the major components (compiler, kernel, and so on) of the\n"
212 "operating system on which the executable runs, unless that component\n"
213 "itself accompanies the executable.\n"
214 "\n"
215 "If distribution of executable or object code is made by offering\n"
216 "access to copy from a designated place, then offering equivalent\n"
217 "access to copy the source code from the same place counts as\n"
218 "distribution of the source code, even though third parties are not\n"
219 "compelled to copy the source along with the object code.\n"
220 "^L\n"
221 "  4. You may not copy, modify, sublicense, or distribute the Program\n"
222 "except as expressly provided under this License.  Any attempt\n"
223 "otherwise to copy, modify, sublicense or distribute the Program is\n"
224 "void, and will automatically terminate your rights under this License.\n"
225 "However, parties who have received copies, or rights, from you under\n"
226 "this License will not have their licenses terminated so long as such\n"
227 "parties remain in full compliance.\n"
228 "\n"
229 "  5. You are not required to accept this License, since you have not\n"
230 "signed it.  However, nothing else grants you permission to modify or\n"
231 "distribute the Program or its derivative works.  These actions are\n"
232 "prohibited by law if you do not accept this License.  Therefore, by\n"
233 "modifying or distributing the Program (or any work based on the\n"
234 "Program), you indicate your acceptance of this License to do so, and\n"
235 "all its terms and conditions for copying, distributing or modifying\n"
236 "the Program or works based on it.\n"
237 "\n"
238 "  6. Each time you redistribute the Program (or any work based on the\n"
239 "Program), the recipient automatically receives a license from the\n"
240 "original licensor to copy, distribute or modify the Program subject to\n"
241 "these terms and conditions.  You may not impose any further\n"
242 "restrictions on the recipients' exercise of the rights granted herein.\n"
243 "You are not responsible for enforcing compliance by third parties to\n"
244 "this License.\n"
245 "\n"
246 "  7. If, as a consequence of a court judgment or allegation of patent\n"
247 "infringement or for any other reason (not limited to patent issues),\n"
248 "conditions are imposed on you (whether by court order, agreement or\n"
249 "otherwise) that contradict the conditions of this License, they do not\n"
250 "excuse you from the conditions of this License.  If you cannot\n"
251 "distribute so as to satisfy simultaneously your obligations under this\n"
252 "License and any other pertinent obligations, then as a consequence you\n"
253 "may not distribute the Program at all.  For example, if a patent\n"
254 "license would not permit royalty-free redistribution of the Program by\n"
255 "all those who receive copies directly or indirectly through you, then\n"
256 "the only way you could satisfy both it and this License would be to\n"
257 "refrain entirely from distribution of the Program.\n"
258 "\n"
259 "If any portion of this section is held invalid or unenforceable under\n"
260 "any particular circumstance, the balance of the section is intended to\n"
261 "apply and the section as a whole is intended to apply in other\n"
262 "circumstances.\n"
263 "\n"
264 "It is not the purpose of this section to induce you to infringe any\n"
265 "patents or other property right claims or to contest validity of any\n"
266 "such claims; this section has the sole purpose of protecting the\n"
267 "integrity of the free software distribution system, which is\n"
268 "implemented by public license practices.  Many people have made\n"
269 "generous contributions to the wide range of software distributed\n"
270 "through that system in reliance on consistent application of that\n"
271 "system; it is up to the author/donor to decide if he or she is willing\n"
272 "to distribute software through any other system and a licensee cannot\n"
273 "impose that choice.\n"
274 "\n"
275 "This section is intended to make thoroughly clear what is believed to\n"
276 "be a consequence of the rest of this License.\n"
277 "\n"
278 "  8. If the distribution and/or use of the Program is restricted in\n"
279 "certain countries either by patents or by copyrighted interfaces, the\n"
280 "original copyright holder who places the Program under this License\n"
281 "may add an explicit geographical distribution limitation excluding\n"
282 "those countries, so that distribution is permitted only in or among\n"
283 "countries not thus excluded.  In such case, this License incorporates\n"
284 "the limitation as if written in the body of this License.\n"
285 "\n"
286 "  9. The Free Software Foundation may publish revised and/or new versions\n"
287 "of the General Public License from time to time.  Such new versions will\n"
288 "be similar in spirit to the present version, but may differ in detail to\n"
289 "address new problems or concerns.\n"
290 "\n"
291 "Each version is given a distinguishing version number.  If the Program\n"
292 "specifies a version number of this License which applies to it and \"any\n"
293 "later version\", you have the option of following the terms and conditions\n"
294 "either of that version or of any later version published by the Free\n"
295 "Software Foundation.  If the Program does not specify a version number of\n"
296 "this License, you may choose any version ever published by the Free Software\n"
297 "Foundation.\n"
298 "\n"
299 "  10. If you wish to incorporate parts of the Program into other free\n"
300 "programs whose distribution conditions are different, write to the author\n"
301 "to ask for permission.  For software which is copyrighted by the Free\n"
302 "Software Foundation, write to the Free Software Foundation; we sometimes\n"
303 "make exceptions for this.  Our decision will be guided by the two goals\n"
304 "of preserving the free status of all derivatives of our free software and\n"
305 "of promoting the sharing and reuse of software generally.\n";
306
307 static char *warranty=
308 "                            NO WARRANTY\n"
309 "\n"
310 "  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
311 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
312 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
313 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
314 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
315 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
316 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
317 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
318 "REPAIR OR CORRECTION.\n"
319 "\n"
320 "  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
321 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
322 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
323 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
324 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
325 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
326 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
327 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
328 "POSSIBILITY OF SUCH DAMAGES.\n";
329 #endif
330
331 static void printTypeInfo(link *);
332 static void printValAggregates (symbol *,link *,char,unsigned int,int);
333 static void printOrSetSymValue (symbol *sym, context *cctxt, 
334                                 int flg, int dnum, int fmt, char *rs, char *val);
335
336 int srcMode = SRC_CMODE ;
337 static set  *dispsymbols = NULL   ; /* set of displayable symbols */
338 static int currentFrame = 0;        /* actual displayed frame     */
339 /*-----------------------------------------------------------------*/
340 /* funcWithName - returns function with name                       */
341 /*-----------------------------------------------------------------*/
342 DEFSETFUNC(funcWithName)
343 {
344     function *func = item;
345     V_ARG(char *,name);
346     V_ARG(function **,funcp);
347
348     if (*funcp)
349         return 0;
350
351     if (strcmp(func->sym->name,name) == 0) {
352         *funcp = func;
353         return 1;
354     }
355     
356     return 0;
357 }
358
359 /*-----------------------------------------------------------------*/
360 /* symWithAddr - look for symbol with sfr / sbit address           */
361 /*-----------------------------------------------------------------*/
362 DEFSETFUNC(symWithAddr)
363 {
364     symbol *sym = item;
365     V_ARG(unsigned long,laddr);
366     V_ARG(int    ,laddrspace);
367     V_ARG(symbol **,rsym);
368
369     if (*rsym)
370         return 0;
371
372     if ( sym->addr == laddr &&
373          sym->addrspace == laddrspace ) 
374     {
375         *rsym = sym;
376         return 1;
377     }
378
379     return 0;
380 }
381
382 /*-----------------------------------------------------------------*/
383 /* setBPatModLine - set break point at the line specified for the  */
384 /*-----------------------------------------------------------------*/
385 static void setBPatModLine (module *mod, int line, char bpType )
386 {
387   int next_line;
388
389     /* look for the first executable line after the line
390        specified & get the break point there */    
391     if (srcMode == SRC_CMODE && line > mod->ncLines) {
392         fprintf(stderr,"No line %d in file \"%s\".\n",
393                 line,mod->c_name);
394         return ;
395     }
396     
397     if (srcMode == SRC_AMODE && line > mod->nasmLines) {
398         fprintf(stderr,"No line %d in file \"%s\".\n",
399                 line,mod->asm_name);
400         return ;
401     }
402
403     next_line = line;
404     for ( ; next_line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ; 
405           next_line++ ) {
406         if (srcMode == SRC_CMODE) {
407             if (mod->cLines[next_line]->addr) {
408                 setBreakPoint (mod->cLines[next_line]->addr, CODE, bpType, 
409                                userBpCB, mod->c_name, next_line);
410                 return;
411 //              break;
412             }
413         }
414         else {
415            if (mod->asmLines[next_line]->addr) {
416                setBreakPoint (mod->asmLines[next_line]->addr, CODE, bpType, 
417                               userBpCB, mod->asm_name, next_line);
418                 return;
419 //             break;
420            } 
421         }
422     }
423
424         fprintf(stderr,"No line %d or after in file \"%s\"..\n",
425                         line,mod->c_name);
426
427     return;
428 }
429
430 /*-----------------------------------------------------------------*/
431 /* clearBPatModLine - clr break point at the line specified        */
432 /*-----------------------------------------------------------------*/
433 static void clearBPatModLine (module *mod, int line)
434 {
435     /* look for the first executable line after the line
436        specified & get the break point there */
437     if (srcMode == SRC_CMODE && line > mod->ncLines) {
438         fprintf(stderr,"No line %d in file \"%s\".\n",
439                 line,mod->c_name);
440         return ;
441     }
442     
443     if (srcMode == SRC_AMODE && line > mod->ncLines) {
444         fprintf(stderr,"No line %d in file \"%s\".\n",
445                 line,mod->c_name);
446         return ;
447     }    
448     
449     for ( ; line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ; 
450           line++ ) {
451         if (srcMode == SRC_CMODE) 
452             if (mod->cLines[line]->addr) {
453                 clearUSERbp (mod->cLines[line]->addr);                    
454                 break;
455             }
456         else
457             if (mod->asmLines[line]->addr) {
458                 clearUSERbp (mod->asmLines[line]->addr);                          
459                 break;
460             }
461     }
462
463     return;
464 }
465
466 /*-----------------------------------------------------------------*/
467 /* moduleLineWithAddr - finds and returns a line  with a given address */
468 /*-----------------------------------------------------------------*/
469 DEFSETFUNC(moduleLineWithAddr)
470 {
471     module *mod = item;
472     int i;
473
474     V_ARG(unsigned int,addr);
475     V_ARG(module **,rmod);
476     V_ARG(int *,line);
477
478     if (*rmod)
479         return 0;
480
481     for (i=0; i < mod->nasmLines; i++ ) 
482     {
483         if ( mod->asmLines[i]->addr == addr)
484         {
485             *rmod = mod ;
486             if (line )
487             {
488                 *line = 0;
489                 for ( i=0; i < mod->ncLines; i++ ) 
490                 {
491                     if ( mod->cLines[i]->addr > addr)
492                         break;
493                     *line = i;
494                 }
495                 return 1;
496             }
497         }
498     }
499
500     return 0;
501 }
502
503 /*-----------------------------------------------------------------*/
504 /* funcWithNameModule - returns functions with a name module combo */
505 /*-----------------------------------------------------------------*/
506 DEFSETFUNC(funcWithNameModule) 
507 {
508     function *func = item;
509     V_ARG(char *,fname);
510     V_ARG(char *,mname);
511     V_ARG(function **,funcp);
512
513     if (*funcp)
514         return 0;
515
516     if (strcmp(func->sym->name,fname) == 0 &&
517         strcmp(func->mod->c_name,mname) == 0) {
518         *funcp = func;
519         return 1;
520     }
521
522     return 0;
523 }
524
525 /*-----------------------------------------------------------------*/
526 /* funcInAddr - given an address returns the function              */
527 /*-----------------------------------------------------------------*/
528 DEFSETFUNC(funcInAddr)
529 {
530     function *func = item;
531     V_ARG(unsigned int,addr);
532     V_ARG(function **,funcp);
533
534     if (*funcp)
535         return 0;
536
537     /* in the address range */
538     if (func->sym->addr <= addr &&
539         func->sym->eaddr >= addr) {
540         
541         *funcp = func;
542         return 1;
543     }
544
545     return 0;       
546 }
547
548 /*-----------------------------------------------------------------*/
549 /* setStepBp - will set STEP Bp @ function entry points            */
550 /*-----------------------------------------------------------------*/
551 DEFSETFUNC(setStepBp)
552 {
553     function *func = item;
554     
555     if (func->sym && func->sym->addr ) {
556         
557         /* set the entry break point */
558         setBreakPoint (func->sym->addr , CODE , STEP , 
559                        stepBpCB ,func->mod->c_name , func->entryline);
560
561         return 1;
562     }
563
564     return 0;
565 }
566
567 /*-----------------------------------------------------------------*/
568 /* setStepEPBp - sets a given type of bp @ the execution point     */
569 /*-----------------------------------------------------------------*/
570 DEFSETFUNC(setStepEPBp)
571 {
572     exePoint *ep = item;
573     V_ARG(int,bptype);
574     V_ARG(char *,mname);
575    
576     setBreakPoint (ep->addr, CODE, bptype, 
577                    stepBpCB, mname, ep->line);
578     return 1;
579 }
580
581 /*-----------------------------------------------------------------*/
582 /* setNextEPBp - sets a given type of bp @ the execution point     */
583 /*-----------------------------------------------------------------*/
584 DEFSETFUNC(setNextEPBp)
585 {
586     exePoint *ep = item;
587     V_ARG(int,bptype);
588     V_ARG(char *,mname);
589    
590     setBreakPoint (ep->addr, CODE, bptype, 
591                    nextBpCB, mname, ep->line);
592     return 1;
593 }
594
595 /*-----------------------------------------------------------------*/
596 /* lineAtAddr - for execution points returns the one with addr     */
597 /*-----------------------------------------------------------------*/
598 DEFSETFUNC(lineAtAddr)
599 {
600     exePoint *ep = item;
601     V_ARG(unsigned int,addr);
602     V_ARG(int *,line);
603     V_ARG(int *,block);
604     V_ARG(int *,level);
605
606     /* address must be an exact match */
607     if (ep->addr == addr) {
608         *line = ep->line;
609         if (block)
610             *block = ep->block ;
611         if (level)
612             *level = ep->level ;
613         return 1;
614     }
615
616     return 0;
617     
618 }
619
620 /*-----------------------------------------------------------------*/
621 /* lineNearAddr - for execution points returns the one with addr   */
622 /*-----------------------------------------------------------------*/
623 DEFSETFUNC(lineNearAddr)
624 {
625     exePoint *ep = item;
626     V_ARG(unsigned int,addr);
627     V_ARG(int *,line);
628     V_ARG(int *,block);
629     V_ARG(int *,level);
630
631     /* the line in which the address is */
632     if (ep->addr <= addr) {
633         *line = ep->line;
634         if (block)
635             *block = ep->block ;
636         if (level)
637             *level = ep->level ;
638         return 1;
639     }
640
641     return 0;
642     
643 }
644
645 /*-----------------------------------------------------------------*/
646 /* discoverContext - find out the current context of the bp        */
647 /*-----------------------------------------------------------------*/
648 context *discoverContext (unsigned addr, function *func)
649 {
650     module   *mod  = NULL;
651     int line = 0;
652
653     /* find the function we are in */
654     if (!func && !applyToSet(functions,funcInAddr,addr,&func)) {
655         if (!applyToSet(functions,funcWithName,"main",&func) ||
656             !applyToSet(modules,moduleLineWithAddr,addr,&mod,NULL))
657         {
658             fprintf(stderr, "Error?:discoverContext: cannot apply addr 0x%x\n",addr);
659             return NULL;
660         }
661         currCtxt->func = func;
662         currCtxt->addr = addr;
663         currCtxt->modName = mod->name;
664         currCtxt->cline = func->exitline;
665     }
666     else
667     {
668         currCtxt->func = func;
669         currCtxt->addr = func->laddr = addr;
670         currCtxt->modName = func->modName;
671     
672         /* find the c line number */
673         if(applyToSet(func->cfpoints,lineAtAddr,addr,
674                   &line,&currCtxt->block,&currCtxt->level)) 
675             currCtxt->cline = func->lline = line;
676         else if(applyToSet(func->cfpoints,lineNearAddr,addr,
677                   &line,&currCtxt->block,&currCtxt->level)) 
678             currCtxt->cline = func->lline = line;
679         else
680             currCtxt->cline = func->exitline;
681     }    
682     /* find the asm line number */
683     line = 0;
684     if (applyToSet(func->afpoints,lineAtAddr,addr,
685                    &line,NULL,NULL))
686         currCtxt->asmline = line;       
687     else
688         currCtxt->asmline = -1;
689         
690     return currCtxt ;
691 }
692
693
694 /*-----------------------------------------------------------------*/
695 /* simGo - send 'go' cmd to simulator and wait till a break occurs */
696 /*-----------------------------------------------------------------*/
697 void simGo (unsigned int gaddr)
698 {   
699     unsigned int addr ;
700     context *ctxt;
701     int rv;
702
703  top:    
704     if ( userinterrupt )
705     {
706         userinterrupt = 0;
707         return;
708     }
709     addr = simGoTillBp (gaddr);
710
711     /* got the pc for the break point now first
712        discover the program context i.e. module, function 
713        linenumber of the source etc, etc etc */
714     currentFrame = 0; 
715     ctxt = discoverContext (addr, NULL);
716     
717     /* dispatch all the break point call back functions */
718     rv = dispatchCB (addr,ctxt);    
719  ret:    
720
721     /* the dispatch call back function will return
722        non-zero if an user break point has been hit
723        if not then we continue with the execution 
724        of the program */
725     if (!rv) 
726     {
727         if ( gaddr == 0 )
728             gaddr = -1;
729         if ( gaddr == -1 || doingSteps == 1 )
730             goto top ;
731     }
732     
733 }
734
735 /*-----------------------------------------------------------------*/
736 /* preparePrint - common parse function for                        */
737 /*                output, print and display                        */
738 /*-----------------------------------------------------------------*/
739 static char *preparePrint(char *s, context *cctxt, int *fmt, symbol **sym)
740 {
741     char *bp = s+strlen(s) -1;
742     char save_ch ;
743
744     *fmt = FMT_NON;
745     *sym = NULL;
746
747     while (isspace(*s)) s++;
748     if (!*s) 
749         return (char *)0;
750
751     while (isspace(*bp)) bp--;
752     bp++ ;
753     *bp = '\0';
754
755     if ( *s == '/' )
756     {
757         /* format of printout */
758         switch ( *++s )
759         {
760             case 'x':
761                 *fmt = FMT_HEX ;
762                 break;
763             case 'o':
764                 *fmt = FMT_OCT ;
765                 break;
766             default:
767             case 'd':
768                 *fmt = FMT_DEZ ;
769                 break;
770             case 't':
771                 *fmt = FMT_BIN ;
772                 break;
773         }
774         s++;
775         while (isspace(*s)) s++;
776     }
777     for ( bp = s; *bp && ( isalnum( *bp ) || *bp == '_'); bp++ );
778     save_ch = *bp;
779     if ( *bp )
780         *bp = '\0';
781
782     *sym = symLookup(s,cctxt);
783     *bp = save_ch;
784
785     if ( ! *sym )
786         fprintf(stdout,"No symbol \"%s\" in current context.\n", s);
787     return bp;
788 }
789
790 static int printAsmLine( function *func, module *m, long saddr, long eaddr)
791 {
792     int i,j,delta;
793     int symaddr;
794     int lastaddr = saddr+1;
795     char *symname;
796
797     if ( func )
798     {
799         symaddr = func->sym->addr;
800         symname = func->sym->name;
801     }
802     else
803     {
804         symaddr = saddr;
805         symname = "" ;
806     }
807     for (j=0,i=0; i < m->nasmLines; i++ ) 
808     {
809         if ( saddr >= 0 && m->asmLines[i]->addr < saddr)
810         {
811                 continue;
812         }
813         if ( eaddr >= 0 && m->asmLines[i]->addr > eaddr)
814         {
815                 continue;
816         }
817         if ( func && 
818             (m->asmLines[i]->addr < func->sym->addr ||
819              m->asmLines[i]->addr > func->sym->eaddr ))
820         {
821             continue;
822         } 
823         delta = m->asmLines[i]->addr - symaddr;
824         if ( delta >= 0 )
825         {
826             j++;
827             lastaddr = m->asmLines[i]->addr;
828             printf("0x%08x <%s",lastaddr,symname);
829             if (delta > 0) printf("+%d",delta);
830             printf(">:\t%s",m->asmLines[i]->src);            
831         }
832     }
833     return lastaddr;
834 }
835
836 /*-----------------------------------------------------------------*/
837 /* cmdDisasm - disassemble  asm instruction                        */
838 /*-----------------------------------------------------------------*/
839 static int cmdDisasm (char *s, context *cctxt, int args)
840 {
841     function *func = NULL;
842     long  saddr = -1;
843     long  eaddr = -1;
844     int   found = 0;
845     module *modul;
846     /* white space skip */
847
848     if ( args > 0 )
849     {
850         while (*s && isspace(*s)) s++;
851
852         if ( isdigit(*s))
853         {
854             saddr = strtol(s,&s,0);
855             if ( args > 1 )
856             {
857                 while (*s && isspace(*s)) s++;
858
859                 if ( isdigit(*s))
860                     eaddr = strtol(s,0,0);
861             }
862             else
863                 eaddr = saddr+1;
864         }
865     }
866
867     if ( eaddr == -1 )
868     {       
869         /* no start or only start so dump function */
870         if ( saddr == -1 )
871         {
872             func = cctxt->func;
873         }
874         else
875         {
876             applyToSet(functions,funcInAddr,saddr,&func);
877         }
878         if ( func )
879         {
880             printf("Dump of assembler code for function %s:\n",func->sym->name);
881             printAsmLine(func,func->mod,-1,-1);
882             printf("End of assembler dump.\n");
883             return 0; 
884         }
885         else
886         {
887             if (applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
888             {
889                 eaddr = saddr + 5;
890                 printf("Dump of assembler code:\n");
891                 printAsmLine(NULL,modul,saddr,eaddr);
892                 printf("End of assembler dump.\n");
893                 return 0; 
894             }
895         }
896     }
897     else
898     {
899         if ( args > 1 )
900             printf("Dump of assembler code from 0x%08x to 0x%08x:\n",saddr,eaddr);
901         found = 0;
902         while ( saddr < eaddr )
903         {
904             func = NULL;
905             if (applyToSet(functions,funcInAddr,saddr,&func))
906             {
907                 found = 1;
908                 modul = func->mod;
909             }
910             else
911             {
912                 if ( found )
913                     break;
914                 if (!applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
915                     break;
916             }
917             saddr = printAsmLine(func,modul,saddr,eaddr) + 1;
918         }
919         if( saddr >= eaddr)
920         {
921             if ( args > 1 )
922                 printf("End of assembler dump.\n");
923             return 0; 
924         }
925         
926     }
927     fprintf(stderr,"No function contains specified address.\n");
928     return 0; 
929 }
930 /*-----------------------------------------------------------------*/
931 /* cmdDisasm1 - disassemble one asm instruction                    */
932 /*-----------------------------------------------------------------*/
933 int cmdDisasm1 (char *s, context *cctxt)
934 {
935     return cmdDisasm( s, cctxt, 1);
936 }
937
938 /*-----------------------------------------------------------------*/
939 /* cmdDisasmF - disassemble asm instructions                       */
940 /*-----------------------------------------------------------------*/
941 int cmdDisasmF(char *s, context *cctxt)
942 {
943     return cmdDisasm( s, cctxt, 2);
944 }
945
946 static int commonSetUserBp(char *s, context *cctxt, char bpType)
947 {
948     char *bp ;
949     function *func = NULL;
950         
951     /* user break point location specification can be of the following
952        forms
953        a) <nothing>        - break point at current location
954        b) lineno           - number of the current module
955        c) filename:lineno  - line number of the given file
956        e) filename:function- function X in file Y (useful for static functions)
957        f) function         - function entry point
958        g) *addr            - break point at address 
959     */
960
961     if (!cctxt) {
962         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
963         return 0;
964     }
965     /* white space skip */
966     while (*s && isspace(*s)) s++;
967     
968     /* null terminate it after stripping trailing blanks*/
969     bp = s + strlen(s);
970     while (bp != s && isspace(*bp)) bp--;
971     *bp = '\0';
972
973     /* case a) nothing */
974     /* if nothing given then current location : we know
975        the current execution location from the currentContext */
976     if (! *s ) {
977
978         /* if current context is known */
979         if (cctxt->func) {
980             if (srcMode == SRC_CMODE)
981                 /* set the break point */
982                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
983                                 cctxt->func->mod->c_name, cctxt->cline);
984             else
985                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
986                                 cctxt->func->mod->asm_name, cctxt->asmline);
987                 
988         }
989         else
990             fprintf(stderr,"No default breakpoint address now.\n");
991                         
992         goto ret ;
993     }
994     /* case g) *addr */
995     if ( *s == '*' && isdigit(*(s+1)))
996     {
997         int  line   = 0;
998         long braddr = strtol(s+1,0,0);
999         if (!applyToSet(functions,funcInAddr,braddr,&func))
1000         {
1001             module *modul;
1002             if (!applyToSet(modules,moduleLineWithAddr,braddr,&modul,&line))
1003             {
1004                 fprintf(stderr,"Address 0x%08x not exists in code.\n",braddr); 
1005             }
1006             else
1007             {
1008                 setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1009                             modul->c_name,line);
1010             }
1011             goto ret ;
1012         }
1013                 else
1014         {
1015             int line = func->exitline;
1016             if ( !applyToSet(func->cfpoints,lineAtAddr,braddr,
1017                                   &line,NULL,NULL))
1018                 applyToSet(func->cfpoints,lineNearAddr,braddr,&line,NULL,NULL);
1019             setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1020                             func->mod->c_name,line);
1021         }
1022         goto ret ;
1023     }
1024     /* case b) lineno */
1025     /* check if line number */
1026     if (isdigit(*s)) {
1027         /* get the lineno */
1028         int line = atoi(s) -1;
1029
1030         /* if current context not present then we must get the module
1031            which has main & set the break point @ line number provided
1032            of that module : if current context known then set the bp 
1033            at the line number given for the current module 
1034         */
1035         if (cctxt->func) {
1036             if (!cctxt->func->mod) {
1037                 if (!applyToSet(functions,funcWithName,"main"))
1038                     fprintf(stderr,"Function \"main\" not defined.\n");
1039                 else 
1040                     setBPatModLine(func->mod,line, bpType);
1041             } else 
1042                 setBPatModLine(cctxt->func->mod,line, bpType);
1043         } else {
1044                 if (list_mod) {
1045                         setBPatModLine(list_mod,line, bpType);
1046                 } else {
1047                   fprintf(stdout,"Sdcdb fails to have module symbol context at %d\n", __LINE__);
1048                 }
1049         }
1050         
1051         goto ret;
1052     }
1053
1054     if ((bp = strchr(s,':'))) {
1055         
1056         module *mod = NULL;
1057         *bp = '\0';
1058         
1059         if (srcMode == SRC_CMODE) {
1060             if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1061                 fprintf (stderr,"No source file named %s.\n",s);
1062                 goto ret;
1063             }
1064         } else {
1065             if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
1066                 fprintf (stderr,"No source file named %s.\n",s);
1067                 goto ret;
1068             }
1069         }
1070                 
1071         /* case c) filename:lineno */
1072         if (isdigit(*(bp +1))) {                    
1073          
1074             setBPatModLine (mod,atoi(bp+1)-1,bpType);       
1075             goto ret;
1076             
1077         }
1078         /* case d) filename:function */
1079         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
1080             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
1081         else        
1082             setBPatModLine (mod,
1083                             (srcMode == SRC_CMODE ? 
1084                              func->entryline :
1085                              func->aentryline),bpType);
1086         
1087         goto ret;
1088     }
1089             
1090     /* case e) function */
1091     if (!applyToSet(functions,funcWithName,s,&func))
1092         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
1093     else
1094         setBPatModLine(func->mod,
1095                        (srcMode == SRC_CMODE ?
1096                         func->entryline :
1097                         func->aentryline),bpType);
1098
1099  ret:    
1100     return 0;
1101 }
1102
1103 /*-----------------------------------------------------------------*/
1104 /* cmdSetTmpUserBp - settempory break point at the user specified location   */
1105 /*-----------------------------------------------------------------*/
1106 int cmdSetTmpUserBp (char *s, context *cctxt)
1107 {
1108     return commonSetUserBp(s, cctxt, TMPUSER );
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* cmdSetUserBp - set break point at the user specified location   */
1113 /*-----------------------------------------------------------------*/
1114 int cmdSetUserBp (char *s, context *cctxt)
1115 {
1116     return commonSetUserBp(s, cctxt, USER );
1117 }
1118
1119 /*-----------------------------------------------------------------*/
1120 /* cmdJump - set program counter                                   */
1121 /*-----------------------------------------------------------------*/
1122 int cmdJump (char *s, context *cctxt)
1123 {
1124     char *bp ;
1125     function *func = NULL;
1126     if (STACK_EMPTY(callStack)) 
1127     {
1128         fprintf(stdout,"The program is not running.\n");
1129         return 0;
1130     } 
1131
1132     /* white space skip */
1133     while (*s && isspace(*s)) s++;
1134     
1135     /* null terminate it after stripping trailing blanks*/
1136     bp = s + strlen(s);
1137     while (bp != s && isspace(*bp)) bp--;
1138     *bp = '\0';
1139     if (! *s ) 
1140     {
1141         fprintf(stdout,"No argument: need line or *addr.\n");
1142         return 0;
1143     }
1144     if ( *s == '*' && isdigit(*(s+1)))
1145     {
1146         unsigned int addr = atoi(s);
1147         if (cctxt && cctxt->func &&
1148             cctxt->func->sym->addr <= addr &&
1149             cctxt->func->sym->eaddr >= addr)
1150         {
1151             simSetPC(addr);
1152             return 0;
1153         }
1154         fprintf(stdout,"Warning addr 0x%x outside actual function.\n",addr);
1155         simSetPC(addr);
1156         return 0;
1157     }
1158     if (isdigit(*s)) 
1159     {
1160         /* get the lineno */
1161         int line = atoi(s) -1;
1162         if (!cctxt || !cctxt->func || !cctxt->func->mod) 
1163         {
1164                     fprintf(stderr,"Function not defined.\n");
1165             return 0;
1166         }
1167         if (line >= cctxt->func->entryline &&
1168             line <= cctxt->func->exitline )
1169         {
1170             simSetPC(cctxt->func->mod->cLines[line]->addr);
1171             return 0;
1172         }
1173         if (line >= cctxt->func->mod->ncLines )
1174         {
1175                     fprintf(stderr,"line not in module.\n");
1176             return 0;
1177         }
1178         fprintf(stdout,"Warning line %d outside actual function.\n",line+1);
1179         simSetPC(cctxt->func->mod->cLines[line]->addr);
1180         return 0;
1181     }
1182     if ((bp = strchr(s,':'))) 
1183     {
1184         int line;
1185         module *mod = NULL;
1186         *bp++ = '\0';
1187         if (!applyToSet(modules,moduleWithCName,s,&mod)) 
1188         {
1189             fprintf (stderr,"No source file named %s.\n",s);
1190             return 0;
1191         } 
1192         if (!isdigit(*bp)) 
1193         {                        
1194             fprintf (stderr,"No line number.\n");
1195             return 0;       
1196         }
1197         line = atoi(bp) -1;
1198         if (line >= mod->ncLines )
1199         {
1200                     fprintf(stderr,"line not in module.\n");
1201             return 0;
1202         }
1203         if ( mod != cctxt->func->mod ||
1204              line < cctxt->func->entryline ||
1205              line > cctxt->func->exitline )
1206         {
1207             fprintf(stdout,"Warning line %d outside actual function.\n",
1208                     line+1);
1209         }             
1210         simSetPC(mod->cLines[line]->addr);
1211     }
1212     return 0;
1213 }
1214
1215 /*-----------------------------------------------------------------*/
1216 /* cmdListAsm - list assembler source code                         */
1217 /*-----------------------------------------------------------------*/
1218 int cmdListAsm (char *s, context *cctxt)
1219 {
1220     if (  cctxt && cctxt->func) 
1221     {
1222         /* actual line */
1223         if (printAsmLine(cctxt->func,cctxt->func->mod,
1224                          (long)cctxt->addr,(long)cctxt->addr))
1225             return 0; 
1226     }
1227     return 0;
1228 }
1229
1230 /*-----------------------------------------------------------------*/
1231 /* cmdSetOption - set debugger options                             */
1232 /*-----------------------------------------------------------------*/
1233 int cmdSetOption (char *s, context *cctxt)
1234 {
1235     while (*s && isspace(*s)) s++;
1236     if (strncmp(s,"srcmode",7) == 0 ) {
1237         if (srcMode == SRC_CMODE)
1238             srcMode = SRC_AMODE;
1239         else
1240             srcMode = SRC_CMODE;
1241         fprintf(stderr,"source mode set to '%s'\n", 
1242                 (srcMode == SRC_CMODE ? "C" : "asm"));
1243         return 0;
1244     }
1245
1246     if (strncmp(s,"listsize ",9) == 0) 
1247     {
1248         listlines = strtol(s+9,0,0);
1249         if ( listlines < LISTLINES )
1250             listlines = LISTLINES;
1251         return 0;
1252     }
1253
1254 #ifdef SDCDB_DEBUG
1255     if (strncmp(s,"debug ",6) == 0) 
1256     {
1257         sdcdbDebug = strtol(s+6,0,0);
1258         return 0;
1259     }
1260 #endif
1261     if (strncmp(s,"variable ",9) == 0) 
1262     {
1263         symbol *sym ;
1264         int fmt;
1265         char *rs;
1266         s += 9;
1267         if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
1268             return 0;
1269         s = rs;
1270         while (*s && *s != '=') s++;
1271         *s++ = '\0';
1272         while (isspace(*s)) *s++ = '\0';
1273         if (*s)
1274         {
1275                 printOrSetSymValue(sym,cctxt,0,0,0,rs,s);
1276                 return 0;
1277         }
1278         else
1279             fprintf(stdout,"No new value for \"%s\".\n",s);
1280         return 0;       
1281     }
1282
1283  
1284     fprintf(stderr,"'set %s' command not yet implemented\n",s);
1285     return 0;
1286 }
1287
1288 /*-----------------------------------------------------------------*/
1289 /* cmdContinue - continue till next break point                    */
1290 /*-----------------------------------------------------------------*/
1291 int cmdContinue (char *s, context *cctxt)
1292 {
1293     if (STACK_EMPTY(callStack)) {
1294         fprintf(stdout,"The program is not being run.\n");
1295         return 0;
1296     }
1297
1298     fprintf(stdout,"Continuing.\n");
1299     simGo(-1);
1300     showfull = 1;
1301     return 0;
1302 }
1303
1304 /*-----------------------------------------------------------------*/
1305 /* cmdDelUserBp - delete user break point                          */
1306 /*-----------------------------------------------------------------*/
1307 int cmdDelUserBp (char *s, context *cctxt)
1308 {
1309     int bpnum ;
1310     while (isspace(*s)) s++;
1311     
1312     if (!*s ) {
1313         if (userBpPresent) {
1314             char buffer[10];
1315             fprintf (stdout,"Delete all breakpoints? (y or n) ");
1316             fflush(stdout);
1317             fgets(buffer,sizeof(buffer),stdin);
1318             if (toupper(buffer[0]) == 'Y')
1319                 deleteUSERbp(-1);          
1320         }
1321         return 0;
1322     }
1323     
1324     /* determine the break point number */
1325     if (sscanf(s,"%d",&bpnum) == 1)
1326         deleteUSERbp(bpnum);
1327
1328     return 0;
1329 }
1330
1331 /*-----------------------------------------------------------------*/
1332 /* cmdStepi - single step exactly one instruction                   */
1333 /*-----------------------------------------------------------------*/
1334 int cmdStepi (char *s, context *cctxt)
1335 {
1336
1337     if (STACK_EMPTY(callStack))
1338         fprintf(stdout,"The program is not being run.\n");
1339     else 
1340     {
1341         doingSteps = 2;
1342             simGo(2);   
1343         doingSteps = 0;
1344         showfull = 1;
1345     }
1346     return 0;
1347 }
1348
1349 /*-----------------------------------------------------------------*/
1350 /* cmdStep - single step thru C source file                        */
1351 /*-----------------------------------------------------------------*/
1352 int cmdStep (char *s, context *cctxt)
1353 {
1354     function *func = NULL;
1355
1356     if (STACK_EMPTY(callStack))
1357         fprintf(stdout,"The program is not being run.\n");
1358     else {
1359         /* if we are @ the end of a function then set
1360            break points at execution points of the
1361            function in the call stack... */
1362         if (cctxt->addr == cctxt->func->sym->eaddr) {
1363             if ((func = STACK_PEEK(callStack))) {
1364                 if (srcMode == SRC_CMODE)
1365                     applyToSet (func->cfpoints,setStepEPBp,STEP,
1366                                 func->mod->c_name);     
1367                 else
1368                     applyToSet (func->afpoints,setStepEPBp,STEP,
1369                                 func->mod->asm_name);
1370             }
1371         } else {
1372             /* set breakpoints at all function entry points
1373                and all exepoints of this functions & for
1374                all functions one up in the call stack */
1375             
1376             /* all function entry points */
1377             applyToSet(functions,setStepBp); 
1378             
1379             if (srcMode == SRC_CMODE) {
1380                 /* for all execution points in this function */
1381                 applyToSet(cctxt->func->cfpoints,setStepEPBp,STEP,
1382                            cctxt->func->mod->c_name);
1383                 
1384                 /* set a break point @ the current function's
1385                    exit */
1386                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
1387                                stepBpCB, cctxt->func->mod->c_name, 
1388                                cctxt->func->exitline);
1389                 
1390                 /* now break point @ callers execution points */
1391                 if ((func = STACK_PPEEK(callStack))) {
1392                     applyToSet (func->cfpoints,setStepEPBp,STEP,
1393                                 func->mod->c_name);     
1394                     /* set bp @ callers exit point */
1395                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
1396                                    stepBpCB, func->mod->c_name, 
1397                                    func->exitline);
1398                 }
1399             } else {
1400                 /* for all execution points in this function */
1401                 applyToSet(cctxt->func->afpoints,setStepEPBp,STEP,
1402                            cctxt->func->mod->asm_name);
1403                 
1404                 /* set a break point @ the current function's
1405                    exit */
1406                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
1407                                stepBpCB, cctxt->func->mod->asm_name, 
1408                                cctxt->func->aexitline);
1409                 
1410                 /* now break point @ callers execution points */
1411                 if ((func = STACK_PPEEK(callStack))) {
1412                     
1413                     applyToSet (func->afpoints,setStepEPBp,STEP,
1414                                 func->mod->asm_name);   
1415                     
1416                     /* set bp @ callers exit point */
1417                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
1418                                    stepBpCB, func->mod->asm_name, 
1419                                    func->aexitline);
1420                 }
1421             }
1422         }
1423
1424         doingSteps = 1;
1425         simGo(2);
1426         doingSteps = 0;
1427         showfull = 1;
1428     }
1429     return 0;
1430 }
1431
1432 /*-----------------------------------------------------------------*/
1433 /* cmdNexti - next instruction but proceed function call           */
1434 /*-----------------------------------------------------------------*/
1435 int cmdNexti (char *s, context *cctxt)
1436 {
1437     if (STACK_EMPTY(callStack))
1438         fprintf(stdout,"The program is not being run.\n");
1439     else 
1440     {
1441         doingSteps = 2;
1442             simGo(1);   
1443         doingSteps = 0;
1444         showfull = 1;
1445     }   
1446     return 0;
1447 }
1448
1449 /*-----------------------------------------------------------------*/
1450 /* cmdNext - next executable C statement file                      */
1451 /*-----------------------------------------------------------------*/
1452 int cmdNext (char *s, context *cctxt)
1453 {
1454     function *func = NULL;
1455     /* next is almost the same as step except we don't
1456        we don't set break point for all function entry
1457        points */
1458     if (STACK_EMPTY(callStack))
1459         fprintf(stdout,"The program is not being run.\n");
1460     else {
1461         /* if we are @ the end of a function then set
1462            break points at execution points of the
1463            function in the call stack... */
1464         if (cctxt->addr == cctxt->func->sym->eaddr) {
1465             if ((func = STACK_PEEK(callStack))) {
1466                 if (srcMode == SRC_CMODE)
1467                     applyToSet (func->cfpoints,setStepEPBp,NEXT,
1468                                 func->mod->c_name);     
1469                 else
1470                     applyToSet (func->afpoints,setStepEPBp,NEXT,
1471                                 func->mod->asm_name);
1472             }
1473         } else {
1474             if (srcMode == SRC_CMODE) {
1475                 /* for all execution points in this function */
1476                 applyToSet(cctxt->func->cfpoints,setNextEPBp,NEXT,
1477                            cctxt->func->mod->c_name);
1478                 /* set a break point @ the current function's
1479                    exit */
1480                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
1481                                nextBpCB, cctxt->func->mod->c_name, 
1482                                cctxt->func->exitline);
1483                 
1484                 /* now break point @ callers execution points */        
1485                 if ((func = STACK_PPEEK(callStack))) {
1486                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
1487                                 func->mod->c_name);     
1488                     /* set bp @ callers exit point */
1489                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
1490                                    stepBpCB, func->mod->c_name, 
1491                                    func->exitline);
1492                 }
1493             } else {
1494                 /* for all execution points in this function */
1495                 applyToSet(cctxt->func->afpoints,setNextEPBp,NEXT,
1496                            cctxt->func->mod->asm_name);
1497                 /* set a break point @ the current function's
1498                    exit */
1499                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
1500                                nextBpCB, cctxt->func->mod->asm_name, 
1501                                cctxt->func->aexitline);
1502                 
1503                 /* now break point @ callers execution points */        
1504                 if ((func = STACK_PPEEK(callStack))) {
1505                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
1506                                 func->mod->asm_name);   
1507                     /* set bp @ callers exit point */
1508                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
1509                                    stepBpCB, func->mod->asm_name, 
1510                                    func->aexitline);
1511                 }
1512             }
1513         }
1514         doingSteps = 1;
1515         simGo(1);       
1516         doingSteps = 0;
1517         showfull = 1;
1518     }    
1519     return 0;
1520 }
1521
1522 /*-----------------------------------------------------------------*/
1523 /* cmdRun  - run till next break point                             */
1524 /*-----------------------------------------------------------------*/
1525 int cmdRun (char *s, context *cctxt)
1526 {
1527     char buff[10];
1528     if (STACK_EMPTY(callStack)) {
1529         fprintf(stdout,"Starting program\n");
1530     if ( ! simactive )
1531     {
1532         fprintf(stdout,"No executable file specified.\nUse the \"file\" command.\n");
1533         return 0;
1534     }
1535         simGo(0);
1536     } else {
1537         
1538         fprintf(stdout,
1539                 "The program being debugged has been started already.\n");
1540         fprintf(stdout,"Start it from the beginning? (y or n) ");
1541         fflush(stdout);
1542
1543         fgets(buff,sizeof(buff),stdin);
1544         if (toupper(buff[0]) == 'Y') {
1545             simReset();
1546             simGo(0);
1547         }
1548     }
1549     showfull = 1;
1550     return 0;
1551 }
1552
1553 /*-----------------------------------------------------------------
1554  cmdListSymbols - list symbols
1555 |-----------------------------------------------------------------*/
1556 int cmdListSymbols (char *s, context *cctxt)
1557 {
1558     int our_verbose = 0;
1559     symbol *sy;
1560     int i;
1561
1562     if (strstr(s, "v1")) {
1563       our_verbose = 1;
1564     } else if (strstr(s, "v2")) {
1565       our_verbose = 2;
1566     }
1567
1568     printf("[symbols]\n");
1569     sy = setFirstItem(symbols);
1570     i = 0;
1571     for (;;) {
1572       if (sy == NULL)
1573         break;
1574       if (our_verbose <= 1)
1575         printf("<%s>", sy->name);
1576
1577       if (our_verbose > 1) {
1578         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
1579           sy->name, sy->size, sy->level, sy->block);
1580         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
1581           sy->isonstack, sy->isfunc, sy->offset, sy->addr);
1582         printf("    eaddr:%d, addr_type:%c, type:%x etype:%x\n",
1583           sy->eaddr, sy->addr_type, sy->type, sy->etype);
1584         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
1585           sy->scopetype, sy->sname, sy->rname, sy->addrspace);
1586         printf("    next:%x\n", sy->next);
1587       }
1588       ++i;
1589       sy = setNextItem(symbols);
1590     }
1591     printf("   %d symbols\n", i);
1592     return 0;
1593 }
1594
1595 /*-----------------------------------------------------------------
1596  cmdListFunctions - list functions.
1597 |-----------------------------------------------------------------*/
1598 int cmdListFunctions (char *s, context *cctxt)
1599 {
1600     function *f;
1601     int i;
1602     int our_verbose = 0;
1603
1604     if (strstr(s, "v1")) {
1605       our_verbose = 1;
1606     } else if (strstr(s, "v2")) {
1607       our_verbose = 2;
1608     }
1609
1610     printf("[functions]\n");
1611     f = setFirstItem(functions);
1612     i = 0;
1613     for (;;) {
1614       if (f == NULL)
1615         break;
1616       if (our_verbose) {
1617         printf("  %d) sym:%x, fname:%s, modName:%s, mod:%x\n", i,
1618           f->sym, f->sym->name, f->modName, f->mod);
1619         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
1620                 f->entryline, f->aentryline, f->exitline, f->aexitline);
1621         printf("    cfpoints:%x, afpoints:%x, laddr:%x, lline:%d\n",
1622                 f->cfpoints, f->afpoints, f->laddr, f->lline);
1623       }
1624       else {
1625         printf("<%s>", f->modName);
1626       }
1627       ++i;
1628       f = setNextItem(functions);
1629     }
1630     printf("   %d functions\n", i);
1631     return 0;
1632 }
1633
1634 /*-----------------------------------------------------------------
1635  cmdListModules - list functions.
1636 |-----------------------------------------------------------------*/
1637 int cmdListModules (char *s, context *cctxt)
1638 {
1639     module *m;
1640     srcLine *cs, *as;
1641     int i, mi;
1642     int our_verbose = 0;
1643
1644     if (strstr(s, "v1")) {
1645       our_verbose = 1;
1646     } else if (strstr(s, "v2")) {
1647       our_verbose = 2;
1648     }
1649
1650     printf("[modules]\n");
1651     m = setFirstItem(modules);
1652     mi = 0;
1653     for (;;) {
1654       if (m == NULL)
1655         break;
1656
1657       if (our_verbose >= 0) {
1658       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
1659         m->cfullname, m->afullname, m->name);
1660       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
1661               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
1662       printf("    cLines:%x, asmLines:%x\n",
1663               m->cLines, m->asmLines);
1664       }
1665       if (our_verbose >= 2) {
1666         if (m->ncLines) {
1667           printf("    [cLines] ");
1668           if ( our_verbose)
1669           for (i=0; i<m->ncLines; i++ ) {
1670               cs = m->cLines[i];
1671               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1672                  i, cs->addr, cs->block, cs->level, cs->src);
1673           }
1674           if (!our_verbose)
1675               printf("%d records", i);
1676         }
1677         if (m->nasmLines) {
1678           printf("    [asmLines] ");
1679           if ( our_verbose)
1680           for (i=0; i<m->nasmLines; i++ ) {
1681               as = m->asmLines[i];
1682               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1683                  i, as->addr, as->block, as->level, as->src);
1684           }
1685           if (!our_verbose)
1686               printf("%d records", i);
1687         }
1688         printf("\n");
1689       }
1690
1691       m = setNextItem(modules);
1692     }
1693     return 0;
1694 }
1695
1696 /*-----------------------------------------------------------------
1697  infoSymbols - This is really just a tool to dump all these
1698    huge program structures out into human readable form.
1699 |-----------------------------------------------------------------*/
1700 static void infoSymbols(context *ctxt)
1701 {
1702   int our_verbose = 0;
1703
1704   printf("[context:%x] func:%x modName:%s addr:%x\n",
1705     ctxt, ctxt->func, ctxt->modName, ctxt->addr);
1706
1707   printf("  cline:%d asmline:%d block:%d level:%d\n",
1708     ctxt->cline, ctxt->asmline, ctxt->level);
1709
1710   printf("[globals] currCtxt:%x, modules:%x, functions:%x symbols:%x\n",
1711     currCtxt, modules, functions, symbols);
1712   printf("  nStructs:%d, structs:%x, ssdirl:%s\n",
1713     nStructs, structs, ssdirl);
1714
1715   /**************** modules *******************/
1716   {
1717     module *m;
1718     srcLine *cs, *as;
1719     int i, mi;
1720     printf("[modules]\n");
1721     m = setFirstItem(modules);
1722     mi = 0;
1723     for (;;) {
1724       if (m == NULL)
1725         break;
1726       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
1727         m->cfullname, m->afullname, m->name);
1728       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
1729               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
1730       printf("    cLines:%x, asmLines:%x\n",
1731               m->cLines, m->asmLines);
1732       i = 0;
1733       if (m->cLines) {
1734         cs = m->cLines[i++];
1735         printf("    [cLines] ");
1736         while (cs) {
1737           if (our_verbose)
1738             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1739                i, cs->addr, cs->block, cs->level, cs->src);
1740           cs = m->cLines[i++];
1741         }
1742         if (!our_verbose)
1743             printf("%d records", i);
1744       }
1745       i = 0;
1746       if (m->asmLines) {
1747         as = m->asmLines[i++];
1748         printf("    [asmLines] ");
1749         while (as) {
1750           if (our_verbose)
1751             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1752                i, as->addr, as->block, as->level, as->src);
1753           as = m->asmLines[i++];
1754         }
1755         if (!our_verbose)
1756             printf("%d records", i);
1757       }
1758       printf("\n");
1759
1760       m = setNextItem(modules);
1761     }
1762   }
1763
1764   /**************** functions *******************/
1765   {
1766     function *f;
1767     int i;
1768     printf("[functions]\n");
1769     f = setFirstItem(functions);
1770     i = 0;
1771     for (;;) {
1772       if (f == NULL)
1773         break;
1774       if (our_verbose) {
1775         printf("  %d) sym:%x, modName:%s, mod:%x\n", i,
1776           f->sym, f->modName, f->mod);
1777         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
1778                 f->entryline, f->aentryline, f->exitline, f->aexitline);
1779         printf("    cfpoints:%x, afpoints:%x, laddr:%x, lline:%d\n",
1780                 f->cfpoints, f->afpoints, f->laddr, f->lline);
1781       }
1782       ++i;
1783       f = setNextItem(functions);
1784     }
1785     if (!our_verbose)
1786       printf("   %d functions\n", i);
1787   }
1788
1789   /**************** symbols *******************/
1790   {
1791     symbol *s;
1792     int i;
1793     printf("[symbols]\n");
1794     s = setFirstItem(symbols);
1795     i = 0;
1796     for (;;) {
1797       if (s == NULL)
1798         break;
1799       if (our_verbose) {
1800         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
1801           s->name, s->size, s->level, s->block);
1802         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
1803           s->isonstack, s->isfunc, s->offset, s->addr);
1804         printf("    eaddr:%d, addr_type:%c, type:%x etype:%x\n",
1805           s->eaddr, s->addr_type, s->type, s->etype);
1806         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
1807           s->scopetype, s->sname, s->rname, s->addrspace);
1808         printf("    next:%x\n", s->next);
1809       }
1810       ++i;
1811       s = setNextItem(symbols);
1812     }
1813     if (!our_verbose)
1814       printf("   %d symbols\n", i);
1815   }
1816
1817 }
1818
1819 /*-----------------------------------------------------------------*/
1820 /* infoRegisters - print register information                      */
1821 /*-----------------------------------------------------------------*/
1822 static void infoRegisters( int all, context *ctxt)
1823 {
1824     static unsigned int regaddrs[] = {0x81,0x82,0x83,0xd0,0xe0,0xf0,0};
1825     unsigned long val;
1826     int i,j,*r;
1827
1828     i   = simGetValue (0xd0,'I',1);
1829     fprintf(stdout,"PC  : 0x%04X  RegisterBank %d:\nR0-7:",ctxt->addr,(i>>3)&3);
1830     for ( j = 0; j < 8 ; j++ )
1831     {
1832         val = simGetValue (j ,'R',1);
1833         fprintf(stdout," 0x%02X",val);
1834     }
1835     fprintf(stdout,"\n");
1836     val = simGetValue (0xe0,'I',1);
1837     fprintf(stdout,"ACC : 0x%02X %d %c\n",val,val,(isprint(val) ? val : '.'));
1838     val = simGetValue (0xf0,'I',1);
1839     fprintf(stdout,"B   : 0x%02X %d %c\n",val,val,(isprint(val) ? val : '.'));
1840     val = simGetValue (0x82,'I',2);
1841     fprintf(stdout,"DPTR: 0x%04X %d\n",val,val);
1842     val = simGetValue (0x81,'I',1);
1843     fprintf(stdout,"SP  : 0x%02X\n",val);
1844     fprintf(stdout,"PSW : 0x%02X | CY : %c | AC : %c | OV : %c | P : %c\n",
1845             i,(i&0x80)?'1':'0',(i&0x40)?'1':'0',(i&4)?'1':'0',(i&1)?'1':'0');
1846     if ( all )
1847     {
1848         fprintf(stdout,"Special Function Registers:\n");
1849         r = regaddrs;
1850         for ( i = 0x80 ; i < 0x100 ; i++ )
1851         {
1852             symbol *sym = NULL;
1853             if ( *r && *r == i )
1854             {
1855                 /* skip normal registers */
1856                 r++ ;
1857                 continue;
1858             }
1859             if (applyToSetFTrue(sfrsymbols,symWithAddr,i,'I',&sym))
1860             {
1861                 val = simGetValue (sym->addr,sym->addrspace,sym->size);
1862                 fprintf(stdout,"%s : 0x%02x",sym->name,val);
1863                 if ( !(i & 0x07 ))
1864                 {
1865                     for ( j = 0 ; j < 8 ; j++ )
1866                     {
1867                         sym = NULL;
1868                         if (applyToSetFTrue(sfrsymbols,symWithAddr,i+j,'J',&sym))
1869                         {
1870                             //val = simGetValue (sym->addr,sym->addrspace,sym->size);
1871                             fprintf(stdout," %s=%c",sym->name,(val&1)? '1':'0');
1872                         }
1873                         val >>= 1;
1874                     }
1875                 }
1876                 fprintf(stdout,"\n");
1877             }
1878         }
1879     }
1880 }
1881
1882 /*-----------------------------------------------------------------*/
1883 /* infoStack - print call stack information                        */
1884 /*-----------------------------------------------------------------*/
1885 static void infoStack(context *ctxt)
1886 {
1887     function *func ;
1888     int i = 0 ;
1889
1890     STACK_STARTWALK(callStack) ;
1891     while ((func = STACK_WALK(callStack))) {
1892     Dprintf(D_break, ("break: infoStack: %s %p (%p)\n",func->sym->name, w_callStack,p_callStack));
1893
1894         fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",i++,
1895                 func->laddr,func->sym->name,
1896                 func->mod->c_name,func->lline+1);
1897     }
1898     if ( !i )
1899         fprintf(stdout,"no stack.\n");
1900 }
1901
1902 /*-----------------------------------------------------------------*/
1903 /* cmdWhere -  where command                                       */
1904 /*-----------------------------------------------------------------*/
1905 int cmdWhere(char *s, context *cctxt)
1906 {
1907         infoStack(cctxt);
1908         return 0;
1909 }
1910
1911
1912 static int infomode = 0;
1913 /*-----------------------------------------------------------------*/
1914 /* cmdInfo - info command                                          */
1915 /*-----------------------------------------------------------------*/
1916 int cmdInfo (char *s, context *cctxt)
1917 {
1918     while (isspace(*s)) s++;
1919
1920     /* list all break points */
1921     if (strncmp(s,"break",5) == 0) {
1922         listUSERbp();
1923         return 0;
1924     }
1925
1926     /* info frame same as frame */
1927     if (strcmp(s,"frame") == 0) {
1928         cmdFrame (s,cctxt);
1929         return 0;
1930     }
1931
1932     if (strncmp(s,"line",4) == 0) {
1933     infomode=1;
1934         cmdListSrc (s+4,cctxt);
1935         return 0;
1936     }
1937     if (strncmp(s,"source",6) == 0) 
1938     {
1939         module *m;
1940         if ( s[6] == 's' )
1941         {
1942             int k = 0;
1943             fprintf(stdout,"Source files for which symbols have been read in:\n\n");
1944             for (m = setFirstItem(modules); m ; m = setNextItem(modules))
1945             {
1946                 fprintf(stdout,"%s%s, %s",k ? ", ":"",m->cfullname, m->afullname); 
1947                 k = 1;
1948             }
1949             fprintf(stdout,"\n"); 
1950         }
1951         else
1952         {
1953             if (!cctxt || !cctxt->func || !cctxt->func->mod) 
1954             {
1955                 fprintf(stdout,"No source file loaded\n");
1956                 return 0;
1957             }
1958             m = cctxt->func->mod;
1959             fprintf(stdout,"Current source file is %s\n",m->c_name);
1960             fprintf(stdout,"Located in %s\n",m->cfullname);
1961             fprintf(stdout,"Contains %d lines.\nSource language is c.\n",
1962                     m->ncLines);
1963         }
1964         return 0;
1965     }
1966     if (strncmp(s,"functions",7) == 0) 
1967     {
1968         function *f;
1969         module *m = NULL;
1970         fprintf(stdout,"All defined functions:\n");
1971         for ( f = setFirstItem(functions); f ; f = setNextItem(functions))
1972         {
1973             if ( f->mod != m )
1974             {
1975                 m = f->mod;
1976                 fprintf(stdout,"\nFile %s\n", m->c_name);
1977             }
1978             fprintf(stdout,"%s();\n",f->sym->name);
1979         }
1980         return 0;
1981     }
1982     /* info stack display call stack */
1983     if (strcmp(s,"stack") == 0) {
1984         infoStack(cctxt);
1985     showfull = 1;
1986         return 0;
1987     }
1988
1989     /* info stack display call stack */
1990     if (strcmp(s,"registers") == 0) {
1991         infoRegisters(0,cctxt);
1992             return 0;
1993     }
1994
1995     /* info stack display call stack */
1996     if (strcmp(s,"all-registers") == 0) 
1997     {
1998         infoRegisters(1,cctxt);
1999         return 0;
2000     }
2001
2002     /* info stack display call stack */
2003     if (strcmp(s,"symbols") == 0) {
2004       /* dump out symbols we have read in */
2005       fprintf(stdout,"Dumping symbols...\n");
2006       infoSymbols(cctxt);
2007       return 0;
2008     }
2009
2010     if (strcmp(s,"variables") == 0) {
2011       /* dump out symbols we have read in */
2012       fprintf(stdout,"Dumping symbols...\n");
2013       infoSymbols(cctxt);
2014       return 0;
2015     }
2016
2017     fprintf(stdout,"Undefined info command: \"%s\".  Try \"help\n",s);
2018     return 0;
2019
2020 }
2021
2022 /*-----------------------------------------------------------------*/
2023 /* cmdQuit  - quit debugging                                       */
2024 /*-----------------------------------------------------------------*/
2025 int cmdQuit (char *s, context *cctxt)
2026 {   
2027     if (simactive)
2028         closeSimulator();
2029     return 1;
2030 }
2031
2032 /*-----------------------------------------------------------------*/
2033 /* cmdListSrc  - list src                                          */
2034 /*-----------------------------------------------------------------*/
2035 int cmdListSrc (char *s, context *cctxt)
2036 {   
2037     static int currline = 0;
2038     int i =0 ;
2039     int pline = 0;
2040     int llines = listlines;
2041     function *func = NULL;
2042
2043
2044     while (*s && isspace(*s)) s++;
2045     
2046     /* if the user has spcified line numer then the line number
2047        can be of the following formats
2048        LINE          - just line number
2049        FILE:LINE     - filename line number
2050        FILE:LINE,LASTLINE  + last line
2051        FUNCTION      - list a function
2052        FILE:FUNCTION - function in file */
2053
2054     if (*s) {
2055         /* case a) LINE */
2056         if (isdigit(*s)) {
2057             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2058               if (!list_mod) {
2059                 fprintf(stdout,"Sdcdb fails to have a proper context at %d.\n", __LINE__);
2060                 return 0;
2061               }
2062             }
2063             else
2064               list_mod = cctxt->func->mod;
2065         pline = strtol(s,&s,10) - 1;
2066         if (s && (s = strchr(s,','))) 
2067         {
2068             /* LINE,LASTLINE */
2069             llines = strtol(s+1,0,10); 
2070             if ( llines > 0 )
2071                 llines -= pline+1;
2072             else
2073                 llines = listlines;
2074         }
2075         }
2076         else {
2077             char *bp;
2078             
2079             /* if ':' present then FILE:LINE || FILE:FUNCTION */
2080             if ((bp = strchr(s,':'))) {
2081                 *bp = '\0';
2082                 bp ++;
2083                 if (isdigit(*bp)) {
2084                     /* FILE:LINE */
2085                     list_mod=NULL;  /* bug fix 2-09-02, moduleWithCName expects mod to be null */
2086                     if (srcMode == SRC_CMODE) {
2087                         if (!applyToSet(modules,moduleWithCName,s,&list_mod)) {
2088                             fprintf (stderr,"No c source file named %s.\n",s);
2089                             return 0;
2090                         }
2091                     } else {
2092                         if (!applyToSet(modules,moduleWithAsmName,s,&list_mod)) {
2093                             fprintf (stderr,"No source file named %s.\n",s);
2094                             return 0;
2095                         }
2096                     }
2097                     pline = strtol(bp,&bp,10) - 1;
2098             if (bp && (bp = strchr(bp,','))) 
2099             {
2100                 /* FILE:LINE,LASTLINE */
2101                 llines = strtol(bp+1,0,10); 
2102                 if ( llines > 0 )
2103                     llines -= pline+1;
2104                 else
2105                     llines = listlines;
2106             }
2107                 } else {
2108                     /* FILE:FUCTION */
2109                     if (!applyToSet(functions,funcWithNameModule,bp,s,&func)) {
2110                         fprintf(stdout,"Function \"%s\" not defined.\n",bp);
2111                         return 0;
2112                     }
2113                     list_mod = func->mod;
2114                     if (srcMode == SRC_CMODE) {
2115                         pline = func->entryline;
2116                         llines = func->exitline - func->entryline + 1;
2117                     } else {
2118                         pline = func->aentryline;
2119                         llines = func->aexitline - func->aentryline + 1;
2120                     }
2121                 }
2122             }
2123             else {
2124                 /* FUNCTION */
2125             if (*s == '\'') 
2126             {
2127                 /* 'FUNCTION' */
2128                 s++ ;
2129                 if ((bp = strrchr(s,'\''))) 
2130                 {
2131                     *bp = '\0';
2132                 }
2133                 
2134             }
2135                 if (!applyToSet(functions,funcWithName,s,&func)) {
2136                     fprintf(stderr,"Function \"%s\" not defined.\n",s); 
2137                     return 0;
2138                 }
2139                 else {
2140                     list_mod = func->mod;
2141                     if (srcMode == SRC_CMODE) {
2142                         pline = func->entryline;
2143                         llines = func->exitline - func->entryline + 1; 
2144                     } else {
2145                         pline = func->aentryline;
2146                         llines = func->aexitline - func->aentryline + 1; 
2147                     }
2148                 }
2149             }
2150         }
2151     } else {
2152         /* if no line specified & we had listed
2153            before then continue from that listing */
2154         if (currline)
2155             pline = currline ;
2156         else {
2157             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2158               fprintf(stdout,"Missing context at %d. Try list filename:lineno\n", __LINE__);
2159               return 0;
2160             }
2161             list_mod = cctxt->func->mod;
2162             if (srcMode == SRC_CMODE)
2163                 pline = cctxt->cline;
2164             else
2165                 pline = cctxt->asmline;
2166         }
2167     }
2168
2169     if (!list_mod) {
2170       fprintf(stdout,"Sdcdb fails to have a valid module context at %d.\n", __LINE__);
2171       return 0;
2172     }
2173
2174     if ( pline < 0 )
2175         return 0;
2176     if ( infomode )
2177     {
2178         int firstaddr , lastaddr ;
2179             if ( pline  >= list_mod->ncLines )
2180             pline = cctxt->cline;
2181         firstaddr = lastaddr = list_mod->cLines[pline]->addr;
2182         if (!func && cctxt && cctxt->func )
2183             func = cctxt->func;
2184             fprintf(stdout,"Line %d of \"%s\" starts at address 0x%08x <%s+%d>", 
2185                 pline+1,
2186                 list_mod->c_name, lastaddr,
2187                 func ? func->sym->name : "?",
2188                 func ? lastaddr -func->sym->addr : 0);
2189         llines = pline +1;
2190         while ( pline < list_mod->ncLines )
2191         {
2192             pline++;
2193             if ( list_mod->cLines[pline]->addr > lastaddr )
2194             {
2195                 lastaddr = list_mod->cLines[pline]->addr -1;
2196                 break;
2197             }
2198         }
2199         fprintf(stdout," and ends at 0x%08x <%s+%d>.\n", 
2200                 lastaddr,
2201                 func ? func->sym->name : "?",
2202                 func ? lastaddr -func->sym->addr : 0);
2203         infomode=0;
2204         if ( func )
2205             fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
2206                     func->mod->cfullname,
2207                     llines,firstaddr);
2208         else
2209             showfull=1;
2210         return 0;
2211     }
2212     for ( i = 0 ; i < llines ; i++ ) {
2213         if (srcMode == SRC_CMODE) {
2214             if ( (pline + i) >= list_mod->ncLines )
2215                 break;
2216             fprintf(stdout,"%d\t%s",pline + i,
2217                     list_mod->cLines[pline +i]->src);
2218         } else {
2219             if ( (pline + i) >= list_mod->nasmLines )
2220                 break;
2221             fprintf(stdout,"%d\t%s",pline + i,
2222                     list_mod->asmLines[pline +i]->src);
2223         }
2224     }
2225     currline = pline + i ;
2226     return 0;
2227 }
2228
2229 static void setValBasic(symbol *sym, link *type,
2230                         char mem, unsigned addr,int size, char *val)
2231 {
2232     char *s;
2233     union 
2234     {   
2235         float f;     
2236         unsigned long val;
2237         long         sval;
2238         struct {
2239             unsigned short    lo;
2240             unsigned short    hi;
2241         } i;
2242         unsigned char b[4];
2243     }v;
2244
2245     if (IS_FLOAT(type))         
2246         v.f = strtof(val,NULL);    
2247     else
2248         if (IS_PTR(type))
2249             v.val = strtol(val,NULL,0);
2250         else
2251     {
2252             if (IS_INTEGRAL(type)) 
2253         {
2254             link *etype;
2255             if ( type->next )
2256                 etype = type->next;
2257             else
2258                 etype = type;
2259             if (IS_CHAR(etype))
2260             {
2261                 if (( s = strchr(val,'\'')))
2262                 {
2263                     if ( s[1] == '\\' )
2264                         v.b[0] = strtol(s+2,NULL,8);
2265                     else 
2266                         v.b[0] = s[1];
2267                 }
2268                 else
2269                 {
2270                     v.b[0] = strtol(val,NULL,0);
2271                 }
2272             }
2273             else
2274                 if (IS_INT(etype)) 
2275                     if (IS_LONG(etype))
2276                         v.val = strtol(val,NULL,0);
2277                     else
2278                         v.i.lo = strtol(val,NULL,0);
2279                 else
2280                     v.val = strtol(val,NULL,0);
2281             } 
2282         else
2283             v.val = strtol(val,NULL,0);
2284     }
2285     simSetValue(addr,mem,size,v.val);   
2286 }
2287
2288 /*-----------------------------------------------------------------*/
2289 /* printFmtInteger - print value in bin,oct,dez or hex             */
2290 /*-----------------------------------------------------------------*/
2291 static void printFmtInteger(char *deffmt,int fmt, long val, 
2292                             int sign, int size)
2293 {
2294     static char digits[] = 
2295     {
2296         '0' , '1' , '2' , '3' , '4' , '5' ,
2297         '6' , '7' , '8' , '9' , 'a' , 'b' ,
2298         'c' , 'd' , 'e' , 'f' , 'g' , 'h' 
2299     };
2300     static int radixOfFormat[] = { 0 , 2, 8 ,10, 16  };
2301     static int olenOfSize[]    = { 0 , 3, 6 , 8, 11  };
2302         char buf[40];
2303         char negative = 0;
2304         int charPos = 38;
2305     int radix;
2306
2307     if ( fmt == FMT_NON || fmt == FMT_DEZ )
2308     {
2309         fprintf(stdout,deffmt,val);
2310         return;
2311     }
2312     radix = radixOfFormat[fmt];
2313
2314     /*
2315     if ( sign && val < 0 )
2316         negative = 1;
2317     */
2318
2319         if (!negative)
2320             val = -val;
2321
2322         buf[39] = '\0';
2323     while (val <= -radix) 
2324     {
2325             buf[charPos--] = digits[-(val % radix)];
2326             val = val / radix;
2327         }
2328         buf[charPos] = digits[-val];
2329
2330     switch ( fmt )
2331     {
2332         case FMT_OCT:
2333             radix = olenOfSize[size];
2334             break;
2335         case FMT_HEX:
2336             radix = size << 1;
2337             break;
2338         case FMT_BIN:
2339             radix = size << 3;
2340             break;
2341     }
2342
2343     while (charPos > 39 - radix )
2344     {
2345         buf[--charPos] = '0';
2346     } 
2347     switch ( fmt )
2348     {
2349         case FMT_OCT:
2350             if ( buf[charPos] != '0' )
2351                 buf[--charPos] = '0';
2352             break;
2353         case FMT_HEX:
2354             buf[--charPos] = 'x';
2355             buf[--charPos] = '0';
2356             break;
2357     }
2358         if (negative) {
2359             buf[--charPos] = '-';
2360         }
2361     fputs(&buf[charPos],stdout);
2362 }
2363
2364 /*-----------------------------------------------------------------*/
2365 /* printValBasic - print value of basic types                      */
2366 /*-----------------------------------------------------------------*/
2367 static void printValBasic(symbol *sym, link *type,
2368                           char mem, unsigned addr,int size, int fmt)
2369 {
2370     union {     
2371         float f;     
2372         unsigned long val;
2373         long         sval;
2374         struct {
2375             unsigned short    lo;
2376             unsigned short    hi;
2377         } i;
2378         unsigned char b[4];
2379     }v;
2380     union {
2381         unsigned char b[4];
2382     }v1;
2383     
2384     v.val = simGetValue(addr,mem,size);
2385     /* if this a floating point number then */
2386     if (IS_FLOAT(type))         
2387         fprintf(stdout,"%f",v.f);    
2388     else
2389         if (IS_PTR(type))
2390             fprintf(stdout,"0x%*x",size<<1,v.val);
2391         else
2392         if (IS_INTEGRAL(type)) 
2393         {
2394             link *etype;
2395             if ( type->next )
2396                 etype = type->next;
2397             else
2398                 etype = type;
2399             if (IS_CHAR(etype))
2400             { 
2401                 if ( isprint(v.val))
2402                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'%c'"),
2403                                     fmt,(long)v.val,0,size);
2404                 else
2405                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'\\%o'"),
2406                                     fmt,(long)v.val,0,size);
2407             }
2408             else
2409             {
2410                 if (IS_INT(etype)) 
2411                     if (IS_LONG(etype))
2412                         if (SPEC_USIGN(etype))
2413                             printFmtInteger("%u",fmt,(long)v.val,0,size);
2414                         else
2415                             printFmtInteger("%d",fmt,(long)v.sval,1,size);
2416                     else
2417                         if (SPEC_USIGN(etype))
2418                             printFmtInteger("%u",fmt,(long)v.i.lo,0,size);
2419                         else
2420                             printFmtInteger("%d",fmt,(long)v.i.lo,1,size);
2421                 else
2422                 {
2423                     if (IS_BITVAR(etype))
2424                         fprintf(stdout,"%c",(v.val?'1':'0'));
2425                     else
2426                         fprintf(stdout,"0x%0*x",size<<1,v.val);
2427                 }
2428             }
2429             } else
2430             fprintf(stdout,"0x%0*x",size<<1,v.val);  
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* printValFunc  - prints function values                          */
2435 /*-----------------------------------------------------------------*/
2436 static void printValFunc (symbol *sym, int fmt)
2437 {
2438     fprintf(stdout,"print function not yet implemented");
2439 }
2440
2441 /*-----------------------------------------------------------------*/
2442 /* printArrayValue - will print the values of array elements       */
2443 /*-----------------------------------------------------------------*/
2444 static void printArrayValue (symbol *sym,  link *type,
2445                              char space, unsigned int addr, int fmt)
2446 {
2447         link *elem_type = type->next;
2448         int i;
2449         
2450         fprintf(stdout,"{");
2451         for (i = 0 ; i < DCL_ELEM(type) ; i++) {                
2452                 if (IS_AGGREGATE(elem_type)) {
2453                         printValAggregates(sym,elem_type,space,addr,fmt);                      
2454                 } else {
2455                         printValBasic(sym,elem_type,space,addr,getSize(elem_type),fmt);
2456                 }
2457                 addr += getSize(elem_type);
2458                 if (i != DCL_ELEM(type) -1)
2459                         fprintf(stdout,",");
2460         }
2461
2462         fprintf(stdout,"}");            
2463 }
2464
2465 /*-----------------------------------------------------------------*/
2466 /* printStructValue - prints structures elements                   */
2467 /*-----------------------------------------------------------------*/
2468 static void printStructValue (symbol *sym, link *type, 
2469                               char space, unsigned int addr, int fmt) 
2470 {
2471         symbol *fields = SPEC_STRUCT(type)->fields;
2472     int first = 1;
2473         fprintf(stdout," { ");
2474         while (fields) {
2475                 fprintf(stdout,"%s%s = ",(first ? "": ", "),fields->name);
2476                 first = 0;
2477         if (IS_AGGREGATE(fields->type)) {
2478                         printValAggregates(fields,fields->type,space, addr, fmt);
2479                 } else {
2480                         printValBasic(fields,fields->type,space,addr,getSize(fields->type), fmt);
2481                 }
2482                 addr += getSize(fields->type);
2483                 fields = fields->next;
2484         }
2485         fprintf(stdout,"}");
2486 }
2487
2488 /*-----------------------------------------------------------------*/
2489 /* printValAggregates - print value of aggregates                  */
2490 /*-----------------------------------------------------------------*/
2491 static void printValAggregates (symbol *sym, link *type,
2492                                 char space,unsigned int addr, int fmt)
2493 {
2494
2495         if (IS_ARRAY(type)) {
2496                 printArrayValue(sym, type, space, addr, fmt);
2497                 return ;
2498         }
2499
2500         if (IS_STRUCT(type)) { 
2501                 printStructValue(sym, type, space, addr, fmt); 
2502                 return; 
2503         } 
2504 }
2505
2506 /*-----------------------------------------------------------------*/
2507 /* printOrSetSymValue - print or set value of a symbol             */
2508 /*-----------------------------------------------------------------*/
2509 static void printOrSetSymValue (symbol *sym, context *cctxt, 
2510                            int flg, int dnum, int fmt, char *rs, char *val)
2511 {
2512     static char fmtChar[] = " todx ";
2513     static int stack = 1;
2514         symbol *fields;
2515     link *type;
2516     unsigned int  addr; 
2517     int size, n;
2518     char *s, *s2;
2519     char save_ch, save_ch2;
2520
2521     /* if it is on stack then compute address & fall thru */
2522     if (sym->isonstack) 
2523     {
2524         symbol *bp = symLookup("bp",cctxt);
2525         if (!bp) 
2526         {
2527             fprintf(stdout,"cannot determine stack frame\n");
2528             return ;
2529         }
2530
2531         sym->addr = simGetValue(bp->addr,bp->addrspace,bp->size)
2532             + sym->offset ;      
2533     }
2534     
2535     /* get the value from the simulator and
2536        print it */
2537     switch (flg)
2538     {
2539         case 0: 
2540         default:
2541             break;
2542         case 1: 
2543             fprintf(stdout,"$%d = ",stack++);
2544             break;
2545         case 2: 
2546             fprintf(stdout,"%d: ", dnum);
2547             if ( fmt != FMT_NON )
2548                 fprintf(stdout,"/%c ",fmtChar[fmt]);
2549             fprintf(stdout,"%s%s = ",sym->name,rs);
2550             break;
2551     }
2552
2553     addr = sym->addr;
2554     type = sym->type;
2555     size = sym->size;
2556
2557     while ( *rs )
2558     {
2559         if ( *rs == '[' && IS_ARRAY(type))
2560         {
2561             s = rs+1;
2562             while ( *rs && *rs != ']' ) rs++ ;
2563             save_ch = *rs;
2564             *rs = '\0' ;
2565             if ( ! isdigit(*s ))
2566             {
2567                 /* index seems a variable */
2568                 for ( s2 = s; *s2 && ( isalnum( *s2 ) || *s2 == '_'); s2++ );
2569                 save_ch2 = *s2;
2570                 if ( *s2 )
2571                     *s2 = '\0';
2572                 fields = symLookup(s,cctxt);
2573                 *s2 = save_ch2;
2574                 if ( ! fields )
2575                 {
2576                     fprintf(stdout,"Unkown variable \"%s\" for index.\n", s);
2577                     return;                    
2578                 }
2579                 /* arrays & structures first */
2580                 if (! IS_INTEGRAL(fields->type))
2581                 {
2582                     fprintf(stdout,"Wrong type of variable \"%s\" for index \n", s);
2583                     return;                    
2584                 }
2585                 n = simGetValue(fields->addr,fields->addrspace,getSize(fields->type));
2586             }
2587             else
2588             {
2589                 n = strtol(s,0,0);
2590             }
2591             if ( n < 0 || n >= DCL_ELEM(type))
2592             {
2593                 fprintf(stdout,"Wrong index %d.\n", n);
2594                 return;                    
2595             }
2596             type = type->next;
2597             size = getSize(type);
2598             addr += size * n;
2599             *rs++ = save_ch;
2600         }
2601         else if ( *rs == '.' && IS_STRUCT(type))
2602         {
2603             s = rs+1;
2604             /* search structure element */
2605             for ( rs = s; *rs && ( isalnum( *rs ) || *rs == '_'); rs++ );
2606             save_ch = *rs;
2607             if ( *rs )
2608                 *rs = '\0';
2609             for (fields = SPEC_STRUCT(type)->fields; fields; fields = fields->next) 
2610             {
2611                 if (!(strcmp(s,fields->name)))
2612                     break;
2613             }
2614             *rs = save_ch;
2615             if ( ! fields )
2616             {
2617                 fprintf(stdout,"Unknown field \"%s\" of structure\n", s);
2618                 return;                    
2619             }
2620             type = fields->type;
2621             size = getSize(type);
2622             addr += fields->offset;
2623         }
2624         else
2625             break;
2626     }
2627
2628     /* arrays & structures first */
2629     if (IS_AGGREGATE(type))
2630     {
2631             if ( val )
2632             fprintf(stdout,"Cannot set aggregate variable\n");
2633         else
2634             printValAggregates(sym,type,sym->addrspace,addr,fmt);
2635     }
2636     else
2637         /* functions */
2638         if (IS_FUNC(type))
2639     {
2640             if ( !val )
2641             printValFunc(sym,fmt);
2642     }
2643         else
2644     { 
2645             if ( val )
2646             setValBasic  (sym,type,sym->addrspace,addr,size,val);
2647         else
2648             printValBasic(sym,type,sym->addrspace,addr,size,fmt);
2649     }
2650     if ( flg > 0 ) fprintf(stdout,"\n");
2651         
2652 }
2653
2654 /*-----------------------------------------------------------------*/
2655 /* printStructInfo - print out structure information               */
2656 /*-----------------------------------------------------------------*/
2657 static void printStructInfo (structdef *sdef)
2658 {
2659     symbol *field = sdef->fields ;
2660     int i = 0 ;
2661     
2662     while (field) {
2663         i += field->offset;
2664         field = field->next;
2665     }
2666
2667     fprintf(stdout,"%s %s {\n",(i ? "struct" : "union" ), sdef->tag);
2668     field = sdef->fields;
2669     while (field) {
2670         printTypeInfo (field->type);
2671         fprintf(stdout," %s ;\n",field->name);
2672         field = field->next ;
2673     }
2674
2675     fprintf(stdout,"}\n");
2676
2677 }
2678
2679 /*-----------------------------------------------------------------*/
2680 /* printTypeInfo - print out the type information                  */
2681 /*-----------------------------------------------------------------*/
2682 static void printTypeInfo(link *p)
2683 {
2684     if (!p)
2685         return ;
2686
2687     if (IS_DECL(p)) {
2688         switch (DCL_TYPE(p))  {
2689         case FUNCTION:
2690             printTypeInfo (p->next);
2691             fprintf(stdout,"()");
2692             break;
2693         case ARRAY:
2694             printTypeInfo (p->next);
2695             fprintf(stdout,"[%d]",DCL_ELEM(p));
2696             break;
2697         
2698         case IPOINTER:
2699         case PPOINTER:
2700         case POINTER:
2701             printTypeInfo (p->next);
2702             fprintf(stdout,"(_near *)");
2703             break;
2704
2705         case FPOINTER:
2706             printTypeInfo (p->next);
2707             fprintf(stdout,"(_xdata *)");
2708             break;
2709
2710         case CPOINTER:
2711             printTypeInfo( p->next);
2712             fprintf(stdout,"(_code *)");
2713             break;
2714             
2715         case GPOINTER:
2716             printTypeInfo( p->next);
2717             fprintf(stdout,"(_generic *)");
2718             break;                   
2719         }
2720     } else {
2721         switch (SPEC_NOUN(p)) { /* depending on the specifier type */
2722         case V_INT:
2723             (IS_LONG(p) ? fputs("long ",stdout) : 
2724              ( IS_SHORT(p) ? fputs("short ",stdout) : 
2725                fputs("int ",stdout))) ;
2726             break;
2727         case V_FLOAT:
2728              fputs("float ",stdout);
2729              break;
2730
2731         case V_CHAR:
2732             fputs ("char ",stdout);
2733             break;
2734
2735         case V_VOID:
2736             fputs("void ",stdout);
2737             break;
2738
2739         case V_STRUCT:
2740             printStructInfo (SPEC_STRUCT(p));
2741             break;
2742
2743         case V_SBIT:
2744             fputs("sbit ",stdout);
2745             break;
2746
2747         case V_BIT:
2748             fprintf(stdout,": %d" ,SPEC_BLEN(p));       
2749             break;
2750         }
2751     }
2752 }
2753
2754 /*-----------------------------------------------------------------*/
2755 /* cmdPrint - print value of variable                              */
2756 /*-----------------------------------------------------------------*/
2757 int cmdPrint (char *s, context *cctxt)
2758 {   
2759     symbol *sym ;
2760     int fmt;
2761     char *rs;
2762     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
2763         return 0;
2764
2765     if ( sym ) 
2766     {
2767         printOrSetSymValue(sym,cctxt,1,0,fmt,rs,NULL);
2768     } 
2769     return 0;
2770 }
2771
2772 /*-----------------------------------------------------------------*/
2773 /* cmdOutput - print value of variable without number and newline  */
2774 /*-----------------------------------------------------------------*/
2775 int cmdOutput (char *s, context *cctxt)
2776 {   
2777     symbol *sym ;
2778     int fmt;
2779     char *rs;
2780     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
2781         return 0;
2782
2783     if ( sym ) 
2784     {
2785         printOrSetSymValue(sym,cctxt,0,0,fmt,rs,NULL);
2786     } 
2787     return 0;
2788 }
2789
2790 /** find display entry with this number */
2791
2792 DEFSETFUNC(dsymWithNumber)
2793 {
2794     dsymbol *dsym = item;
2795     V_ARG(int , dnum);
2796     V_ARG(dsymbol **,dsymp);
2797
2798     if ( dsym->dnum == dnum )
2799     {
2800         *dsymp = dsym;
2801         return 1;
2802     }
2803     return 0;
2804 }
2805
2806 /*-----------------------------------------------------------------*/
2807 /* displayAll  - display all valid variables                       */
2808 /*-----------------------------------------------------------------*/
2809 void displayAll(context *cctxt)
2810 {
2811     dsymbol *dsym;
2812     symbol  *sym;
2813     if ( !dispsymbols )
2814         return;
2815     for (dsym = setFirstItem(dispsymbols);
2816          dsym ;
2817          dsym = setNextItem(dispsymbols)) 
2818     {
2819         if ( (sym = symLookup(dsym->name,cctxt)))
2820             printOrSetSymValue(sym,cctxt,2,dsym->dnum,dsym->fmt,dsym->rs,NULL);
2821     }
2822 }
2823
2824 /*-----------------------------------------------------------------*/
2825 /* cmdDisplay  - display value of variable                         */
2826 /*-----------------------------------------------------------------*/
2827 int cmdDisplay (char *s, context *cctxt)
2828 {   
2829     static int dnum = 1;
2830     symbol *sym ;
2831     int fmt;
2832     char *rs;
2833     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
2834     {
2835         displayAll(cctxt);
2836         return 0;
2837     }
2838
2839     if ( sym ) 
2840     {
2841         dsymbol *dsym = (dsymbol *)Safe_calloc(1,sizeof(dsymbol));
2842         dsym->dnum = dnum++ ;
2843         dsym->name = sym->name;
2844         dsym->fmt  = fmt;
2845         dsym->rs   = gc_strdup(rs);
2846         addSetHead(&dispsymbols,dsym);
2847     }
2848     return 0;
2849 }
2850
2851 /*-----------------------------------------------------------------*/
2852 /* cmdUnDisplay  - undisplay value of variable                              */
2853 /*-----------------------------------------------------------------*/
2854 int cmdUnDisplay (char *s, context *cctxt)
2855 {   
2856     dsymbol *dsym;
2857     int dnum;
2858
2859     while (isspace(*s)) s++;
2860     if (!*s)
2861     {
2862         for (dsym = setFirstItem(dispsymbols);
2863              dsym;
2864              dsym = setNextItem(dispsymbols))
2865         {
2866             Safe_free(dsym->rs);
2867             Safe_free(dsym); 
2868         }
2869         deleteSet(&dispsymbols);
2870         return 0;
2871     }
2872     while ( s && *s )
2873     {
2874         dnum = strtol(s,&s,10);
2875         if (applyToSetFTrue(dispsymbols,dsymWithNumber,dnum,&dsym)) 
2876         {
2877             deleteSetItem(&dispsymbols,dsym);
2878             Safe_free(dsym->rs);
2879             Safe_free(dsym); 
2880         } 
2881         else
2882         {
2883             fprintf(stdout,"Arguments must be display numbers.\n");    
2884         }
2885     }
2886     return 0;
2887 }
2888
2889 /*-----------------------------------------------------------------*/
2890 /* cmdPrintType - print type of a variable                         */
2891 /*-----------------------------------------------------------------*/
2892 int cmdPrintType (char *s, context *cctxt)
2893 {   
2894         symbol *sym ;
2895     char *bp = s+strlen(s) -1;
2896
2897     while (isspace(*s)) s++;
2898     if (!*s) return 0;
2899     while (isspace(*bp)) bp--;
2900     bp++ ;
2901     *bp = '\0';
2902
2903     if ((sym = symLookup(s,cctxt))) {
2904         printTypeInfo(sym->type);
2905         fprintf(stdout,"\n");
2906     } else {
2907         fprintf(stdout,
2908                 "No symbol \"%s\" in current context.\n",
2909                 s);
2910     }
2911     return 0;   
2912 }
2913
2914 /*-----------------------------------------------------------------*/
2915 /* cmdClrUserBp - clear user break point                           */
2916 /*-----------------------------------------------------------------*/
2917 int cmdClrUserBp (char *s, context *cctxt)
2918 {   
2919     char *bp ;    
2920     function *func = NULL;
2921         
2922     /* clear break point location specification can be of the following
2923        forms
2924        a) <nothing>        - break point at current location
2925        b) lineno           - number of the current module
2926        c) filename:lineno  - line number of the given file
2927        e) filename:function- function X in file Y (useful for static functions)
2928        f) function         - function entry point
2929     */
2930
2931     if (!cctxt) {
2932         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
2933         return 0;
2934     }
2935
2936     /* white space skip */
2937     while (*s && isspace(*s)) s++;
2938     
2939     /* null terminate it after stripping trailing blanks*/
2940     bp = s + strlen(s);
2941     while (bp != s && isspace(*bp)) bp--;
2942     *bp = '\0';
2943
2944     /* case a) nothing */
2945     /* if nothing given then current location : we know
2946        the current execution location from the currentContext */
2947     if (! *s ) {
2948
2949         /* if current context is known */
2950         if (cctxt->func) 
2951             /* clear the break point @ current location */
2952             clearUSERbp (cctxt->addr);
2953         else
2954             fprintf(stderr,"No default breakpoint address now.\n");
2955                         
2956         goto ret ;
2957     }
2958
2959     /* case b) lineno */
2960     /* check if line number */
2961     if (isdigit(*s)) {
2962         /* get the lineno */
2963         int line = atoi(s);
2964
2965         /* if current context not present then we must get the module
2966            which has main & set the break point @ line number provided
2967            of that module : if current context known then set the bp 
2968            at the line number given for the current module 
2969         */
2970         if (cctxt->func) {
2971             if (!cctxt->func->mod) {
2972                 if (!applyToSet(functions,funcWithName,"main"))
2973                     fprintf(stderr,"Function \"main\" not defined.\n");
2974                 else 
2975                     clearBPatModLine(func->mod,line);
2976             } else 
2977                 clearBPatModLine(cctxt->func->mod,line);                        
2978         }
2979         
2980         goto ret;
2981     }
2982
2983     if ((bp = strchr(s,':'))) {
2984         
2985         module *mod = NULL;
2986         *bp = '\0';
2987         
2988         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
2989             fprintf (stderr,"No source file named %s.\n",s);
2990             goto ret;
2991         }
2992
2993         /* case c) filename:lineno */
2994         if (isdigit(*(bp +1))) {                    
2995          
2996             clearBPatModLine (mod,atoi(bp+1));      
2997             goto ret;
2998             
2999         }
3000         /* case d) filename:function */
3001         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
3002             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
3003         else
3004             clearBPatModLine (mod,func->entryline);
3005         
3006         goto ret;
3007     }
3008             
3009     /* case e) function */
3010     if (!applyToSet(functions,funcWithName,s,&func))
3011         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
3012     else
3013         clearBPatModLine(func->mod,func->entryline);
3014
3015  ret:    
3016     return 0;        
3017 }
3018
3019
3020 /*-----------------------------------------------------------------*/
3021 /* cmdSimulator - send command to simulator                        */
3022 /*-----------------------------------------------------------------*/
3023 int cmdSimulator (char *s, context *cctxt)
3024 {   
3025   char tmpstr[82];
3026
3027     if (strlen(s) > 80) {
3028       printf("error 3A\n");
3029       exit(1);
3030     }
3031     strcpy(tmpstr, s);
3032     strcat(tmpstr, "\n");
3033     sendSim(tmpstr);
3034     waitForSim(200,NULL);
3035     fprintf(stdout,"%s",simResponse());
3036     return 0;
3037 }
3038
3039 void setMainContext()
3040 {
3041     function *func = NULL;
3042     currentFrame = 0; 
3043     if (!applyToSet(functions,funcWithName,"main",&func) &&
3044         !applyToSet(functions,funcWithName,"_main",&func))
3045         return;
3046
3047     discoverContext (func->sym->addr, func);
3048 }
3049     
3050 static void printFrame()
3051 {
3052     int i;
3053     function *func     = NULL;
3054     function *lastfunc = NULL;
3055
3056     if ( currentFrame < 0 )
3057     {
3058         currentFrame = 0;
3059         fprintf(stdout,"Bottom (i.e., innermost) frame selected; you cannot go down.\n");
3060         return;
3061     }
3062     STACK_STARTWALK(callStack) ;
3063     for ( i = 0; i <= currentFrame ; i++ )
3064     {
3065         func = STACK_WALK(callStack);
3066         if ( !func )
3067         {
3068             currentFrame = i-1;
3069             fprintf(stdout,"Initial frame selected; you cannot go up.\n");
3070             return;
3071         }
3072     }
3073     fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",
3074             currentFrame,func->laddr,func->sym->name,func->mod->c_name,func->lline+1);
3075     fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
3076             func->mod->cfullname,func->lline+1,func->laddr);
3077
3078     discoverContext (func->laddr, func);
3079 }
3080
3081
3082 /*-----------------------------------------------------------------*/
3083 /* cmdUp -  Up command                                             */
3084 /*-----------------------------------------------------------------*/
3085 int cmdUp(char *s, context *cctxt)
3086 {
3087     while (isspace(*s)) s++;
3088     if ( *s )
3089         currentFrame += strtol(s,0,10);
3090     else
3091         currentFrame++ ;
3092
3093     printFrame();
3094         return 0;
3095 }
3096
3097 /*-----------------------------------------------------------------*/
3098 /* cmdDown - down command                                          */
3099 /*-----------------------------------------------------------------*/
3100 int cmdDown(char *s, context *cctxt)
3101 {
3102     while (isspace(*s)) s++;
3103     if ( *s )
3104         currentFrame -= strtol(s,0,10);
3105     else
3106         currentFrame-- ;
3107
3108     printFrame();
3109         return 0;
3110 }
3111 /*-----------------------------------------------------------------*/
3112 /* cmdFrame - Frame command                                        */
3113 /*-----------------------------------------------------------------*/
3114 int cmdFrame (char *s, context *cctxt)
3115 {   
3116     function *func = NULL;
3117     int i, framenr = 0;
3118
3119     while (isspace(*s)) s++;
3120     if ( *s )
3121         currentFrame = strtol(s,0,10);
3122     printFrame();
3123     return 0;
3124 }
3125
3126 /*-----------------------------------------------------------------*/
3127 /* cmdFinish - exec till end of current function                   */
3128 /*-----------------------------------------------------------------*/
3129 int cmdFinish (char *s, context *ctxt)
3130 {
3131     if (STACK_EMPTY(callStack)) {
3132         fprintf(stdout,"The program is not running.\n");
3133         return 0;
3134     }
3135
3136     if (srcMode == SRC_CMODE) {
3137         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
3138                        stepBpCB, ctxt->func->mod->c_name, 
3139                        ctxt->func->exitline);
3140     } else {
3141         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
3142                        stepBpCB, ctxt->func->mod->asm_name, 
3143                        ctxt->func->aexitline);
3144     }
3145
3146     simGo(-1);
3147     showfull = 1;
3148     return 0;
3149     
3150 }
3151
3152
3153 /*-----------------------------------------------------------------*/
3154 /* cmdShow - show command                                          */
3155 /*-----------------------------------------------------------------*/
3156 int cmdShow (char *s, context *cctxt)
3157 {
3158     /* skip white space */
3159     while (*s && isspace(*s)) s++ ;
3160
3161     if (strcmp(s,"copying") == 0) {
3162         fputs(copying,stdout);
3163         return 0;
3164     }
3165     
3166     if (strcmp(s,"warranty") == 0) {
3167         fputs(warranty,stdout);
3168         return 0;
3169     }
3170
3171     return 0;
3172 }
3173