Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / debugger / mcs51 / cmd.c
1 /*-------------------------------------------------------------------------
2     cmd.c - source  file for debugger command execution
3         Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
4
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by the
7    Free Software Foundation; either version 2, or (at your option) any
8    later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19    In other words, you are welcome to use, share and improve this program.
20    You are forbidden to forbid anyone else to use, share and improve
21    what you give them.   Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
23
24 #include "sdcdb.h"
25 #include "symtab.h"
26 #include "simi.h"
27 #include "break.h"
28 #include "cmd.h"
29 #include "newalloc.h"
30
31 /* default number of lines to list out */
32 #define LISTLINES 10
33 static int listlines = LISTLINES;
34
35 /* mainly used to retain a reference to the active module being
36    listed.  May be used as a general context for other commands if
37    no better context is available */
38 static module *list_mod = NULL;
39
40 #if defined(__APPLE__) && defined(__MACH__)
41 static char *copying=
42 {" GNU GENERAL PUBLIC LICENSE Version 2"};
43 static char *warranty=
44 {" NO WARRANTY"};
45 #else
46 static char *copying=
47 "                   GNU GENERAL PUBLIC LICENSE\n"
48 "                       Version 2, June 1991\n"
49 "\n"
50 " Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n"
51 " 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
52 " Everyone is permitted to copy and distribute verbatim copies\n"
53 " of this license document, but changing it is not allowed.\n"
54 "\n"
55 "                            Preamble\n"
56 "\n"
57 "  The licenses for most software are designed to take away your\n"
58 "freedom to share and change it.  By contrast, the GNU General Public\n"
59 "License is intended to guarantee your freedom to share and change free\n"
60 "software--to make sure the software is free for all its users.  This\n"
61 "General Public License applies to most of the Free Software\n"
62 "Foundation's software and to any other program whose authors commit to\n"
63 "using it.  (Some other Free Software Foundation software is covered by\n"
64 "the GNU Library General Public License instead.)  You can apply it to\n"
65 "your programs, too.\n"
66 "\n"
67 "  When we speak of free software, we are referring to freedom, not\n"
68 "price.  Our General Public Licenses are designed to make sure that you\n"
69 "have the freedom to distribute copies of free software (and charge for\n"
70 "this service if you wish), that you receive source code or can get it\n"
71 "if you want it, that you can change the software or use pieces of it\n"
72 "in new free programs; and that you know you can do these things.\n"
73 "\n"
74 "  To protect your rights, we need to make restrictions that forbid\n"
75 "anyone to deny you these rights or to ask you to surrender the rights.\n"
76 "These restrictions translate to certain responsibilities for you if you\n"
77 "distribute copies of the software, or if you modify it.\n"
78 "\n"
79 "  For example, if you distribute copies of such a program, whether\n"
80 "gratis or for a fee, you must give the recipients all the rights that\n"
81 "you have.  You must make sure that they, too, receive or can get the\n"
82 "source code.  And you must show them these terms so they know their\n"
83 "rights.\n"
84 "\n"
85 "  We protect your rights with two steps: (1) copyright the software, and\n"
86 "(2) offer you this license which gives you legal permission to copy,\n"
87 "distribute and/or modify the software.\n"
88 "\n"
89 "  Also, for each author's protection and ours, we want to make certain\n"
90 "that everyone understands that there is no warranty for this free\n"
91 "software.  If the software is modified by someone else and passed on, we\n"
92 "want its recipients to know that what they have is not the original, so\n"
93 "that any problems introduced by others will not reflect on the original\n"
94 "authors' reputations.\n"
95 "\n"
96 "  Finally, any free program is threatened constantly by software\n"
97 "patents.  We wish to avoid the danger that redistributors of a free\n"
98 "program will individually obtain patent licenses, in effect making the\n"
99 "program proprietary.  To prevent this, we have made it clear that any\n"
100 "patent must be licensed for everyone's free use or not licensed at all.\n"
101 "\n"
102 "  The precise terms and conditions for copying, distribution and\n"
103 "modification follow.\n"
104 "^L\n"
105 "                    GNU GENERAL PUBLIC LICENSE\n"
106 "   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n"
107 "\n"
108 "  0. This License applies to any program or other work which contains\n"
109 "a notice placed by the copyright holder saying it may be distributed\n"
110 "under the terms of this General Public License.  The \"Program\", below,\n"
111 "refers to any such program or work, and a \"work based on the Program\"\n"
112 "means either the Program or any derivative work under copyright law:\n"
113 "that is to say, a work containing the Program or a portion of it,\n"
114 "either verbatim or with modifications and/or translated into another\n"
115 "language.  (Hereinafter, translation is included without limitation in\n"
116 "the term \"modification\".)  Each licensee is addressed as \"you\".\n"
117 "\n"
118 "Activities other than copying, distribution and modification are not\n"
119 "covered by this License; they are outside its scope.  The act of\n"
120 "running the Program is not restricted, and the output from the Program\n"
121 "is covered only if its contents constitute a work based on the\n"
122 "Program (independent of having been made by running the Program).\n"
123 "Whether that is true depends on what the Program does.\n"
124 "\n"
125 "  1. You may copy and distribute verbatim copies of the Program's\n"
126 "source code as you receive it, in any medium, provided that you\n"
127 "conspicuously and appropriately publish on each copy an appropriate\n"
128 "copyright notice and disclaimer of warranty; keep intact all the\n"
129 "notices that refer to this License and to the absence of any warranty;\n"
130 "and give any other recipients of the Program a copy of this License\n"
131 "along with the Program.\n"
132 "\n"
133 "You may charge a fee for the physical act of transferring a copy, and\n"
134 "you may at your option offer warranty protection in exchange for a fee.\n"
135 "\n"
136 "  2. You may modify your copy or copies of the Program or any portion\n"
137 "of it, thus forming a work based on the Program, and copy and\n"
138 "distribute such modifications or work under the terms of Section 1\n"
139 "above, provided that you also meet all of these conditions:\n"
140 "\n"
141 "    a) You must cause the modified files to carry prominent notices\n"
142 "    stating that you changed the files and the date of any change.\n"
143 "\n"
144 "    b) You must cause any work that you distribute or publish, that in\n"
145 "    whole or in part contains or is derived from the Program or any\n"
146 "    part thereof, to be licensed as a whole at no charge to all third\n"
147 "    parties under the terms of this License.\n"
148 "\n"
149 "    c) If the modified program normally reads commands interactively\n"
150 "    when run, you must cause it, when started running for such\n"
151 "    interactive use in the most ordinary way, to print or display an\n"
152 "    announcement including an appropriate copyright notice and a\n"
153 "    notice that there is no warranty (or else, saying that you provide\n"
154 "    a warranty) and that users may redistribute the program under\n"
155 "    these conditions, and telling the user how to view a copy of this\n"
156 "    License.  (Exception: if the Program itself is interactive but\n"
157 "    does not normally print such an announcement, your work based on\n"
158 "    the Program is not required to print an announcement.)\n"
159 "\n"
160 "These requirements apply to the modified work as a whole.  If\n"
161 "identifiable sections of that work are not derived from the Program,\n"
162 "and can be reasonably considered independent and separate works in\n"
163 "themselves, then this License, and its terms, do not apply to those\n"
164 "sections when you distribute them as separate works.  But when you\n"
165 "distribute the same sections as part of a whole which is a work based\n"
166 "on the Program, the distribution of the whole must be on the terms of\n"
167 "this License, whose permissions for other licensees extend to the\n"
168 "entire whole, and thus to each and every part regardless of who wrote it.\n"
169 "\n"
170 "Thus, it is not the intent of this section to claim rights or contest\n"
171 "your rights to work written entirely by you; rather, the intent is to\n"
172 "exercise the right to control the distribution of derivative or\n"
173 "collective works based on the Program.\n"
174 "\n"
175 "In addition, mere aggregation of another work not based on the Program\n"
176 "with the Program (or with a work based on the Program) on a volume of\n"
177 "a storage or distribution medium does not bring the other work under\n"
178 "the scope of this License.\n"
179 "\n"
180 "  3. You may copy and distribute the Program (or a work based on it,\n"
181 "under Section 2) in object code or executable form under the terms of\n"
182 "Sections 1 and 2 above provided that you also do one of the following:\n"
183 "\n"
184 "    a) Accompany it with the complete corresponding machine-readable\n"
185 "    source code, which must be distributed under the terms of Sections\n"
186 "    1 and 2 above on a medium customarily used for software interchange; or,\n"
187 "\n"
188 "    b) Accompany it with a written offer, valid for at least three\n"
189 "    years, to give any third party, for a charge no more than your\n"
190 "    cost of physically performing source distribution, a complete\n"
191 "    machine-readable copy of the corresponding source code, to be\n"
192 "    distributed under the terms of Sections 1 and 2 above on a medium\n"
193 "    customarily used for software interchange; or,\n"
194 "\n"
195 "    c) Accompany it with the information you received as to the offer\n"
196 "    to distribute corresponding source code.  (This alternative is\n"
197 "    allowed only for noncommercial distribution and only if you\n"
198 "    received the program in object code or executable form with such\n"
199 "    an offer, in accord with Subsection b above.)\n"
200 "\n"
201 "The source code for a work means the preferred form of the work for\n"
202 "making modifications to it.  For an executable work, complete source\n"
203 "code means all the source code for all modules it contains, plus any\n"
204 "associated interface definition files, plus the scripts used to\n"
205 "control compilation and installation of the executable.  However, as a\n"
206 "special exception, the source code distributed need not include\n"
207 "anything that is normally distributed (in either source or binary\n"
208 "form) with the major components (compiler, kernel, and so on) of the\n"
209 "operating system on which the executable runs, unless that component\n"
210 "itself accompanies the executable.\n"
211 "\n"
212 "If distribution of executable or object code is made by offering\n"
213 "access to copy from a designated place, then offering equivalent\n"
214 "access to copy the source code from the same place counts as\n"
215 "distribution of the source code, even though third parties are not\n"
216 "compelled to copy the source along with the object code.\n"
217 "^L\n"
218 "  4. You may not copy, modify, sublicense, or distribute the Program\n"
219 "except as expressly provided under this License.  Any attempt\n"
220 "otherwise to copy, modify, sublicense or distribute the Program is\n"
221 "void, and will automatically terminate your rights under this License.\n"
222 "However, parties who have received copies, or rights, from you under\n"
223 "this License will not have their licenses terminated so long as such\n"
224 "parties remain in full compliance.\n"
225 "\n"
226 "  5. You are not required to accept this License, since you have not\n"
227 "signed it.  However, nothing else grants you permission to modify or\n"
228 "distribute the Program or its derivative works.  These actions are\n"
229 "prohibited by law if you do not accept this License.  Therefore, by\n"
230 "modifying or distributing the Program (or any work based on the\n"
231 "Program), you indicate your acceptance of this License to do so, and\n"
232 "all its terms and conditions for copying, distributing or modifying\n"
233 "the Program or works based on it.\n"
234 "\n"
235 "  6. Each time you redistribute the Program (or any work based on the\n"
236 "Program), the recipient automatically receives a license from the\n"
237 "original licensor to copy, distribute or modify the Program subject to\n"
238 "these terms and conditions.  You may not impose any further\n"
239 "restrictions on the recipients' exercise of the rights granted herein.\n"
240 "You are not responsible for enforcing compliance by third parties to\n"
241 "this License.\n"
242 "\n"
243 "  7. If, as a consequence of a court judgment or allegation of patent\n"
244 "infringement or for any other reason (not limited to patent issues),\n"
245 "conditions are imposed on you (whether by court order, agreement or\n"
246 "otherwise) that contradict the conditions of this License, they do not\n"
247 "excuse you from the conditions of this License.  If you cannot\n"
248 "distribute so as to satisfy simultaneously your obligations under this\n"
249 "License and any other pertinent obligations, then as a consequence you\n"
250 "may not distribute the Program at all.  For example, if a patent\n"
251 "license would not permit royalty-free redistribution of the Program by\n"
252 "all those who receive copies directly or indirectly through you, then\n"
253 "the only way you could satisfy both it and this License would be to\n"
254 "refrain entirely from distribution of the Program.\n"
255 "\n"
256 "If any portion of this section is held invalid or unenforceable under\n"
257 "any particular circumstance, the balance of the section is intended to\n"
258 "apply and the section as a whole is intended to apply in other\n"
259 "circumstances.\n"
260 "\n"
261 "It is not the purpose of this section to induce you to infringe any\n"
262 "patents or other property right claims or to contest validity of any\n"
263 "such claims; this section has the sole purpose of protecting the\n"
264 "integrity of the free software distribution system, which is\n"
265 "implemented by public license practices.  Many people have made\n"
266 "generous contributions to the wide range of software distributed\n"
267 "through that system in reliance on consistent application of that\n"
268 "system; it is up to the author/donor to decide if he or she is willing\n"
269 "to distribute software through any other system and a licensee cannot\n"
270 "impose that choice.\n"
271 "\n"
272 "This section is intended to make thoroughly clear what is believed to\n"
273 "be a consequence of the rest of this License.\n"
274 "\n"
275 "  8. If the distribution and/or use of the Program is restricted in\n"
276 "certain countries either by patents or by copyrighted interfaces, the\n"
277 "original copyright holder who places the Program under this License\n"
278 "may add an explicit geographical distribution limitation excluding\n"
279 "those countries, so that distribution is permitted only in or among\n"
280 "countries not thus excluded.  In such case, this License incorporates\n"
281 "the limitation as if written in the body of this License.\n"
282 "\n"
283 "  9. The Free Software Foundation may publish revised and/or new versions\n"
284 "of the General Public License from time to time.  Such new versions will\n"
285 "be similar in spirit to the present version, but may differ in detail to\n"
286 "address new problems or concerns.\n"
287 "\n"
288 "Each version is given a distinguishing version number.  If the Program\n"
289 "specifies a version number of this License which applies to it and \"any\n"
290 "later version\", you have the option of following the terms and conditions\n"
291 "either of that version or of any later version published by the Free\n"
292 "Software Foundation.  If the Program does not specify a version number of\n"
293 "this License, you may choose any version ever published by the Free Software\n"
294 "Foundation.\n"
295 "\n"
296 "  10. If you wish to incorporate parts of the Program into other free\n"
297 "programs whose distribution conditions are different, write to the author\n"
298 "to ask for permission.  For software which is copyrighted by the Free\n"
299 "Software Foundation, write to the Free Software Foundation; we sometimes\n"
300 "make exceptions for this.  Our decision will be guided by the two goals\n"
301 "of preserving the free status of all derivatives of our free software and\n"
302 "of promoting the sharing and reuse of software generally.\n";
303
304 static char *warranty=
305 "                            NO WARRANTY\n"
306 "\n"
307 "  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
308 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
309 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
310 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
311 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
312 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
313 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
314 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
315 "REPAIR OR CORRECTION.\n"
316 "\n"
317 "  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
318 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
319 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
320 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
321 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
322 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
323 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
324 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
325 "POSSIBILITY OF SUCH DAMAGES.\n";
326 #endif
327
328 static void printTypeInfo(link *);
329 static void printValAggregates (symbol *,link *,char,unsigned int,int,int);
330 static  int printOrSetSymValue (symbol *sym, context *cctxt,
331                                 int flg, int dnum, int fmt,
332                                 char *rs, char *val, char cmp);
333
334 int srcMode = SRC_CMODE ;
335 set *dispsymbols = NULL   ; /* set of displayable symbols */
336 static int currentFrame = 0;        /* actual displayed frame     */
337 /*-----------------------------------------------------------------*/
338 /* funcWithName - returns function with name                       */
339 /*-----------------------------------------------------------------*/
340 DEFSETFUNC(funcWithName)
341 {
342     function *func = item;
343     V_ARG(char *,name);
344     V_ARG(function **,funcp);
345
346     if (*funcp)
347         return 0;
348
349     if (strcmp(func->sym->name,name) == 0) {
350         *funcp = func;
351         return 1;
352     }
353
354     return 0;
355 }
356
357 /*-----------------------------------------------------------------*/
358 /* symWithAddr - look for symbol with sfr / sbit address           */
359 /*-----------------------------------------------------------------*/
360 DEFSETFUNC(symWithAddr)
361 {
362     symbol *sym = item;
363     V_ARG(unsigned long,laddr);
364     V_ARG(int    ,laddrspace);
365     V_ARG(symbol **,rsym);
366
367     if (*rsym)
368         return 0;
369
370     if ( sym->addr == laddr &&
371          sym->addrspace == laddrspace )
372     {
373         *rsym = sym;
374         return 1;
375     }
376
377     return 0;
378 }
379
380 /*-----------------------------------------------------------------*/
381 /* setBPatModLine - set break point at the line specified for the  */
382 /*-----------------------------------------------------------------*/
383 static void setBPatModLine (module *mod, int line, char bpType )
384 {
385     int next_line;
386
387     /* look for the first executable line after the line
388        specified & get the break point there */
389
390     if ( line < 0 )
391         return;
392
393     if (srcMode == SRC_CMODE && line > mod->ncLines) {
394         fprintf(stderr,"No line %d in file \"%s\".\n",
395                 line,mod->c_name);
396         return ;
397     }
398
399     if (srcMode == SRC_AMODE && line > mod->nasmLines) {
400         fprintf(stderr,"No line %d in file \"%s\".\n",
401                 line,mod->asm_name);
402         return ;
403     }
404
405     next_line = line;
406     for ( ; next_line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ;
407           next_line++ ) {
408         if (srcMode == SRC_CMODE) {
409             if (mod->cLines[next_line]->addr != INT_MAX) {
410                 setBreakPoint (mod->cLines[next_line]->addr, CODE, bpType,
411                                userBpCB, mod->c_name, next_line);
412                 return;
413 //              break;
414             }
415         }
416         else {
417            if (mod->asmLines[next_line]->addr != INT_MAX) {
418                setBreakPoint (mod->asmLines[next_line]->addr, CODE, bpType,
419                               userBpCB, mod->asm_name, next_line);
420                 return;
421 //             break;
422            }
423         }
424     }
425
426         fprintf(stderr,"No line %d or after in file \"%s\"..\n",
427                         line,mod->c_name);
428
429     return;
430 }
431
432 /*-----------------------------------------------------------------*/
433 /* clearBPatModLine - clr break point at the line specified        */
434 /*-----------------------------------------------------------------*/
435 static void clearBPatModLine (module *mod, int line)
436 {
437     /* look for the first executable line after the line
438        specified & get the break point there */
439     if (srcMode == SRC_CMODE && line > mod->ncLines) {
440         fprintf(stderr,"No line %d in file \"%s\".\n",
441                 line,mod->c_name);
442         return ;
443     }
444
445     if (srcMode == SRC_AMODE && line > mod->ncLines) {
446         fprintf(stderr,"No line %d in file \"%s\".\n",
447                 line,mod->c_name);
448         return ;
449     }
450
451     for ( ; line < (srcMode == SRC_CMODE ? mod->ncLines : mod->nasmLines ) ;
452           line++ ) {
453         if (srcMode == SRC_CMODE)
454             if (mod->cLines[line]->addr) {
455                 clearUSERbp (mod->cLines[line]->addr);
456                 break;
457             }
458         else
459             if (mod->asmLines[line]->addr) {
460                 clearUSERbp (mod->asmLines[line]->addr);
461                 break;
462             }
463     }
464
465     return;
466 }
467
468 /*-----------------------------------------------------------------*/
469 /* moduleLineWithAddr - finds and returns a line  with a given address */
470 /*-----------------------------------------------------------------*/
471 DEFSETFUNC(moduleLineWithAddr)
472 {
473     module *mod = item;
474     int i;
475
476     V_ARG(unsigned int,addr);
477     V_ARG(module **,rmod);
478     V_ARG(int *,line);
479
480     if (*rmod)
481         return 0;
482
483     for (i=0; i < mod->nasmLines; i++ )
484     {
485         if ( mod->asmLines[i]->addr == addr)
486         {
487             *rmod = mod ;
488             if (line )
489             {
490                 *line = 0;
491                 for ( i=0; i < mod->ncLines; i++ )
492                 {
493                     if ( mod->cLines[i]->addr > addr)
494                         break;
495                     *line = i;
496                 }
497                 return 1;
498             }
499         }
500     }
501
502     return 0;
503 }
504
505 /*-----------------------------------------------------------------*/
506 /* funcWithNameModule - returns functions with a name module combo */
507 /*-----------------------------------------------------------------*/
508 DEFSETFUNC(funcWithNameModule)
509 {
510     function *func = item;
511     V_ARG(char *,fname);
512     V_ARG(char *,mname);
513     V_ARG(function **,funcp);
514
515     if (*funcp)
516         return 0;
517
518     if (strcmp(func->sym->name,fname) == 0 &&
519         strcmp(func->mod->c_name,mname) == 0) {
520         *funcp = func;
521         return 1;
522     }
523
524     return 0;
525 }
526
527 /*-----------------------------------------------------------------*/
528 /* funcInAddr - given an address returns the function              */
529 /*-----------------------------------------------------------------*/
530 DEFSETFUNC(funcInAddr)
531 {
532     function *func = item;
533     V_ARG(unsigned int,addr);
534     V_ARG(function **,funcp);
535
536     if (*funcp)
537         return 0;
538
539     /* in the address range */
540     if (func->sym->addr <= addr &&
541         func->sym->eaddr >= addr) {
542
543         *funcp = func;
544         return 1;
545     }
546
547     return 0;
548 }
549
550 /*-----------------------------------------------------------------*/
551 /* setStepBp - will set STEP Bp @ function entry points            */
552 /*-----------------------------------------------------------------*/
553 DEFSETFUNC(setStepBp)
554 {
555     function *func = item;
556
557     if (func->sym && func->sym->addr ) {
558
559         /* set the entry break point */
560         setBreakPoint (func->sym->addr , CODE , STEP ,
561                        stepBpCB ,func->mod->c_name , func->entryline);
562
563         return 1;
564     }
565
566     return 0;
567 }
568
569 /*-----------------------------------------------------------------*/
570 /* setStepEPBp - sets a given type of bp @ the execution point     */
571 /*-----------------------------------------------------------------*/
572 DEFSETFUNC(setStepEPBp)
573 {
574     exePoint *ep = item;
575     V_ARG(int,bptype);
576     V_ARG(char *,mname);
577
578     setBreakPoint (ep->addr, CODE, bptype,
579                    stepBpCB, mname, ep->line);
580     return 1;
581 }
582
583 /*-----------------------------------------------------------------*/
584 /* setNextEPBp - sets a given type of bp @ the execution point     */
585 /*-----------------------------------------------------------------*/
586 DEFSETFUNC(setNextEPBp)
587 {
588     exePoint *ep = item;
589     V_ARG(int,bptype);
590     V_ARG(char *,mname);
591
592     setBreakPoint (ep->addr, CODE, bptype,
593                    nextBpCB, mname, ep->line);
594     return 1;
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* lineAtAddr - for execution points returns the one with addr     */
599 /*-----------------------------------------------------------------*/
600 DEFSETFUNC(lineAtAddr)
601 {
602     exePoint *ep = item;
603     V_ARG(unsigned int,addr);
604     V_ARG(int *,line);
605     V_ARG(int *,block);
606     V_ARG(int *,level);
607
608     /* address must be an exact match */
609     if (ep->addr == addr) {
610         *line = ep->line;
611         if (block)
612             *block = ep->block ;
613         if (level)
614             *level = ep->level ;
615         return 1;
616     }
617
618     return 0;
619
620 }
621
622 /*-----------------------------------------------------------------*/
623 /* lineNearAddr - for execution points returns the one with addr   */
624 /*-----------------------------------------------------------------*/
625 DEFSETFUNC(lineNearAddr)
626 {
627     exePoint *ep = item;
628     V_ARG(unsigned int,addr);
629     V_ARG(int *,line);
630     V_ARG(int *,block);
631     V_ARG(int *,level);
632
633     /* the line in which the address is */
634     if (ep->addr <= addr) {
635         *line = ep->line;
636         if (block)
637             *block = ep->block ;
638         if (level)
639             *level = ep->level ;
640         return 1;
641     }
642
643     return 0;
644
645 }
646
647 /*-----------------------------------------------------------------*/
648 /* discoverContext - find out the current context of the bp        */
649 /*-----------------------------------------------------------------*/
650 context *discoverContext (unsigned addr, function *func, context *ctxt)
651 {
652     module   *mod  = NULL;
653     int line = 0;
654
655     /* find the function we are in */
656     if (!func && !applyToSet(functions,funcInAddr,addr,&func)) {
657         if (!applyToSet(functions,funcWithName,"_main",&func) ||
658             !applyToSet(modules,moduleLineWithAddr,addr,&mod,NULL))
659         {
660             fprintf(stderr, "addr 0x%x in no module/function (runtime env?)\n",addr);
661             return NULL;
662         }
663         ctxt->func = func;
664         ctxt->addr = addr;
665         ctxt->modName = mod->name;
666         ctxt->cline = func->exitline;
667     }
668     else
669     {
670         ctxt->func = func;
671         ctxt->addr = func->laddr = addr;
672         ctxt->modName = func->modName;
673
674         /* find the c line number */
675         if(applyToSet(func->cfpoints,lineAtAddr,addr,
676                   &line,&ctxt->block,&ctxt->level))
677             ctxt->cline = func->lline = line;
678         else if(applyToSet(func->cfpoints,lineNearAddr,addr,
679                   &line,&ctxt->block,&ctxt->level))
680             ctxt->cline = func->lline = line;
681         else
682             ctxt->cline = -1;
683     }
684     /* find the asm line number */
685     line = 0;
686     if (applyToSet(func->afpoints,lineAtAddr,addr,
687                    &line,NULL,NULL))
688         ctxt->asmline = line;
689     else
690         ctxt->asmline = -1;
691
692     return ctxt;
693 }
694
695 #define IS_BRANCH       1
696 #define IS_CALL         2
697 #define IS_RET          4
698 #define IS_ADDR11       8
699 #define IS_ADDR16       16
700 #define IS_COND         32
701
702 struct instruction {
703         unsigned char   flags;
704         unsigned char   len;
705 };
706
707 static struct instruction instructions[] = {
708         [0x28] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
709         [0x29] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
710         [0x2A] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
711         [0x2B] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
712         [0x2C] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
713         [0x2D] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
714         [0x2E] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
715         [0x2F] = { .flags = 0, .len = 1 },      /* ADD A,Rn */
716         [0x25] = { .flags = 0, .len = 2 },      /* ADD A,direct */
717         [0x26] = { .flags = 0, .len = 1 },      /* ADD A,@Ri */
718         [0x27] = { .flags = 0, .len = 1 },      /* ADD A,@Ri */
719         [0x24] = { .flags = 0, .len = 2 },      /* ADD A,#data */
720         
721         [0x38] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
722         [0x39] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
723         [0x3A] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
724         [0x3B] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
725         [0x3C] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
726         [0x3D] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
727         [0x3E] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
728         [0x3F] = { .flags = 0, .len = 1 },      /* ADDC A,Rn */
729         [0x35] = { .flags = 0, .len = 2 },      /* ADDC A,direct */
730         [0x36] = { .flags = 0, .len = 1 },      /* ADDC A,@Ri */
731         [0x37] = { .flags = 0, .len = 1 },      /* ADDC A,@Ri */
732         [0x34] = { .flags = 0, .len = 2 },      /* ADDC A,#data */
733         
734         [0x98] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
735         [0x99] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
736         [0x9A] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
737         [0x9B] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
738         [0x9C] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
739         [0x9D] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
740         [0x9E] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
741         [0x9F] = { .flags = 0, .len = 1 },      /* SUBB A,Rn */
742         [0x95] = { .flags = 0, .len = 2 },      /* SUBB A,direct */
743         [0x96] = { .flags = 0, .len = 1 },      /* SUBB A,@Ri */
744         [0x97] = { .flags = 0, .len = 1 },      /* SUBB A,@Ri */
745         [0x94] = { .flags = 0, .len = 2 },      /* SUBB A,#data */
746         
747         [0x08] = { .flags = 0, .len = 1 },      /* INC Rn */
748         [0x09] = { .flags = 0, .len = 1 },      /* INC Rn */
749         [0x0A] = { .flags = 0, .len = 1 },      /* INC Rn */
750         [0x0B] = { .flags = 0, .len = 1 },      /* INC Rn */
751         [0x0C] = { .flags = 0, .len = 1 },      /* INC Rn */
752         [0x0D] = { .flags = 0, .len = 1 },      /* INC Rn */
753         [0x0E] = { .flags = 0, .len = 1 },      /* INC Rn */
754         [0x0F] = { .flags = 0, .len = 1 },      /* INC Rn */
755         [0x05] = { .flags = 0, .len = 2 },      /* INC direct */
756         [0x06] = { .flags = 0, .len = 1 },      /* INC @Ri */
757         [0x07] = { .flags = 0, .len = 1 },      /* INC @Ri */
758         [0x04] = { .flags = 0, .len = 1 },      /* INC A */
759
760         [0xA3] = { .flags = 0, .len = 1 },      /* INC DPTR */
761
762         [0x18] = { .flags = 0, .len = 1 },      /* DEC Rn */
763         [0x19] = { .flags = 0, .len = 1 },      /* DEC Rn */
764         [0x1A] = { .flags = 0, .len = 1 },      /* DEC Rn */
765         [0x1B] = { .flags = 0, .len = 1 },      /* DEC Rn */
766         [0x1C] = { .flags = 0, .len = 1 },      /* DEC Rn */
767         [0x1D] = { .flags = 0, .len = 1 },      /* DEC Rn */
768         [0x1E] = { .flags = 0, .len = 1 },      /* DEC Rn */
769         [0x1F] = { .flags = 0, .len = 1 },      /* DEC Rn */
770         [0x15] = { .flags = 0, .len = 2 },      /* DEC direct */
771         [0x16] = { .flags = 0, .len = 1 },      /* DEC @Ri */
772         [0x17] = { .flags = 0, .len = 1 },      /* DEC @Ri */
773         [0x14] = { .flags = 0, .len = 1 },      /* DEC A */
774
775         [0xA4] = { .flags = 0, .len = 1 },      /* MUL AB */
776         [0x84] = { .flags = 0, .len = 1 },      /* DIV AB */
777
778         [0xD4] = { .flags = 0, .len = 1 },      /* DA A */
779
780         [0x58] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
781         [0x59] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
782         [0x5A] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
783         [0x5B] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
784         [0x5C] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
785         [0x5D] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
786         [0x5E] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
787         [0x5F] = { .flags = 0, .len = 1 },      /* ANL A,Rn */
788         [0x55] = { .flags = 0, .len = 2 },      /* ANL A,direct */
789         [0x56] = { .flags = 0, .len = 1 },      /* ANL A,@Ri */
790         [0x57] = { .flags = 0, .len = 1 },      /* ANL A,@Ri */
791         [0x54] = { .flags = 0, .len = 2 },      /* ANL A,#data */
792         [0x52] = { .flags = 0, .len = 2 },      /* ANL direct,A */
793         [0x53] = { .flags = 0, .len = 3 },      /* ANL direct,#data */
794
795         [0x48] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
796         [0x49] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
797         [0x4A] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
798         [0x4B] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
799         [0x4C] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
800         [0x4D] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
801         [0x4E] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
802         [0x4F] = { .flags = 0, .len = 1 },      /* ORL A,Rn */
803         [0x45] = { .flags = 0, .len = 2 },      /* ORL A,direct */
804         [0x46] = { .flags = 0, .len = 1 },      /* ORL A,@Ri */
805         [0x47] = { .flags = 0, .len = 1 },      /* ORL A,@Ri */
806         [0x44] = { .flags = 0, .len = 2 },      /* ORL A,#data */
807         [0x42] = { .flags = 0, .len = 2 },      /* ORL direct,A */
808         [0x43] = { .flags = 0, .len = 3 },      /* ORL direct,#data */
809
810         [0x68] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
811         [0x69] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
812         [0x6A] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
813         [0x6B] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
814         [0x6C] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
815         [0x6D] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
816         [0x6E] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
817         [0x6F] = { .flags = 0, .len = 1 },      /* XRL A,Rn */
818         [0x65] = { .flags = 0, .len = 2 },      /* XRL A,direct */
819         [0x66] = { .flags = 0, .len = 1 },      /* XRL A,@Ri */
820         [0x67] = { .flags = 0, .len = 1 },      /* XRL A,@Ri */
821         [0x64] = { .flags = 0, .len = 2 },      /* XRL A,#data */
822         [0x62] = { .flags = 0, .len = 2 },      /* XRL direct,A */
823         [0x63] = { .flags = 0, .len = 3 },      /* XRL direct,#data */
824         
825         [0xE4] = { .flags = 0, .len = 1 },      /* CLR A */
826         [0xF4] = { .flags = 0, .len = 1 },      /* CPL A */
827
828         [0x23] = { .flags = 0, .len = 1 },      /* RL A */
829         [0x33] = { .flags = 0, .len = 1 },      /* RLC A */
830         [0x03] = { .flags = 0, .len = 1 },      /* RR A */
831         [0x13] = { .flags = 0, .len = 1 },      /* RRC A */
832         
833         [0xC4] = { .flags = 0, .len = 1 },      /* SWAP A */
834
835         [0xE8] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
836         [0xE9] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
837         [0xEA] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
838         [0xEB] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
839         [0xEC] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
840         [0xED] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
841         [0xEE] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
842         [0xEF] = { .flags = 0, .len = 1 },      /* MOV A,Rn */
843         [0xE5] = { .flags = 0, .len = 2 },      /* MOV A,direct */
844         [0xE6] = { .flags = 0, .len = 1 },      /* MOV A,@Ri */
845         [0xE7] = { .flags = 0, .len = 1 },      /* MOV A,@Ri */
846         [0x74] = { .flags = 0, .len = 2 },      /* MOV A,#data */
847
848         [0xF8] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
849         [0xF9] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
850         [0xFA] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
851         [0xFB] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
852         [0xFC] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
853         [0xFD] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
854         [0xFE] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
855         [0xFF] = { .flags = 0, .len = 1 },      /* MOV Rn,A */
856         
857         [0xA8] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
858         [0xA9] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
859         [0xAA] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
860         [0xAB] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
861         [0xAC] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
862         [0xAD] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
863         [0xAE] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
864         [0xAF] = { .flags = 0, .len = 2 },      /* MOV Rn,direct */
865
866         [0x78] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
867         [0x79] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
868         [0x7A] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
869         [0x7B] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
870         [0x7C] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
871         [0x7D] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
872         [0x7E] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
873         [0x7F] = { .flags = 0, .len = 2 },      /* MOV Rn,#data */
874         
875         [0xF5] = { .flags = 0, .len = 2 },      /* MOV direct,A */
876         [0x88] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
877         [0x89] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
878         [0x8A] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
879         [0x8B] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
880         [0x8C] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
881         [0x8D] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
882         [0x8E] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
883         [0x8F] = { .flags = 0, .len = 2 },      /* MOV direct,Rn */
884         [0x85] = { .flags = 0, .len = 3 },      /* MOV direct,direct */
885         [0x86] = { .flags = 0, .len = 2 },      /* MOV direct,@Ri */
886         [0x87] = { .flags = 0, .len = 2 },      /* MOV direct,@Ri */
887         [0x75] = { .flags = 0, .len = 3 },      /* MOV direct,#data */
888         
889         [0xF6] = { .flags = 0, .len = 1 },      /* MOV @Ri,A */
890         [0xF7] = { .flags = 0, .len = 1 },      /* MOV @Ri,A */
891         [0xA6] = { .flags = 0, .len = 2 },      /* MOV @Ri,direct */
892         [0xA7] = { .flags = 0, .len = 2 },      /* MOV @Ri,direct */
893         [0x76] = { .flags = 0, .len = 2 },      /* MOV @Ri,#data */
894         [0x77] = { .flags = 0, .len = 2 },      /* MOV @Ri,#data */
895         
896
897         [0x90] = { .flags = 0, .len = 3 },      /* MOV DPTR,#data16 */
898         
899         [0x93] = { .flags = 0, .len = 1 },      /* MOVC A,@A+DPTR */
900         [0x83] = { .flags = 0, .len = 1 },      /* MOVC A,@A+PC */
901         
902         [0xE2] = { .flags = 0, .len = 1 },      /* MOVX A,@Ri */
903         [0xE3] = { .flags = 0, .len = 1 },      /* MOVX A,@Ri */
904         [0xE0] = { .flags = 0, .len = 1 },      /* MOVX A,@DPTR */
905         [0xF2] = { .flags = 0, .len = 1 },      /* MOVX @Ri,A */
906         [0xF3] = { .flags = 0, .len = 1 },      /* MOVX @Ri,A */
907         [0xF0] = { .flags = 0, .len = 1 },      /* MOVX @DPTR,A */
908
909         [0xC0] = { .flags = 0, .len = 2 },      /* PUSH direct */
910         [0xD0] = { .flags = 0, .len = 2 },      /* POP direct */
911         [0xF5] = { .flags = 0, .len = 2 },      /* MOV direct,A */
912         [0xF5] = { .flags = 0, .len = 2 },      /* MOV direct,A */
913         [0xF5] = { .flags = 0, .len = 2 },      /* MOV direct,A */
914         [0xF5] = { .flags = 0, .len = 2 },      /* MOV direct,A */
915
916         [0xC8] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
917         [0xC9] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
918         [0xCA] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
919         [0xCB] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
920         [0xCC] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
921         [0xCD] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
922         [0xCE] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
923         [0xCF] = { .flags = 0, .len = 1 },      /* XCH A,Rn */
924         [0xC5] = { .flags = 0, .len = 2 },      /* XCH A,direct */
925         [0xC6] = { .flags = 0, .len = 1 },      /* XCH A,@Ri */
926         [0xC7] = { .flags = 0, .len = 1 },      /* XCH A,@Ri */
927         [0xD6] = { .flags = 0, .len = 1 },      /* XCHD A,@Ri */
928         [0xD7] = { .flags = 0, .len = 1 },      /* XCHD A,@Ri */
929
930         [0x11] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
931         [0x31] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
932         [0x51] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
933         [0x71] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
934         [0x91] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
935         [0xb1] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
936         [0xd1] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
937         [0xf1] = { .flags = IS_CALL, .len = 2 },        /* ACALL addr11 */
938         [0x12] = { .flags = IS_CALL, .len = 3 },        /* LCALL addr16 */      
939         
940         [0x22] = { .flags = IS_RET, .len = 1 },         /* RET */       
941         [0x32] = { .flags = IS_RET, .len = 1 },         /* RETI */      
942         
943         [0x01] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
944         [0x21] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
945         [0x41] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
946         [0x61] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
947         [0x81] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
948         [0xa1] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
949         [0xc1] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
950         [0xe1] = { .flags = IS_BRANCH, .len = 2 },      /* AJMP addr11 */
951         [0x02] = { .flags = IS_BRANCH, .len = 3 },      /* LJMP addr16 */
952         
953         [0x80] = { .flags = IS_BRANCH, .len = 2 },      /* SJMP rel */
954         
955         [0x73] = { .flags = IS_BRANCH, .len = 1 },      /* JMP @A+DPTR */
956         
957         [0x60] = { .flags = IS_BRANCH, .len = 2 },      /* JZ rel */
958         [0x70] = { .flags = IS_BRANCH, .len = 2 },      /* JNZ rel */
959         [0x40] = { .flags = IS_BRANCH, .len = 2 },      /* JC rel */
960         [0x50] = { .flags = IS_BRANCH, .len = 2 },      /* JNC rel */
961         [0x20] = { .flags = IS_BRANCH, .len = 3 },      /* JB bit,rel */
962         [0x30] = { .flags = IS_BRANCH, .len = 3 },      /* JNB bit,rel */
963         [0x10] = { .flags = IS_BRANCH, .len = 3 },      /* JBC bit,direct rel */
964         
965         [0xB5] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE A,direct rel */
966         [0xB4] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE A,#data rel */
967         [0xB8] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
968         [0xB9] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
969         [0xBA] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
970         [0xBB] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
971         [0xBC] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
972         [0xBD] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
973         [0xBE] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
974         [0xBF] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE Rn,#data rel */
975         [0xB6] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE @Ri,direct rel */
976         [0xB7] = { .flags = IS_BRANCH, .len = 3 },      /* CJNE @Ri,direct rel */
977         
978         [0xD8] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
979         [0xD9] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
980         [0xDA] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
981         [0xDB] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
982         [0xDC] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
983         [0xDD] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
984         [0xDE] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
985         [0xDF] = { .flags = IS_BRANCH, .len = 2 },      /* DNJZ Rn,rel */
986         [0xD5] = { .flags = IS_BRANCH, .len = 3 },      /* DNJZ direct,rel */
987
988         [0x00] = { .flags = 0, .len = 1 },              /* NOP */
989
990         [0xC3] = { .flags = 0, .len = 1 },              /* CLR C */
991         [0xC2] = { .flags = 0, .len = 2 },              /* CLR bit */
992         [0xD3] = { .flags = 0, .len = 1 },              /* SETB C */
993         [0xD2] = { .flags = 0, .len = 2 },              /* SETB bit */
994         
995         [0xB3] = { .flags = 0, .len = 1 },              /* CPL C */
996         [0xB2] = { .flags = 0, .len = 2 },              /* CPL bit */
997         
998         [0x82] = { .flags = 0, .len = 2 },              /* ANL C,bit */
999         [0xB0] = { .flags = 0, .len = 2 },              /* ANL C,/bit */
1000         [0x72] = { .flags = 0, .len = 2 },              /* ORL C,bit */
1001         [0xA0] = { .flags = 0, .len = 2 },              /* ORL C,/bit */
1002         
1003         [0xA2] = { .flags = 0, .len = 2 },              /* MOV C,bit */
1004         [0x92] = { .flags = 0, .len = 2 },              /* MOV bit,C */
1005         
1006         [0xA5] = { .flags = 0, .len = 1 },              /* TRAP */
1007 };
1008
1009 #define RET     0x22
1010 #define RETI    0x32
1011
1012 #define PUSH            0xC0
1013 #define POP             0xD0
1014 #define MOV_direct_A    0xF5
1015 #define MOV_A_direct    0xE5
1016 #define ADD_A_imm       0x24
1017 #define SP              0x81
1018 #define RET             0x22
1019 #define RETI            0x32
1020 #define LJMP_addr16     0x02
1021 #define SJMP_rel        0x80
1022
1023 static int stack_change(unsigned addr)
1024 {
1025         unsigned char insn;
1026         unsigned char direct;
1027
1028         insn = simGetValue(addr, 'C', 1);
1029         switch (insn) {
1030         case PUSH:
1031                 return 1;
1032         case POP:
1033                 return -1;
1034         case MOV_direct_A:
1035                 direct = simGetValue(addr+1, 'C', 1);
1036                 if (direct == SP) {
1037                         unsigned char   add_insn;
1038                         unsigned char   add_direct;
1039
1040                         add_insn = simGetValue(addr-2, 'C', 1);
1041                         if (add_insn == ADD_A_imm) {
1042                                 add_direct = simGetValue(addr-1, 'C', 1);
1043                                 return (signed char) add_direct;
1044                         }
1045                 }
1046                 break;
1047         case RET:
1048                 return 0;
1049         case RETI:
1050                 return 1;
1051         default:
1052                 return 0;
1053         }
1054 }
1055
1056 static void
1057 do_indent(int indent);
1058
1059 #if 1
1060 #define DPC(x)
1061 #else
1062 #define DPC(x)  do { do_indent(indent); printf x; } while (0);
1063 #endif
1064
1065 static int pc_change(unsigned addr, unsigned addrs[2], int indent)
1066 {
1067         unsigned char insn;
1068         unsigned new_addr;
1069         signed char delta;
1070         int len;
1071
1072         insn = simGetValue(addr, 'C', 1);
1073         if (instructions[insn].flags & IS_RET)
1074                 return 0;
1075
1076         if (!(instructions[insn].flags & IS_BRANCH)) {
1077                 addrs[0] = addr + instructions[insn].len;
1078                 return 1;
1079         }
1080
1081         if (insn == LJMP_addr16) {
1082                 addrs[0] = ((simGetValue(addr+1, 'C', 1) << 8) |
1083                           (simGetValue(addr+2, 'C', 1)));
1084                 DPC(("0x%04x LJMP 0x%04x\n", addr, addrs[0]));
1085                 return 1;
1086         }
1087         
1088         /* AJMP */
1089         if ((insn & 0x1f) == 0x01) {
1090                 unsigned char   direct = simGetValue(addr+1,'C', 1);
1091
1092                 addrs[0] = ((addr + 2) & 0xf800) | ((insn & 0xe0) << 3) | direct;
1093                 DPC(("0x%04x AJMP 0x%04x\n", addr, addrs[0]));
1094                 return 1;
1095         }
1096
1097         /* otherwise, relative branch */
1098         len = instructions[insn].len;
1099
1100         delta = (signed char) simGetValue(addr+len-1, 'C', 1);
1101         new_addr = (addr + len) + delta;
1102         
1103         if (insn == SJMP_rel || (addr + len) == new_addr) {
1104                 addrs[0] = new_addr;
1105                 DPC(("0x%04x SJMP 0x%04x\n", addr, addrs[0]));
1106                 return 1;
1107         }
1108         addrs[0] = (addr + len) & 0xffff;
1109         addrs[1] = new_addr & 0xffff;
1110
1111         DPC(("0x%04x SJMP 0x%04x 0x%04x\n", addr, addrs[0], addrs[1]));
1112         return 2;
1113 }
1114
1115 #define SEARCH_LOOP     0x8000
1116 #define SEARCH_EXPIRED  0x8001
1117
1118 #define MAX_STACK_BRANCH_TRACE  8192
1119 static unsigned stack_branch_trace[MAX_STACK_BRANCH_TRACE];
1120
1121 static int
1122 been_here(unsigned pc, int ntrace)
1123 {
1124         int t;
1125         
1126         for (t = 0; t < ntrace; t++)
1127                 if (stack_branch_trace[t] == pc)
1128                         return 1;
1129         return 0;
1130 }
1131
1132 #define MAX_SEARCH      100
1133
1134 #define indent (MAX_SEARCH - search)
1135
1136 static int
1137 stack_depth(unsigned pc, int search, int ntrace)
1138 {
1139         unsigned new_pc[2];
1140         int d[2];
1141         int n;
1142         int s;
1143         int change;
1144
1145         change = 0;
1146         for (;;) {
1147                 change += stack_change(pc);
1148                 n = pc_change(pc, new_pc, MAX_SEARCH - search);
1149                 if (n == 0)
1150                         return change;
1151                 if (n != 1)
1152                         break;
1153                 if (new_pc[0] <= pc) {
1154                         if (been_here(pc, ntrace)) {
1155                                 DPC(("0x%04x loop 1\n", pc));
1156                                 return SEARCH_LOOP;
1157                         }
1158                         stack_branch_trace[ntrace++] = pc;
1159                 }
1160                 pc = new_pc[0];
1161         }
1162         
1163         if (search == 0) {
1164                 DPC(("0x%04x max depth\n", pc));
1165                 return SEARCH_EXPIRED;
1166         }
1167         
1168         if (been_here(pc, ntrace))
1169         {
1170                 DPC(("0x%04x loop 2\n", pc));
1171                 return SEARCH_LOOP;
1172         }
1173         stack_branch_trace[ntrace++] = pc;
1174
1175         for (s = 0; s < search - 1; s++) {
1176                 int i, j, d;
1177                 
1178                 i = 0;
1179                 while (i < n) {
1180                         d = stack_depth(new_pc[i], search-1, ntrace);
1181                         if (d == SEARCH_LOOP) {
1182                                 for (j = i; j < n-1; j++)
1183                                         new_pc[j] = new_pc[j+1];
1184                                 n--;
1185                                 continue;
1186                         }
1187                         if (d != SEARCH_EXPIRED) {
1188                                 DPC(("success %d\n", d + change));
1189                                 return d + change;
1190                         }
1191                         i++;
1192                 }
1193                 if (n == 0) {
1194                         DPC(("0x%04x loop 3\n", pc));
1195                         return SEARCH_LOOP;
1196                 }
1197         }
1198         DPC(("search expired\n"));
1199         return SEARCH_EXPIRED;
1200 }
1201
1202 #undef indent
1203
1204 unsigned int
1205 stack_start(void)
1206 {
1207         symbol *start_stack = symLookup("__start_stack", NULL);
1208         if (start_stack)
1209                 return start_stack->addr;
1210         return 0x8;
1211 }
1212
1213 static int
1214 frameStart(unsigned int *bpp, unsigned int *pcp)
1215 {
1216         unsigned int bp;
1217         unsigned int sp;
1218         unsigned int pc;
1219         int depth;
1220         symbol *bp_sym;
1221
1222         pc = simGetPC();
1223         sp = simGetValue(0x81,'I',1);
1224         depth = stack_depth(pc, MAX_SEARCH, 0);
1225         if (depth == SEARCH_LOOP || depth == SEARCH_EXPIRED)
1226                 bp = 0;
1227         else
1228                 bp = sp + depth;
1229         *bpp = bp;
1230         *pcp = pc;
1231         return 1;
1232 }
1233
1234 static int
1235 frameNext(unsigned int *bpp, unsigned int *pcp)
1236 {
1237         unsigned int bp = *bpp;
1238         unsigned int pc;
1239         int depth;
1240         symbol *start_stack;
1241
1242         if (bp < stack_start())
1243                 return 0;
1244         pc = simGetValue(bp - 1, 'B', 2);
1245         if (pc == 0xffff)
1246                 return 0;
1247         depth = stack_depth(pc, MAX_SEARCH, 0);
1248         if (depth == SEARCH_LOOP || depth == SEARCH_EXPIRED)
1249                 bp = 0;
1250         else
1251                 bp = bp - 2 + depth;
1252         *bpp = bp;
1253         *pcp = pc;
1254         return 1;
1255 }
1256
1257 static int running = 0;
1258
1259 static int is_running(void) {
1260     return running;
1261 }
1262
1263 static int set_running(int run) {
1264     running = run;
1265 }
1266
1267 /*-----------------------------------------------------------------*/
1268 /* simGo - send 'go' cmd to simulator and wait till a break occurs */
1269 /*-----------------------------------------------------------------*/
1270 void simGo (unsigned int gaddr)
1271 {
1272     unsigned int addr ;
1273     context *ctxt;
1274     int rv;
1275     stopCommandList();
1276  top:
1277     if ( userinterrupt )
1278     {
1279         userinterrupt = 0;
1280         return;
1281     }
1282 #if 0
1283     if ( gaddr == 0 )
1284     {
1285         function *func = NULL;;
1286         if (applyToSet(functions,funcInAddr,gaddr,&func))
1287             STACK_PUSH(callStack,func);
1288     }
1289 #endif
1290     addr = simGoTillBp (gaddr);
1291
1292     /* got the pc for the break point now first
1293        discover the program context i.e. module, function
1294        linenumber of the source etc, etc etc */
1295     currentFrame = 0;
1296     ctxt = discoverContext (addr, NULL, currCtxt);
1297
1298     /* dispatch all the break point call back functions */
1299     rv = dispatchCB (addr,ctxt);
1300
1301     /* the dispatch call back function will return
1302        non-zero if an user break point has been hit
1303        if not then we continue with the execution
1304        of the program */
1305     if (!rv)
1306     {
1307         if ( gaddr == 0 )
1308             gaddr = -1;
1309         if ( gaddr == -1 || doingSteps == 1 )
1310             goto top ;
1311     }
1312
1313 }
1314
1315 /*-----------------------------------------------------------------*/
1316 /* preparePrint - common parse function for  set variable,         */
1317 /*                output, print and display                        */
1318 /*-----------------------------------------------------------------*/
1319 static char *preparePrint(char *s, context *cctxt, int *fmt, symbol **sym)
1320 {
1321     char *bp;
1322     char save_ch ;
1323     int ptr = 0;
1324
1325     *fmt = FMT_NON;
1326     *sym = NULL;
1327
1328     s = trim(s);
1329     if (!*s)
1330         return (char *)0;
1331
1332     if ( *s == '/' )
1333     {
1334         /* format of printout */
1335         switch ( *++s )
1336         {
1337             case 'x':
1338                 *fmt = FMT_HEX ;
1339                 break;
1340             case 'o':
1341                 *fmt = FMT_OCT ;
1342                 break;
1343             default:
1344             case 'd':
1345                 *fmt = FMT_DEZ ;
1346                 break;
1347             case 't':
1348                 *fmt = FMT_BIN ;
1349                 break;
1350         }
1351         s++;
1352         s = trim_left(s);
1353     }
1354     while (*s == '*') {
1355         ptr++;
1356         s++;
1357     }
1358     for ( bp = s; *bp && ( isalnum( *bp ) || *bp == '_' || *bp == '$'); bp++ );
1359     save_ch = *bp;
1360     if ( *bp )
1361         *bp = '\0';
1362
1363     if ( *s )
1364         *sym = symLookup(s,cctxt);
1365     *bp = save_ch;
1366     while (ptr--)
1367         strcat(bp,"*");
1368
1369     if ( ! *sym )
1370         fprintf(stdout,"No symbol \"%s\" in current context.\n", s);
1371     return bp;
1372 }
1373
1374 static int printAsmLine( function *func, module *m, unsigned saddr, unsigned eaddr)
1375 {
1376     int i,j,delta;
1377     unsigned symaddr;
1378     unsigned lastaddr = saddr+1;
1379     char *symname;
1380
1381     if ( func )
1382     {
1383         symaddr = func->sym->addr;
1384         symname = func->sym->name;
1385     }
1386     else
1387     {
1388         symaddr = saddr;
1389         symname = "" ;
1390     }
1391     for (j=0,i=0; i < m->nasmLines; i++ )
1392     {
1393         if ( saddr >= 0 && m->asmLines[i]->addr < saddr)
1394         {
1395                 continue;
1396         }
1397         if ( eaddr >= 0 && m->asmLines[i]->addr > eaddr)
1398         {
1399                 continue;
1400         }
1401         if ( func &&
1402             (m->asmLines[i]->addr < func->sym->addr ||
1403              m->asmLines[i]->addr > func->sym->eaddr ))
1404         {
1405             continue;
1406         }
1407         delta = m->asmLines[i]->addr - symaddr;
1408         if ( delta >= 0 )
1409         {
1410             j++;
1411             lastaddr = m->asmLines[i]->addr;
1412             printf("0x%08x <%s",lastaddr,symname);
1413             if (delta > 0) printf("+%d",delta);
1414             printf(">:\t%s",m->asmLines[i]->src);
1415         }
1416     }
1417     return lastaddr;
1418 }
1419
1420 /*-----------------------------------------------------------------*/
1421 /* cmdDisasm - disassemble  asm instruction                        */
1422 /*-----------------------------------------------------------------*/
1423 static int cmdDisasm (char *s, context *cctxt, int args)
1424 {
1425     function *func = NULL;
1426     long  saddr = -1;
1427     long  eaddr = -1;
1428     int   found = 0;
1429     module *modul;
1430     /* white space skip */
1431
1432     if ( args > 0 )
1433     {
1434         s = trim_left(s);
1435
1436         if ( isdigit(*s))
1437         {
1438             saddr = strtol(s,&s,0);
1439             if ( args > 1 )
1440             {
1441                 s = trim_left(s);
1442
1443                 if ( isdigit(*s))
1444                     eaddr = strtol(s,0,0);
1445             }
1446             else
1447                 eaddr = saddr+1;
1448         }
1449     }
1450
1451     if ( eaddr == -1 )
1452     {
1453         /* no start or only start so dump function */
1454         if ( saddr == -1 )
1455         {
1456             func = cctxt->func;
1457         }
1458         else
1459         {
1460             applyToSet(functions,funcInAddr,saddr,&func);
1461         }
1462         if ( func )
1463         {
1464             printf("Dump of assembler code for function %s:\n",func->sym->name);
1465             printAsmLine(func,func->mod,-1,-1);
1466             printf("End of assembler dump.\n");
1467             return 0;
1468         }
1469         else
1470         {
1471             if (applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
1472             {
1473                 eaddr = saddr + 5;
1474                 printf("Dump of assembler code:\n");
1475                 printAsmLine(NULL,modul,saddr,eaddr);
1476                 printf("End of assembler dump.\n");
1477                 return 0;
1478             }
1479         }
1480     }
1481     else
1482     {
1483         if ( args > 1 )
1484             printf("Dump of assembler code from 0x%08lx to 0x%08lx:\n",saddr,eaddr);
1485         found = 0;
1486         while ( saddr < eaddr )
1487         {
1488             func = NULL;
1489             if (applyToSet(functions,funcInAddr,saddr,&func))
1490             {
1491                 found = 1;
1492                 modul = func->mod;
1493             }
1494             else
1495             {
1496                 if ( found )
1497                     break;
1498                 if (!applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
1499                     break;
1500             }
1501             saddr = printAsmLine(func,modul,saddr,eaddr) + 1;
1502         }
1503         if( saddr >= eaddr)
1504         {
1505             if ( args > 1 )
1506                 printf("End of assembler dump.\n");
1507             return 0;
1508         }
1509
1510     }
1511     fprintf(stderr,"No function contains specified address.\n");
1512     if( saddr >= 0 )
1513     {
1514         char lbuf[64];
1515         sprintf(lbuf,"dis 0x%lx 0 %ld\n",saddr,( eaddr == -1 )?1L:eaddr-saddr);
1516         sendSim(lbuf);
1517         waitForSim(1000, NULL);
1518         fputs(simResponse(),stdout);
1519     }
1520     return 0;
1521 }
1522 /*-----------------------------------------------------------------*/
1523 /* cmdDisasm1 - disassemble one asm instruction                    */
1524 /*-----------------------------------------------------------------*/
1525 int cmdDisasm1 (char *s, context *cctxt)
1526 {
1527     return cmdDisasm( s, cctxt, 1);
1528 }
1529
1530 /*-----------------------------------------------------------------*/
1531 /* cmdDisasmF - disassemble asm instructions                       */
1532 /*-----------------------------------------------------------------*/
1533 int cmdDisasmF(char *s, context *cctxt)
1534 {
1535     return cmdDisasm( s, cctxt, 2);
1536 }
1537
1538 static int commonSetUserBp(char *s, context *cctxt, char bpType)
1539 {
1540     char *bp ;
1541     function *func = NULL;
1542
1543     /* user break point location specification can be of the following
1544        forms
1545        a) <nothing>        - break point at current location
1546        b) lineno           - number of the current module
1547        c) filename:lineno  - line number of the given file
1548        e) filename:function- function X in file Y (useful for static functions)
1549        f) function         - function entry point
1550        g) *addr            - break point at address
1551     */
1552
1553     if (!cctxt) {
1554         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
1555         return 0;
1556     }
1557     /* trim left and right */
1558     s = trim(s);
1559
1560     /* case a) nothing */
1561     /* if nothing given then current location : we know
1562        the current execution location from the currentContext */
1563     if (! *s ) {
1564
1565         /* if current context is known */
1566         if (cctxt->func) {
1567         Dprintf(D_break, ("commonSetUserBp: a) cctxtaddr:%x \n",cctxt->addr));
1568             if (srcMode == SRC_CMODE)
1569                 /* set the break point */
1570                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
1571                                 cctxt->func->mod->c_name, cctxt->cline);
1572             else
1573                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
1574                                 cctxt->func->mod->asm_name, cctxt->asmline);
1575
1576         }
1577         else
1578             fprintf(stderr,"No default breakpoint address now.\n");
1579
1580         goto ret ;
1581     }
1582     /* case g) *addr */
1583     if ( *s == '*' && isdigit(*(s+1)))
1584     {
1585         int  line   = 0;
1586         long braddr = strtol(s+1,0,0);
1587         if (!applyToSet(functions,funcInAddr,braddr,&func))
1588         {
1589             module *modul;
1590             if (!applyToSet(modules,moduleLineWithAddr,braddr,&modul,&line))
1591             {
1592                 fprintf(stderr,"Address 0x%08lx not exists in code.\n",braddr);
1593             }
1594             else
1595             {
1596                 Dprintf(D_break, ("commonSetUserBp: g) addr:%lx \n",braddr));
1597                 setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1598                             modul->c_name,line);
1599             }
1600             goto ret ;
1601         }
1602                 else
1603         {
1604             int line = func->exitline;
1605             if ( !applyToSet(func->cfpoints,lineAtAddr,braddr,
1606                                   &line,NULL,NULL))
1607                 applyToSet(func->cfpoints,lineNearAddr,braddr,&line,NULL,NULL);
1608             setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1609                             func->mod->c_name,line);
1610         }
1611         goto ret ;
1612     }
1613     /* case b) lineno */
1614     /* check if line number */
1615     if ( !strchr(s,':') && isdigit(*s)) {
1616         /* get the lineno */
1617         int line = atoi(s) -1;
1618     Dprintf(D_break, ("commonSetUserBp: b) line:%d \n",line));
1619     if ( line < 0 )
1620     {
1621                 fprintf(stdout,"linenumber <= 0\n");
1622         goto ret;
1623     }
1624         /* if current context not present then we must get the module
1625            which has main & set the break point @ line number provided
1626            of that module : if current context known then set the bp
1627            at the line number given for the current module
1628         */
1629         if (cctxt->func) {
1630             if (!cctxt->func->mod) {
1631                 if (!applyToSet(functions,funcWithName,"main"))
1632                     fprintf(stderr,"Function \"main\" not defined.\n");
1633                 else
1634                     setBPatModLine(func->mod,line, bpType);
1635             } else
1636                 setBPatModLine(cctxt->func->mod,line, bpType);
1637         } else {
1638                 if (list_mod) {
1639                         setBPatModLine(list_mod,line, bpType);
1640                 } else {
1641                   fprintf(stdout,"Sdcdb fails to have module symbol context at %d\n", __LINE__);
1642                 }
1643         }
1644
1645         goto ret;
1646     }
1647
1648     if ((bp = strchr(s,':'))) {
1649
1650         module *mod = NULL;
1651         *bp = '\0';
1652
1653         if (srcMode == SRC_CMODE) {
1654             if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1655                 fprintf (stderr,"No source file named %s.\n",s);
1656                 goto ret;
1657             }
1658         } else {
1659             if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
1660                 fprintf (stderr,"No source file named %s.\n",s);
1661                 goto ret;
1662             }
1663         }
1664
1665         /* case c) filename:lineno */
1666         if (isdigit(*(bp +1))) {
1667         Dprintf(D_break, ("commonSetUserBp: c) line:%d \n",atoi(bp+1)));
1668             setBPatModLine (mod,atoi(bp+1)-1,bpType);
1669             goto ret;
1670
1671         }
1672         /* case d) filename:function */
1673         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func))
1674             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1);
1675         else
1676         Dprintf(D_break, ("commonSetUserBp: d) \n"));
1677             setBPatModLine (mod,
1678                             (srcMode == SRC_CMODE ?
1679                              func->entryline :
1680                              func->aentryline),bpType);
1681
1682         goto ret;
1683     }
1684
1685     /* case e) function */
1686     Dprintf(D_break, ("commonSetUserBp: e) \n"));
1687     if (!applyToSet(functions,funcWithName,s,&func))
1688         fprintf(stderr,"Function \"%s\" not defined.\n",s);
1689     else
1690         setBPatModLine(func->mod,
1691                        (srcMode == SRC_CMODE ?
1692                         func->entryline :
1693                         func->aentryline),bpType);
1694
1695  ret:
1696     return 0;
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* cmdSetTmpUserBp - settempory break point at the user specified location   */
1701 /*-----------------------------------------------------------------*/
1702 int cmdSetTmpUserBp (char *s, context *cctxt)
1703 {
1704     return commonSetUserBp(s, cctxt, TMPUSER );
1705 }
1706
1707 /*-----------------------------------------------------------------*/
1708 /* cmdSetUserBp - set break point at the user specified location   */
1709 /*-----------------------------------------------------------------*/
1710 int cmdSetUserBp (char *s, context *cctxt)
1711 {
1712     return commonSetUserBp(s, cctxt, USER );
1713 }
1714
1715 /*-----------------------------------------------------------------*/
1716 /* cmdJump - set program counter                                   */
1717 /*-----------------------------------------------------------------*/
1718 int cmdJump (char *s, context *cctxt)
1719 {
1720     char *bp;
1721     function *func = NULL;
1722     if (!is_running())
1723     {
1724         fprintf(stdout,"The program is not running.\n");
1725         return 0;
1726     }
1727
1728     /* trim left and right */
1729     s = trim(s);
1730
1731     if (! *s )
1732     {
1733         fprintf(stdout,"No argument: need line or *addr.\n");
1734         return 0;
1735     }
1736     if ( *s == '*' && isdigit(*(s+1)))
1737     {
1738         unsigned int addr = atoi(s);
1739         if (cctxt && cctxt->func &&
1740             cctxt->func->sym->addr <= addr &&
1741             cctxt->func->sym->eaddr >= addr)
1742         {
1743             simSetPC(addr);
1744             return 0;
1745         }
1746         fprintf(stdout,"Warning addr 0x%x outside actual function.\n",addr);
1747         simSetPC(addr);
1748         return 0;
1749     }
1750     if (isdigit(*s))
1751     {
1752         /* get the lineno */
1753         int line = atoi(s) -1;
1754         if (!cctxt || !cctxt->func || !cctxt->func->mod)
1755         {
1756                     fprintf(stderr,"Function not defined.\n");
1757             return 0;
1758         }
1759         if (line >= cctxt->func->entryline &&
1760             line <= cctxt->func->exitline )
1761         {
1762             simSetPC(cctxt->func->mod->cLines[line]->addr);
1763             return 0;
1764         }
1765         if (line >= cctxt->func->mod->ncLines )
1766         {
1767                     fprintf(stderr,"line not in module.\n");
1768             return 0;
1769         }
1770         fprintf(stdout,"Warning line %d outside actual function.\n",line+1);
1771         simSetPC(cctxt->func->mod->cLines[line]->addr);
1772         return 0;
1773     }
1774     if ((bp = strchr(s,':')))
1775     {
1776         int line;
1777         module *mod = NULL;
1778         *bp++ = '\0';
1779         if (!applyToSet(modules,moduleWithCName,s,&mod))
1780         {
1781             fprintf (stderr,"No source file named %s.\n",s);
1782             return 0;
1783         }
1784         if (!isdigit(*bp))
1785         {
1786             fprintf (stderr,"No line number.\n");
1787             return 0;
1788         }
1789         line = atoi(bp) -1;
1790         if (line >= mod->ncLines )
1791         {
1792                     fprintf(stderr,"line not in module.\n");
1793             return 0;
1794         }
1795         if ( mod != cctxt->func->mod ||
1796              line < cctxt->func->entryline ||
1797              line > cctxt->func->exitline )
1798         {
1799             fprintf(stdout,"Warning line %d outside actual function.\n",
1800                     line+1);
1801         }
1802         simSetPC(mod->cLines[line]->addr);
1803     }
1804     return 0;
1805 }
1806
1807 /*-----------------------------------------------------------------*/
1808 /* cmdListAsm - list assembler source code                         */
1809 /*-----------------------------------------------------------------*/
1810 int cmdListAsm (char *s, context *cctxt)
1811 {
1812     if (  cctxt && cctxt->func)
1813     {
1814         /* actual line */
1815         if ( cctxt->addr != INT_MAX )
1816         {
1817             if (printAsmLine(cctxt->func,cctxt->func->mod,
1818                          (long)cctxt->addr,(long)cctxt->addr))
1819             return 0;
1820         }
1821     }
1822     return 0;
1823 }
1824
1825 /*-----------------------------------------------------------------*/
1826 /* cmdSetOption - set debugger options                             */
1827 /*-----------------------------------------------------------------*/
1828 int cmdSetOption (char *s, context *cctxt)
1829 {
1830     s = trim_left(s);
1831     if (strncmp(s,"srcmode",7) == 0 ) {
1832         if (srcMode == SRC_CMODE)
1833             srcMode = SRC_AMODE;
1834         else
1835             srcMode = SRC_CMODE;
1836         fprintf(stderr,"source mode set to '%s'\n",
1837                 (srcMode == SRC_CMODE ? "C" : "asm"));
1838         return 0;
1839     }
1840
1841     if (strncmp(s,"listsize ",9) == 0)
1842     {
1843         listlines = strtol(s+9,0,0);
1844         if ( listlines < LISTLINES )
1845             listlines = LISTLINES;
1846         return 0;
1847     }
1848
1849 #ifdef SDCDB_DEBUG
1850     if (strncmp(s,"debug ",6) == 0)
1851     {
1852         sdcdbDebug = strtol(s+6,0,0);
1853         return 0;
1854     }
1855 #endif
1856     if (strncmp(s,"variable ",9) == 0)
1857     {
1858         symbol *sym ;
1859         int fmt;
1860         char *rs;
1861         s += 9;
1862         if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
1863             return 0;
1864         s = rs;
1865         while (*s && *s != '=') s++;
1866         *s++ = '\0';
1867         s = trim_left(s);
1868         if (*s && sym)
1869         {
1870             printOrSetSymValue(sym,cctxt,0,0,0,rs,s,'\0');
1871             return 0;
1872         }
1873         else
1874             fprintf(stdout,"No new value for \"%s\".\n",s);
1875         return 0;
1876     }
1877
1878
1879     fprintf(stderr,"'set %s' command not yet implemented\n",s);
1880     return 0;
1881 }
1882
1883 /*-----------------------------------------------------------------*/
1884 /* cmdContinue - continue till next break point                    */
1885 /*-----------------------------------------------------------------*/
1886 int cmdContinue (char *s, context *cctxt)
1887 {
1888     if (!is_running()) {
1889         fprintf(stdout,"The program is not being run.\n");
1890         return 0;
1891     }
1892
1893     fprintf(stdout,"Continuing.\n");
1894     simGo(-1);
1895     showfull = 1;
1896     return 0;
1897 }
1898
1899 /*-----------------------------------------------------------------*/
1900 /* cmdIgnore - set ignorecount for breakpoint                      */
1901 /*-----------------------------------------------------------------*/
1902 int cmdIgnore (char *s, context *cctxt)
1903 {
1904     int bpnum, cnt ;
1905     s = trim_left(s);
1906     if (!*s )
1907     {
1908         fprintf(stdout,"Argument required (breakpoint number).\n");
1909         return 0;
1910     }
1911     bpnum = strtol(s,&s,10);
1912     s = trim_left(s);
1913     if (!*s )
1914     {
1915         fprintf(stdout,"Second argument (specified ignore-count) is missing.");
1916         return 0;
1917     }
1918     cnt = strtol(s,0,10);
1919     setUserbpIgnCount(bpnum,cnt);
1920     return 0;
1921 }
1922
1923 /*-----------------------------------------------------------------*/
1924 /* cmdCondition - set condition for breakpoint                     */
1925 /*-----------------------------------------------------------------*/
1926 int cmdCondition (char *s, context *cctxt)
1927 {
1928     int bpnum ;
1929     s = trim_left(s);
1930     if (!*s )
1931     {
1932         fprintf(stdout,"Argument required (breakpoint number).\n");
1933         return 0;
1934     }
1935     bpnum = strtol(s,&s,10);
1936     s = trim_left(s);
1937     if (*s)
1938         s = Safe_strdup(s);
1939     else
1940         s = NULL;
1941     setUserbpCondition(bpnum,s);
1942     return 0;
1943 }
1944
1945 /*-----------------------------------------------------------------*/
1946 /* cmdCommands - set commands for breakpoint                       */
1947 /*-----------------------------------------------------------------*/
1948 int cmdCommands (char *s, context *cctxt)
1949 {
1950     int bpnum ;
1951     char *cmds,*line;
1952     s = trim_left(s);
1953
1954     if (!*s )
1955         bpnum = getLastBreakptNumber();
1956     else
1957         bpnum = strtol(s,0,10);
1958
1959     cmds = NULL;
1960     while ((line = getNextCmdLine()))
1961     {
1962         line = trim_left(line);
1963         if (!strncmp(line,"end",3))
1964             break;
1965         if (! cmds )
1966         {
1967             cmds = Safe_strdup(line);
1968         }
1969         else
1970         {
1971             cmds = Safe_realloc( cmds, strlen(cmds) + 1 + strlen(line));
1972             strcat(cmds,line);
1973         }
1974     }
1975     setUserbpCommand(bpnum,cmds);
1976     return 0;
1977 }
1978
1979 /*-----------------------------------------------------------------*/
1980 /* cmdDelUserBp - delete user break point                          */
1981 /*-----------------------------------------------------------------*/
1982 int cmdDelUserBp (char *s, context *cctxt)
1983 {
1984     int bpnum ;
1985     s = trim_left(s);
1986
1987     if (!*s ) {
1988         if (userBpPresent) {
1989             char buffer[10];
1990             fprintf (stdout,"Delete all breakpoints? (y or n) ");
1991             fflush(stdout);
1992             fgets(buffer,sizeof(buffer),stdin);
1993             if (toupper(buffer[0]) == 'Y')
1994                 deleteUSERbp(-1);
1995         }
1996         return 0;
1997     }
1998
1999     /* determine the break point number */
2000     if (sscanf(s,"%d",&bpnum) == 1)
2001         deleteUSERbp(bpnum);
2002
2003     return 0;
2004 }
2005
2006 /*-----------------------------------------------------------------*/
2007 /* cmdStepi - single step exactly one instruction                   */
2008 /*-----------------------------------------------------------------*/
2009 int cmdStepi (char *s, context *cctxt)
2010 {
2011
2012     if (!is_running())
2013         fprintf(stdout,"The program is not being run.\n");
2014     else
2015     {
2016         doingSteps = 2;
2017             simGo(2);
2018         doingSteps = 0;
2019         showfull = 1;
2020     }
2021     return 0;
2022 }
2023
2024 static unsigned line_start_addr(context *ctx, int line)
2025 {
2026         function *func = ctx->func;
2027         module *mod = func->mod;
2028         unsigned addr;
2029         int nlines;
2030         
2031         if (srcMode == SRC_CMODE)
2032                 nlines = mod->ncLines;
2033         else
2034                 nlines = mod->nasmLines;
2035
2036         do {
2037                 if (srcMode == SRC_CMODE)
2038                         addr = mod->cLines[line]->addr;
2039                 else
2040                         addr = mod->asmLines[line]->addr;
2041                 ++line;
2042         } while (addr == 0x7fffffff && line < nlines);
2043         if (addr == 0x7fffffff)
2044                 addr = func->sym->eaddr;
2045         return addr;
2046 }
2047
2048 static unsigned line_end_addr(context *ctx, int line)
2049 {
2050         function *func = ctx->func;
2051         module *mod = func->mod;
2052         int next_line, nlines;
2053         unsigned start_addr = line_start_addr(ctx, line);
2054         unsigned next_addr = func->sym->eaddr + 1;
2055         unsigned addr;
2056
2057         if (srcMode == SRC_CMODE)
2058                 nlines = mod->ncLines;
2059         else
2060                 nlines = mod->nasmLines;
2061         for (next_line = 0; next_line < nlines; next_line++) {
2062                 if (next_line == line)
2063                         continue;
2064                 if (srcMode == SRC_CMODE)
2065                         addr = mod->cLines[next_line]->addr;
2066                 else
2067                         addr = mod->asmLines[next_line]->addr;
2068                 if (start_addr < addr && addr < next_addr)
2069                         next_addr = addr;
2070         }
2071         return next_addr;
2072 }
2073
2074 BP_CALLBACK(step_bp_callback)
2075 {
2076         deleteSTEPbp();
2077         return 1;
2078 }
2079
2080 static int do_step(context *ctx, int into)
2081 {
2082         function *func = ctx->func;
2083         module *mod = func->mod;
2084         srcLine **lines;
2085         srcLine *line;
2086         int     nlines;
2087         int     start, end;
2088         int     start_l;
2089         unsigned len;
2090         unsigned start_addr, end_addr, addr;
2091         unsigned char insn;
2092         unsigned char flags;
2093         
2094         if (srcMode == SRC_CMODE) {
2095                 lines = mod->cLines;
2096                 nlines = mod->ncLines;
2097                 start_l = ctx->cline;
2098         } else {
2099                 lines = mod->asmLines;
2100                 nlines = mod->nasmLines;
2101                 start_l = ctx->asmline;
2102         }
2103         if (start_l == -1)
2104                 return 0;
2105         flags = IS_BRANCH|IS_RET;
2106         if (into)
2107                 flags |= IS_CALL;
2108         line = lines[start_l];
2109         start = line_start_addr(ctx, start_l);
2110         end = line_end_addr(ctx, start_l);
2111
2112         while (start <= ctx->addr && ctx->addr < end) {
2113                 insn = 0xff;
2114                 for (addr = ctx->addr; addr < end; addr += len) {
2115                         insn = simGetValue(addr, 'C', 1);
2116                         if (instructions[insn].flags & flags)
2117                                 break;
2118                         len = instructions[insn].len;
2119                         if (len == 0) {
2120                                 fprintf(stderr, "Unknown opcode 0x%02x\n", insn);
2121                                 return 0;
2122                         }
2123                 }
2124                 if (addr != ctx->addr) {
2125                         setBreakPoint(addr, CODE, STEP,
2126                                       step_bp_callback,
2127                                       mod->name, start_l);
2128                         doingSteps = 1;
2129                         /* run to breakpoint */
2130                         simGo(-1);
2131                         doingSteps = 0;
2132                 }
2133                 /* step over instruction at breakpoint */
2134                 if (start <= ctx->addr && ctx->addr < end) {
2135                         doingSteps = 2;
2136                         simGo(2);
2137                         doingSteps = 0;
2138                 }
2139         }
2140         stepBpCB(ctx->addr, NULL, ctx);
2141         showfull = 1;
2142 }
2143
2144 /*-----------------------------------------------------------------*/
2145 /* cmdStep - single step thru C source file                        */
2146 /*-----------------------------------------------------------------*/
2147 int cmdStep (char *s, context *cctxt)
2148 {
2149     function *func = NULL;
2150
2151     if (!is_running())
2152         fprintf(stdout,"The program is not being run.\n");
2153     else
2154         do_step(cctxt, 1);
2155     return 0;
2156 }
2157
2158 /*-----------------------------------------------------------------*/
2159 /* cmdNexti - next instruction but proceed function call           */
2160 /*-----------------------------------------------------------------*/
2161 int cmdNexti (char *s, context *cctxt)
2162 {
2163     if (!is_running())
2164         fprintf(stdout,"The program is not being run.\n");
2165     else
2166     {
2167         doingSteps = 2;
2168             simGo(1);
2169         doingSteps = 0;
2170         showfull = 1;
2171     }
2172     return 0;
2173 }
2174
2175 /*-----------------------------------------------------------------*/
2176 /* cmdNext - next executable C statement file                      */
2177 /*-----------------------------------------------------------------*/
2178 int cmdNext (char *s, context *cctxt)
2179 {
2180     function *func = NULL;
2181     /* next is almost the same as step except we don't
2182        we don't set break point for all function entry
2183        points */
2184     if (!is_running())
2185         fprintf(stdout,"The program is not being run.\n");
2186     else
2187         do_step(cctxt, 0);
2188     return 0;
2189 }
2190
2191 /*-----------------------------------------------------------------*/
2192 /* cmdRun  - run till next break point                             */
2193 /*-----------------------------------------------------------------*/
2194 int cmdRun (char *s, context *cctxt)
2195 {
2196     char buff[10];
2197
2198     if (!is_running()) {
2199         fprintf(stdout,"Starting program\n");
2200     if ( ! simactive )
2201     {
2202         fprintf(stdout,"No executable file specified.\nUse the \"file\" command.\n");
2203         return 0;
2204     }
2205     resetHitCount();
2206         simGo(0);
2207     } else {
2208
2209         fprintf(stdout,
2210                 "The program being debugged has been started already.\n");
2211         fprintf(stdout,"Start it from the beginning? (y or n) ");
2212         fflush(stdout);
2213
2214         fgets(buff,sizeof(buff),stdin);
2215         if (toupper(buff[0]) == 'Y') {
2216             simReset();
2217         resetHitCount();
2218             simGo(0);
2219         }
2220     }
2221     showfull = 1;
2222     set_running(1);
2223     return 0;
2224 }
2225
2226 /*-----------------------------------------------------------------
2227  cmdListSymbols - list symbols
2228 |-----------------------------------------------------------------*/
2229 int cmdListSymbols (char *s, context *cctxt)
2230 {
2231     int our_verbose = 0;
2232     symbol *sy;
2233     int i;
2234
2235     if (strstr(s, "v1")) {
2236       our_verbose = 1;
2237     } else if (strstr(s, "v2")) {
2238       our_verbose = 2;
2239     }
2240
2241     printf("[symbols]\n");
2242     sy = setFirstItem(symbols);
2243     i = 0;
2244     for (;;) {
2245       if (sy == NULL)
2246         break;
2247       if (our_verbose <= 1)
2248         printf("<%s>", sy->name);
2249
2250       if (our_verbose > 1) {
2251         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
2252           sy->name, sy->size, sy->level, sy->block);
2253         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
2254           sy->isonstack, sy->isfunc, sy->offset, sy->addr);
2255         printf("    eaddr:%d, addr_type:%c, type:%p etype:%p\n",
2256           sy->eaddr, sy->addr_type, sy->type, sy->etype);
2257         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
2258           sy->scopetype, sy->sname, sy->rname, sy->addrspace);
2259         printf("    next:%p\n", sy->next);
2260       }
2261       ++i;
2262       sy = setNextItem(symbols);
2263     }
2264     printf("   %d symbols\n", i);
2265     return 0;
2266 }
2267
2268 /*-----------------------------------------------------------------
2269  cmdListFunctions - list functions.
2270 |-----------------------------------------------------------------*/
2271 int cmdListFunctions (char *s, context *cctxt)
2272 {
2273     function *f;
2274     int i;
2275     int our_verbose = 0;
2276
2277     if (strstr(s, "v1")) {
2278       our_verbose = 1;
2279     } else if (strstr(s, "v2")) {
2280       our_verbose = 2;
2281     }
2282
2283     printf("[functions]\n");
2284     f = setFirstItem(functions);
2285     i = 0;
2286     while (f != NULL) {
2287       if (our_verbose) {
2288         printf("  %d) sym:%p, fname:%s, modName:%s, mod:%p\n", i,
2289           f->sym, f->sym->name, f->modName, f->mod);
2290         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
2291                 f->entryline, f->aentryline, f->exitline, f->aexitline);
2292         printf("    cfpoints:%p, afpoints:%p, laddr:%x, lline:%d\n",
2293                 f->cfpoints, f->afpoints, f->laddr, f->lline);
2294       }
2295       else {
2296         printf("<%s>", f->sym->name);
2297       }
2298       ++i;
2299       f = setNextItem(functions);
2300     }
2301     printf("   %d functions\n", i);
2302     return 0;
2303 }
2304
2305 /*-----------------------------------------------------------------
2306  cmdListModules - list modules.
2307 |-----------------------------------------------------------------*/
2308 int cmdListModules (char *s, context *cctxt)
2309 {
2310     module *m;
2311     srcLine *cs, *as;
2312     int i, mi;
2313     int our_verbose = 0;
2314
2315     if (strstr(s, "v1")) {
2316       our_verbose = 1;
2317     } else if (strstr(s, "v2")) {
2318       our_verbose = 2;
2319     }
2320
2321     printf("[modules]\n");
2322     m = setFirstItem(modules);
2323     mi = 0;
2324     for (;;) {
2325       if (m == NULL)
2326         break;
2327
2328       if (our_verbose >= 0) {
2329       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
2330         m->cfullname, m->afullname, m->name);
2331       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
2332               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
2333       printf("    cLines:%p, asmLines:%p\n",
2334               m->cLines, m->asmLines);
2335       }
2336       if (our_verbose >= 2) {
2337         if (m->ncLines) {
2338           printf("    [cLines] ");
2339           if ( our_verbose)
2340           for (i=0; i<m->ncLines; i++ ) {
2341               cs = m->cLines[i];
2342               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2343                  i, cs->addr, cs->block, cs->level, cs->src);
2344           }
2345           if (!our_verbose)
2346               printf("%d records", i);
2347         }
2348         if (m->nasmLines) {
2349           printf("    [asmLines] ");
2350           if ( our_verbose)
2351           for (i=0; i<m->nasmLines; i++ ) {
2352               as = m->asmLines[i];
2353               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2354                  i, as->addr, as->block, as->level, as->src);
2355           }
2356           if (!our_verbose)
2357               printf("%d records", i);
2358         }
2359         printf("\n");
2360       }
2361
2362       m = setNextItem(modules);
2363     }
2364     return 0;
2365 }
2366
2367 /*-----------------------------------------------------------------
2368  infoSymbols - This is really just a tool to dump all these
2369    huge program structures out into human readable form.
2370 |-----------------------------------------------------------------*/
2371 static void infoSymbols(context *ctxt)
2372 {
2373   int our_verbose = 0;
2374
2375   printf("[context:%p] func:%p modName:%s addr:%x\n",
2376     ctxt, ctxt->func, ctxt->modName, ctxt->addr);
2377
2378   printf("  cline:%d asmline:%d block:%d level:%d\n",
2379     ctxt->cline, ctxt->asmline, ctxt->block, ctxt->level);
2380
2381   printf("[globals] currCtxt:%p, modules:%p, functions:%p symbols:%p\n",
2382     currCtxt, modules, functions, symbols);
2383   printf("  nStructs:%d, structs:%p, ssdirl:%s\n",
2384     nStructs, structs, ssdirl);
2385
2386   /**************** modules *******************/
2387   {
2388     module *m;
2389     srcLine *cs, *as;
2390     int i, mi;
2391     printf("[modules]\n");
2392     m = setFirstItem(modules);
2393     mi = 0;
2394     for (;;) {
2395       if (m == NULL)
2396         break;
2397       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
2398         m->cfullname, m->afullname, m->name);
2399       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
2400               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
2401       printf("    cLines:%p, asmLines:%p\n",
2402               m->cLines, m->asmLines);
2403       i = 0;
2404       if (m->cLines) {
2405         cs = m->cLines[i++];
2406         printf("    [cLines] ");
2407         while (cs) {
2408           if (our_verbose)
2409             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2410                i, cs->addr, cs->block, cs->level, cs->src);
2411           cs = m->cLines[i++];
2412         }
2413         if (!our_verbose)
2414             printf("%d records", i);
2415       }
2416       i = 0;
2417       if (m->asmLines) {
2418         as = m->asmLines[i++];
2419         printf("    [asmLines] ");
2420         while (as) {
2421           if (our_verbose)
2422             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2423                i, as->addr, as->block, as->level, as->src);
2424           as = m->asmLines[i++];
2425         }
2426         if (!our_verbose)
2427             printf("%d records", i);
2428       }
2429       printf("\n");
2430
2431       m = setNextItem(modules);
2432     }
2433   }
2434
2435   /**************** functions *******************/
2436   {
2437     function *f;
2438     int i;
2439     printf("[functions]\n");
2440     f = setFirstItem(functions);
2441     i = 0;
2442     for (;;) {
2443       if (f == NULL)
2444         break;
2445       if (our_verbose) {
2446         printf("  %d) sym:%p, modName:%s, mod:%p\n", i,
2447           f->sym, f->modName, f->mod);
2448         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
2449                 f->entryline, f->aentryline, f->exitline, f->aexitline);
2450         printf("    cfpoints:%p, afpoints:%p, laddr:%x, lline:%d\n",
2451                 f->cfpoints, f->afpoints, f->laddr, f->lline);
2452       }
2453       ++i;
2454       f = setNextItem(functions);
2455     }
2456     if (!our_verbose)
2457       printf("   %d functions\n", i);
2458   }
2459
2460   /**************** symbols *******************/
2461   {
2462     symbol *s;
2463     int i;
2464     printf("[symbols]\n");
2465     s = setFirstItem(symbols);
2466     i = 0;
2467     for (;;) {
2468       if (s == NULL)
2469         break;
2470       if (our_verbose) {
2471         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
2472           s->name, s->size, s->level, s->block);
2473         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
2474           s->isonstack, s->isfunc, s->offset, s->addr);
2475         printf("    eaddr:%d, addr_type:%c, type:%p etype:%p\n",
2476           s->eaddr, s->addr_type, s->type, s->etype);
2477         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
2478           s->scopetype, s->sname, s->rname, s->addrspace);
2479         printf("    next:%p\n", s->next);
2480       }
2481       ++i;
2482       s = setNextItem(symbols);
2483     }
2484     if (!our_verbose)
2485       printf("   %d symbols\n", i);
2486   }
2487
2488 }
2489
2490 /*-----------------------------------------------------------------*/
2491 /* infoRegisters - print register information                      */
2492 /*-----------------------------------------------------------------*/
2493 static void infoRegisters( int all, context *ctxt)
2494 {
2495     static int regaddrs[] = {0x81,0x82,0x83,0xb8,0xd0,0xe0,0xf0,0};
2496     unsigned long val;
2497     int i,j,*r;
2498
2499     i = simGetValue (0xd0,'I',1);
2500     fprintf(stdout,"IP  : 0x%04X  RegisterBank %d:\nR0-7:",ctxt->addr,(i>>3)&3);
2501     for ( j = 0; j < 8 ; j++ )
2502     {
2503         val = simGetValue (j,'R',1);
2504         fprintf(stdout," 0x%02lX",val);
2505     }
2506     fprintf(stdout,"\n");
2507     val = simGetValue (0xe0,'I',1);
2508     fprintf(stdout,"ACC : 0x%02lX %lu %c\n",val,val,(isprint(val) ? (char)val : '.'));
2509     val = simGetValue (0xf0,'I',1);
2510     fprintf(stdout,"B   : 0x%02lX %lu %c\n",val,val,(isprint(val) ? (char)val : '.'));
2511     val = simGetValue (0x82,'I',2);
2512     fprintf(stdout,"DPTR: 0x%04lX %lu\n",val,val);
2513     val = simGetValue (0x81,'I',1);
2514     fprintf(stdout,"SP  : 0x%02lX (0x%04lX)\n",val,simGetValue (val-1,'B',2));
2515     fprintf(stdout,"PSW : 0x%02X | CY : %c | AC : %c | OV : %c | P : %c\n",
2516             i,(i&0x80)?'1':'0',(i&0x40)?'1':'0',(i&4)?'1':'0',(i&1)?'1':'0');
2517     if ( all )
2518     {
2519         fprintf(stdout,"Special Function Registers:\n");
2520         r = regaddrs;
2521         for ( i = 0x80 ; i < 0x100 ; i++ )
2522         {
2523             symbol *sym = NULL;
2524             if ( *r && *r == i )
2525             {
2526                 /* skip normal registers */
2527                 r++ ;
2528                 continue;
2529             }
2530             if (applyToSetFTrue(sfrsymbols,symWithAddr,i,'I',&sym))
2531             {
2532                 val = simGetValue (sym->addr,sym->addrspace,sym->size);
2533                 fprintf(stdout,"%s : 0x%02lx",sym->name,val);
2534                 if ( !(i & 0x07 ))
2535                 {
2536                     for ( j = 0 ; j < 8 ; j++ )
2537                     {
2538                         sym = NULL;
2539                         if (applyToSetFTrue(sfrsymbols,symWithAddr,i+j,'J',&sym))
2540                         {
2541                             //val = simGetValue (sym->addr,sym->addrspace,sym->size);
2542                             fprintf(stdout," %s=%c",sym->name,(val&1)? '1':'0');
2543                         }
2544                         val >>= 1;
2545                     }
2546                 }
2547                 fprintf(stdout,"\n");
2548             }
2549         }
2550     }
2551 }
2552
2553 /*-----------------------------------------------------------------*/
2554 /* infoStack - print call stack information                        */
2555 /*-----------------------------------------------------------------*/
2556 static void infoStack(context *ctxt)
2557 {
2558     function *func ;
2559     int i = 0 ;
2560     context *ctx, my_context;
2561     unsigned int bp, pc, addr = ctxt->addr;
2562     int status;
2563
2564     for (status = frameStart(&bp,&pc); status; status = frameNext(&bp, &pc)) {
2565         ctx = discoverContext(pc, NULL, &my_context);
2566         if (ctx) {
2567             func = ctx->func;
2568         Dprintf(D_break, ("break: infoStack: %s 0x%02x\n",func->sym->name, bp));
2569     
2570             fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",i++,
2571                     pc,func->sym->name,
2572                     func->mod->c_name,func->lline+1);
2573         } else {
2574             fprintf(stdout,"#%d  0x%08x\n", i++, pc);
2575         }
2576     }
2577     if ( !i )
2578         fprintf(stdout,"no stack.\n");
2579 }
2580
2581 /*-----------------------------------------------------------------*/
2582 /* cmdWhere -  where command                                       */
2583 /*-----------------------------------------------------------------*/
2584 int cmdWhere(char *s, context *cctxt)
2585 {
2586         infoStack(cctxt);
2587         return 0;
2588 }
2589
2590
2591 static int infomode = 0;
2592 /*-----------------------------------------------------------------*/
2593 /* cmdInfo - info command                                          */
2594 /*-----------------------------------------------------------------*/
2595 int cmdInfo (char *s, context *cctxt)
2596 {
2597     /* trim left and_right*/
2598     s = trim(s);
2599
2600     /* list all break points */
2601     if (strncmp(s,"break",5) == 0) {
2602         listUSERbp();
2603         return 0;
2604     }
2605
2606     /* info frame same as frame */
2607     if (strncmp(s,"frame",5) == 0) {
2608         cmdFrame (s+5,cctxt);
2609         return 0;
2610     }
2611
2612     if (strncmp(s,"line",4) == 0) {
2613         infomode=1;
2614         cmdListSrc (s+4,cctxt);
2615         return 0;
2616     }
2617     if (strncmp(s,"source",6) == 0)
2618     {
2619         module *m;
2620         if ( s[6] == 's' )
2621         {
2622             int k = 0;
2623             fprintf(stdout,"Source files for which symbols have been read in:\n\n");
2624             for (m = setFirstItem(modules); m ; m = setNextItem(modules))
2625             {
2626                 fprintf(stdout,"%s%s, %s",k ? ", ":"",m->cfullname, m->afullname);
2627                 k = 1;
2628             }
2629             fprintf(stdout,"\n");
2630         }
2631         else
2632         {
2633             if (!cctxt || !cctxt->func || !cctxt->func->mod)
2634             {
2635                 fprintf(stdout,"No source file loaded\n");
2636                 return 0;
2637             }
2638             m = cctxt->func->mod;
2639             fprintf(stdout,"Current source file is %s\n",m->c_name);
2640             fprintf(stdout,"Located in %s\n",m->cfullname);
2641             fprintf(stdout,"Contains %d lines.\nSource language is c.\n",
2642                     m->ncLines);
2643         }
2644         return 0;
2645     }
2646     if (strcmp(s,"functions") == 0)
2647     {
2648         function *f;
2649         module *m = NULL;
2650         fprintf(stdout,"All defined functions:\n");
2651         for ( f = setFirstItem(functions); f ; f = setNextItem(functions))
2652         {
2653             if ( f->mod != m )
2654             {
2655                 m = f->mod;
2656                 fprintf(stdout,"\nFile %s\n", m->c_name);
2657             }
2658             fprintf(stdout,"%s();\n",f->sym->name);
2659         }
2660         return 0;
2661     }
2662     /* info stack display call stack */
2663     if (strcmp(s,"stack") == 0) {
2664         infoStack(cctxt);
2665         showfull = 1;
2666         return 0;
2667     }
2668
2669     /* info stack display call stack */
2670     if (strcmp(s,"registers") == 0) {
2671         infoRegisters(0,cctxt);
2672             return 0;
2673     }
2674
2675     /* info stack display call stack */
2676     if (strcmp(s,"all-registers") == 0)
2677     {
2678         infoRegisters(1,cctxt);
2679         return 0;
2680     }
2681
2682     /* info stack display call stack */
2683     if (strcmp(s,"symbols") == 0) {
2684       /* dump out symbols we have read in */
2685       fprintf(stdout,"Dumping symbols...\n");
2686       infoSymbols(cctxt);
2687       return 0;
2688     }
2689
2690     if (strcmp(s,"variables") == 0) {
2691       /* dump out symbols we have read in */
2692       fprintf(stdout,"Dumping symbols...\n");
2693       infoSymbols(cctxt);
2694       return 0;
2695     }
2696
2697     fprintf(stdout,"Undefined info command: \"%s\".  Try \"help\n",s);
2698     return 0;
2699
2700 }
2701
2702 /*-----------------------------------------------------------------*/
2703 /* cmdQuit  - quit debugging                                       */
2704 /*-----------------------------------------------------------------*/
2705 int cmdQuit (char *s, context *cctxt)
2706 {
2707     if (simactive)
2708         closeSimulator();
2709     return 1;
2710 }
2711
2712 /*-----------------------------------------------------------------*/
2713 /* cmdListSrc  - list src                                          */
2714 /*-----------------------------------------------------------------*/
2715 int cmdListSrc (char *s, context *cctxt)
2716 {
2717     static int currline = 0;
2718     int i =0 ;
2719     int pline = 0;
2720     int llines = listlines;
2721     function *func = NULL;
2722
2723
2724     s = trim_left(s);
2725
2726     /* if the user has spcified line numer then the line number
2727        can be of the following formats
2728        LINE          - just line number
2729        FILE:LINE     - filename line number
2730        FILE:LINE,LASTLINE  + last line
2731        FUNCTION      - list a function
2732        FILE:FUNCTION - function in file */
2733
2734     if (*s) {
2735         /* case a) LINE */
2736         if (isdigit(*s)) {
2737             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2738               if (!list_mod) {
2739                 fprintf(stdout,"Sdcdb fails to have a proper context at %d.\n", __LINE__);
2740                 return 0;
2741               }
2742             }
2743             else
2744               list_mod = cctxt->func->mod;
2745         pline = strtol(s,&s,10) - 1;
2746         if (s && (s = strchr(s,',')))
2747         {
2748             /* LINE,LASTLINE */
2749             llines = strtol(s+1,0,10);
2750             if ( llines > 0 )
2751                 llines -= pline+1;
2752             else
2753                 llines = listlines;
2754         }
2755         }
2756         else {
2757             char *bp;
2758
2759             /* if ':' present then FILE:LINE || FILE:FUNCTION */
2760             if ((bp = strchr(s,':'))) {
2761                 *bp = '\0';
2762                 bp ++;
2763                 if (isdigit(*bp)) {
2764                     /* FILE:LINE */
2765                     list_mod=NULL;  /* bug fix 2-09-02, moduleWithCName expects mod to be null */
2766                     if (srcMode == SRC_CMODE) {
2767                         if (!applyToSet(modules,moduleWithCName,s,&list_mod)) {
2768                             fprintf (stderr,"No c source file named %s.\n",s);
2769                             return 0;
2770                         }
2771                     } else {
2772                         if (!applyToSet(modules,moduleWithAsmName,s,&list_mod)) {
2773                             fprintf (stderr,"No source file named %s.\n",s);
2774                             return 0;
2775                         }
2776                     }
2777                     pline = strtol(bp,&bp,10) - 1;
2778             if (bp && (bp = strchr(bp,',')))
2779             {
2780                 /* FILE:LINE,LASTLINE */
2781                 llines = strtol(bp+1,0,10);
2782                 if ( llines > 0 )
2783                     llines -= pline+1;
2784                 else
2785                     llines = listlines;
2786             }
2787                 } else {
2788                     /* FILE:FUCTION */
2789                     if (!applyToSet(functions,funcWithNameModule,bp,s,&func)) {
2790                         fprintf(stdout,"Function \"%s\" not defined.\n",bp);
2791                         return 0;
2792                     }
2793                     list_mod = func->mod;
2794                     if (srcMode == SRC_CMODE) {
2795                         pline = func->entryline;
2796                         llines = func->exitline - func->entryline + 1;
2797                     } else {
2798                         pline = func->aentryline;
2799                         llines = func->aexitline - func->aentryline + 1;
2800                     }
2801                 }
2802             }
2803             else {
2804                 /* FUNCTION */
2805             if (*s == '\'')
2806             {
2807                 /* 'FUNCTION' */
2808                 s++ ;
2809                 if ((bp = strrchr(s,'\'')))
2810                 {
2811                     *bp = '\0';
2812                 }
2813
2814             }
2815                 if (!applyToSet(functions,funcWithName,s,&func)) {
2816                     fprintf(stderr,"Function \"%s\" not defined.\n",s);
2817                     return 0;
2818                 }
2819                 else {
2820                     list_mod = func->mod;
2821                     if (srcMode == SRC_CMODE) {
2822                         pline = func->entryline;
2823                         llines = func->exitline - func->entryline + 1;
2824                     } else {
2825                         pline = func->aentryline;
2826                         llines = func->aexitline - func->aentryline + 1;
2827                     }
2828                 }
2829             }
2830         }
2831     } else {
2832         /* if no line specified & we had listed
2833            before then continue from that listing */
2834         if (currline)
2835             pline = currline ;
2836         else {
2837             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2838               fprintf(stdout,"Missing context at %d. Try list filename:lineno\n", __LINE__);
2839               return 0;
2840             }
2841             list_mod = cctxt->func->mod;
2842             if (srcMode == SRC_CMODE)
2843                 pline = cctxt->cline;
2844             else
2845                 pline = cctxt->asmline;
2846         }
2847     }
2848
2849     if (!list_mod) {
2850       fprintf(stdout,"Sdcdb fails to have a valid module context at %d.\n", __LINE__);
2851       return 0;
2852     }
2853
2854     if ( pline < 0 )
2855         return 0;
2856     if ( infomode )
2857     {
2858         unsigned firstaddr , lastaddr ;
2859             if ( pline  >= list_mod->ncLines )
2860             pline = cctxt->cline;
2861         firstaddr = lastaddr = list_mod->cLines[pline]->addr;
2862         if (!func && cctxt && cctxt->func )
2863             func = cctxt->func;
2864             fprintf(stdout,"Line %d of \"%s\" starts at address 0x%08x <%s+%d>",
2865                 pline+1,
2866                 list_mod->c_name, lastaddr,
2867                 func ? func->sym->name : "?",
2868                 func ? lastaddr -func->sym->addr : 0);
2869         llines = pline +1;
2870         for ( ; pline < list_mod->ncLines; pline++ )
2871         {
2872             if ( list_mod->cLines[pline]->addr > lastaddr )
2873             {
2874                 lastaddr = list_mod->cLines[pline]->addr -1;
2875                 break;
2876             }
2877         }
2878         fprintf(stdout," and ends at 0x%08x <%s+%d>.\n",
2879                 lastaddr,
2880                 func ? func->sym->name : "?",
2881                 func ? lastaddr -func->sym->addr : 0);
2882         infomode=0;
2883         if ( func )
2884             fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
2885                     canonname(func->mod->cfullname),
2886                     llines,firstaddr);
2887         else
2888             showfull=1;
2889         return 0;
2890     }
2891     for ( i = 0 ; i < llines ; i++ ) {
2892         if (srcMode == SRC_CMODE) {
2893             if ( (pline + i) >= list_mod->ncLines )
2894                 break;
2895             fprintf(stdout,"%d\t%s",pline + i,
2896                     list_mod->cLines[pline +i]->src);
2897         } else {
2898             if ( (pline + i) >= list_mod->nasmLines )
2899                 break;
2900             fprintf(stdout,"%d\t%s",pline + i,
2901                     list_mod->asmLines[pline +i]->src);
2902         }
2903     }
2904     currline = pline + i ;
2905     return 0;
2906 }
2907
2908 static unsigned long getValBasic(symbol *sym, link *type, char *val)
2909 {
2910     char *s;
2911     union
2912     {
2913         float f;
2914         unsigned long val;
2915         long         sval;
2916         struct {
2917             unsigned short    lo;
2918             unsigned short    hi;
2919         } i;
2920         unsigned char b[4];
2921     }v;
2922
2923     if (IS_FLOAT(type))
2924         v.f = strtod(val,NULL);
2925     else
2926         if (IS_PTR(type))
2927             v.val = strtol(val,NULL,0);
2928         else
2929     {
2930             if (IS_INTEGRAL(type))
2931         {
2932             link *etype;
2933             if ( type->next )
2934                 etype = type->next;
2935             else
2936                 etype = type;
2937             if (IS_CHAR(etype))
2938             {
2939                 if (( s = strchr(val,'\'')))
2940                 {
2941                     if ( s[1] == '\\' )
2942                         v.b[0] = strtol(s+2,NULL,8);
2943                     else
2944                         v.b[0] = s[1];
2945                 }
2946                 else
2947                 {
2948                     v.b[0] = strtol(val,NULL,0);
2949                 }
2950             }
2951             else
2952                 if (IS_INT(etype))
2953                     if (IS_LONG(etype))
2954                         v.val = strtol(val,NULL,0);
2955                     else
2956                         v.i.lo = strtol(val,NULL,0);
2957                 else
2958                     v.val = strtol(val,NULL,0);
2959             }
2960         else
2961             v.val = strtol(val,NULL,0);
2962     }
2963     return v.val;
2964 }
2965
2966 /*-----------------------------------------------------------------*/
2967 /* printFmtInteger - print value in bin,oct,dez or hex             */
2968 /*-----------------------------------------------------------------*/
2969 static void printFmtInteger(char *deffmt,int fmt, long val,
2970                             int sign, int size)
2971 {
2972     static char digits[] =
2973     {
2974         '0' , '1' , '2' , '3' , '4' , '5' ,
2975         '6' , '7' , '8' , '9' , 'a' , 'b' ,
2976         'c' , 'd' , 'e' , 'f' , 'g' , 'h'
2977     };
2978     static int radixOfFormat[] = { 0 , 2, 8 ,10, 16  };
2979     static int olenOfSize[]    = { 0 , 3, 6 , 8, 11  };
2980         char buf[40];
2981         char negative = 0;
2982         int charPos = 38;
2983     int radix;
2984
2985     if ( fmt == FMT_NON || fmt == FMT_DEZ )
2986     {
2987         fprintf(stdout,deffmt,val);
2988         return;
2989     }
2990     radix = radixOfFormat[fmt];
2991
2992     /*
2993     if ( sign && val < 0 )
2994         negative = 1;
2995     */
2996
2997         if (!negative)
2998             val = -val;
2999
3000         buf[39] = '\0';
3001     while (val <= -radix)
3002     {
3003             buf[charPos--] = digits[-(val % radix)];
3004             val = val / radix;
3005         }
3006         buf[charPos] = digits[-val];
3007
3008     switch ( fmt )
3009     {
3010         case FMT_OCT:
3011             radix = olenOfSize[size];
3012             break;
3013         case FMT_HEX:
3014             radix = size << 1;
3015             break;
3016         case FMT_BIN:
3017             radix = size << 3;
3018             break;
3019     }
3020
3021     while (charPos > 39 - radix )
3022     {
3023         buf[--charPos] = '0';
3024     }
3025     switch ( fmt )
3026     {
3027         case FMT_OCT:
3028             if ( buf[charPos] != '0' )
3029                 buf[--charPos] = '0';
3030             break;
3031         case FMT_HEX:
3032             buf[--charPos] = 'x';
3033             buf[--charPos] = '0';
3034             break;
3035     }
3036         if (negative) {
3037             buf[--charPos] = '-';
3038         }
3039     fputs(&buf[charPos],stdout);
3040 }
3041
3042 /*-----------------------------------------------------------------*/
3043 /* printValBasic - print value of basic types                      */
3044 /*-----------------------------------------------------------------*/
3045 static void printValBasic(symbol *sym, link *type,
3046                           char mem, unsigned addr,int size, int fmt)
3047 {
3048     union {
3049         float f;
3050         unsigned long val;
3051         long         sval;
3052         struct {
3053             unsigned short    lo;
3054             unsigned short    hi;
3055         } i;
3056         unsigned char b[4];
3057     }v;
3058
3059     v.val = simGetValue(addr,mem,size);
3060     /* if this a floating point number then */
3061     if (IS_FLOAT(type))
3062         fprintf(stdout,"%f",v.f);
3063     else
3064         if (IS_PTR(type))
3065             fprintf(stdout,"0x%0*lx",size<<1,v.val);
3066         else
3067         if (IS_INTEGRAL(type))
3068         {
3069             link *etype;
3070             if ( type->next )
3071                 etype = type->next;
3072             else
3073                 etype = type;
3074             if (IS_CHAR(etype))
3075             {
3076                 if ( isprint(v.val))
3077                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'%c'"),
3078                                     fmt,(long)v.val,0,size);
3079                 else
3080                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'\\%o'"),
3081                                     fmt,(long)v.val,0,size);
3082             }
3083             else
3084             {
3085                 if (IS_INT(etype))
3086                     if (IS_LONG(etype))
3087                         if (SPEC_USIGN(etype))
3088                             printFmtInteger("%u",fmt,(long)v.val,0,size);
3089                         else
3090                             printFmtInteger("%d",fmt,(long)v.sval,1,size);
3091                     else
3092                         if (SPEC_USIGN(etype))
3093                             printFmtInteger("%u",fmt,(long)v.i.lo,0,size);
3094                         else
3095                             printFmtInteger("%d",fmt,(long)v.i.lo,1,size);
3096                 else
3097                 {
3098                     if (IS_BITVAR(etype))
3099                         fprintf(stdout,"%c",(v.val?'1':'0'));
3100                     else
3101                         fprintf(stdout,"0x%0*lx",size<<1,v.val);
3102                 }
3103             }
3104             } else
3105             fprintf(stdout,"0x%0*lx",size<<1,v.val);
3106 }
3107
3108 /*-----------------------------------------------------------------*/
3109 /* printValFunc  - prints function values                          */
3110 /*-----------------------------------------------------------------*/
3111 static void printValFunc (symbol *sym, int fmt)
3112 {
3113     fprintf(stdout,"print function not yet implemented");
3114 }
3115
3116 static void
3117 do_indent(int indent) {
3118     while (indent--)
3119         fprintf(stdout, "  ");
3120
3121 }
3122
3123 /*-----------------------------------------------------------------*/
3124 /* printArrayValue - will print the values of array elements       */
3125 /*-----------------------------------------------------------------*/
3126 static void printArrayValue (symbol *sym,  link *type,
3127                              char space, unsigned int addr, int fmt,
3128                              int indent)
3129 {
3130     link *elem_type = type->next;
3131     int i;
3132     int col;
3133
3134     fprintf(stdout,"{");
3135     for (i = 0 ; i < DCL_ELEM(type) ; i++) {
3136         if (IS_AGGREGATE(elem_type)) {
3137             printValAggregates(sym,elem_type,space,addr,fmt,indent);
3138             col = 0;
3139         } else {
3140             printValBasic(sym,elem_type,space,addr,getSize(elem_type),fmt);
3141             col++;
3142         }
3143         addr += getSize(elem_type);
3144         if (i != DCL_ELEM(type) -1) {
3145             fprintf(stdout,",");
3146             if (col == 16) {
3147                 fprintf(stdout,"\n");
3148                 do_indent(indent);
3149                 col = 0;
3150             }
3151         }
3152     }
3153
3154     fprintf(stdout,"}");
3155 }
3156
3157 /*-----------------------------------------------------------------*/
3158 /* printStructValue - prints structures elements                   */
3159 /*-----------------------------------------------------------------*/
3160 static void printStructValue (symbol *sym, link *type,
3161                               char space, unsigned int addr, int fmt,
3162                               int indent)
3163 {
3164     symbol *fields = SPEC_STRUCT(type)->fields;
3165     int first = 1;
3166     do_indent (indent);
3167     fprintf(stdout,"{\n");
3168     while (fields) {
3169         do_indent(indent + 1);
3170         fprintf(stdout,"%s = ", fields->name);
3171         first = 0;
3172         if (IS_AGGREGATE(fields->type)) {
3173             printValAggregates(fields,fields->type,space, addr, fmt, indent + 1);
3174         } else {
3175             printValBasic(fields,fields->type,space,addr,getSize(fields->type), fmt);
3176         }
3177         fprintf(stdout,",\n");
3178         addr += getSize(fields->type);
3179         fields = fields->next;
3180     }
3181     do_indent(indent);
3182     fprintf(stdout,"}");
3183 }
3184
3185 /*-----------------------------------------------------------------*/
3186 /* printValAggregates - print value of aggregates                  */
3187 /*-----------------------------------------------------------------*/
3188 static void printValAggregates (symbol *sym, link *type,
3189                                 char space,unsigned int addr, int fmt,
3190                                 int indent)
3191 {
3192
3193         if (IS_ARRAY(type)) {
3194                 printArrayValue(sym, type, space, addr, fmt, indent);
3195                 return ;
3196         }
3197
3198         if (IS_STRUCT(type)) {
3199                 printStructValue(sym, type, space, addr, fmt, indent);
3200                 return;
3201         }
3202 }
3203
3204 /*-----------------------------------------------------------------*/
3205 /* printOrSetSymValue - print or set value of a symbol             */
3206 /*-----------------------------------------------------------------*/
3207 static int printOrSetSymValue (symbol *sym, context *cctxt,
3208                                 int flg, int dnum, int fmt, char *rs,
3209                                 char *val, char cmp )
3210 {
3211     static char fmtChar[] = " todx ";
3212     static int stack = 1;
3213         symbol *fields;
3214     link *type;
3215     unsigned int  addr;
3216     int size, n;
3217     char *s, *s2;
3218     char save_ch, save_ch2;
3219     int get_member = 0;
3220
3221     /* if it is on stack then compute address & fall thru */
3222     if (sym->isonstack)
3223     {
3224         symbol *bp = symLookup("bp",cctxt);
3225         if (!bp)
3226         {
3227             fprintf(stdout,"cannot determine stack frame\n");
3228             return 1;
3229         }
3230
3231         sym->addr = simGetValue(bp->addr,bp->addrspace,bp->size)
3232             + sym->offset ;
3233     }
3234
3235     /* get the value from the simulator and
3236        print it */
3237     switch (flg)
3238     {
3239         case 0:
3240         default:
3241             break;
3242         case 1:
3243             fprintf(stdout,"$%d = ",stack++);
3244             break;
3245         case 2:
3246             fprintf(stdout,"%d: ", dnum);
3247             if ( fmt != FMT_NON )
3248                 fprintf(stdout,"/%c ",fmtChar[fmt]);
3249             fprintf(stdout,"%s%s = ",sym->name,rs);
3250             break;
3251     }
3252
3253     addr = sym->addr;
3254     type = sym->type;
3255     size = sym->size;
3256
3257     while ( *rs )
3258     {
3259         if ( *rs == '[' && (IS_ARRAY(type) || IS_PTR(type)))
3260         {
3261             s = rs+1;
3262             while ( *rs && *rs != ']' ) rs++ ;
3263             save_ch = *rs;
3264             *rs = '\0' ;
3265             if ( ! isdigit(*s ))
3266             {
3267                 /* index seems a variable */
3268                 for ( s2 = s; *s2 && ( isalnum( *s2 ) || *s2 == '_'); s2++ );
3269                 save_ch2 = *s2;
3270                 if ( *s2 )
3271                     *s2 = '\0';
3272                 fields = symLookup(s,cctxt);
3273                 *s2 = save_ch2;
3274                 if ( ! fields )
3275                 {
3276                     fprintf(stdout,"Unknown variable \"%s\" for index.\n", s);
3277                     return 1;
3278                 }
3279                 /* arrays & structures first */
3280                 if (! IS_INTEGRAL(fields->type))
3281                 {
3282                     fprintf(stdout,"Wrong type of variable \"%s\" for index \n", s);
3283                     return 1;
3284                 }
3285                 n = simGetValue(fields->addr,fields->addrspace,getSize(fields->type));
3286             }
3287             else
3288             {
3289                 n = strtol(s,0,0);
3290             }
3291             if ( IS_ARRAY(type) && (n < 0 || n >= DCL_ELEM(type)))
3292             {
3293                 fprintf(stdout,"Wrong index %d.\n", n);
3294                 return 1;
3295             }
3296             if (IS_PTR(type))
3297                 addr = simGetValue(addr, sym->addrspace, size);
3298             type = type->next;
3299             size = getSize(type);
3300             addr += size * n;
3301             *rs++ = save_ch;
3302         }
3303         else if ( (*rs == '.' || get_member) && IS_STRUCT(type))
3304         {
3305             s = rs+1;
3306             /* search structure element */
3307             for ( rs = s; *rs && ( isalnum( *rs ) || *rs == '_'); rs++ );
3308             save_ch = *rs;
3309             if ( *rs )
3310                 *rs = '\0';
3311             for (fields = SPEC_STRUCT(type)->fields; fields; fields = fields->next)
3312             {
3313                 if (!(strcmp(s,fields->name)))
3314                     break;
3315             }
3316             *rs = save_ch;
3317             if ( ! fields )
3318             {
3319                 fprintf(stdout,"Unknown field \"%s\" of structure\n", s);
3320                 return 1;
3321             }
3322             type = fields->type;
3323             size = getSize(type);
3324             addr += fields->offset;
3325         }
3326         else if ( *rs == '*' && IS_PTR(type))
3327         {
3328             addr = simGetValue(addr, sym->addrspace, size);
3329             type = type->next;
3330             size = getSize(type);
3331             rs++;
3332         }
3333         else if ( rs[0] == '-' && rs[1] == '>' &&
3334                  IS_PTR(type) && IS_STRUCT(type->next))
3335         {
3336             addr = simGetValue(addr, sym->addrspace, size);
3337             type = type->next;
3338             size = getSize(type);
3339             rs++;
3340             get_member = 1;
3341             continue;
3342         }
3343         else
3344             break;
3345         get_member = 0;
3346     }
3347
3348     /* arrays & structures first */
3349     if (IS_AGGREGATE(type))
3350     {
3351             if ( val )
3352         {
3353             fprintf(stdout,"Cannot set/compare aggregate variable\n");
3354             return 1;
3355         }
3356         else
3357             printValAggregates(sym,type,sym->addrspace,addr,fmt,0);
3358     }
3359     else
3360         /* functions */
3361         if (IS_FUNC(type))
3362     {
3363             if ( !val )
3364             printValFunc(sym,fmt);
3365         else
3366             return 1;
3367     }
3368         else
3369     {
3370             if ( val )
3371         {
3372             unsigned long newval;
3373             newval = getValBasic(sym,type,val);
3374
3375             if ( cmp )
3376             {
3377                 unsigned long lval;
3378                 lval = simGetValue(addr,sym->addrspace,size);
3379                 switch ( cmp )
3380                 {
3381                     case '<' : return ( lval <  newval ? 1:0 ); break;
3382                     case '>' : return ( lval >  newval ? 1:0 ); break;
3383                     case 'l' : return ( lval <= newval ? 1:0 ); break;
3384                     case 'g' : return ( lval >= newval ? 1:0 ); break;
3385                     case '=' : return ( lval == newval ? 1:0 ); break;
3386                     case '!' : return ( lval != newval ? 1:0 ); break;
3387                 }
3388             }
3389             else
3390             {
3391                 if ( sym->addrspace == 'I' && addr == 0xb8 )
3392                 {
3393                     /* Symbol with address of IP */
3394                     if ( cctxt ) cctxt->addr = newval;
3395                     simSetPC(cctxt->addr);
3396                 }
3397                 else
3398                     simSetValue(addr,sym->addrspace,size,newval);
3399                 return 1;
3400             }
3401         }
3402         else
3403             printValBasic(sym,type,sym->addrspace,addr,size,fmt);
3404     }
3405     if ( flg > 0 ) fprintf(stdout,"\n");
3406         return 0;
3407 }
3408
3409 /*-----------------------------------------------------------------*/
3410 /* printStructInfo - print out structure information               */
3411 /*-----------------------------------------------------------------*/
3412 static void printStructInfo (structdef *sdef)
3413 {
3414     symbol *field = sdef->fields ;
3415     int i = 0 ;
3416
3417     while (field) {
3418         i += field->offset;
3419         field = field->next;
3420     }
3421
3422     fprintf(stdout,"%s %s {\n",(i ? "struct" : "union" ), sdef->tag);
3423     field = sdef->fields;
3424     while (field) {
3425         printTypeInfo (field->type);
3426         fprintf(stdout," %s ;\n",field->name);
3427         field = field->next ;
3428     }
3429
3430     fprintf(stdout,"}\n");
3431
3432 }
3433
3434 /*-----------------------------------------------------------------*/
3435 /* printTypeInfo - print out the type information                  */
3436 /*-----------------------------------------------------------------*/
3437 static void printTypeInfo(link *p)
3438 {
3439     if (!p)
3440         return ;
3441
3442     if (IS_DECL(p)) {
3443         switch (DCL_TYPE(p))  {
3444         case FUNCTION:
3445             printTypeInfo (p->next);
3446             fprintf(stdout,"()");
3447             break;
3448         case ARRAY:
3449             printTypeInfo (p->next);
3450             fprintf(stdout,"[%d]",DCL_ELEM(p));
3451             break;
3452
3453         case IPOINTER:
3454         case PPOINTER:
3455         case POINTER:
3456             printTypeInfo (p->next);
3457             fprintf(stdout,"(_near *)");
3458             break;
3459
3460         case FPOINTER:
3461             printTypeInfo (p->next);
3462             fprintf(stdout,"(_xdata *)");
3463             break;
3464
3465         case CPOINTER:
3466             printTypeInfo( p->next);
3467             fprintf(stdout,"(_code *)");
3468             break;
3469
3470         case GPOINTER:
3471             printTypeInfo( p->next);
3472             fprintf(stdout,"(_generic *)");
3473             break;
3474         }
3475     } else {
3476         switch (SPEC_NOUN(p)) { /* depending on the specifier type */
3477         case V_INT:
3478             (IS_LONG(p) ? fputs("long ",stdout) :
3479              ( IS_SHORT(p) ? fputs("short ",stdout) :
3480                fputs("int ",stdout))) ;
3481             break;
3482         case V_FLOAT:
3483              fputs("float ",stdout);
3484              break;
3485
3486         case V_CHAR:
3487             fputs ("char ",stdout);
3488             break;
3489
3490         case V_VOID:
3491             fputs("void ",stdout);
3492             break;
3493
3494         case V_STRUCT:
3495             printStructInfo (SPEC_STRUCT(p));
3496             break;
3497
3498         case V_SBIT:
3499             fputs("sbit ",stdout);
3500             break;
3501
3502         case V_BIT:
3503             fprintf(stdout,": %d" ,SPEC_BLEN(p));
3504             break;
3505         }
3506     }
3507 }
3508
3509 /*-----------------------------------------------------------------*/
3510 /* conditionIsTrue - compare variable with constant value        */
3511 /*-----------------------------------------------------------------*/
3512 int conditionIsTrue( char *s, context *cctxt)
3513 {
3514     symbol *sym = NULL;
3515     int fmt;
3516     char *rs, *dup, cmp_char;
3517     dup = s = Safe_strdup(s);
3518     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )) || !sym)
3519         fmt = 1;
3520     else if (!( s =  strpbrk(rs,"<>=!")))
3521         fmt = 1;
3522     else
3523     {
3524         cmp_char = *s;
3525         *s++ = '\0';
3526         if ( *s == '=' )
3527         {
3528             /* if <= or >= an other char is used
3529              * == or !=  not checked in switch
3530              */
3531             switch( cmp_char )
3532             {
3533                 case '>': cmp_char = 'g' ; break;
3534                 case '<': cmp_char = 'l' ; break;
3535             }
3536             s++ ;
3537         }
3538         s = trim_left(s);
3539         fmt = printOrSetSymValue(sym,cctxt,0,0,0,rs,s,cmp_char);
3540     }
3541     Safe_free(dup);
3542     return fmt;
3543 }
3544
3545 /*-----------------------------------------------------------------*/
3546 /* cmdPrint - print value of variable                              */
3547 /*-----------------------------------------------------------------*/
3548 int cmdPrint (char *s, context *cctxt)
3549 {
3550     symbol *sym ;
3551     int fmt;
3552     char *rs;
3553     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
3554         return 0;
3555
3556     if ( sym )
3557     {
3558         printOrSetSymValue(sym,cctxt,1,0,fmt,rs,NULL,'\0');
3559     }
3560     return 0;
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* cmdOutput - print value of variable without number and newline  */
3565 /*-----------------------------------------------------------------*/
3566 int cmdOutput (char *s, context *cctxt)
3567 {
3568     symbol *sym ;
3569     int fmt;
3570     char *rs;
3571     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
3572         return 0;
3573
3574     if ( sym )
3575     {
3576         printOrSetSymValue(sym,cctxt,0,0,fmt,rs,NULL,'\0');
3577     }
3578     return 0;
3579 }
3580
3581 /** find display entry with this number */
3582
3583 DEFSETFUNC(dsymWithNumber)
3584 {
3585     dsymbol *dsym = item;
3586     V_ARG(int , dnum);
3587     V_ARG(dsymbol **,dsymp);
3588
3589     if ( dsym->dnum == dnum )
3590     {
3591         *dsymp = dsym;
3592         return 1;
3593     }
3594     return 0;
3595 }
3596
3597 /*-----------------------------------------------------------------*/
3598 /* displayAll  - display all valid variables                       */
3599 /*-----------------------------------------------------------------*/
3600 void displayAll(context *cctxt)
3601 {
3602     dsymbol *dsym;
3603     symbol  *sym;
3604     if ( !dispsymbols )
3605         return;
3606     for (dsym = setFirstItem(dispsymbols);
3607          dsym ;
3608          dsym = setNextItem(dispsymbols))
3609     {
3610         if ( (sym = symLookup(dsym->name,cctxt)))
3611             printOrSetSymValue(sym,cctxt,2,dsym->dnum,dsym->fmt,
3612                                dsym->rs,NULL,'\0');
3613     }
3614 }
3615
3616 /*-----------------------------------------------------------------*/
3617 /* cmdDisplay  - display value of variable                         */
3618 /*-----------------------------------------------------------------*/
3619 int cmdDisplay (char *s, context *cctxt)
3620 {
3621     static int dnum = 1;
3622     symbol *sym ;
3623     int fmt;
3624     char *rs;
3625     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
3626     {
3627         displayAll(cctxt);
3628         return 0;
3629     }
3630
3631     if ( sym )
3632     {
3633         dsymbol *dsym = (dsymbol *)Safe_calloc(1,sizeof(dsymbol));
3634         dsym->dnum = dnum++ ;
3635         dsym->name = sym->name;
3636         dsym->fmt  = fmt;
3637         dsym->rs   = gc_strdup(rs);
3638         addSetHead(&dispsymbols,dsym);
3639     }
3640     return 0;
3641 }
3642
3643 /*-----------------------------------------------------------------*/
3644 /* cmdUnDisplay  - undisplay value of variable                              */
3645 /*-----------------------------------------------------------------*/
3646 int cmdUnDisplay (char *s, context *cctxt)
3647 {
3648     dsymbol *dsym;
3649     int dnum;
3650
3651     s = trim_left(s);
3652     if (!*s)
3653     {
3654         for (dsym = setFirstItem(dispsymbols);
3655              dsym;
3656              dsym = setNextItem(dispsymbols))
3657         {
3658             Safe_free(dsym->rs);
3659             Safe_free(dsym);
3660         }
3661         deleteSet(&dispsymbols);
3662         return 0;
3663     }
3664     while ( s && *s )
3665     {
3666         dnum = strtol(s,&s,10);
3667         if (applyToSetFTrue(dispsymbols,dsymWithNumber,dnum,&dsym))
3668         {
3669             deleteSetItem(&dispsymbols,dsym);
3670             Safe_free(dsym->rs);
3671             Safe_free(dsym);
3672         }
3673         else
3674         {
3675             fprintf(stdout,"Arguments must be display numbers.\n");
3676         }
3677     }
3678     return 0;
3679 }
3680
3681 /*-----------------------------------------------------------------*/
3682 /* cmdPrintType - print type of a variable                         */
3683 /*-----------------------------------------------------------------*/
3684 int cmdPrintType (char *s, context *cctxt)
3685 {
3686     symbol *sym ;
3687
3688     /* trim left and right */
3689     s = trim(s);
3690     if (!*s) return 0;
3691
3692     if ((sym = symLookup(s,cctxt))) {
3693         printTypeInfo(sym->type);
3694         fprintf(stdout,"\n");
3695     } else {
3696         fprintf(stdout,
3697                 "No symbol \"%s\" in current context.\n",
3698                 s);
3699     }
3700     return 0;
3701 }
3702
3703 /*-----------------------------------------------------------------*/
3704 /* cmdClrUserBp - clear user break point                           */
3705 /*-----------------------------------------------------------------*/
3706 int cmdClrUserBp (char *s, context *cctxt)
3707 {
3708     char *bp ;
3709     function *func = NULL;
3710
3711     /* clear break point location specification can be of the following
3712        forms
3713        a) <nothing>        - break point at current location
3714        b) lineno           - number of the current module
3715        c) filename:lineno  - line number of the given file
3716        e) filename:function- function X in file Y (useful for static functions)
3717        f) function         - function entry point
3718     */
3719
3720     if (!cctxt) {
3721         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
3722         return 0;
3723     }
3724
3725     /* trim left and right */
3726     s = trim(s);
3727
3728     /* case a) nothing */
3729     /* if nothing given then current location : we know
3730        the current execution location from the currentContext */
3731     if (! *s ) {
3732
3733         /* if current context is known */
3734         if (cctxt->func)
3735             /* clear the break point @ current location */
3736             clearUSERbp (cctxt->addr);
3737         else
3738             fprintf(stderr,"No default breakpoint address now.\n");
3739
3740         goto ret ;
3741     }
3742
3743     /* case b) lineno */
3744     /* check if line number */
3745     if (isdigit(*s)) {
3746         /* get the lineno */
3747         int line = atoi(s);
3748
3749         /* if current context not present then we must get the module
3750            which has main & set the break point @ line number provided
3751            of that module : if current context known then set the bp
3752            at the line number given for the current module
3753         */
3754         if (cctxt->func) {
3755             if (!cctxt->func->mod) {
3756                 if (!applyToSet(functions,funcWithName,"main"))
3757                     fprintf(stderr,"Function \"main\" not defined.\n");
3758                 else
3759                     clearBPatModLine(func->mod,line);
3760             } else
3761                 clearBPatModLine(cctxt->func->mod,line);
3762         }
3763
3764         goto ret;
3765     }
3766
3767     if ((bp = strchr(s,':'))) {
3768
3769         module *mod = NULL;
3770         *bp = '\0';
3771
3772         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
3773             fprintf (stderr,"No source file named %s.\n",s);
3774             goto ret;
3775         }
3776
3777         /* case c) filename:lineno */
3778         if (isdigit(*(bp +1))) {
3779
3780             clearBPatModLine (mod,atoi(bp+1));
3781             goto ret;
3782
3783         }
3784         /* case d) filename:function */
3785         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func))
3786             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1);
3787         else
3788             clearBPatModLine (mod,func->entryline);
3789
3790         goto ret;
3791     }
3792
3793     /* case e) function */
3794     if (!applyToSet(functions,funcWithName,s,&func))
3795         fprintf(stderr,"Function \"%s\" not defined.\n",s);
3796     else
3797         clearBPatModLine(func->mod,func->entryline);
3798
3799  ret:
3800     return 0;
3801 }
3802
3803 /*-----------------------------------------------------------------*/
3804 /* cmdSimulator - send command to simulator                        */
3805 /*-----------------------------------------------------------------*/
3806 int cmdSimulator (char *s, context *cctxt)
3807 {
3808   char tmpstr[82];
3809
3810     if (strlen(s) > 80) {
3811       printf("error 3A\n");
3812       exit(1);
3813     }
3814     strcpy(tmpstr, s);
3815     strcat(tmpstr, "\n");
3816     sendSim(tmpstr);
3817     waitForSim(200,NULL);
3818     fprintf(stdout,"%s",simResponse());
3819     return 0;
3820 }
3821
3822 void setMainContext()
3823 {
3824     function *func = NULL;
3825     currentFrame = 0;
3826     if (!applyToSet(functions,funcWithName,"_main",&func) &&
3827         !applyToSet(functions,funcWithName,"main",&func))
3828             return;
3829
3830     discoverContext (func->sym->addr, func, currCtxt);
3831 }
3832
3833 function *needExtraMainFunction()
3834 {
3835     function *func = NULL;
3836     if (!applyToSet(functions,funcWithName,"_main",&func))
3837     {
3838         if (applyToSet(functions,funcWithName,"main",&func))
3839         {
3840             return func;
3841         }
3842     }
3843     return NULL;
3844 }
3845
3846 static void printFrame()
3847 {
3848     int i;
3849     function *func     = NULL;
3850     function *lastfunc = NULL;
3851     context *ctx, my_context;
3852     unsigned int bp, pc;
3853     int status;
3854
3855     if ( currentFrame < 0 )
3856     {
3857         currentFrame = 0;
3858         fprintf(stdout,"Bottom (i.e., innermost) frame selected; you cannot go down.\n");
3859         return;
3860     }
3861     i = 0;
3862     for (status = frameStart(&bp, &pc); status; status = frameNext(&bp, &pc))
3863     {
3864         if (i >= currentFrame)
3865             break;
3866         i++;
3867     }
3868     if (i < currentFrame) {
3869         currentFrame = i;
3870         fprintf(stdout,"Initial frame selected; you cannot go up.\n");
3871         return;
3872     }
3873     ctx = discoverContext(pc, NULL, &my_context);
3874     if (ctx && (func = ctx->func)) {
3875         fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",
3876                 currentFrame,pc,func->sym->name,func->mod->c_name,func->lline+1);
3877         fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
3878                 canonname(func->mod->cfullname),func->lline+1,func->laddr);
3879     } else {
3880         fprintf(stdout,"#%d  0x%08x\n",
3881                 currentFrame,pc);
3882     }
3883 }
3884
3885
3886 /*-----------------------------------------------------------------*/
3887 /* cmdUp -  Up command                                             */
3888 /*-----------------------------------------------------------------*/
3889 int cmdUp(char *s, context *cctxt)
3890 {
3891     s = trim_left(s);
3892     if ( *s )
3893         currentFrame += strtol(s,0,10);
3894     else
3895         currentFrame++ ;
3896
3897     printFrame();
3898         return 0;
3899 }
3900
3901 /*-----------------------------------------------------------------*/
3902 /* cmdDown - down command                                          */
3903 /*-----------------------------------------------------------------*/
3904 int cmdDown(char *s, context *cctxt)
3905 {
3906     s = trim_left(s);
3907     if ( *s )
3908         currentFrame -= strtol(s,0,10);
3909     else
3910         currentFrame-- ;
3911
3912     printFrame();
3913         return 0;
3914 }
3915 /*-----------------------------------------------------------------*/
3916 /* cmdFrame - Frame command                                        */
3917 /*-----------------------------------------------------------------*/
3918 int cmdFrame (char *s, context *cctxt)
3919 {
3920     function *func = NULL;
3921     int framenr = 0;
3922
3923     s = trim_left(s);
3924     if ( *s )
3925         currentFrame = strtol(s,0,10);
3926     printFrame();
3927     return 0;
3928 }
3929
3930 /*-----------------------------------------------------------------*/
3931 /* cmdFinish - exec till end of current function                   */
3932 /*-----------------------------------------------------------------*/
3933 int cmdFinish (char *s, context *ctxt)
3934 {
3935 #if 0
3936     if (STACK_EMPTY(callStack)) {
3937         fprintf(stdout,"The program is not running.\n");
3938         return 0;
3939     }
3940 #endif
3941
3942     if (srcMode == SRC_CMODE) {
3943         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP,
3944                        stepBpCB, ctxt->func->mod->c_name,
3945                        ctxt->func->exitline);
3946     } else {
3947         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP,
3948                        stepBpCB, ctxt->func->mod->asm_name,
3949                        ctxt->func->aexitline);
3950     }
3951
3952     simGo(-1);
3953     showfull = 1;
3954     return 0;
3955
3956 }
3957
3958
3959 /*-----------------------------------------------------------------*/
3960 /* cmdShow - show command                                          */
3961 /*-----------------------------------------------------------------*/
3962 int cmdShow (char *s, context *cctxt)
3963 {
3964     /* skip white space */
3965     s = trim_left(s);
3966
3967     if (strcmp(s,"copying") == 0) {
3968         fputs(copying,stdout);
3969         return 0;
3970     }
3971
3972     if (strcmp(s,"warranty") == 0) {
3973         fputs(warranty,stdout);
3974         return 0;
3975     }
3976
3977     return 0;
3978 }
3979