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