(infoRegisters): show return address on stack
[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  int printOrSetSymValue (symbol *sym, context *cctxt, 
334                                 int flg, int dnum, int fmt, 
335                                 char *rs, char *val, char cmp);
336
337 int srcMode = SRC_CMODE ;
338 static set  *dispsymbols = NULL   ; /* set of displayable symbols */
339 static int currentFrame = 0;        /* actual displayed frame     */
340 /*-----------------------------------------------------------------*/
341 /* funcWithName - returns function with name                       */
342 /*-----------------------------------------------------------------*/
343 DEFSETFUNC(funcWithName)
344 {
345     function *func = item;
346     V_ARG(char *,name);
347     V_ARG(function **,funcp);
348
349     if (*funcp)
350         return 0;
351
352     if (strcmp(func->sym->name,name) == 0) {
353         *funcp = func;
354         return 1;
355     }
356     
357     return 0;
358 }
359
360 /*-----------------------------------------------------------------*/
361 /* symWithAddr - look for symbol with sfr / sbit address           */
362 /*-----------------------------------------------------------------*/
363 DEFSETFUNC(symWithAddr)
364 {
365     symbol *sym = item;
366     V_ARG(unsigned long,laddr);
367     V_ARG(int    ,laddrspace);
368     V_ARG(symbol **,rsym);
369
370     if (*rsym)
371         return 0;
372
373     if ( sym->addr == laddr &&
374          sym->addrspace == laddrspace ) 
375     {
376         *rsym = sym;
377         return 1;
378     }
379
380     return 0;
381 }
382
383 /*-----------------------------------------------------------------*/
384 /* setBPatModLine - set break point at the line specified for the  */
385 /*-----------------------------------------------------------------*/
386 static void setBPatModLine (module *mod, int line, char bpType )
387 {
388     int next_line;
389
390     /* look for the first executable line after the line
391        specified & get the break point there */   
392
393     if ( line < 0 )
394         return;
395
396     if (srcMode == SRC_CMODE && line > mod->ncLines) {
397         fprintf(stderr,"No line %d in file \"%s\".\n",
398                 line,mod->c_name);
399         return ;
400     }
401     
402     if (srcMode == SRC_AMODE && line > mod->nasmLines) {
403         fprintf(stderr,"No line %d in file \"%s\".\n",
404                 line,mod->asm_name);
405         return ;
406     }
407
408     next_line = line;
409     for ( ; next_line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ; 
410           next_line++ ) {
411         if (srcMode == SRC_CMODE) {
412             if (mod->cLines[next_line]->addr != INT_MAX) {
413                 setBreakPoint (mod->cLines[next_line]->addr, CODE, bpType, 
414                                userBpCB, mod->c_name, next_line);
415                 return;
416 //              break;
417             }
418         }
419         else {
420            if (mod->asmLines[next_line]->addr != INT_MAX) {
421                setBreakPoint (mod->asmLines[next_line]->addr, CODE, bpType, 
422                               userBpCB, mod->asm_name, next_line);
423                 return;
424 //             break;
425            } 
426         }
427     }
428
429         fprintf(stderr,"No line %d or after in file \"%s\"..\n",
430                         line,mod->c_name);
431
432     return;
433 }
434
435 /*-----------------------------------------------------------------*/
436 /* clearBPatModLine - clr break point at the line specified        */
437 /*-----------------------------------------------------------------*/
438 static void clearBPatModLine (module *mod, int line)
439 {
440     /* look for the first executable line after the line
441        specified & get the break point there */
442     if (srcMode == SRC_CMODE && line > mod->ncLines) {
443         fprintf(stderr,"No line %d in file \"%s\".\n",
444                 line,mod->c_name);
445         return ;
446     }
447     
448     if (srcMode == SRC_AMODE && line > mod->ncLines) {
449         fprintf(stderr,"No line %d in file \"%s\".\n",
450                 line,mod->c_name);
451         return ;
452     }    
453     
454     for ( ; line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ; 
455           line++ ) {
456         if (srcMode == SRC_CMODE) 
457             if (mod->cLines[line]->addr) {
458                 clearUSERbp (mod->cLines[line]->addr);                    
459                 break;
460             }
461         else
462             if (mod->asmLines[line]->addr) {
463                 clearUSERbp (mod->asmLines[line]->addr);                          
464                 break;
465             }
466     }
467
468     return;
469 }
470
471 /*-----------------------------------------------------------------*/
472 /* moduleLineWithAddr - finds and returns a line  with a given address */
473 /*-----------------------------------------------------------------*/
474 DEFSETFUNC(moduleLineWithAddr)
475 {
476     module *mod = item;
477     int i;
478
479     V_ARG(unsigned int,addr);
480     V_ARG(module **,rmod);
481     V_ARG(int *,line);
482
483     if (*rmod)
484         return 0;
485
486     for (i=0; i < mod->nasmLines; i++ ) 
487     {
488         if ( mod->asmLines[i]->addr == addr)
489         {
490             *rmod = mod ;
491             if (line )
492             {
493                 *line = 0;
494                 for ( i=0; i < mod->ncLines; i++ ) 
495                 {
496                     if ( mod->cLines[i]->addr > addr)
497                         break;
498                     *line = i;
499                 }
500                 return 1;
501             }
502         }
503     }
504
505     return 0;
506 }
507
508 /*-----------------------------------------------------------------*/
509 /* funcWithNameModule - returns functions with a name module combo */
510 /*-----------------------------------------------------------------*/
511 DEFSETFUNC(funcWithNameModule) 
512 {
513     function *func = item;
514     V_ARG(char *,fname);
515     V_ARG(char *,mname);
516     V_ARG(function **,funcp);
517
518     if (*funcp)
519         return 0;
520
521     if (strcmp(func->sym->name,fname) == 0 &&
522         strcmp(func->mod->c_name,mname) == 0) {
523         *funcp = func;
524         return 1;
525     }
526
527     return 0;
528 }
529
530 /*-----------------------------------------------------------------*/
531 /* funcInAddr - given an address returns the function              */
532 /*-----------------------------------------------------------------*/
533 DEFSETFUNC(funcInAddr)
534 {
535     function *func = item;
536     V_ARG(unsigned int,addr);
537     V_ARG(function **,funcp);
538
539     if (*funcp)
540         return 0;
541
542     /* in the address range */
543     if (func->sym->addr <= addr &&
544         func->sym->eaddr >= addr) {
545         
546         *funcp = func;
547         return 1;
548     }
549
550     return 0;       
551 }
552
553 /*-----------------------------------------------------------------*/
554 /* setStepBp - will set STEP Bp @ function entry points            */
555 /*-----------------------------------------------------------------*/
556 DEFSETFUNC(setStepBp)
557 {
558     function *func = item;
559     
560     if (func->sym && func->sym->addr ) {
561         
562         /* set the entry break point */
563         setBreakPoint (func->sym->addr , CODE , STEP , 
564                        stepBpCB ,func->mod->c_name , func->entryline);
565
566         return 1;
567     }
568
569     return 0;
570 }
571
572 /*-----------------------------------------------------------------*/
573 /* setStepEPBp - sets a given type of bp @ the execution point     */
574 /*-----------------------------------------------------------------*/
575 DEFSETFUNC(setStepEPBp)
576 {
577     exePoint *ep = item;
578     V_ARG(int,bptype);
579     V_ARG(char *,mname);
580    
581     setBreakPoint (ep->addr, CODE, bptype, 
582                    stepBpCB, mname, ep->line);
583     return 1;
584 }
585
586 /*-----------------------------------------------------------------*/
587 /* setNextEPBp - sets a given type of bp @ the execution point     */
588 /*-----------------------------------------------------------------*/
589 DEFSETFUNC(setNextEPBp)
590 {
591     exePoint *ep = item;
592     V_ARG(int,bptype);
593     V_ARG(char *,mname);
594    
595     setBreakPoint (ep->addr, CODE, bptype, 
596                    nextBpCB, mname, ep->line);
597     return 1;
598 }
599
600 /*-----------------------------------------------------------------*/
601 /* lineAtAddr - for execution points returns the one with addr     */
602 /*-----------------------------------------------------------------*/
603 DEFSETFUNC(lineAtAddr)
604 {
605     exePoint *ep = item;
606     V_ARG(unsigned int,addr);
607     V_ARG(int *,line);
608     V_ARG(int *,block);
609     V_ARG(int *,level);
610
611     /* address must be an exact match */
612     if (ep->addr == addr) {
613         *line = ep->line;
614         if (block)
615             *block = ep->block ;
616         if (level)
617             *level = ep->level ;
618         return 1;
619     }
620
621     return 0;
622     
623 }
624
625 /*-----------------------------------------------------------------*/
626 /* lineNearAddr - for execution points returns the one with addr   */
627 /*-----------------------------------------------------------------*/
628 DEFSETFUNC(lineNearAddr)
629 {
630     exePoint *ep = item;
631     V_ARG(unsigned int,addr);
632     V_ARG(int *,line);
633     V_ARG(int *,block);
634     V_ARG(int *,level);
635
636     /* the line in which the address is */
637     if (ep->addr <= addr) {
638         *line = ep->line;
639         if (block)
640             *block = ep->block ;
641         if (level)
642             *level = ep->level ;
643         return 1;
644     }
645
646     return 0;
647     
648 }
649
650 /*-----------------------------------------------------------------*/
651 /* discoverContext - find out the current context of the bp        */
652 /*-----------------------------------------------------------------*/
653 context *discoverContext (unsigned addr, function *func)
654 {
655     module   *mod  = NULL;
656     int line = 0;
657
658     /* find the function we are in */
659     if (!func && !applyToSet(functions,funcInAddr,addr,&func)) {
660         if (!applyToSet(functions,funcWithName,"_main",&func) ||
661             !applyToSet(modules,moduleLineWithAddr,addr,&mod,NULL))
662         {
663             fprintf(stderr, "addr 0x%x in no module/function (runtime env?)\n",addr);
664             return NULL;
665         }
666         currCtxt->func = func;
667         currCtxt->addr = addr;
668         currCtxt->modName = mod->name;
669         currCtxt->cline = func->exitline;
670     }
671     else
672     {
673         currCtxt->func = func;
674         currCtxt->addr = func->laddr = addr;
675         currCtxt->modName = func->modName;
676     
677         /* find the c line number */
678         if(applyToSet(func->cfpoints,lineAtAddr,addr,
679                   &line,&currCtxt->block,&currCtxt->level)) 
680             currCtxt->cline = func->lline = line;
681         else if(applyToSet(func->cfpoints,lineNearAddr,addr,
682                   &line,&currCtxt->block,&currCtxt->level)) 
683             currCtxt->cline = func->lline = line;
684         else
685             currCtxt->cline = -1;
686     }    
687     /* find the asm line number */
688     line = 0;
689     if (applyToSet(func->afpoints,lineAtAddr,addr,
690                    &line,NULL,NULL))
691         currCtxt->asmline = line;       
692     else
693         currCtxt->asmline = -1;
694         
695     return currCtxt ;
696 }
697
698
699 /*-----------------------------------------------------------------*/
700 /* simGo - send 'go' cmd to simulator and wait till a break occurs */
701 /*-----------------------------------------------------------------*/
702 void simGo (unsigned int gaddr)
703 {   
704     unsigned int addr ;
705     context *ctxt;
706     int rv;
707     stopCommandList();
708  top:    
709     if ( userinterrupt )
710     {
711         userinterrupt = 0;
712         return;
713     }
714     if ( gaddr == 0 )
715     {
716         function *func = NULL;;
717         if (applyToSet(functions,funcInAddr,gaddr,&func))
718             STACK_PUSH(callStack,func);
719     }
720     addr = simGoTillBp (gaddr);
721
722     /* got the pc for the break point now first
723        discover the program context i.e. module, function 
724        linenumber of the source etc, etc etc */
725     currentFrame = 0; 
726     ctxt = discoverContext (addr, NULL);
727     
728     /* dispatch all the break point call back functions */
729     rv = dispatchCB (addr,ctxt);    
730  ret:    
731
732     /* the dispatch call back function will return
733        non-zero if an user break point has been hit
734        if not then we continue with the execution 
735        of the program */
736     if (!rv) 
737     {
738         if ( gaddr == 0 )
739             gaddr = -1;
740         if ( gaddr == -1 || doingSteps == 1 )
741             goto top ;
742     }
743     
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* preparePrint - common parse function for  set variable,         */
748 /*                output, print and display                        */
749 /*-----------------------------------------------------------------*/
750 static char *preparePrint(char *s, context *cctxt, int *fmt, symbol **sym)
751 {
752     char *bp = s+strlen(s) -1;
753     char save_ch ;
754
755     *fmt = FMT_NON;
756     *sym = NULL;
757
758     while (isspace(*s)) s++;
759     if (!*s) 
760         return (char *)0;
761
762     while (isspace(*bp)) bp--;
763     bp++ ;
764     *bp = '\0';
765
766     if ( *s == '/' )
767     {
768         /* format of printout */
769         switch ( *++s )
770         {
771             case 'x':
772                 *fmt = FMT_HEX ;
773                 break;
774             case 'o':
775                 *fmt = FMT_OCT ;
776                 break;
777             default:
778             case 'd':
779                 *fmt = FMT_DEZ ;
780                 break;
781             case 't':
782                 *fmt = FMT_BIN ;
783                 break;
784         }
785         s++;
786         while (isspace(*s)) s++;
787     }
788     for ( bp = s; *bp && ( isalnum( *bp ) || *bp == '_' || *bp == '$'); bp++ );
789     save_ch = *bp;
790     if ( *bp )
791         *bp = '\0';
792
793     if ( *s )
794         *sym = symLookup(s,cctxt);
795     *bp = save_ch;
796
797     if ( ! *sym )
798         fprintf(stdout,"No symbol \"%s\" in current context.\n", s);
799     return bp;
800 }
801
802 static int printAsmLine( function *func, module *m, long saddr, long eaddr)
803 {
804     int i,j,delta;
805     int symaddr;
806     int lastaddr = saddr+1;
807     char *symname;
808
809     if ( func )
810     {
811         symaddr = func->sym->addr;
812         symname = func->sym->name;
813     }
814     else
815     {
816         symaddr = saddr;
817         symname = "" ;
818     }
819     for (j=0,i=0; i < m->nasmLines; i++ ) 
820     {
821         if ( saddr >= 0 && m->asmLines[i]->addr < saddr)
822         {
823                 continue;
824         }
825         if ( eaddr >= 0 && m->asmLines[i]->addr > eaddr)
826         {
827                 continue;
828         }
829         if ( func && 
830             (m->asmLines[i]->addr < func->sym->addr ||
831              m->asmLines[i]->addr > func->sym->eaddr ))
832         {
833             continue;
834         } 
835         delta = m->asmLines[i]->addr - symaddr;
836         if ( delta >= 0 )
837         {
838             j++;
839             lastaddr = m->asmLines[i]->addr;
840             printf("0x%08x <%s",lastaddr,symname);
841             if (delta > 0) printf("+%d",delta);
842             printf(">:\t%s",m->asmLines[i]->src);            
843         }
844     }
845     return lastaddr;
846 }
847
848 /*-----------------------------------------------------------------*/
849 /* cmdDisasm - disassemble  asm instruction                        */
850 /*-----------------------------------------------------------------*/
851 static int cmdDisasm (char *s, context *cctxt, int args)
852 {
853     function *func = NULL;
854     long  saddr = -1;
855     long  eaddr = -1;
856     int   found = 0;
857     module *modul;
858     /* white space skip */
859
860     if ( args > 0 )
861     {
862         while (*s && isspace(*s)) s++;
863
864         if ( isdigit(*s))
865         {
866             saddr = strtol(s,&s,0);
867             if ( args > 1 )
868             {
869                 while (*s && isspace(*s)) s++;
870
871                 if ( isdigit(*s))
872                     eaddr = strtol(s,0,0);
873             }
874             else
875                 eaddr = saddr+1;
876         }
877     }
878
879     if ( eaddr == -1 )
880     {       
881         /* no start or only start so dump function */
882         if ( saddr == -1 )
883         {
884             func = cctxt->func;
885         }
886         else
887         {
888             applyToSet(functions,funcInAddr,saddr,&func);
889         }
890         if ( func )
891         {
892             printf("Dump of assembler code for function %s:\n",func->sym->name);
893             printAsmLine(func,func->mod,-1,-1);
894             printf("End of assembler dump.\n");
895             return 0; 
896         }
897         else
898         {
899             if (applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
900             {
901                 eaddr = saddr + 5;
902                 printf("Dump of assembler code:\n");
903                 printAsmLine(NULL,modul,saddr,eaddr);
904                 printf("End of assembler dump.\n");
905                 return 0; 
906             }
907         }
908     }
909     else
910     {
911         if ( args > 1 )
912             printf("Dump of assembler code from 0x%08x to 0x%08x:\n",saddr,eaddr);
913         found = 0;
914         while ( saddr < eaddr )
915         {
916             func = NULL;
917             if (applyToSet(functions,funcInAddr,saddr,&func))
918             {
919                 found = 1;
920                 modul = func->mod;
921             }
922             else
923             {
924                 if ( found )
925                     break;
926                 if (!applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
927                     break;
928             }
929             saddr = printAsmLine(func,modul,saddr,eaddr) + 1;
930         }
931         if( saddr >= eaddr)
932         {
933             if ( args > 1 )
934                 printf("End of assembler dump.\n");
935             return 0; 
936         }
937         
938     }
939     fprintf(stderr,"No function contains specified address.\n");
940     if( saddr >= 0 )
941     {
942         char lbuf[64];
943         sprintf(lbuf,"dis 0x%lx 0 %ld\n",saddr,( eaddr == -1 )?1L:eaddr-saddr);
944         sendSim(lbuf);
945         waitForSim(1000, NULL);
946         fputs(simResponse(),stdout);
947     }
948     return 0; 
949 }
950 /*-----------------------------------------------------------------*/
951 /* cmdDisasm1 - disassemble one asm instruction                    */
952 /*-----------------------------------------------------------------*/
953 int cmdDisasm1 (char *s, context *cctxt)
954 {
955     return cmdDisasm( s, cctxt, 1);
956 }
957
958 /*-----------------------------------------------------------------*/
959 /* cmdDisasmF - disassemble asm instructions                       */
960 /*-----------------------------------------------------------------*/
961 int cmdDisasmF(char *s, context *cctxt)
962 {
963     return cmdDisasm( s, cctxt, 2);
964 }
965
966 static int commonSetUserBp(char *s, context *cctxt, char bpType)
967 {
968     char *bp ;
969     function *func = NULL;
970         
971     /* user break point location specification can be of the following
972        forms
973        a) <nothing>        - break point at current location
974        b) lineno           - number of the current module
975        c) filename:lineno  - line number of the given file
976        e) filename:function- function X in file Y (useful for static functions)
977        f) function         - function entry point
978        g) *addr            - break point at address 
979     */
980
981     if (!cctxt) {
982         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
983         return 0;
984     }
985     /* white space skip */
986     while (*s && isspace(*s)) s++;
987     
988     /* null terminate it after stripping trailing blanks*/
989     bp = s + strlen(s);
990     while (bp != s && isspace(*bp)) bp--;
991     *bp = '\0';
992
993     /* case a) nothing */
994     /* if nothing given then current location : we know
995        the current execution location from the currentContext */
996     if (! *s ) {
997
998         /* if current context is known */
999         if (cctxt->func) {
1000         Dprintf(D_break, ("commonSetUserBp: a) cctxtaddr:%x \n",cctxt->addr));
1001             if (srcMode == SRC_CMODE)
1002                 /* set the break point */
1003                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
1004                                 cctxt->func->mod->c_name, cctxt->cline);
1005             else
1006                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
1007                                 cctxt->func->mod->asm_name, cctxt->asmline);
1008                 
1009         }
1010         else
1011             fprintf(stderr,"No default breakpoint address now.\n");
1012                         
1013         goto ret ;
1014     }
1015     /* case g) *addr */
1016     if ( *s == '*' && isdigit(*(s+1)))
1017     {
1018         int  line   = 0;
1019         long braddr = strtol(s+1,0,0);
1020         if (!applyToSet(functions,funcInAddr,braddr,&func))
1021         {
1022             module *modul;
1023             if (!applyToSet(modules,moduleLineWithAddr,braddr,&modul,&line))
1024             {
1025                 fprintf(stderr,"Address 0x%08x not exists in code.\n",braddr); 
1026             }
1027             else
1028             {
1029                 Dprintf(D_break, ("commonSetUserBp: g) addr:%x \n",braddr));
1030                 setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1031                             modul->c_name,line);
1032             }
1033             goto ret ;
1034         }
1035                 else
1036         {
1037             int line = func->exitline;
1038             if ( !applyToSet(func->cfpoints,lineAtAddr,braddr,
1039                                   &line,NULL,NULL))
1040                 applyToSet(func->cfpoints,lineNearAddr,braddr,&line,NULL,NULL);
1041             setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1042                             func->mod->c_name,line);
1043         }
1044         goto ret ;
1045     }
1046     /* case b) lineno */
1047     /* check if line number */
1048     if ( !strchr(s,':') && isdigit(*s)) {
1049         /* get the lineno */
1050         int line = atoi(s) -1;
1051     Dprintf(D_break, ("commonSetUserBp: b) line:%d \n",line));
1052     if ( line < 0 )
1053     {
1054                 fprintf(stdout,"linenumber <= 0\n");
1055         goto ret;
1056     }
1057         /* if current context not present then we must get the module
1058            which has main & set the break point @ line number provided
1059            of that module : if current context known then set the bp 
1060            at the line number given for the current module 
1061         */
1062         if (cctxt->func) {
1063             if (!cctxt->func->mod) {
1064                 if (!applyToSet(functions,funcWithName,"main"))
1065                     fprintf(stderr,"Function \"main\" not defined.\n");
1066                 else 
1067                     setBPatModLine(func->mod,line, bpType);
1068             } else 
1069                 setBPatModLine(cctxt->func->mod,line, bpType);
1070         } else {
1071                 if (list_mod) {
1072                         setBPatModLine(list_mod,line, bpType);
1073                 } else {
1074                   fprintf(stdout,"Sdcdb fails to have module symbol context at %d\n", __LINE__);
1075                 }
1076         }
1077         
1078         goto ret;
1079     }
1080
1081     if ((bp = strchr(s,':'))) {
1082         
1083         module *mod = NULL;
1084         *bp = '\0';
1085         
1086         if (srcMode == SRC_CMODE) {
1087             if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1088                 fprintf (stderr,"No source file named %s.\n",s);
1089                 goto ret;
1090             }
1091         } else {
1092             if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
1093                 fprintf (stderr,"No source file named %s.\n",s);
1094                 goto ret;
1095             }
1096         }
1097                 
1098         /* case c) filename:lineno */
1099         if (isdigit(*(bp +1))) {                         
1100         Dprintf(D_break, ("commonSetUserBp: c) line:%d \n",atoi(bp+1)));
1101             setBPatModLine (mod,atoi(bp+1)-1,bpType);       
1102             goto ret;
1103             
1104         }
1105         /* case d) filename:function */
1106         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
1107             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
1108         else        
1109         Dprintf(D_break, ("commonSetUserBp: d) \n"));
1110             setBPatModLine (mod,
1111                             (srcMode == SRC_CMODE ? 
1112                              func->entryline :
1113                              func->aentryline),bpType);
1114         
1115         goto ret;
1116     }
1117             
1118     /* case e) function */
1119     Dprintf(D_break, ("commonSetUserBp: e) \n"));
1120     if (!applyToSet(functions,funcWithName,s,&func))
1121         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
1122     else
1123         setBPatModLine(func->mod,
1124                        (srcMode == SRC_CMODE ?
1125                         func->entryline :
1126                         func->aentryline),bpType);
1127
1128  ret:    
1129     return 0;
1130 }
1131
1132 /*-----------------------------------------------------------------*/
1133 /* cmdSetTmpUserBp - settempory break point at the user specified location   */
1134 /*-----------------------------------------------------------------*/
1135 int cmdSetTmpUserBp (char *s, context *cctxt)
1136 {
1137     return commonSetUserBp(s, cctxt, TMPUSER );
1138 }
1139
1140 /*-----------------------------------------------------------------*/
1141 /* cmdSetUserBp - set break point at the user specified location   */
1142 /*-----------------------------------------------------------------*/
1143 int cmdSetUserBp (char *s, context *cctxt)
1144 {
1145     return commonSetUserBp(s, cctxt, USER );
1146 }
1147
1148 /*-----------------------------------------------------------------*/
1149 /* cmdJump - set program counter                                   */
1150 /*-----------------------------------------------------------------*/
1151 int cmdJump (char *s, context *cctxt)
1152 {
1153     char *bp ;
1154     function *func = NULL;
1155     if (STACK_EMPTY(callStack)) 
1156     {
1157         fprintf(stdout,"The program is not running.\n");
1158         return 0;
1159     } 
1160
1161     /* white space skip */
1162     while (*s && isspace(*s)) s++;
1163     
1164     /* null terminate it after stripping trailing blanks*/
1165     bp = s + strlen(s);
1166     while (bp != s && isspace(*bp)) bp--;
1167     *bp = '\0';
1168     if (! *s ) 
1169     {
1170         fprintf(stdout,"No argument: need line or *addr.\n");
1171         return 0;
1172     }
1173     if ( *s == '*' && isdigit(*(s+1)))
1174     {
1175         unsigned int addr = atoi(s);
1176         if (cctxt && cctxt->func &&
1177             cctxt->func->sym->addr <= addr &&
1178             cctxt->func->sym->eaddr >= addr)
1179         {
1180             simSetPC(addr);
1181             return 0;
1182         }
1183         fprintf(stdout,"Warning addr 0x%x outside actual function.\n",addr);
1184         simSetPC(addr);
1185         return 0;
1186     }
1187     if (isdigit(*s)) 
1188     {
1189         /* get the lineno */
1190         int line = atoi(s) -1;
1191         if (!cctxt || !cctxt->func || !cctxt->func->mod) 
1192         {
1193                     fprintf(stderr,"Function not defined.\n");
1194             return 0;
1195         }
1196         if (line >= cctxt->func->entryline &&
1197             line <= cctxt->func->exitline )
1198         {
1199             simSetPC(cctxt->func->mod->cLines[line]->addr);
1200             return 0;
1201         }
1202         if (line >= cctxt->func->mod->ncLines )
1203         {
1204                     fprintf(stderr,"line not in module.\n");
1205             return 0;
1206         }
1207         fprintf(stdout,"Warning line %d outside actual function.\n",line+1);
1208         simSetPC(cctxt->func->mod->cLines[line]->addr);
1209         return 0;
1210     }
1211     if ((bp = strchr(s,':'))) 
1212     {
1213         int line;
1214         module *mod = NULL;
1215         *bp++ = '\0';
1216         if (!applyToSet(modules,moduleWithCName,s,&mod)) 
1217         {
1218             fprintf (stderr,"No source file named %s.\n",s);
1219             return 0;
1220         } 
1221         if (!isdigit(*bp)) 
1222         {                        
1223             fprintf (stderr,"No line number.\n");
1224             return 0;       
1225         }
1226         line = atoi(bp) -1;
1227         if (line >= mod->ncLines )
1228         {
1229                     fprintf(stderr,"line not in module.\n");
1230             return 0;
1231         }
1232         if ( mod != cctxt->func->mod ||
1233              line < cctxt->func->entryline ||
1234              line > cctxt->func->exitline )
1235         {
1236             fprintf(stdout,"Warning line %d outside actual function.\n",
1237                     line+1);
1238         }             
1239         simSetPC(mod->cLines[line]->addr);
1240     }
1241     return 0;
1242 }
1243
1244 /*-----------------------------------------------------------------*/
1245 /* cmdListAsm - list assembler source code                         */
1246 /*-----------------------------------------------------------------*/
1247 int cmdListAsm (char *s, context *cctxt)
1248 {
1249     if (  cctxt && cctxt->func) 
1250     {
1251         /* actual line */
1252         if ( cctxt->addr != INT_MAX )
1253         {
1254             if (printAsmLine(cctxt->func,cctxt->func->mod,
1255                          (long)cctxt->addr,(long)cctxt->addr))
1256             return 0; 
1257         }
1258     }
1259     return 0;
1260 }
1261
1262 /*-----------------------------------------------------------------*/
1263 /* cmdSetOption - set debugger options                             */
1264 /*-----------------------------------------------------------------*/
1265 int cmdSetOption (char *s, context *cctxt)
1266 {
1267     while (*s && isspace(*s)) s++;
1268     if (strncmp(s,"srcmode",7) == 0 ) {
1269         if (srcMode == SRC_CMODE)
1270             srcMode = SRC_AMODE;
1271         else
1272             srcMode = SRC_CMODE;
1273         fprintf(stderr,"source mode set to '%s'\n", 
1274                 (srcMode == SRC_CMODE ? "C" : "asm"));
1275         return 0;
1276     }
1277
1278     if (strncmp(s,"listsize ",9) == 0) 
1279     {
1280         listlines = strtol(s+9,0,0);
1281         if ( listlines < LISTLINES )
1282             listlines = LISTLINES;
1283         return 0;
1284     }
1285
1286 #ifdef SDCDB_DEBUG
1287     if (strncmp(s,"debug ",6) == 0) 
1288     {
1289         sdcdbDebug = strtol(s+6,0,0);
1290         return 0;
1291     }
1292 #endif
1293     if (strncmp(s,"variable ",9) == 0) 
1294     {
1295         symbol *sym ;
1296         int fmt;
1297         char *rs;
1298         s += 9;
1299         if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
1300             return 0;
1301         s = rs;
1302         while (*s && *s != '=') s++;
1303         *s++ = '\0';
1304         while (isspace(*s)) *s++ = '\0';
1305         if (*s && sym)
1306         {
1307             printOrSetSymValue(sym,cctxt,0,0,0,rs,s,'\0');
1308             return 0;
1309         }
1310         else
1311             fprintf(stdout,"No new value for \"%s\".\n",s);
1312         return 0;       
1313     }
1314
1315  
1316     fprintf(stderr,"'set %s' command not yet implemented\n",s);
1317     return 0;
1318 }
1319
1320 /*-----------------------------------------------------------------*/
1321 /* cmdContinue - continue till next break point                    */
1322 /*-----------------------------------------------------------------*/
1323 int cmdContinue (char *s, context *cctxt)
1324 {
1325     if (STACK_EMPTY(callStack)) {
1326         fprintf(stdout,"The program is not being run.\n");
1327         return 0;
1328     }
1329
1330     fprintf(stdout,"Continuing.\n");
1331     simGo(-1);
1332     showfull = 1;
1333     return 0;
1334 }
1335
1336 /*-----------------------------------------------------------------*/
1337 /* cmdIgnore - set ignorecount for breakpoint                      */
1338 /*-----------------------------------------------------------------*/
1339 int cmdIgnore (char *s, context *cctxt)
1340 {   
1341     int bpnum, cnt ;
1342     while (isspace(*s)) s++;
1343     if (!*s ) 
1344     {
1345         fprintf(stdout,"Argument required (breakpoint number).\n");
1346         return 0;
1347     }
1348     bpnum = strtol(s,&s,10);
1349     while (isspace(*s)) s++;
1350     if (!*s ) 
1351     {
1352         fprintf(stdout,"Second argument (specified ignore-count) is missing.");
1353         return 0;
1354     }
1355     cnt = strtol(s,0,10);
1356     setUserbpIgnCount(bpnum,cnt);
1357     return 0;
1358 }
1359
1360 /*-----------------------------------------------------------------*/
1361 /* cmdCondition - set condition for breakpoint                     */
1362 /*-----------------------------------------------------------------*/
1363 int cmdCondition (char *s, context *cctxt)
1364 {   
1365     int bpnum ;
1366     while (isspace(*s)) s++;
1367     if (!*s ) 
1368     {
1369         fprintf(stdout,"Argument required (breakpoint number).\n");
1370         return 0;
1371     }
1372     bpnum = strtol(s,&s,10);
1373     while (isspace(*s)) s++;
1374     if (*s)
1375         s = Safe_strdup(s);
1376     else
1377         s = NULL;
1378     setUserbpCondition(bpnum,s);
1379     return 0;
1380 }
1381
1382 /*-----------------------------------------------------------------*/
1383 /* cmdCommands - set commands for breakpoint                       */
1384 /*-----------------------------------------------------------------*/
1385 int cmdCommands (char *s, context *cctxt)
1386 {   
1387     int bpnum ;
1388     char *cmds,*line;
1389     while (isspace(*s)) s++;
1390     
1391     if (!*s ) 
1392         bpnum = getLastBreakptNumber();
1393     else
1394         bpnum = strtol(s,0,10);
1395
1396     cmds = NULL;
1397     while ((line = getNextCmdLine()))
1398     {
1399         while (isspace(*line)) line++;
1400         if (!strncmp(line,"end",3))
1401             break;
1402         if (! cmds )
1403         {
1404             cmds = Safe_strdup(line);
1405         }
1406         else
1407         {
1408             cmds = Safe_realloc( cmds, strlen(cmds) + 1 + strlen(line));
1409             strcat(cmds,line);
1410         }
1411     }
1412     setUserbpCommand(bpnum,cmds);
1413     return 0;
1414 }
1415
1416 /*-----------------------------------------------------------------*/
1417 /* cmdDelUserBp - delete user break point                          */
1418 /*-----------------------------------------------------------------*/
1419 int cmdDelUserBp (char *s, context *cctxt)
1420 {
1421     int bpnum ;
1422     while (isspace(*s)) s++;
1423     
1424     if (!*s ) {
1425         if (userBpPresent) {
1426             char buffer[10];
1427             fprintf (stdout,"Delete all breakpoints? (y or n) ");
1428             fflush(stdout);
1429             fgets(buffer,sizeof(buffer),stdin);
1430             if (toupper(buffer[0]) == 'Y')
1431                 deleteUSERbp(-1);          
1432         }
1433         return 0;
1434     }
1435     
1436     /* determine the break point number */
1437     if (sscanf(s,"%d",&bpnum) == 1)
1438         deleteUSERbp(bpnum);
1439
1440     return 0;
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* cmdStepi - single step exactly one instruction                   */
1445 /*-----------------------------------------------------------------*/
1446 int cmdStepi (char *s, context *cctxt)
1447 {
1448
1449     if (0 /*STACK_EMPTY(callStack)*/)
1450         fprintf(stdout,"The program is not being run.\n");
1451     else 
1452     {
1453         doingSteps = 2;
1454             simGo(2);   
1455         doingSteps = 0;
1456         showfull = 1;
1457     }
1458     return 0;
1459 }
1460
1461 /*-----------------------------------------------------------------*/
1462 /* cmdStep - single step thru C source file                        */
1463 /*-----------------------------------------------------------------*/
1464 int cmdStep (char *s, context *cctxt)
1465 {
1466     function *func = NULL;
1467
1468     if (STACK_EMPTY(callStack))
1469         fprintf(stdout,"The program is not being run.\n");
1470     else {
1471         /* if we are @ the end of a function then set
1472            break points at execution points of the
1473            function in the call stack... */
1474         if (cctxt->addr == cctxt->func->sym->eaddr) {
1475             if ((func = STACK_PEEK(callStack))) {
1476                 if (srcMode == SRC_CMODE)
1477                     applyToSet (func->cfpoints,setStepEPBp,STEP,
1478                                 func->mod->c_name);     
1479                 else
1480                     applyToSet (func->afpoints,setStepEPBp,STEP,
1481                                 func->mod->asm_name);
1482             }
1483         } else {
1484             /* set breakpoints at all function entry points
1485                and all exepoints of this functions & for
1486                all functions one up in the call stack */
1487             
1488             /* all function entry points */
1489             applyToSet(functions,setStepBp); 
1490             
1491             if (srcMode == SRC_CMODE) {
1492                 /* for all execution points in this function */
1493                 applyToSet(cctxt->func->cfpoints,setStepEPBp,STEP,
1494                            cctxt->func->mod->c_name);
1495                 
1496                 /* set a break point @ the current function's
1497                    exit */
1498                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
1499                                stepBpCB, cctxt->func->mod->c_name, 
1500                                cctxt->func->exitline);
1501                 
1502                 /* now break point @ callers execution points */
1503                 if ((func = STACK_PPEEK(callStack))) {
1504                     applyToSet (func->cfpoints,setStepEPBp,STEP,
1505                                 func->mod->c_name);     
1506                     /* set bp @ callers exit point */
1507                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
1508                                    stepBpCB, func->mod->c_name, 
1509                                    func->exitline);
1510                 }
1511             } else {
1512                 /* for all execution points in this function */
1513                 applyToSet(cctxt->func->afpoints,setStepEPBp,STEP,
1514                            cctxt->func->mod->asm_name);
1515                 
1516                 /* set a break point @ the current function's
1517                    exit */
1518                 setBreakPoint (cctxt->func->sym->eaddr, CODE, STEP , 
1519                                stepBpCB, cctxt->func->mod->asm_name, 
1520                                cctxt->func->aexitline);
1521                 
1522                 /* now break point @ callers execution points */
1523                 if ((func = STACK_PPEEK(callStack))) {
1524                     
1525                     applyToSet (func->afpoints,setStepEPBp,STEP,
1526                                 func->mod->asm_name);   
1527                     
1528                     /* set bp @ callers exit point */
1529                     setBreakPoint (func->sym->eaddr, CODE, STEP , 
1530                                    stepBpCB, func->mod->asm_name, 
1531                                    func->aexitline);
1532                 }
1533             }
1534         }
1535
1536         doingSteps = 1;
1537         simGo(2);
1538         doingSteps = 0;
1539         showfull = 1;
1540     }
1541     return 0;
1542 }
1543
1544 /*-----------------------------------------------------------------*/
1545 /* cmdNexti - next instruction but proceed function call           */
1546 /*-----------------------------------------------------------------*/
1547 int cmdNexti (char *s, context *cctxt)
1548 {
1549     if (STACK_EMPTY(callStack))
1550         fprintf(stdout,"The program is not being run.\n");
1551     else 
1552     {
1553         doingSteps = 2;
1554             simGo(1);   
1555         doingSteps = 0;
1556         showfull = 1;
1557     }   
1558     return 0;
1559 }
1560
1561 /*-----------------------------------------------------------------*/
1562 /* cmdNext - next executable C statement file                      */
1563 /*-----------------------------------------------------------------*/
1564 int cmdNext (char *s, context *cctxt)
1565 {
1566     function *func = NULL;
1567     /* next is almost the same as step except we don't
1568        we don't set break point for all function entry
1569        points */
1570     if (STACK_EMPTY(callStack))
1571         fprintf(stdout,"The program is not being run.\n");
1572     else {
1573         /* if we are @ the end of a function then set
1574            break points at execution points of the
1575            function in the call stack... */
1576         if (cctxt->addr == cctxt->func->sym->eaddr) {
1577             if ((func = STACK_PEEK(callStack))) {
1578                 if (srcMode == SRC_CMODE)
1579                     applyToSet (func->cfpoints,setStepEPBp,NEXT,
1580                                 func->mod->c_name);     
1581                 else
1582                     applyToSet (func->afpoints,setStepEPBp,NEXT,
1583                                 func->mod->asm_name);
1584             }
1585         } else {
1586             if (srcMode == SRC_CMODE) {
1587                 /* for all execution points in this function */
1588                 applyToSet(cctxt->func->cfpoints,setNextEPBp,NEXT,
1589                            cctxt->func->mod->c_name);
1590                 /* set a break point @ the current function's
1591                    exit */
1592                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
1593                                nextBpCB, cctxt->func->mod->c_name, 
1594                                cctxt->func->exitline);
1595                 
1596                 /* now break point @ callers execution points */        
1597                 if ((func = STACK_PPEEK(callStack))) {
1598                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
1599                                 func->mod->c_name);     
1600                     /* set bp @ callers exit point */
1601                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
1602                                    stepBpCB, func->mod->c_name, 
1603                                    func->exitline);
1604                 }
1605             } else {
1606                 /* for all execution points in this function */
1607                 applyToSet(cctxt->func->afpoints,setNextEPBp,NEXT,
1608                            cctxt->func->mod->asm_name);
1609                 /* set a break point @ the current function's
1610                    exit */
1611                 setBreakPoint (cctxt->func->sym->eaddr, CODE, NEXT , 
1612                                nextBpCB, cctxt->func->mod->asm_name, 
1613                                cctxt->func->aexitline);
1614                 
1615                 /* now break point @ callers execution points */        
1616                 if ((func = STACK_PPEEK(callStack))) {
1617                     applyToSet (func->cfpoints,setNextEPBp,NEXT ,
1618                                 func->mod->asm_name);   
1619                     /* set bp @ callers exit point */
1620                     setBreakPoint (func->sym->eaddr, CODE, NEXT , 
1621                                    stepBpCB, func->mod->asm_name, 
1622                                    func->aexitline);
1623                 }
1624             }
1625         }
1626         doingSteps = 1;
1627         simGo(1);       
1628         doingSteps = 0;
1629         showfull = 1;
1630     }    
1631     return 0;
1632 }
1633
1634 /*-----------------------------------------------------------------*/
1635 /* cmdRun  - run till next break point                             */
1636 /*-----------------------------------------------------------------*/
1637 int cmdRun (char *s, context *cctxt)
1638 {
1639     char buff[10];
1640     if (STACK_EMPTY(callStack)) {
1641         fprintf(stdout,"Starting program\n");
1642     if ( ! simactive )
1643     {
1644         fprintf(stdout,"No executable file specified.\nUse the \"file\" command.\n");
1645         return 0;
1646     }
1647     resetHitCount();
1648         simGo(0);
1649     } else {
1650         
1651         fprintf(stdout,
1652                 "The program being debugged has been started already.\n");
1653         fprintf(stdout,"Start it from the beginning? (y or n) ");
1654         fflush(stdout);
1655
1656         fgets(buff,sizeof(buff),stdin);
1657         if (toupper(buff[0]) == 'Y') {
1658             simReset();
1659         resetHitCount();
1660             simGo(0);
1661         }
1662     }
1663     showfull = 1;
1664     return 0;
1665 }
1666
1667 /*-----------------------------------------------------------------
1668  cmdListSymbols - list symbols
1669 |-----------------------------------------------------------------*/
1670 int cmdListSymbols (char *s, context *cctxt)
1671 {
1672     int our_verbose = 0;
1673     symbol *sy;
1674     int i;
1675
1676     if (strstr(s, "v1")) {
1677       our_verbose = 1;
1678     } else if (strstr(s, "v2")) {
1679       our_verbose = 2;
1680     }
1681
1682     printf("[symbols]\n");
1683     sy = setFirstItem(symbols);
1684     i = 0;
1685     for (;;) {
1686       if (sy == NULL)
1687         break;
1688       if (our_verbose <= 1)
1689         printf("<%s>", sy->name);
1690
1691       if (our_verbose > 1) {
1692         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
1693           sy->name, sy->size, sy->level, sy->block);
1694         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
1695           sy->isonstack, sy->isfunc, sy->offset, sy->addr);
1696         printf("    eaddr:%d, addr_type:%c, type:%x etype:%x\n",
1697           sy->eaddr, sy->addr_type, sy->type, sy->etype);
1698         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
1699           sy->scopetype, sy->sname, sy->rname, sy->addrspace);
1700         printf("    next:%x\n", sy->next);
1701       }
1702       ++i;
1703       sy = setNextItem(symbols);
1704     }
1705     printf("   %d symbols\n", i);
1706     return 0;
1707 }
1708
1709 /*-----------------------------------------------------------------
1710  cmdListFunctions - list functions.
1711 |-----------------------------------------------------------------*/
1712 int cmdListFunctions (char *s, context *cctxt)
1713 {
1714     function *f;
1715     int i;
1716     int our_verbose = 0;
1717
1718     if (strstr(s, "v1")) {
1719       our_verbose = 1;
1720     } else if (strstr(s, "v2")) {
1721       our_verbose = 2;
1722     }
1723
1724     printf("[functions]\n");
1725     f = setFirstItem(functions);
1726     i = 0;
1727     for (;;) {
1728       if (f == NULL)
1729         break;
1730       if (our_verbose) {
1731         printf("  %d) sym:%x, fname:%s, modName:%s, mod:%x\n", i,
1732           f->sym, f->sym->name, f->modName, f->mod);
1733         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
1734                 f->entryline, f->aentryline, f->exitline, f->aexitline);
1735         printf("    cfpoints:%x, afpoints:%x, laddr:%x, lline:%d\n",
1736                 f->cfpoints, f->afpoints, f->laddr, f->lline);
1737       }
1738       else {
1739         printf("<%s>", f->modName);
1740       }
1741       ++i;
1742       f = setNextItem(functions);
1743     }
1744     printf("   %d functions\n", i);
1745     return 0;
1746 }
1747
1748 /*-----------------------------------------------------------------
1749  cmdListModules - list functions.
1750 |-----------------------------------------------------------------*/
1751 int cmdListModules (char *s, context *cctxt)
1752 {
1753     module *m;
1754     srcLine *cs, *as;
1755     int i, mi;
1756     int our_verbose = 0;
1757
1758     if (strstr(s, "v1")) {
1759       our_verbose = 1;
1760     } else if (strstr(s, "v2")) {
1761       our_verbose = 2;
1762     }
1763
1764     printf("[modules]\n");
1765     m = setFirstItem(modules);
1766     mi = 0;
1767     for (;;) {
1768       if (m == NULL)
1769         break;
1770
1771       if (our_verbose >= 0) {
1772       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
1773         m->cfullname, m->afullname, m->name);
1774       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
1775               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
1776       printf("    cLines:%x, asmLines:%x\n",
1777               m->cLines, m->asmLines);
1778       }
1779       if (our_verbose >= 2) {
1780         if (m->ncLines) {
1781           printf("    [cLines] ");
1782           if ( our_verbose)
1783           for (i=0; i<m->ncLines; i++ ) {
1784               cs = m->cLines[i];
1785               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1786                  i, cs->addr, cs->block, cs->level, cs->src);
1787           }
1788           if (!our_verbose)
1789               printf("%d records", i);
1790         }
1791         if (m->nasmLines) {
1792           printf("    [asmLines] ");
1793           if ( our_verbose)
1794           for (i=0; i<m->nasmLines; i++ ) {
1795               as = m->asmLines[i];
1796               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1797                  i, as->addr, as->block, as->level, as->src);
1798           }
1799           if (!our_verbose)
1800               printf("%d records", i);
1801         }
1802         printf("\n");
1803       }
1804
1805       m = setNextItem(modules);
1806     }
1807     return 0;
1808 }
1809
1810 /*-----------------------------------------------------------------
1811  infoSymbols - This is really just a tool to dump all these
1812    huge program structures out into human readable form.
1813 |-----------------------------------------------------------------*/
1814 static void infoSymbols(context *ctxt)
1815 {
1816   int our_verbose = 0;
1817
1818   printf("[context:%x] func:%x modName:%s addr:%x\n",
1819     ctxt, ctxt->func, ctxt->modName, ctxt->addr);
1820
1821   printf("  cline:%d asmline:%d block:%d level:%d\n",
1822     ctxt->cline, ctxt->asmline, ctxt->level);
1823
1824   printf("[globals] currCtxt:%x, modules:%x, functions:%x symbols:%x\n",
1825     currCtxt, modules, functions, symbols);
1826   printf("  nStructs:%d, structs:%x, ssdirl:%s\n",
1827     nStructs, structs, ssdirl);
1828
1829   /**************** modules *******************/
1830   {
1831     module *m;
1832     srcLine *cs, *as;
1833     int i, mi;
1834     printf("[modules]\n");
1835     m = setFirstItem(modules);
1836     mi = 0;
1837     for (;;) {
1838       if (m == NULL)
1839         break;
1840       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
1841         m->cfullname, m->afullname, m->name);
1842       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
1843               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
1844       printf("    cLines:%x, asmLines:%x\n",
1845               m->cLines, m->asmLines);
1846       i = 0;
1847       if (m->cLines) {
1848         cs = m->cLines[i++];
1849         printf("    [cLines] ");
1850         while (cs) {
1851           if (our_verbose)
1852             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1853                i, cs->addr, cs->block, cs->level, cs->src);
1854           cs = m->cLines[i++];
1855         }
1856         if (!our_verbose)
1857             printf("%d records", i);
1858       }
1859       i = 0;
1860       if (m->asmLines) {
1861         as = m->asmLines[i++];
1862         printf("    [asmLines] ");
1863         while (as) {
1864           if (our_verbose)
1865             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
1866                i, as->addr, as->block, as->level, as->src);
1867           as = m->asmLines[i++];
1868         }
1869         if (!our_verbose)
1870             printf("%d records", i);
1871       }
1872       printf("\n");
1873
1874       m = setNextItem(modules);
1875     }
1876   }
1877
1878   /**************** functions *******************/
1879   {
1880     function *f;
1881     int i;
1882     printf("[functions]\n");
1883     f = setFirstItem(functions);
1884     i = 0;
1885     for (;;) {
1886       if (f == NULL)
1887         break;
1888       if (our_verbose) {
1889         printf("  %d) sym:%x, modName:%s, mod:%x\n", i,
1890           f->sym, f->modName, f->mod);
1891         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
1892                 f->entryline, f->aentryline, f->exitline, f->aexitline);
1893         printf("    cfpoints:%x, afpoints:%x, laddr:%x, lline:%d\n",
1894                 f->cfpoints, f->afpoints, f->laddr, f->lline);
1895       }
1896       ++i;
1897       f = setNextItem(functions);
1898     }
1899     if (!our_verbose)
1900       printf("   %d functions\n", i);
1901   }
1902
1903   /**************** symbols *******************/
1904   {
1905     symbol *s;
1906     int i;
1907     printf("[symbols]\n");
1908     s = setFirstItem(symbols);
1909     i = 0;
1910     for (;;) {
1911       if (s == NULL)
1912         break;
1913       if (our_verbose) {
1914         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
1915           s->name, s->size, s->level, s->block);
1916         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
1917           s->isonstack, s->isfunc, s->offset, s->addr);
1918         printf("    eaddr:%d, addr_type:%c, type:%x etype:%x\n",
1919           s->eaddr, s->addr_type, s->type, s->etype);
1920         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
1921           s->scopetype, s->sname, s->rname, s->addrspace);
1922         printf("    next:%x\n", s->next);
1923       }
1924       ++i;
1925       s = setNextItem(symbols);
1926     }
1927     if (!our_verbose)
1928       printf("   %d symbols\n", i);
1929   }
1930
1931 }
1932
1933 /*-----------------------------------------------------------------*/
1934 /* infoRegisters - print register information                      */
1935 /*-----------------------------------------------------------------*/
1936 static void infoRegisters( int all, context *ctxt)
1937 {
1938     static unsigned int regaddrs[] = {0x81,0x82,0x83,0xb8,0xd0,0xe0,0xf0,0};
1939     unsigned long val;
1940     int i,j,*r;
1941
1942     i   = simGetValue (0xd0,'I',1);
1943     fprintf(stdout,"IP  : 0x%04X  RegisterBank %d:\nR0-7:",ctxt->addr,(i>>3)&3);
1944     for ( j = 0; j < 8 ; j++ )
1945     {
1946         val = simGetValue (j ,'R',1);
1947         fprintf(stdout," 0x%02X",val);
1948     }
1949     fprintf(stdout,"\n");
1950     val = simGetValue (0xe0,'I',1);
1951     fprintf(stdout,"ACC : 0x%02X %d %c\n",val,val,(isprint(val) ? val : '.'));
1952     val = simGetValue (0xf0,'I',1);
1953     fprintf(stdout,"B   : 0x%02X %d %c\n",val,val,(isprint(val) ? val : '.'));
1954     val = simGetValue (0x82,'I',2);
1955     fprintf(stdout,"DPTR: 0x%04X %d\n",val,val);
1956     val = simGetValue (0x81,'I',1);
1957     fprintf(stdout,"SP  : 0x%02X (0x%04X)\n",val,simGetValue (val-1,'B',2));
1958     fprintf(stdout,"PSW : 0x%02X | CY : %c | AC : %c | OV : %c | P : %c\n",
1959             i,(i&0x80)?'1':'0',(i&0x40)?'1':'0',(i&4)?'1':'0',(i&1)?'1':'0');
1960     if ( all )
1961     {
1962         fprintf(stdout,"Special Function Registers:\n");
1963         r = regaddrs;
1964         for ( i = 0x80 ; i < 0x100 ; i++ )
1965         {
1966             symbol *sym = NULL;
1967             if ( *r && *r == i )
1968             {
1969                 /* skip normal registers */
1970                 r++ ;
1971                 continue;
1972             }
1973             if (applyToSetFTrue(sfrsymbols,symWithAddr,i,'I',&sym))
1974             {
1975                 val = simGetValue (sym->addr,sym->addrspace,sym->size);
1976                 fprintf(stdout,"%s : 0x%02x",sym->name,val);
1977                 if ( !(i & 0x07 ))
1978                 {
1979                     for ( j = 0 ; j < 8 ; j++ )
1980                     {
1981                         sym = NULL;
1982                         if (applyToSetFTrue(sfrsymbols,symWithAddr,i+j,'J',&sym))
1983                         {
1984                             //val = simGetValue (sym->addr,sym->addrspace,sym->size);
1985                             fprintf(stdout," %s=%c",sym->name,(val&1)? '1':'0');
1986                         }
1987                         val >>= 1;
1988                     }
1989                 }
1990                 fprintf(stdout,"\n");
1991             }
1992         }
1993     }
1994 }
1995
1996 /*-----------------------------------------------------------------*/
1997 /* infoStack - print call stack information                        */
1998 /*-----------------------------------------------------------------*/
1999 static void infoStack(context *ctxt)
2000 {
2001     function *func ;
2002     int i = 0 ;
2003
2004     STACK_STARTWALK(callStack) ;
2005     while ((func = STACK_WALK(callStack))) {
2006     Dprintf(D_break, ("break: infoStack: %s %p (%p)\n",func->sym->name, w_callStack,p_callStack));
2007
2008         fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",i++,
2009                 func->laddr,func->sym->name,
2010                 func->mod->c_name,func->lline+1);
2011     }
2012     if ( !i )
2013         fprintf(stdout,"no stack.\n");
2014 }
2015
2016 /*-----------------------------------------------------------------*/
2017 /* cmdWhere -  where command                                       */
2018 /*-----------------------------------------------------------------*/
2019 int cmdWhere(char *s, context *cctxt)
2020 {
2021         infoStack(cctxt);
2022         return 0;
2023 }
2024
2025
2026 static int infomode = 0;
2027 /*-----------------------------------------------------------------*/
2028 /* cmdInfo - info command                                          */
2029 /*-----------------------------------------------------------------*/
2030 int cmdInfo (char *s, context *cctxt)
2031 {
2032     while (isspace(*s)) s++;
2033
2034     /* list all break points */
2035     if (strncmp(s,"break",5) == 0) {
2036         listUSERbp();
2037         return 0;
2038     }
2039
2040     /* info frame same as frame */
2041     if (strcmp(s,"frame") == 0) {
2042         cmdFrame (s,cctxt);
2043         return 0;
2044     }
2045
2046     if (strncmp(s,"line",4) == 0) {
2047     infomode=1;
2048         cmdListSrc (s+4,cctxt);
2049         return 0;
2050     }
2051     if (strncmp(s,"source",6) == 0) 
2052     {
2053         module *m;
2054         if ( s[6] == 's' )
2055         {
2056             int k = 0;
2057             fprintf(stdout,"Source files for which symbols have been read in:\n\n");
2058             for (m = setFirstItem(modules); m ; m = setNextItem(modules))
2059             {
2060                 fprintf(stdout,"%s%s, %s",k ? ", ":"",m->cfullname, m->afullname); 
2061                 k = 1;
2062             }
2063             fprintf(stdout,"\n"); 
2064         }
2065         else
2066         {
2067             if (!cctxt || !cctxt->func || !cctxt->func->mod) 
2068             {
2069                 fprintf(stdout,"No source file loaded\n");
2070                 return 0;
2071             }
2072             m = cctxt->func->mod;
2073             fprintf(stdout,"Current source file is %s\n",m->c_name);
2074             fprintf(stdout,"Located in %s\n",m->cfullname);
2075             fprintf(stdout,"Contains %d lines.\nSource language is c.\n",
2076                     m->ncLines);
2077         }
2078         return 0;
2079     }
2080     if (strncmp(s,"functions",7) == 0) 
2081     {
2082         function *f;
2083         module *m = NULL;
2084         fprintf(stdout,"All defined functions:\n");
2085         for ( f = setFirstItem(functions); f ; f = setNextItem(functions))
2086         {
2087             if ( f->mod != m )
2088             {
2089                 m = f->mod;
2090                 fprintf(stdout,"\nFile %s\n", m->c_name);
2091             }
2092             fprintf(stdout,"%s();\n",f->sym->name);
2093         }
2094         return 0;
2095     }
2096     /* info stack display call stack */
2097     if (strcmp(s,"stack") == 0) {
2098         infoStack(cctxt);
2099     showfull = 1;
2100         return 0;
2101     }
2102
2103     /* info stack display call stack */
2104     if (strcmp(s,"registers") == 0) {
2105         infoRegisters(0,cctxt);
2106             return 0;
2107     }
2108
2109     /* info stack display call stack */
2110     if (strcmp(s,"all-registers") == 0) 
2111     {
2112         infoRegisters(1,cctxt);
2113         return 0;
2114     }
2115
2116     /* info stack display call stack */
2117     if (strcmp(s,"symbols") == 0) {
2118       /* dump out symbols we have read in */
2119       fprintf(stdout,"Dumping symbols...\n");
2120       infoSymbols(cctxt);
2121       return 0;
2122     }
2123
2124     if (strcmp(s,"variables") == 0) {
2125       /* dump out symbols we have read in */
2126       fprintf(stdout,"Dumping symbols...\n");
2127       infoSymbols(cctxt);
2128       return 0;
2129     }
2130
2131     fprintf(stdout,"Undefined info command: \"%s\".  Try \"help\n",s);
2132     return 0;
2133
2134 }
2135
2136 /*-----------------------------------------------------------------*/
2137 /* cmdQuit  - quit debugging                                       */
2138 /*-----------------------------------------------------------------*/
2139 int cmdQuit (char *s, context *cctxt)
2140 {   
2141     if (simactive)
2142         closeSimulator();
2143     return 1;
2144 }
2145
2146 /*-----------------------------------------------------------------*/
2147 /* cmdListSrc  - list src                                          */
2148 /*-----------------------------------------------------------------*/
2149 int cmdListSrc (char *s, context *cctxt)
2150 {   
2151     static int currline = 0;
2152     int i =0 ;
2153     int pline = 0;
2154     int llines = listlines;
2155     function *func = NULL;
2156
2157
2158     while (*s && isspace(*s)) s++;
2159     
2160     /* if the user has spcified line numer then the line number
2161        can be of the following formats
2162        LINE          - just line number
2163        FILE:LINE     - filename line number
2164        FILE:LINE,LASTLINE  + last line
2165        FUNCTION      - list a function
2166        FILE:FUNCTION - function in file */
2167
2168     if (*s) {
2169         /* case a) LINE */
2170         if (isdigit(*s)) {
2171             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2172               if (!list_mod) {
2173                 fprintf(stdout,"Sdcdb fails to have a proper context at %d.\n", __LINE__);
2174                 return 0;
2175               }
2176             }
2177             else
2178               list_mod = cctxt->func->mod;
2179         pline = strtol(s,&s,10) - 1;
2180         if (s && (s = strchr(s,','))) 
2181         {
2182             /* LINE,LASTLINE */
2183             llines = strtol(s+1,0,10); 
2184             if ( llines > 0 )
2185                 llines -= pline+1;
2186             else
2187                 llines = listlines;
2188         }
2189         }
2190         else {
2191             char *bp;
2192             
2193             /* if ':' present then FILE:LINE || FILE:FUNCTION */
2194             if ((bp = strchr(s,':'))) {
2195                 *bp = '\0';
2196                 bp ++;
2197                 if (isdigit(*bp)) {
2198                     /* FILE:LINE */
2199                     list_mod=NULL;  /* bug fix 2-09-02, moduleWithCName expects mod to be null */
2200                     if (srcMode == SRC_CMODE) {
2201                         if (!applyToSet(modules,moduleWithCName,s,&list_mod)) {
2202                             fprintf (stderr,"No c source file named %s.\n",s);
2203                             return 0;
2204                         }
2205                     } else {
2206                         if (!applyToSet(modules,moduleWithAsmName,s,&list_mod)) {
2207                             fprintf (stderr,"No source file named %s.\n",s);
2208                             return 0;
2209                         }
2210                     }
2211                     pline = strtol(bp,&bp,10) - 1;
2212             if (bp && (bp = strchr(bp,','))) 
2213             {
2214                 /* FILE:LINE,LASTLINE */
2215                 llines = strtol(bp+1,0,10); 
2216                 if ( llines > 0 )
2217                     llines -= pline+1;
2218                 else
2219                     llines = listlines;
2220             }
2221                 } else {
2222                     /* FILE:FUCTION */
2223                     if (!applyToSet(functions,funcWithNameModule,bp,s,&func)) {
2224                         fprintf(stdout,"Function \"%s\" not defined.\n",bp);
2225                         return 0;
2226                     }
2227                     list_mod = func->mod;
2228                     if (srcMode == SRC_CMODE) {
2229                         pline = func->entryline;
2230                         llines = func->exitline - func->entryline + 1;
2231                     } else {
2232                         pline = func->aentryline;
2233                         llines = func->aexitline - func->aentryline + 1;
2234                     }
2235                 }
2236             }
2237             else {
2238                 /* FUNCTION */
2239             if (*s == '\'') 
2240             {
2241                 /* 'FUNCTION' */
2242                 s++ ;
2243                 if ((bp = strrchr(s,'\''))) 
2244                 {
2245                     *bp = '\0';
2246                 }
2247                 
2248             }
2249                 if (!applyToSet(functions,funcWithName,s,&func)) {
2250                     fprintf(stderr,"Function \"%s\" not defined.\n",s); 
2251                     return 0;
2252                 }
2253                 else {
2254                     list_mod = func->mod;
2255                     if (srcMode == SRC_CMODE) {
2256                         pline = func->entryline;
2257                         llines = func->exitline - func->entryline + 1; 
2258                     } else {
2259                         pline = func->aentryline;
2260                         llines = func->aexitline - func->aentryline + 1; 
2261                     }
2262                 }
2263             }
2264         }
2265     } else {
2266         /* if no line specified & we had listed
2267            before then continue from that listing */
2268         if (currline)
2269             pline = currline ;
2270         else {
2271             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2272               fprintf(stdout,"Missing context at %d. Try list filename:lineno\n", __LINE__);
2273               return 0;
2274             }
2275             list_mod = cctxt->func->mod;
2276             if (srcMode == SRC_CMODE)
2277                 pline = cctxt->cline;
2278             else
2279                 pline = cctxt->asmline;
2280         }
2281     }
2282
2283     if (!list_mod) {
2284       fprintf(stdout,"Sdcdb fails to have a valid module context at %d.\n", __LINE__);
2285       return 0;
2286     }
2287
2288     if ( pline < 0 )
2289         return 0;
2290     if ( infomode )
2291     {
2292         int firstaddr , lastaddr ;
2293             if ( pline  >= list_mod->ncLines )
2294             pline = cctxt->cline;
2295         firstaddr = lastaddr = list_mod->cLines[pline]->addr;
2296         if (!func && cctxt && cctxt->func )
2297             func = cctxt->func;
2298             fprintf(stdout,"Line %d of \"%s\" starts at address 0x%08x <%s+%d>", 
2299                 pline+1,
2300                 list_mod->c_name, lastaddr,
2301                 func ? func->sym->name : "?",
2302                 func ? lastaddr -func->sym->addr : 0);
2303         llines = pline +1;
2304         for ( ; pline < list_mod->ncLines; pline++ )
2305         {
2306             if ( list_mod->cLines[pline]->addr > lastaddr )
2307             {
2308                 lastaddr = list_mod->cLines[pline]->addr -1;
2309                 break;
2310             }
2311         }
2312         fprintf(stdout," and ends at 0x%08x <%s+%d>.\n", 
2313                 lastaddr,
2314                 func ? func->sym->name : "?",
2315                 func ? lastaddr -func->sym->addr : 0);
2316         infomode=0;
2317         if ( func )
2318             fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
2319                     func->mod->cfullname,
2320                     llines,firstaddr);
2321         else
2322             showfull=1;
2323         return 0;
2324     }
2325     for ( i = 0 ; i < llines ; i++ ) {
2326         if (srcMode == SRC_CMODE) {
2327             if ( (pline + i) >= list_mod->ncLines )
2328                 break;
2329             fprintf(stdout,"%d\t%s",pline + i,
2330                     list_mod->cLines[pline +i]->src);
2331         } else {
2332             if ( (pline + i) >= list_mod->nasmLines )
2333                 break;
2334             fprintf(stdout,"%d\t%s",pline + i,
2335                     list_mod->asmLines[pline +i]->src);
2336         }
2337     }
2338     currline = pline + i ;
2339     return 0;
2340 }
2341
2342 static unsigned long getValBasic(symbol *sym, link *type, char *val)
2343 {
2344     char *s;
2345     union 
2346     {   
2347         float f;     
2348         unsigned long val;
2349         long         sval;
2350         struct {
2351             unsigned short    lo;
2352             unsigned short    hi;
2353         } i;
2354         unsigned char b[4];
2355     }v;
2356
2357     if (IS_FLOAT(type))         
2358         v.f = strtod(val,NULL);    
2359     else
2360         if (IS_PTR(type))
2361             v.val = strtol(val,NULL,0);
2362         else
2363     {
2364             if (IS_INTEGRAL(type)) 
2365         {
2366             link *etype;
2367             if ( type->next )
2368                 etype = type->next;
2369             else
2370                 etype = type;
2371             if (IS_CHAR(etype))
2372             {
2373                 if (( s = strchr(val,'\'')))
2374                 {
2375                     if ( s[1] == '\\' )
2376                         v.b[0] = strtol(s+2,NULL,8);
2377                     else 
2378                         v.b[0] = s[1];
2379                 }
2380                 else
2381                 {
2382                     v.b[0] = strtol(val,NULL,0);
2383                 }
2384             }
2385             else
2386                 if (IS_INT(etype)) 
2387                     if (IS_LONG(etype))
2388                         v.val = strtol(val,NULL,0);
2389                     else
2390                         v.i.lo = strtol(val,NULL,0);
2391                 else
2392                     v.val = strtol(val,NULL,0);
2393             } 
2394         else
2395             v.val = strtol(val,NULL,0);
2396     }
2397     return v.val;
2398 }
2399
2400 /*-----------------------------------------------------------------*/
2401 /* printFmtInteger - print value in bin,oct,dez or hex             */
2402 /*-----------------------------------------------------------------*/
2403 static void printFmtInteger(char *deffmt,int fmt, long val, 
2404                             int sign, int size)
2405 {
2406     static char digits[] = 
2407     {
2408         '0' , '1' , '2' , '3' , '4' , '5' ,
2409         '6' , '7' , '8' , '9' , 'a' , 'b' ,
2410         'c' , 'd' , 'e' , 'f' , 'g' , 'h' 
2411     };
2412     static int radixOfFormat[] = { 0 , 2, 8 ,10, 16  };
2413     static int olenOfSize[]    = { 0 , 3, 6 , 8, 11  };
2414         char buf[40];
2415         char negative = 0;
2416         int charPos = 38;
2417     int radix;
2418
2419     if ( fmt == FMT_NON || fmt == FMT_DEZ )
2420     {
2421         fprintf(stdout,deffmt,val);
2422         return;
2423     }
2424     radix = radixOfFormat[fmt];
2425
2426     /*
2427     if ( sign && val < 0 )
2428         negative = 1;
2429     */
2430
2431         if (!negative)
2432             val = -val;
2433
2434         buf[39] = '\0';
2435     while (val <= -radix) 
2436     {
2437             buf[charPos--] = digits[-(val % radix)];
2438             val = val / radix;
2439         }
2440         buf[charPos] = digits[-val];
2441
2442     switch ( fmt )
2443     {
2444         case FMT_OCT:
2445             radix = olenOfSize[size];
2446             break;
2447         case FMT_HEX:
2448             radix = size << 1;
2449             break;
2450         case FMT_BIN:
2451             radix = size << 3;
2452             break;
2453     }
2454
2455     while (charPos > 39 - radix )
2456     {
2457         buf[--charPos] = '0';
2458     } 
2459     switch ( fmt )
2460     {
2461         case FMT_OCT:
2462             if ( buf[charPos] != '0' )
2463                 buf[--charPos] = '0';
2464             break;
2465         case FMT_HEX:
2466             buf[--charPos] = 'x';
2467             buf[--charPos] = '0';
2468             break;
2469     }
2470         if (negative) {
2471             buf[--charPos] = '-';
2472         }
2473     fputs(&buf[charPos],stdout);
2474 }
2475
2476 /*-----------------------------------------------------------------*/
2477 /* printValBasic - print value of basic types                      */
2478 /*-----------------------------------------------------------------*/
2479 static void printValBasic(symbol *sym, link *type,
2480                           char mem, unsigned addr,int size, int fmt)
2481 {
2482     union {     
2483         float f;     
2484         unsigned long val;
2485         long         sval;
2486         struct {
2487             unsigned short    lo;
2488             unsigned short    hi;
2489         } i;
2490         unsigned char b[4];
2491     }v;
2492     union {
2493         unsigned char b[4];
2494     }v1;
2495     
2496     v.val = simGetValue(addr,mem,size);
2497     /* if this a floating point number then */
2498     if (IS_FLOAT(type))         
2499         fprintf(stdout,"%f",v.f);    
2500     else
2501         if (IS_PTR(type))
2502             fprintf(stdout,"0x%*x",size<<1,v.val);
2503         else
2504         if (IS_INTEGRAL(type)) 
2505         {
2506             link *etype;
2507             if ( type->next )
2508                 etype = type->next;
2509             else
2510                 etype = type;
2511             if (IS_CHAR(etype))
2512             { 
2513                 if ( isprint(v.val))
2514                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'%c'"),
2515                                     fmt,(long)v.val,0,size);
2516                 else
2517                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'\\%o'"),
2518                                     fmt,(long)v.val,0,size);
2519             }
2520             else
2521             {
2522                 if (IS_INT(etype)) 
2523                     if (IS_LONG(etype))
2524                         if (SPEC_USIGN(etype))
2525                             printFmtInteger("%u",fmt,(long)v.val,0,size);
2526                         else
2527                             printFmtInteger("%d",fmt,(long)v.sval,1,size);
2528                     else
2529                         if (SPEC_USIGN(etype))
2530                             printFmtInteger("%u",fmt,(long)v.i.lo,0,size);
2531                         else
2532                             printFmtInteger("%d",fmt,(long)v.i.lo,1,size);
2533                 else
2534                 {
2535                     if (IS_BITVAR(etype))
2536                         fprintf(stdout,"%c",(v.val?'1':'0'));
2537                     else
2538                         fprintf(stdout,"0x%0*x",size<<1,v.val);
2539                 }
2540             }
2541             } else
2542             fprintf(stdout,"0x%0*x",size<<1,v.val);  
2543 }
2544
2545 /*-----------------------------------------------------------------*/
2546 /* printValFunc  - prints function values                          */
2547 /*-----------------------------------------------------------------*/
2548 static void printValFunc (symbol *sym, int fmt)
2549 {
2550     fprintf(stdout,"print function not yet implemented");
2551 }
2552
2553 /*-----------------------------------------------------------------*/
2554 /* printArrayValue - will print the values of array elements       */
2555 /*-----------------------------------------------------------------*/
2556 static void printArrayValue (symbol *sym,  link *type,
2557                              char space, unsigned int addr, int fmt)
2558 {
2559         link *elem_type = type->next;
2560         int i;
2561         
2562         fprintf(stdout,"{");
2563         for (i = 0 ; i < DCL_ELEM(type) ; i++) {                
2564                 if (IS_AGGREGATE(elem_type)) {
2565                         printValAggregates(sym,elem_type,space,addr,fmt);                      
2566                 } else {
2567                         printValBasic(sym,elem_type,space,addr,getSize(elem_type),fmt);
2568                 }
2569                 addr += getSize(elem_type);
2570                 if (i != DCL_ELEM(type) -1)
2571                         fprintf(stdout,",");
2572         }
2573
2574         fprintf(stdout,"}");            
2575 }
2576
2577 /*-----------------------------------------------------------------*/
2578 /* printStructValue - prints structures elements                   */
2579 /*-----------------------------------------------------------------*/
2580 static void printStructValue (symbol *sym, link *type, 
2581                               char space, unsigned int addr, int fmt) 
2582 {
2583         symbol *fields = SPEC_STRUCT(type)->fields;
2584     int first = 1;
2585         fprintf(stdout," { ");
2586         while (fields) {
2587                 fprintf(stdout,"%s%s = ",(first ? "": ", "),fields->name);
2588                 first = 0;
2589         if (IS_AGGREGATE(fields->type)) {
2590                         printValAggregates(fields,fields->type,space, addr, fmt);
2591                 } else {
2592                         printValBasic(fields,fields->type,space,addr,getSize(fields->type), fmt);
2593                 }
2594                 addr += getSize(fields->type);
2595                 fields = fields->next;
2596         }
2597         fprintf(stdout,"}");
2598 }
2599
2600 /*-----------------------------------------------------------------*/
2601 /* printValAggregates - print value of aggregates                  */
2602 /*-----------------------------------------------------------------*/
2603 static void printValAggregates (symbol *sym, link *type,
2604                                 char space,unsigned int addr, int fmt)
2605 {
2606
2607         if (IS_ARRAY(type)) {
2608                 printArrayValue(sym, type, space, addr, fmt);
2609                 return ;
2610         }
2611
2612         if (IS_STRUCT(type)) { 
2613                 printStructValue(sym, type, space, addr, fmt); 
2614                 return; 
2615         } 
2616 }
2617
2618 /*-----------------------------------------------------------------*/
2619 /* printOrSetSymValue - print or set value of a symbol             */
2620 /*-----------------------------------------------------------------*/
2621 static int printOrSetSymValue (symbol *sym, context *cctxt, 
2622                                 int flg, int dnum, int fmt, char *rs, 
2623                                 char *val, char cmp )
2624 {
2625     static char fmtChar[] = " todx ";
2626     static int stack = 1;
2627         symbol *fields;
2628     link *type;
2629     unsigned int  addr; 
2630     int size, n;
2631     char *s, *s2;
2632     char save_ch, save_ch2;
2633
2634     /* if it is on stack then compute address & fall thru */
2635     if (sym->isonstack) 
2636     {
2637         symbol *bp = symLookup("bp",cctxt);
2638         if (!bp) 
2639         {
2640             fprintf(stdout,"cannot determine stack frame\n");
2641             return 1;
2642         }
2643
2644         sym->addr = simGetValue(bp->addr,bp->addrspace,bp->size)
2645             + sym->offset ;      
2646     }
2647     
2648     /* get the value from the simulator and
2649        print it */
2650     switch (flg)
2651     {
2652         case 0: 
2653         default:
2654             break;
2655         case 1: 
2656             fprintf(stdout,"$%d = ",stack++);
2657             break;
2658         case 2: 
2659             fprintf(stdout,"%d: ", dnum);
2660             if ( fmt != FMT_NON )
2661                 fprintf(stdout,"/%c ",fmtChar[fmt]);
2662             fprintf(stdout,"%s%s = ",sym->name,rs);
2663             break;
2664     }
2665
2666     addr = sym->addr;
2667     type = sym->type;
2668     size = sym->size;
2669
2670     while ( *rs )
2671     {
2672         if ( *rs == '[' && IS_ARRAY(type))
2673         {
2674             s = rs+1;
2675             while ( *rs && *rs != ']' ) rs++ ;
2676             save_ch = *rs;
2677             *rs = '\0' ;
2678             if ( ! isdigit(*s ))
2679             {
2680                 /* index seems a variable */
2681                 for ( s2 = s; *s2 && ( isalnum( *s2 ) || *s2 == '_'); s2++ );
2682                 save_ch2 = *s2;
2683                 if ( *s2 )
2684                     *s2 = '\0';
2685                 fields = symLookup(s,cctxt);
2686                 *s2 = save_ch2;
2687                 if ( ! fields )
2688                 {
2689                     fprintf(stdout,"Unknown variable \"%s\" for index.\n", s);
2690                     return 1;                    
2691                 }
2692                 /* arrays & structures first */
2693                 if (! IS_INTEGRAL(fields->type))
2694                 {
2695                     fprintf(stdout,"Wrong type of variable \"%s\" for index \n", s);
2696                     return 1;                    
2697                 }
2698                 n = simGetValue(fields->addr,fields->addrspace,getSize(fields->type));
2699             }
2700             else
2701             {
2702                 n = strtol(s,0,0);
2703             }
2704             if ( n < 0 || n >= DCL_ELEM(type))
2705             {
2706                 fprintf(stdout,"Wrong index %d.\n", n);
2707                 return 1;                    
2708             }
2709             type = type->next;
2710             size = getSize(type);
2711             addr += size * n;
2712             *rs++ = save_ch;
2713         }
2714         else if ( *rs == '.' && IS_STRUCT(type))
2715         {
2716             s = rs+1;
2717             /* search structure element */
2718             for ( rs = s; *rs && ( isalnum( *rs ) || *rs == '_'); rs++ );
2719             save_ch = *rs;
2720             if ( *rs )
2721                 *rs = '\0';
2722             for (fields = SPEC_STRUCT(type)->fields; fields; fields = fields->next) 
2723             {
2724                 if (!(strcmp(s,fields->name)))
2725                     break;
2726             }
2727             *rs = save_ch;
2728             if ( ! fields )
2729             {
2730                 fprintf(stdout,"Unknown field \"%s\" of structure\n", s);
2731                 return 1;                    
2732             }
2733             type = fields->type;
2734             size = getSize(type);
2735             addr += fields->offset;
2736         }
2737         else
2738             break;
2739     }
2740
2741     /* arrays & structures first */
2742     if (IS_AGGREGATE(type))
2743     {
2744             if ( val )
2745         {
2746             fprintf(stdout,"Cannot set/compare aggregate variable\n");
2747             return 1;
2748         }
2749         else
2750             printValAggregates(sym,type,sym->addrspace,addr,fmt);
2751     }
2752     else
2753         /* functions */
2754         if (IS_FUNC(type))
2755     {
2756             if ( !val )
2757             printValFunc(sym,fmt);
2758         else
2759             return 1;
2760     }
2761         else
2762     { 
2763             if ( val )
2764         {
2765             unsigned long newval;
2766             newval = getValBasic(sym,type,val);
2767
2768             if ( cmp )
2769             {
2770                 unsigned long lval;
2771                 lval = simGetValue(addr,sym->addrspace,size);
2772                 switch ( cmp )
2773                 {
2774                     case '<' : return ( lval <  newval ? 1:0 ); break;
2775                     case '>' : return ( lval >  newval ? 1:0 ); break;
2776                     case 'l' : return ( lval <= newval ? 1:0 ); break;
2777                     case 'g' : return ( lval >= newval ? 1:0 ); break;
2778                     case '=' : return ( lval == newval ? 1:0 ); break;
2779                     case '!' : return ( lval != newval ? 1:0 ); break;
2780                 }
2781             }
2782             else
2783             {
2784                 if ( sym->addrspace == 'I' && addr == 0xb8 )
2785                 {
2786                     /* Symbol with address of IP */
2787                     if ( cctxt ) cctxt->addr = newval;
2788                     simSetPC(cctxt->addr); 
2789                 }
2790                 else
2791                     simSetValue(addr,sym->addrspace,size,newval);       
2792                 return 1;
2793             }
2794         }
2795         else
2796             printValBasic(sym,type,sym->addrspace,addr,size,fmt);
2797     }
2798     if ( flg > 0 ) fprintf(stdout,"\n");
2799         return 0;
2800 }
2801
2802 /*-----------------------------------------------------------------*/
2803 /* printStructInfo - print out structure information               */
2804 /*-----------------------------------------------------------------*/
2805 static void printStructInfo (structdef *sdef)
2806 {
2807     symbol *field = sdef->fields ;
2808     int i = 0 ;
2809     
2810     while (field) {
2811         i += field->offset;
2812         field = field->next;
2813     }
2814
2815     fprintf(stdout,"%s %s {\n",(i ? "struct" : "union" ), sdef->tag);
2816     field = sdef->fields;
2817     while (field) {
2818         printTypeInfo (field->type);
2819         fprintf(stdout," %s ;\n",field->name);
2820         field = field->next ;
2821     }
2822
2823     fprintf(stdout,"}\n");
2824
2825 }
2826
2827 /*-----------------------------------------------------------------*/
2828 /* printTypeInfo - print out the type information                  */
2829 /*-----------------------------------------------------------------*/
2830 static void printTypeInfo(link *p)
2831 {
2832     if (!p)
2833         return ;
2834
2835     if (IS_DECL(p)) {
2836         switch (DCL_TYPE(p))  {
2837         case FUNCTION:
2838             printTypeInfo (p->next);
2839             fprintf(stdout,"()");
2840             break;
2841         case ARRAY:
2842             printTypeInfo (p->next);
2843             fprintf(stdout,"[%d]",DCL_ELEM(p));
2844             break;
2845         
2846         case IPOINTER:
2847         case PPOINTER:
2848         case POINTER:
2849             printTypeInfo (p->next);
2850             fprintf(stdout,"(_near *)");
2851             break;
2852
2853         case FPOINTER:
2854             printTypeInfo (p->next);
2855             fprintf(stdout,"(_xdata *)");
2856             break;
2857
2858         case CPOINTER:
2859             printTypeInfo( p->next);
2860             fprintf(stdout,"(_code *)");
2861             break;
2862             
2863         case GPOINTER:
2864             printTypeInfo( p->next);
2865             fprintf(stdout,"(_generic *)");
2866             break;                   
2867         }
2868     } else {
2869         switch (SPEC_NOUN(p)) { /* depending on the specifier type */
2870         case V_INT:
2871             (IS_LONG(p) ? fputs("long ",stdout) : 
2872              ( IS_SHORT(p) ? fputs("short ",stdout) : 
2873                fputs("int ",stdout))) ;
2874             break;
2875         case V_FLOAT:
2876              fputs("float ",stdout);
2877              break;
2878
2879         case V_CHAR:
2880             fputs ("char ",stdout);
2881             break;
2882
2883         case V_VOID:
2884             fputs("void ",stdout);
2885             break;
2886
2887         case V_STRUCT:
2888             printStructInfo (SPEC_STRUCT(p));
2889             break;
2890
2891         case V_SBIT:
2892             fputs("sbit ",stdout);
2893             break;
2894
2895         case V_BIT:
2896             fprintf(stdout,": %d" ,SPEC_BLEN(p));       
2897             break;
2898         }
2899     }
2900 }
2901
2902 /*-----------------------------------------------------------------*/
2903 /* conditionIsTrue - compare variable with constant value        */
2904 /*-----------------------------------------------------------------*/
2905 int conditionIsTrue( char *s, context *cctxt)
2906 {   
2907     symbol *sym = NULL;
2908     int fmt;
2909     char *rs, *dup, cmp_char;
2910     dup = s = Safe_strdup(s);
2911     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )) || !sym)
2912         fmt = 1;
2913     else if (!( s =  strpbrk(rs,"<>=!")))
2914         fmt = 1;
2915     else
2916     {
2917         cmp_char = *s;    
2918         *s++ = '\0';
2919         if ( *s == '=' )
2920         {
2921             /* if <= or >= an other char is used 
2922              * == or !=  not checked in switch 
2923              */
2924             switch( cmp_char )
2925             {
2926                 case '>': cmp_char = 'g' ; break;
2927                 case '<': cmp_char = 'l' ; break;
2928             }
2929             s++ ;
2930         }
2931         while (isspace(*s)) *s++ = '\0';
2932         fmt = printOrSetSymValue(sym,cctxt,0,0,0,rs,s,cmp_char);
2933     }
2934     Safe_free(dup);
2935     return fmt;
2936 }
2937
2938 /*-----------------------------------------------------------------*/
2939 /* cmdPrint - print value of variable                              */
2940 /*-----------------------------------------------------------------*/
2941 int cmdPrint (char *s, context *cctxt)
2942 {   
2943     symbol *sym ;
2944     int fmt;
2945     char *rs;
2946     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
2947         return 0;
2948
2949     if ( sym ) 
2950     {
2951         printOrSetSymValue(sym,cctxt,1,0,fmt,rs,NULL,'\0');
2952     } 
2953     return 0;
2954 }
2955
2956 /*-----------------------------------------------------------------*/
2957 /* cmdOutput - print value of variable without number and newline  */
2958 /*-----------------------------------------------------------------*/
2959 int cmdOutput (char *s, context *cctxt)
2960 {   
2961     symbol *sym ;
2962     int fmt;
2963     char *rs;
2964     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
2965         return 0;
2966
2967     if ( sym ) 
2968     {
2969         printOrSetSymValue(sym,cctxt,0,0,fmt,rs,NULL,'\0');
2970     } 
2971     return 0;
2972 }
2973
2974 /** find display entry with this number */
2975
2976 DEFSETFUNC(dsymWithNumber)
2977 {
2978     dsymbol *dsym = item;
2979     V_ARG(int , dnum);
2980     V_ARG(dsymbol **,dsymp);
2981
2982     if ( dsym->dnum == dnum )
2983     {
2984         *dsymp = dsym;
2985         return 1;
2986     }
2987     return 0;
2988 }
2989
2990 /*-----------------------------------------------------------------*/
2991 /* displayAll  - display all valid variables                       */
2992 /*-----------------------------------------------------------------*/
2993 void displayAll(context *cctxt)
2994 {
2995     dsymbol *dsym;
2996     symbol  *sym;
2997     if ( !dispsymbols )
2998         return;
2999     for (dsym = setFirstItem(dispsymbols);
3000          dsym ;
3001          dsym = setNextItem(dispsymbols)) 
3002     {
3003         if ( (sym = symLookup(dsym->name,cctxt)))
3004             printOrSetSymValue(sym,cctxt,2,dsym->dnum,dsym->fmt,
3005                                dsym->rs,NULL,'\0');
3006     }
3007 }
3008
3009 /*-----------------------------------------------------------------*/
3010 /* cmdDisplay  - display value of variable                         */
3011 /*-----------------------------------------------------------------*/
3012 int cmdDisplay (char *s, context *cctxt)
3013 {   
3014     static int dnum = 1;
3015     symbol *sym ;
3016     int fmt;
3017     char *rs;
3018     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
3019     {
3020         displayAll(cctxt);
3021         return 0;
3022     }
3023
3024     if ( sym ) 
3025     {
3026         dsymbol *dsym = (dsymbol *)Safe_calloc(1,sizeof(dsymbol));
3027         dsym->dnum = dnum++ ;
3028         dsym->name = sym->name;
3029         dsym->fmt  = fmt;
3030         dsym->rs   = gc_strdup(rs);
3031         addSetHead(&dispsymbols,dsym);
3032     }
3033     return 0;
3034 }
3035
3036 /*-----------------------------------------------------------------*/
3037 /* cmdUnDisplay  - undisplay value of variable                              */
3038 /*-----------------------------------------------------------------*/
3039 int cmdUnDisplay (char *s, context *cctxt)
3040 {   
3041     dsymbol *dsym;
3042     int dnum;
3043
3044     while (isspace(*s)) s++;
3045     if (!*s)
3046     {
3047         for (dsym = setFirstItem(dispsymbols);
3048              dsym;
3049              dsym = setNextItem(dispsymbols))
3050         {
3051             Safe_free(dsym->rs);
3052             Safe_free(dsym); 
3053         }
3054         deleteSet(&dispsymbols);
3055         return 0;
3056     }
3057     while ( s && *s )
3058     {
3059         dnum = strtol(s,&s,10);
3060         if (applyToSetFTrue(dispsymbols,dsymWithNumber,dnum,&dsym)) 
3061         {
3062             deleteSetItem(&dispsymbols,dsym);
3063             Safe_free(dsym->rs);
3064             Safe_free(dsym); 
3065         } 
3066         else
3067         {
3068             fprintf(stdout,"Arguments must be display numbers.\n");    
3069         }
3070     }
3071     return 0;
3072 }
3073
3074 /*-----------------------------------------------------------------*/
3075 /* cmdPrintType - print type of a variable                         */
3076 /*-----------------------------------------------------------------*/
3077 int cmdPrintType (char *s, context *cctxt)
3078 {   
3079         symbol *sym ;
3080     char *bp = s+strlen(s) -1;
3081
3082     while (isspace(*s)) s++;
3083     if (!*s) return 0;
3084     while (isspace(*bp)) bp--;
3085     bp++ ;
3086     *bp = '\0';
3087
3088     if ((sym = symLookup(s,cctxt))) {
3089         printTypeInfo(sym->type);
3090         fprintf(stdout,"\n");
3091     } else {
3092         fprintf(stdout,
3093                 "No symbol \"%s\" in current context.\n",
3094                 s);
3095     }
3096     return 0;   
3097 }
3098
3099 /*-----------------------------------------------------------------*/
3100 /* cmdClrUserBp - clear user break point                           */
3101 /*-----------------------------------------------------------------*/
3102 int cmdClrUserBp (char *s, context *cctxt)
3103 {   
3104     char *bp ;    
3105     function *func = NULL;
3106         
3107     /* clear break point location specification can be of the following
3108        forms
3109        a) <nothing>        - break point at current location
3110        b) lineno           - number of the current module
3111        c) filename:lineno  - line number of the given file
3112        e) filename:function- function X in file Y (useful for static functions)
3113        f) function         - function entry point
3114     */
3115
3116     if (!cctxt) {
3117         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
3118         return 0;
3119     }
3120
3121     /* white space skip */
3122     while (*s && isspace(*s)) s++;
3123     
3124     /* null terminate it after stripping trailing blanks*/
3125     bp = s + strlen(s);
3126     while (bp != s && isspace(*bp)) bp--;
3127     *bp = '\0';
3128
3129     /* case a) nothing */
3130     /* if nothing given then current location : we know
3131        the current execution location from the currentContext */
3132     if (! *s ) {
3133
3134         /* if current context is known */
3135         if (cctxt->func) 
3136             /* clear the break point @ current location */
3137             clearUSERbp (cctxt->addr);
3138         else
3139             fprintf(stderr,"No default breakpoint address now.\n");
3140                         
3141         goto ret ;
3142     }
3143
3144     /* case b) lineno */
3145     /* check if line number */
3146     if (isdigit(*s)) {
3147         /* get the lineno */
3148         int line = atoi(s);
3149
3150         /* if current context not present then we must get the module
3151            which has main & set the break point @ line number provided
3152            of that module : if current context known then set the bp 
3153            at the line number given for the current module 
3154         */
3155         if (cctxt->func) {
3156             if (!cctxt->func->mod) {
3157                 if (!applyToSet(functions,funcWithName,"main"))
3158                     fprintf(stderr,"Function \"main\" not defined.\n");
3159                 else 
3160                     clearBPatModLine(func->mod,line);
3161             } else 
3162                 clearBPatModLine(cctxt->func->mod,line);                        
3163         }
3164         
3165         goto ret;
3166     }
3167
3168     if ((bp = strchr(s,':'))) {
3169         
3170         module *mod = NULL;
3171         *bp = '\0';
3172         
3173         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
3174             fprintf (stderr,"No source file named %s.\n",s);
3175             goto ret;
3176         }
3177
3178         /* case c) filename:lineno */
3179         if (isdigit(*(bp +1))) {                    
3180          
3181             clearBPatModLine (mod,atoi(bp+1));      
3182             goto ret;
3183             
3184         }
3185         /* case d) filename:function */
3186         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func)) 
3187             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1); 
3188         else
3189             clearBPatModLine (mod,func->entryline);
3190         
3191         goto ret;
3192     }
3193             
3194     /* case e) function */
3195     if (!applyToSet(functions,funcWithName,s,&func))
3196         fprintf(stderr,"Function \"%s\" not defined.\n",s); 
3197     else
3198         clearBPatModLine(func->mod,func->entryline);
3199
3200  ret:    
3201     return 0;        
3202 }
3203
3204 /*-----------------------------------------------------------------*/
3205 /* cmdSimulator - send command to simulator                        */
3206 /*-----------------------------------------------------------------*/
3207 int cmdSimulator (char *s, context *cctxt)
3208 {   
3209   char tmpstr[82];
3210
3211     if (strlen(s) > 80) {
3212       printf("error 3A\n");
3213       exit(1);
3214     }
3215     strcpy(tmpstr, s);
3216     strcat(tmpstr, "\n");
3217     sendSim(tmpstr);
3218     waitForSim(200,NULL);
3219     fprintf(stdout,"%s",simResponse());
3220     return 0;
3221 }
3222
3223 void setMainContext()
3224 {
3225     function *func = NULL;
3226     currentFrame = 0; 
3227     if (!applyToSet(functions,funcWithName,"_main",&func) &&
3228         !applyToSet(functions,funcWithName,"main",&func))
3229             return;
3230
3231     discoverContext (func->sym->addr, func);
3232 }
3233
3234 function *needExtraMainFunction()
3235 {
3236     function *func = NULL;
3237     if (!applyToSet(functions,funcWithName,"_main",&func))
3238     {
3239         if (applyToSet(functions,funcWithName,"main",&func))
3240         {
3241             return func;
3242         }
3243     }
3244     return NULL;
3245 }
3246     
3247 static void printFrame()
3248 {
3249     int i;
3250     function *func     = NULL;
3251     function *lastfunc = NULL;
3252
3253     if ( currentFrame < 0 )
3254     {
3255         currentFrame = 0;
3256         fprintf(stdout,"Bottom (i.e., innermost) frame selected; you cannot go down.\n");
3257         return;
3258     }
3259     STACK_STARTWALK(callStack) ;
3260     for ( i = 0; i <= currentFrame ; i++ )
3261     {
3262         func = STACK_WALK(callStack);
3263         if ( !func )
3264         {
3265             currentFrame = i-1;
3266             fprintf(stdout,"Initial frame selected; you cannot go up.\n");
3267             return;
3268         }
3269     }
3270     fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",
3271             currentFrame,func->laddr,func->sym->name,func->mod->c_name,func->lline+1);
3272     fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
3273             func->mod->cfullname,func->lline+1,func->laddr);
3274
3275     discoverContext (func->laddr, func);
3276 }
3277
3278
3279 /*-----------------------------------------------------------------*/
3280 /* cmdUp -  Up command                                             */
3281 /*-----------------------------------------------------------------*/
3282 int cmdUp(char *s, context *cctxt)
3283 {
3284     while (isspace(*s)) s++;
3285     if ( *s )
3286         currentFrame += strtol(s,0,10);
3287     else
3288         currentFrame++ ;
3289
3290     printFrame();
3291         return 0;
3292 }
3293
3294 /*-----------------------------------------------------------------*/
3295 /* cmdDown - down command                                          */
3296 /*-----------------------------------------------------------------*/
3297 int cmdDown(char *s, context *cctxt)
3298 {
3299     while (isspace(*s)) s++;
3300     if ( *s )
3301         currentFrame -= strtol(s,0,10);
3302     else
3303         currentFrame-- ;
3304
3305     printFrame();
3306         return 0;
3307 }
3308 /*-----------------------------------------------------------------*/
3309 /* cmdFrame - Frame command                                        */
3310 /*-----------------------------------------------------------------*/
3311 int cmdFrame (char *s, context *cctxt)
3312 {   
3313     function *func = NULL;
3314     int i, framenr = 0;
3315
3316     while (isspace(*s)) s++;
3317     if ( *s )
3318         currentFrame = strtol(s,0,10);
3319     printFrame();
3320     return 0;
3321 }
3322
3323 /*-----------------------------------------------------------------*/
3324 /* cmdFinish - exec till end of current function                   */
3325 /*-----------------------------------------------------------------*/
3326 int cmdFinish (char *s, context *ctxt)
3327 {
3328     if (STACK_EMPTY(callStack)) {
3329         fprintf(stdout,"The program is not running.\n");
3330         return 0;
3331     }
3332
3333     if (srcMode == SRC_CMODE) {
3334         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
3335                        stepBpCB, ctxt->func->mod->c_name, 
3336                        ctxt->func->exitline);
3337     } else {
3338         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP, 
3339                        stepBpCB, ctxt->func->mod->asm_name, 
3340                        ctxt->func->aexitline);
3341     }
3342
3343     simGo(-1);
3344     showfull = 1;
3345     return 0;
3346     
3347 }
3348
3349
3350 /*-----------------------------------------------------------------*/
3351 /* cmdShow - show command                                          */
3352 /*-----------------------------------------------------------------*/
3353 int cmdShow (char *s, context *cctxt)
3354 {
3355     /* skip white space */
3356     while (*s && isspace(*s)) s++ ;
3357
3358     if (strcmp(s,"copying") == 0) {
3359         fputs(copying,stdout);
3360         return 0;
3361     }
3362     
3363     if (strcmp(s,"warranty") == 0) {
3364         fputs(warranty,stdout);
3365         return 0;
3366     }
3367
3368     return 0;
3369 }
3370