4cae0c91c5ec1284ef09a7437c965a3744e58e3b
[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 int pc_change(unsigned addr, unsigned addrs[2])
1057 {
1058         unsigned char insn;
1059         unsigned new_addr;
1060         signed char delta;
1061         int len;
1062
1063         insn = simGetValue(addr, 'C', 1);
1064         if (instructions[insn].flags & IS_RET)
1065                 return 0;
1066
1067         if (!(instructions[insn].flags & IS_BRANCH)) {
1068                 addrs[0] = addr + instructions[insn].len;
1069                 return 1;
1070         }
1071
1072         if (insn == LJMP_addr16) {
1073                 addrs[0] = ((simGetValue(addr+1, 'C', 1) << 8) |
1074                           (simGetValue(addr+2, 'C', 1)));
1075                 return 1;
1076         }
1077         
1078         /* AJMP */
1079         if ((insn & 0x1f) == 0x01) {
1080                 unsigned char   direct = simGetValue(addr+1,'C', 1);
1081
1082                 addrs[0] = ((addr + 2) & 0xf800) | ((insn & 0xe0) << 3) | direct;
1083                 return 1;
1084         }
1085
1086         /* otherwise, relative branch */
1087         len = instructions[insn].len;
1088
1089         delta = (signed char) simGetValue(addr+len-1, 'C', 1);
1090         new_addr = (addr + len) + delta;
1091         
1092         if (insn == SJMP_rel) {
1093                 addrs[0] = new_addr;
1094                 return 1;
1095         }
1096
1097         addrs[0] = addr + len;
1098         addrs[1] = new_addr;
1099         return 2;
1100 }
1101
1102 #define SEARCH_FAILED   0x8000
1103
1104 static int
1105 stack_depth(unsigned pc, int search)
1106 {
1107         unsigned new_pc[2];
1108         unsigned max_pc = pc;
1109         int n;
1110         int s;
1111         int change;
1112
1113         change = 0;
1114         for (;;) {
1115                 change += stack_change(pc);
1116                 n = pc_change(pc, new_pc);
1117                 if (n == 0)
1118                         return change;
1119                 if (n != 1)
1120                         break;
1121                 pc = new_pc[0];
1122                 /* detect infinite loop */
1123                 if (pc == max_pc)
1124                         return change;
1125                 if (pc > max_pc)
1126                         max_pc = pc;
1127         }
1128         
1129         if (search == 0)
1130                 return SEARCH_FAILED;
1131         
1132         for (s = 0; s < search - 1; s++) {
1133                 int d;
1134                 int i;
1135                 d = SEARCH_FAILED;
1136                 for (i = 0; i < n; i++) {
1137                         d = stack_depth(new_pc[i], search-1);
1138                         if (d != SEARCH_FAILED)
1139                                 return d + change;
1140                 }
1141         }
1142         return SEARCH_FAILED;
1143 }
1144
1145 unsigned int
1146 stack_start(void)
1147 {
1148         symbol *start_stack = symLookup("__start_stack", NULL);
1149         if (start_stack)
1150                 return start_stack->addr;
1151         return 0x8;
1152 }
1153
1154 static int
1155 frameStart(unsigned int *bpp, unsigned int *pcp)
1156 {
1157         unsigned int bp;
1158         unsigned int sp;
1159         unsigned int pc;
1160         int depth;
1161         symbol *bp_sym;
1162
1163         pc = simGetPC();
1164         sp = simGetValue(0x81,'I',1);
1165         depth = stack_depth(pc, 100);
1166         bp = sp + depth;
1167         if (bp < stack_start())
1168                 return 0;
1169         *bpp = bp;
1170         *pcp = pc;
1171         return 1;
1172 }
1173
1174 static int
1175 frameNext(unsigned int *bpp, unsigned int *pcp)
1176 {
1177         unsigned int bp = *bpp;
1178         unsigned int pc;
1179         int depth;
1180         symbol *start_stack;
1181
1182         if (bp < stack_start())
1183                 return 0;
1184         pc = simGetValue(bp - 1, 'B', 2);
1185         depth = stack_depth(pc, 100);
1186         bp = bp - 2 + depth;
1187         *bpp = bp;
1188         *pcp = pc;
1189         return 1;
1190 }
1191
1192 static int running = 0;
1193
1194 static int is_running(void) {
1195     return running;
1196 }
1197
1198 static int set_running(int run) {
1199     running = run;
1200 }
1201
1202 /*-----------------------------------------------------------------*/
1203 /* simGo - send 'go' cmd to simulator and wait till a break occurs */
1204 /*-----------------------------------------------------------------*/
1205 void simGo (unsigned int gaddr)
1206 {
1207     unsigned int addr ;
1208     context *ctxt;
1209     int rv;
1210     stopCommandList();
1211  top:
1212     if ( userinterrupt )
1213     {
1214         userinterrupt = 0;
1215         return;
1216     }
1217 #if 0
1218     if ( gaddr == 0 )
1219     {
1220         function *func = NULL;;
1221         if (applyToSet(functions,funcInAddr,gaddr,&func))
1222             STACK_PUSH(callStack,func);
1223     }
1224 #endif
1225     addr = simGoTillBp (gaddr);
1226
1227     /* got the pc for the break point now first
1228        discover the program context i.e. module, function
1229        linenumber of the source etc, etc etc */
1230     currentFrame = 0;
1231     ctxt = discoverContext (addr, NULL, currCtxt);
1232
1233     /* dispatch all the break point call back functions */
1234     rv = dispatchCB (addr,ctxt);
1235
1236     /* the dispatch call back function will return
1237        non-zero if an user break point has been hit
1238        if not then we continue with the execution
1239        of the program */
1240     if (!rv)
1241     {
1242         if ( gaddr == 0 )
1243             gaddr = -1;
1244         if ( gaddr == -1 || doingSteps == 1 )
1245             goto top ;
1246     }
1247
1248 }
1249
1250 /*-----------------------------------------------------------------*/
1251 /* preparePrint - common parse function for  set variable,         */
1252 /*                output, print and display                        */
1253 /*-----------------------------------------------------------------*/
1254 static char *preparePrint(char *s, context *cctxt, int *fmt, symbol **sym)
1255 {
1256     char *bp;
1257     char save_ch ;
1258     int ptr = 0;
1259
1260     *fmt = FMT_NON;
1261     *sym = NULL;
1262
1263     s = trim(s);
1264     if (!*s)
1265         return (char *)0;
1266
1267     if ( *s == '/' )
1268     {
1269         /* format of printout */
1270         switch ( *++s )
1271         {
1272             case 'x':
1273                 *fmt = FMT_HEX ;
1274                 break;
1275             case 'o':
1276                 *fmt = FMT_OCT ;
1277                 break;
1278             default:
1279             case 'd':
1280                 *fmt = FMT_DEZ ;
1281                 break;
1282             case 't':
1283                 *fmt = FMT_BIN ;
1284                 break;
1285         }
1286         s++;
1287         s = trim_left(s);
1288     }
1289     while (*s == '*') {
1290         ptr++;
1291         s++;
1292     }
1293     for ( bp = s; *bp && ( isalnum( *bp ) || *bp == '_' || *bp == '$'); bp++ );
1294     save_ch = *bp;
1295     if ( *bp )
1296         *bp = '\0';
1297
1298     if ( *s )
1299         *sym = symLookup(s,cctxt);
1300     *bp = save_ch;
1301     while (ptr--)
1302         strcat(bp,"*");
1303
1304     if ( ! *sym )
1305         fprintf(stdout,"No symbol \"%s\" in current context.\n", s);
1306     return bp;
1307 }
1308
1309 static int printAsmLine( function *func, module *m, unsigned saddr, unsigned eaddr)
1310 {
1311     int i,j,delta;
1312     unsigned symaddr;
1313     unsigned lastaddr = saddr+1;
1314     char *symname;
1315
1316     if ( func )
1317     {
1318         symaddr = func->sym->addr;
1319         symname = func->sym->name;
1320     }
1321     else
1322     {
1323         symaddr = saddr;
1324         symname = "" ;
1325     }
1326     for (j=0,i=0; i < m->nasmLines; i++ )
1327     {
1328         if ( saddr >= 0 && m->asmLines[i]->addr < saddr)
1329         {
1330                 continue;
1331         }
1332         if ( eaddr >= 0 && m->asmLines[i]->addr > eaddr)
1333         {
1334                 continue;
1335         }
1336         if ( func &&
1337             (m->asmLines[i]->addr < func->sym->addr ||
1338              m->asmLines[i]->addr > func->sym->eaddr ))
1339         {
1340             continue;
1341         }
1342         delta = m->asmLines[i]->addr - symaddr;
1343         if ( delta >= 0 )
1344         {
1345             j++;
1346             lastaddr = m->asmLines[i]->addr;
1347             printf("0x%08x <%s",lastaddr,symname);
1348             if (delta > 0) printf("+%d",delta);
1349             printf(">:\t%s",m->asmLines[i]->src);
1350         }
1351     }
1352     return lastaddr;
1353 }
1354
1355 /*-----------------------------------------------------------------*/
1356 /* cmdDisasm - disassemble  asm instruction                        */
1357 /*-----------------------------------------------------------------*/
1358 static int cmdDisasm (char *s, context *cctxt, int args)
1359 {
1360     function *func = NULL;
1361     long  saddr = -1;
1362     long  eaddr = -1;
1363     int   found = 0;
1364     module *modul;
1365     /* white space skip */
1366
1367     if ( args > 0 )
1368     {
1369         s = trim_left(s);
1370
1371         if ( isdigit(*s))
1372         {
1373             saddr = strtol(s,&s,0);
1374             if ( args > 1 )
1375             {
1376                 s = trim_left(s);
1377
1378                 if ( isdigit(*s))
1379                     eaddr = strtol(s,0,0);
1380             }
1381             else
1382                 eaddr = saddr+1;
1383         }
1384     }
1385
1386     if ( eaddr == -1 )
1387     {
1388         /* no start or only start so dump function */
1389         if ( saddr == -1 )
1390         {
1391             func = cctxt->func;
1392         }
1393         else
1394         {
1395             applyToSet(functions,funcInAddr,saddr,&func);
1396         }
1397         if ( func )
1398         {
1399             printf("Dump of assembler code for function %s:\n",func->sym->name);
1400             printAsmLine(func,func->mod,-1,-1);
1401             printf("End of assembler dump.\n");
1402             return 0;
1403         }
1404         else
1405         {
1406             if (applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
1407             {
1408                 eaddr = saddr + 5;
1409                 printf("Dump of assembler code:\n");
1410                 printAsmLine(NULL,modul,saddr,eaddr);
1411                 printf("End of assembler dump.\n");
1412                 return 0;
1413             }
1414         }
1415     }
1416     else
1417     {
1418         if ( args > 1 )
1419             printf("Dump of assembler code from 0x%08lx to 0x%08lx:\n",saddr,eaddr);
1420         found = 0;
1421         while ( saddr < eaddr )
1422         {
1423             func = NULL;
1424             if (applyToSet(functions,funcInAddr,saddr,&func))
1425             {
1426                 found = 1;
1427                 modul = func->mod;
1428             }
1429             else
1430             {
1431                 if ( found )
1432                     break;
1433                 if (!applyToSet(modules,moduleLineWithAddr,saddr,&modul,NULL))
1434                     break;
1435             }
1436             saddr = printAsmLine(func,modul,saddr,eaddr) + 1;
1437         }
1438         if( saddr >= eaddr)
1439         {
1440             if ( args > 1 )
1441                 printf("End of assembler dump.\n");
1442             return 0;
1443         }
1444
1445     }
1446     fprintf(stderr,"No function contains specified address.\n");
1447     if( saddr >= 0 )
1448     {
1449         char lbuf[64];
1450         sprintf(lbuf,"dis 0x%lx 0 %ld\n",saddr,( eaddr == -1 )?1L:eaddr-saddr);
1451         sendSim(lbuf);
1452         waitForSim(1000, NULL);
1453         fputs(simResponse(),stdout);
1454     }
1455     return 0;
1456 }
1457 /*-----------------------------------------------------------------*/
1458 /* cmdDisasm1 - disassemble one asm instruction                    */
1459 /*-----------------------------------------------------------------*/
1460 int cmdDisasm1 (char *s, context *cctxt)
1461 {
1462     return cmdDisasm( s, cctxt, 1);
1463 }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* cmdDisasmF - disassemble asm instructions                       */
1467 /*-----------------------------------------------------------------*/
1468 int cmdDisasmF(char *s, context *cctxt)
1469 {
1470     return cmdDisasm( s, cctxt, 2);
1471 }
1472
1473 static int commonSetUserBp(char *s, context *cctxt, char bpType)
1474 {
1475     char *bp ;
1476     function *func = NULL;
1477
1478     /* user break point location specification can be of the following
1479        forms
1480        a) <nothing>        - break point at current location
1481        b) lineno           - number of the current module
1482        c) filename:lineno  - line number of the given file
1483        e) filename:function- function X in file Y (useful for static functions)
1484        f) function         - function entry point
1485        g) *addr            - break point at address
1486     */
1487
1488     if (!cctxt) {
1489         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
1490         return 0;
1491     }
1492     /* trim left and right */
1493     s = trim(s);
1494
1495     /* case a) nothing */
1496     /* if nothing given then current location : we know
1497        the current execution location from the currentContext */
1498     if (! *s ) {
1499
1500         /* if current context is known */
1501         if (cctxt->func) {
1502         Dprintf(D_break, ("commonSetUserBp: a) cctxtaddr:%x \n",cctxt->addr));
1503             if (srcMode == SRC_CMODE)
1504                 /* set the break point */
1505                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
1506                                 cctxt->func->mod->c_name, cctxt->cline);
1507             else
1508                 setBreakPoint ( cctxt->addr , CODE , bpType , userBpCB ,
1509                                 cctxt->func->mod->asm_name, cctxt->asmline);
1510
1511         }
1512         else
1513             fprintf(stderr,"No default breakpoint address now.\n");
1514
1515         goto ret ;
1516     }
1517     /* case g) *addr */
1518     if ( *s == '*' && isdigit(*(s+1)))
1519     {
1520         int  line   = 0;
1521         long braddr = strtol(s+1,0,0);
1522         if (!applyToSet(functions,funcInAddr,braddr,&func))
1523         {
1524             module *modul;
1525             if (!applyToSet(modules,moduleLineWithAddr,braddr,&modul,&line))
1526             {
1527                 fprintf(stderr,"Address 0x%08lx not exists in code.\n",braddr);
1528             }
1529             else
1530             {
1531                 Dprintf(D_break, ("commonSetUserBp: g) addr:%lx \n",braddr));
1532                 setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1533                             modul->c_name,line);
1534             }
1535             goto ret ;
1536         }
1537                 else
1538         {
1539             int line = func->exitline;
1540             if ( !applyToSet(func->cfpoints,lineAtAddr,braddr,
1541                                   &line,NULL,NULL))
1542                 applyToSet(func->cfpoints,lineNearAddr,braddr,&line,NULL,NULL);
1543             setBreakPoint ( braddr , CODE , bpType , userBpCB ,
1544                             func->mod->c_name,line);
1545         }
1546         goto ret ;
1547     }
1548     /* case b) lineno */
1549     /* check if line number */
1550     if ( !strchr(s,':') && isdigit(*s)) {
1551         /* get the lineno */
1552         int line = atoi(s) -1;
1553     Dprintf(D_break, ("commonSetUserBp: b) line:%d \n",line));
1554     if ( line < 0 )
1555     {
1556                 fprintf(stdout,"linenumber <= 0\n");
1557         goto ret;
1558     }
1559         /* if current context not present then we must get the module
1560            which has main & set the break point @ line number provided
1561            of that module : if current context known then set the bp
1562            at the line number given for the current module
1563         */
1564         if (cctxt->func) {
1565             if (!cctxt->func->mod) {
1566                 if (!applyToSet(functions,funcWithName,"main"))
1567                     fprintf(stderr,"Function \"main\" not defined.\n");
1568                 else
1569                     setBPatModLine(func->mod,line, bpType);
1570             } else
1571                 setBPatModLine(cctxt->func->mod,line, bpType);
1572         } else {
1573                 if (list_mod) {
1574                         setBPatModLine(list_mod,line, bpType);
1575                 } else {
1576                   fprintf(stdout,"Sdcdb fails to have module symbol context at %d\n", __LINE__);
1577                 }
1578         }
1579
1580         goto ret;
1581     }
1582
1583     if ((bp = strchr(s,':'))) {
1584
1585         module *mod = NULL;
1586         *bp = '\0';
1587
1588         if (srcMode == SRC_CMODE) {
1589             if (!applyToSet(modules,moduleWithCName,s,&mod)) {
1590                 fprintf (stderr,"No source file named %s.\n",s);
1591                 goto ret;
1592             }
1593         } else {
1594             if (!applyToSet(modules,moduleWithAsmName,s,&mod)) {
1595                 fprintf (stderr,"No source file named %s.\n",s);
1596                 goto ret;
1597             }
1598         }
1599
1600         /* case c) filename:lineno */
1601         if (isdigit(*(bp +1))) {
1602         Dprintf(D_break, ("commonSetUserBp: c) line:%d \n",atoi(bp+1)));
1603             setBPatModLine (mod,atoi(bp+1)-1,bpType);
1604             goto ret;
1605
1606         }
1607         /* case d) filename:function */
1608         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func))
1609             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1);
1610         else
1611         Dprintf(D_break, ("commonSetUserBp: d) \n"));
1612             setBPatModLine (mod,
1613                             (srcMode == SRC_CMODE ?
1614                              func->entryline :
1615                              func->aentryline),bpType);
1616
1617         goto ret;
1618     }
1619
1620     /* case e) function */
1621     Dprintf(D_break, ("commonSetUserBp: e) \n"));
1622     if (!applyToSet(functions,funcWithName,s,&func))
1623         fprintf(stderr,"Function \"%s\" not defined.\n",s);
1624     else
1625         setBPatModLine(func->mod,
1626                        (srcMode == SRC_CMODE ?
1627                         func->entryline :
1628                         func->aentryline),bpType);
1629
1630  ret:
1631     return 0;
1632 }
1633
1634 /*-----------------------------------------------------------------*/
1635 /* cmdSetTmpUserBp - settempory break point at the user specified location   */
1636 /*-----------------------------------------------------------------*/
1637 int cmdSetTmpUserBp (char *s, context *cctxt)
1638 {
1639     return commonSetUserBp(s, cctxt, TMPUSER );
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* cmdSetUserBp - set break point at the user specified location   */
1644 /*-----------------------------------------------------------------*/
1645 int cmdSetUserBp (char *s, context *cctxt)
1646 {
1647     return commonSetUserBp(s, cctxt, USER );
1648 }
1649
1650 /*-----------------------------------------------------------------*/
1651 /* cmdJump - set program counter                                   */
1652 /*-----------------------------------------------------------------*/
1653 int cmdJump (char *s, context *cctxt)
1654 {
1655     char *bp;
1656     function *func = NULL;
1657     if (!is_running())
1658     {
1659         fprintf(stdout,"The program is not running.\n");
1660         return 0;
1661     }
1662
1663     /* trim left and right */
1664     s = trim(s);
1665
1666     if (! *s )
1667     {
1668         fprintf(stdout,"No argument: need line or *addr.\n");
1669         return 0;
1670     }
1671     if ( *s == '*' && isdigit(*(s+1)))
1672     {
1673         unsigned int addr = atoi(s);
1674         if (cctxt && cctxt->func &&
1675             cctxt->func->sym->addr <= addr &&
1676             cctxt->func->sym->eaddr >= addr)
1677         {
1678             simSetPC(addr);
1679             return 0;
1680         }
1681         fprintf(stdout,"Warning addr 0x%x outside actual function.\n",addr);
1682         simSetPC(addr);
1683         return 0;
1684     }
1685     if (isdigit(*s))
1686     {
1687         /* get the lineno */
1688         int line = atoi(s) -1;
1689         if (!cctxt || !cctxt->func || !cctxt->func->mod)
1690         {
1691                     fprintf(stderr,"Function not defined.\n");
1692             return 0;
1693         }
1694         if (line >= cctxt->func->entryline &&
1695             line <= cctxt->func->exitline )
1696         {
1697             simSetPC(cctxt->func->mod->cLines[line]->addr);
1698             return 0;
1699         }
1700         if (line >= cctxt->func->mod->ncLines )
1701         {
1702                     fprintf(stderr,"line not in module.\n");
1703             return 0;
1704         }
1705         fprintf(stdout,"Warning line %d outside actual function.\n",line+1);
1706         simSetPC(cctxt->func->mod->cLines[line]->addr);
1707         return 0;
1708     }
1709     if ((bp = strchr(s,':')))
1710     {
1711         int line;
1712         module *mod = NULL;
1713         *bp++ = '\0';
1714         if (!applyToSet(modules,moduleWithCName,s,&mod))
1715         {
1716             fprintf (stderr,"No source file named %s.\n",s);
1717             return 0;
1718         }
1719         if (!isdigit(*bp))
1720         {
1721             fprintf (stderr,"No line number.\n");
1722             return 0;
1723         }
1724         line = atoi(bp) -1;
1725         if (line >= mod->ncLines )
1726         {
1727                     fprintf(stderr,"line not in module.\n");
1728             return 0;
1729         }
1730         if ( mod != cctxt->func->mod ||
1731              line < cctxt->func->entryline ||
1732              line > cctxt->func->exitline )
1733         {
1734             fprintf(stdout,"Warning line %d outside actual function.\n",
1735                     line+1);
1736         }
1737         simSetPC(mod->cLines[line]->addr);
1738     }
1739     return 0;
1740 }
1741
1742 /*-----------------------------------------------------------------*/
1743 /* cmdListAsm - list assembler source code                         */
1744 /*-----------------------------------------------------------------*/
1745 int cmdListAsm (char *s, context *cctxt)
1746 {
1747     if (  cctxt && cctxt->func)
1748     {
1749         /* actual line */
1750         if ( cctxt->addr != INT_MAX )
1751         {
1752             if (printAsmLine(cctxt->func,cctxt->func->mod,
1753                          (long)cctxt->addr,(long)cctxt->addr))
1754             return 0;
1755         }
1756     }
1757     return 0;
1758 }
1759
1760 /*-----------------------------------------------------------------*/
1761 /* cmdSetOption - set debugger options                             */
1762 /*-----------------------------------------------------------------*/
1763 int cmdSetOption (char *s, context *cctxt)
1764 {
1765     s = trim_left(s);
1766     if (strncmp(s,"srcmode",7) == 0 ) {
1767         if (srcMode == SRC_CMODE)
1768             srcMode = SRC_AMODE;
1769         else
1770             srcMode = SRC_CMODE;
1771         fprintf(stderr,"source mode set to '%s'\n",
1772                 (srcMode == SRC_CMODE ? "C" : "asm"));
1773         return 0;
1774     }
1775
1776     if (strncmp(s,"listsize ",9) == 0)
1777     {
1778         listlines = strtol(s+9,0,0);
1779         if ( listlines < LISTLINES )
1780             listlines = LISTLINES;
1781         return 0;
1782     }
1783
1784 #ifdef SDCDB_DEBUG
1785     if (strncmp(s,"debug ",6) == 0)
1786     {
1787         sdcdbDebug = strtol(s+6,0,0);
1788         return 0;
1789     }
1790 #endif
1791     if (strncmp(s,"variable ",9) == 0)
1792     {
1793         symbol *sym ;
1794         int fmt;
1795         char *rs;
1796         s += 9;
1797         if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
1798             return 0;
1799         s = rs;
1800         while (*s && *s != '=') s++;
1801         *s++ = '\0';
1802         s = trim_left(s);
1803         if (*s && sym)
1804         {
1805             printOrSetSymValue(sym,cctxt,0,0,0,rs,s,'\0');
1806             return 0;
1807         }
1808         else
1809             fprintf(stdout,"No new value for \"%s\".\n",s);
1810         return 0;
1811     }
1812
1813
1814     fprintf(stderr,"'set %s' command not yet implemented\n",s);
1815     return 0;
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* cmdContinue - continue till next break point                    */
1820 /*-----------------------------------------------------------------*/
1821 int cmdContinue (char *s, context *cctxt)
1822 {
1823     if (!is_running()) {
1824         fprintf(stdout,"The program is not being run.\n");
1825         return 0;
1826     }
1827
1828     fprintf(stdout,"Continuing.\n");
1829     simGo(-1);
1830     showfull = 1;
1831     return 0;
1832 }
1833
1834 /*-----------------------------------------------------------------*/
1835 /* cmdIgnore - set ignorecount for breakpoint                      */
1836 /*-----------------------------------------------------------------*/
1837 int cmdIgnore (char *s, context *cctxt)
1838 {
1839     int bpnum, cnt ;
1840     s = trim_left(s);
1841     if (!*s )
1842     {
1843         fprintf(stdout,"Argument required (breakpoint number).\n");
1844         return 0;
1845     }
1846     bpnum = strtol(s,&s,10);
1847     s = trim_left(s);
1848     if (!*s )
1849     {
1850         fprintf(stdout,"Second argument (specified ignore-count) is missing.");
1851         return 0;
1852     }
1853     cnt = strtol(s,0,10);
1854     setUserbpIgnCount(bpnum,cnt);
1855     return 0;
1856 }
1857
1858 /*-----------------------------------------------------------------*/
1859 /* cmdCondition - set condition for breakpoint                     */
1860 /*-----------------------------------------------------------------*/
1861 int cmdCondition (char *s, context *cctxt)
1862 {
1863     int bpnum ;
1864     s = trim_left(s);
1865     if (!*s )
1866     {
1867         fprintf(stdout,"Argument required (breakpoint number).\n");
1868         return 0;
1869     }
1870     bpnum = strtol(s,&s,10);
1871     s = trim_left(s);
1872     if (*s)
1873         s = Safe_strdup(s);
1874     else
1875         s = NULL;
1876     setUserbpCondition(bpnum,s);
1877     return 0;
1878 }
1879
1880 /*-----------------------------------------------------------------*/
1881 /* cmdCommands - set commands for breakpoint                       */
1882 /*-----------------------------------------------------------------*/
1883 int cmdCommands (char *s, context *cctxt)
1884 {
1885     int bpnum ;
1886     char *cmds,*line;
1887     s = trim_left(s);
1888
1889     if (!*s )
1890         bpnum = getLastBreakptNumber();
1891     else
1892         bpnum = strtol(s,0,10);
1893
1894     cmds = NULL;
1895     while ((line = getNextCmdLine()))
1896     {
1897         line = trim_left(line);
1898         if (!strncmp(line,"end",3))
1899             break;
1900         if (! cmds )
1901         {
1902             cmds = Safe_strdup(line);
1903         }
1904         else
1905         {
1906             cmds = Safe_realloc( cmds, strlen(cmds) + 1 + strlen(line));
1907             strcat(cmds,line);
1908         }
1909     }
1910     setUserbpCommand(bpnum,cmds);
1911     return 0;
1912 }
1913
1914 /*-----------------------------------------------------------------*/
1915 /* cmdDelUserBp - delete user break point                          */
1916 /*-----------------------------------------------------------------*/
1917 int cmdDelUserBp (char *s, context *cctxt)
1918 {
1919     int bpnum ;
1920     s = trim_left(s);
1921
1922     if (!*s ) {
1923         if (userBpPresent) {
1924             char buffer[10];
1925             fprintf (stdout,"Delete all breakpoints? (y or n) ");
1926             fflush(stdout);
1927             fgets(buffer,sizeof(buffer),stdin);
1928             if (toupper(buffer[0]) == 'Y')
1929                 deleteUSERbp(-1);
1930         }
1931         return 0;
1932     }
1933
1934     /* determine the break point number */
1935     if (sscanf(s,"%d",&bpnum) == 1)
1936         deleteUSERbp(bpnum);
1937
1938     return 0;
1939 }
1940
1941 /*-----------------------------------------------------------------*/
1942 /* cmdStepi - single step exactly one instruction                   */
1943 /*-----------------------------------------------------------------*/
1944 int cmdStepi (char *s, context *cctxt)
1945 {
1946
1947     if (!is_running())
1948         fprintf(stdout,"The program is not being run.\n");
1949     else
1950     {
1951         doingSteps = 2;
1952             simGo(2);
1953         doingSteps = 0;
1954         showfull = 1;
1955     }
1956     return 0;
1957 }
1958
1959 static unsigned line_start_addr(context *ctx, int line)
1960 {
1961         function *func = ctx->func;
1962         module *mod = func->mod;
1963         unsigned addr;
1964         int nlines;
1965         
1966         if (srcMode == SRC_CMODE)
1967                 nlines = mod->ncLines;
1968         else
1969                 nlines = mod->nasmLines;
1970
1971         do {
1972                 if (srcMode == SRC_CMODE)
1973                         addr = mod->cLines[line]->addr;
1974                 else
1975                         addr = mod->asmLines[line]->addr;
1976                 ++line;
1977         } while (addr == 0x7fffffff && line < nlines);
1978         if (addr == 0x7fffffff)
1979                 addr = func->sym->eaddr;
1980         return addr;
1981 }
1982
1983 static unsigned line_end_addr(context *ctx, int line)
1984 {
1985         function *func = ctx->func;
1986         module *mod = func->mod;
1987         int next_line, nlines;
1988         unsigned start_addr = line_start_addr(ctx, line);
1989         unsigned next_addr = func->sym->eaddr + 1;
1990         unsigned addr;
1991
1992         if (srcMode == SRC_CMODE)
1993                 nlines = mod->ncLines;
1994         else
1995                 nlines = mod->nasmLines;
1996         for (next_line = 0; next_line < nlines; next_line++) {
1997                 if (next_line == line)
1998                         continue;
1999                 if (srcMode == SRC_CMODE)
2000                         addr = mod->cLines[next_line]->addr;
2001                 else
2002                         addr = mod->asmLines[next_line]->addr;
2003                 if (start_addr < addr && addr < next_addr)
2004                         next_addr = addr;
2005         }
2006         return next_addr;
2007 }
2008
2009 BP_CALLBACK(step_bp_callback)
2010 {
2011         deleteSTEPbp();
2012         return 1;
2013 }
2014
2015 static int do_step(context *ctx, int into)
2016 {
2017         function *func = ctx->func;
2018         module *mod = func->mod;
2019         srcLine **lines;
2020         srcLine *line;
2021         int     nlines;
2022         int     start, end;
2023         int     start_l;
2024         unsigned len;
2025         unsigned start_addr, end_addr, addr;
2026         unsigned char insn;
2027         unsigned char flags;
2028         
2029         if (srcMode == SRC_CMODE) {
2030                 lines = mod->cLines;
2031                 nlines = mod->ncLines;
2032                 start_l = ctx->cline;
2033         } else {
2034                 lines = mod->asmLines;
2035                 nlines = mod->nasmLines;
2036                 start_l = ctx->asmline;
2037         }
2038         if (start_l == -1)
2039                 return 0;
2040         flags = IS_BRANCH|IS_RET;
2041         if (into)
2042                 flags |= IS_CALL;
2043         line = lines[start_l];
2044         start = line_start_addr(ctx, start_l);
2045         end = line_end_addr(ctx, start_l);
2046
2047         while (start <= ctx->addr && ctx->addr < end) {
2048                 insn = 0xff;
2049                 for (addr = ctx->addr; addr < end; addr += len) {
2050                         insn = simGetValue(addr, 'C', 1);
2051                         if (instructions[insn].flags & flags)
2052                                 break;
2053                         len = instructions[insn].len;
2054                         if (len == 0) {
2055                                 fprintf(stderr, "Unknown opcode 0x%02x\n", insn);
2056                                 return 0;
2057                         }
2058                 }
2059                 if (addr != ctx->addr) {
2060                         setBreakPoint(addr, CODE, STEP,
2061                                       step_bp_callback,
2062                                       mod->name, start_l);
2063                         doingSteps = 1;
2064                         /* run to breakpoint */
2065                         simGo(-1);
2066                         doingSteps = 0;
2067                 }
2068                 /* step over instruction at breakpoint */
2069                 if (start <= ctx->addr && ctx->addr < end) {
2070                         doingSteps = 2;
2071                         simGo(2);
2072                         doingSteps = 0;
2073                 }
2074         }
2075         stepBpCB(ctx->addr, NULL, ctx);
2076         showfull = 1;
2077 }
2078
2079 /*-----------------------------------------------------------------*/
2080 /* cmdStep - single step thru C source file                        */
2081 /*-----------------------------------------------------------------*/
2082 int cmdStep (char *s, context *cctxt)
2083 {
2084     function *func = NULL;
2085
2086     if (!is_running())
2087         fprintf(stdout,"The program is not being run.\n");
2088     else
2089         do_step(cctxt, 1);
2090     return 0;
2091 }
2092
2093 /*-----------------------------------------------------------------*/
2094 /* cmdNexti - next instruction but proceed function call           */
2095 /*-----------------------------------------------------------------*/
2096 int cmdNexti (char *s, context *cctxt)
2097 {
2098     if (!is_running())
2099         fprintf(stdout,"The program is not being run.\n");
2100     else
2101     {
2102         doingSteps = 2;
2103             simGo(1);
2104         doingSteps = 0;
2105         showfull = 1;
2106     }
2107     return 0;
2108 }
2109
2110 /*-----------------------------------------------------------------*/
2111 /* cmdNext - next executable C statement file                      */
2112 /*-----------------------------------------------------------------*/
2113 int cmdNext (char *s, context *cctxt)
2114 {
2115     function *func = NULL;
2116     /* next is almost the same as step except we don't
2117        we don't set break point for all function entry
2118        points */
2119     if (!is_running())
2120         fprintf(stdout,"The program is not being run.\n");
2121     else
2122         do_step(cctxt, 0);
2123     return 0;
2124 }
2125
2126 /*-----------------------------------------------------------------*/
2127 /* cmdRun  - run till next break point                             */
2128 /*-----------------------------------------------------------------*/
2129 int cmdRun (char *s, context *cctxt)
2130 {
2131     char buff[10];
2132
2133     if (!is_running()) {
2134         fprintf(stdout,"Starting program\n");
2135     if ( ! simactive )
2136     {
2137         fprintf(stdout,"No executable file specified.\nUse the \"file\" command.\n");
2138         return 0;
2139     }
2140     resetHitCount();
2141         simGo(0);
2142     } else {
2143
2144         fprintf(stdout,
2145                 "The program being debugged has been started already.\n");
2146         fprintf(stdout,"Start it from the beginning? (y or n) ");
2147         fflush(stdout);
2148
2149         fgets(buff,sizeof(buff),stdin);
2150         if (toupper(buff[0]) == 'Y') {
2151             simReset();
2152         resetHitCount();
2153             simGo(0);
2154         }
2155     }
2156     showfull = 1;
2157     set_running(1);
2158     return 0;
2159 }
2160
2161 /*-----------------------------------------------------------------
2162  cmdListSymbols - list symbols
2163 |-----------------------------------------------------------------*/
2164 int cmdListSymbols (char *s, context *cctxt)
2165 {
2166     int our_verbose = 0;
2167     symbol *sy;
2168     int i;
2169
2170     if (strstr(s, "v1")) {
2171       our_verbose = 1;
2172     } else if (strstr(s, "v2")) {
2173       our_verbose = 2;
2174     }
2175
2176     printf("[symbols]\n");
2177     sy = setFirstItem(symbols);
2178     i = 0;
2179     for (;;) {
2180       if (sy == NULL)
2181         break;
2182       if (our_verbose <= 1)
2183         printf("<%s>", sy->name);
2184
2185       if (our_verbose > 1) {
2186         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
2187           sy->name, sy->size, sy->level, sy->block);
2188         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
2189           sy->isonstack, sy->isfunc, sy->offset, sy->addr);
2190         printf("    eaddr:%d, addr_type:%c, type:%p etype:%p\n",
2191           sy->eaddr, sy->addr_type, sy->type, sy->etype);
2192         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
2193           sy->scopetype, sy->sname, sy->rname, sy->addrspace);
2194         printf("    next:%p\n", sy->next);
2195       }
2196       ++i;
2197       sy = setNextItem(symbols);
2198     }
2199     printf("   %d symbols\n", i);
2200     return 0;
2201 }
2202
2203 /*-----------------------------------------------------------------
2204  cmdListFunctions - list functions.
2205 |-----------------------------------------------------------------*/
2206 int cmdListFunctions (char *s, context *cctxt)
2207 {
2208     function *f;
2209     int i;
2210     int our_verbose = 0;
2211
2212     if (strstr(s, "v1")) {
2213       our_verbose = 1;
2214     } else if (strstr(s, "v2")) {
2215       our_verbose = 2;
2216     }
2217
2218     printf("[functions]\n");
2219     f = setFirstItem(functions);
2220     i = 0;
2221     while (f != NULL) {
2222       if (our_verbose) {
2223         printf("  %d) sym:%p, fname:%s, modName:%s, mod:%p\n", i,
2224           f->sym, f->sym->name, f->modName, f->mod);
2225         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
2226                 f->entryline, f->aentryline, f->exitline, f->aexitline);
2227         printf("    cfpoints:%p, afpoints:%p, laddr:%x, lline:%d\n",
2228                 f->cfpoints, f->afpoints, f->laddr, f->lline);
2229       }
2230       else {
2231         printf("<%s>", f->sym->name);
2232       }
2233       ++i;
2234       f = setNextItem(functions);
2235     }
2236     printf("   %d functions\n", i);
2237     return 0;
2238 }
2239
2240 /*-----------------------------------------------------------------
2241  cmdListModules - list modules.
2242 |-----------------------------------------------------------------*/
2243 int cmdListModules (char *s, context *cctxt)
2244 {
2245     module *m;
2246     srcLine *cs, *as;
2247     int i, mi;
2248     int our_verbose = 0;
2249
2250     if (strstr(s, "v1")) {
2251       our_verbose = 1;
2252     } else if (strstr(s, "v2")) {
2253       our_verbose = 2;
2254     }
2255
2256     printf("[modules]\n");
2257     m = setFirstItem(modules);
2258     mi = 0;
2259     for (;;) {
2260       if (m == NULL)
2261         break;
2262
2263       if (our_verbose >= 0) {
2264       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
2265         m->cfullname, m->afullname, m->name);
2266       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
2267               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
2268       printf("    cLines:%p, asmLines:%p\n",
2269               m->cLines, m->asmLines);
2270       }
2271       if (our_verbose >= 2) {
2272         if (m->ncLines) {
2273           printf("    [cLines] ");
2274           if ( our_verbose)
2275           for (i=0; i<m->ncLines; i++ ) {
2276               cs = m->cLines[i];
2277               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2278                  i, cs->addr, cs->block, cs->level, cs->src);
2279           }
2280           if (!our_verbose)
2281               printf("%d records", i);
2282         }
2283         if (m->nasmLines) {
2284           printf("    [asmLines] ");
2285           if ( our_verbose)
2286           for (i=0; i<m->nasmLines; i++ ) {
2287               as = m->asmLines[i];
2288               printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2289                  i, as->addr, as->block, as->level, as->src);
2290           }
2291           if (!our_verbose)
2292               printf("%d records", i);
2293         }
2294         printf("\n");
2295       }
2296
2297       m = setNextItem(modules);
2298     }
2299     return 0;
2300 }
2301
2302 /*-----------------------------------------------------------------
2303  infoSymbols - This is really just a tool to dump all these
2304    huge program structures out into human readable form.
2305 |-----------------------------------------------------------------*/
2306 static void infoSymbols(context *ctxt)
2307 {
2308   int our_verbose = 0;
2309
2310   printf("[context:%p] func:%p modName:%s addr:%x\n",
2311     ctxt, ctxt->func, ctxt->modName, ctxt->addr);
2312
2313   printf("  cline:%d asmline:%d block:%d level:%d\n",
2314     ctxt->cline, ctxt->asmline, ctxt->block, ctxt->level);
2315
2316   printf("[globals] currCtxt:%p, modules:%p, functions:%p symbols:%p\n",
2317     currCtxt, modules, functions, symbols);
2318   printf("  nStructs:%d, structs:%p, ssdirl:%s\n",
2319     nStructs, structs, ssdirl);
2320
2321   /**************** modules *******************/
2322   {
2323     module *m;
2324     srcLine *cs, *as;
2325     int i, mi;
2326     printf("[modules]\n");
2327     m = setFirstItem(modules);
2328     mi = 0;
2329     for (;;) {
2330       if (m == NULL)
2331         break;
2332       printf("  %d) cfullname:%s, afullname:%s, name:%s\n", ++mi,
2333         m->cfullname, m->afullname, m->name);
2334       printf("    c_name:%s, asm_name:%s, ncLines:%d, nasmLines:%d\n",
2335               m->c_name, m->asm_name, m->ncLines, m->nasmLines);
2336       printf("    cLines:%p, asmLines:%p\n",
2337               m->cLines, m->asmLines);
2338       i = 0;
2339       if (m->cLines) {
2340         cs = m->cLines[i++];
2341         printf("    [cLines] ");
2342         while (cs) {
2343           if (our_verbose)
2344             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2345                i, cs->addr, cs->block, cs->level, cs->src);
2346           cs = m->cLines[i++];
2347         }
2348         if (!our_verbose)
2349             printf("%d records", i);
2350       }
2351       i = 0;
2352       if (m->asmLines) {
2353         as = m->asmLines[i++];
2354         printf("    [asmLines] ");
2355         while (as) {
2356           if (our_verbose)
2357             printf("   (%d) addr:%x, block:%d, level:%d, src:%s\n",
2358                i, as->addr, as->block, as->level, as->src);
2359           as = m->asmLines[i++];
2360         }
2361         if (!our_verbose)
2362             printf("%d records", i);
2363       }
2364       printf("\n");
2365
2366       m = setNextItem(modules);
2367     }
2368   }
2369
2370   /**************** functions *******************/
2371   {
2372     function *f;
2373     int i;
2374     printf("[functions]\n");
2375     f = setFirstItem(functions);
2376     i = 0;
2377     for (;;) {
2378       if (f == NULL)
2379         break;
2380       if (our_verbose) {
2381         printf("  %d) sym:%p, modName:%s, mod:%p\n", i,
2382           f->sym, f->modName, f->mod);
2383         printf("    entryline:%d, aentryline:%d, exitline:%d, aexitline:%d\n",
2384                 f->entryline, f->aentryline, f->exitline, f->aexitline);
2385         printf("    cfpoints:%p, afpoints:%p, laddr:%x, lline:%d\n",
2386                 f->cfpoints, f->afpoints, f->laddr, f->lline);
2387       }
2388       ++i;
2389       f = setNextItem(functions);
2390     }
2391     if (!our_verbose)
2392       printf("   %d functions\n", i);
2393   }
2394
2395   /**************** symbols *******************/
2396   {
2397     symbol *s;
2398     int i;
2399     printf("[symbols]\n");
2400     s = setFirstItem(symbols);
2401     i = 0;
2402     for (;;) {
2403       if (s == NULL)
2404         break;
2405       if (our_verbose) {
2406         printf("  %d) name:%s, size:%d, level:%d block:%d\n", i,
2407           s->name, s->size, s->level, s->block);
2408         printf("    isonstack:%d, isfunc:%d, offset:%d addr:%d\n",
2409           s->isonstack, s->isfunc, s->offset, s->addr);
2410         printf("    eaddr:%d, addr_type:%c, type:%p etype:%p\n",
2411           s->eaddr, s->addr_type, s->type, s->etype);
2412         printf("    scopetype:%c, sname:%s, rname:%s addrspace:%c\n",
2413           s->scopetype, s->sname, s->rname, s->addrspace);
2414         printf("    next:%p\n", s->next);
2415       }
2416       ++i;
2417       s = setNextItem(symbols);
2418     }
2419     if (!our_verbose)
2420       printf("   %d symbols\n", i);
2421   }
2422
2423 }
2424
2425 /*-----------------------------------------------------------------*/
2426 /* infoRegisters - print register information                      */
2427 /*-----------------------------------------------------------------*/
2428 static void infoRegisters( int all, context *ctxt)
2429 {
2430     static int regaddrs[] = {0x81,0x82,0x83,0xb8,0xd0,0xe0,0xf0,0};
2431     unsigned long val;
2432     int i,j,*r;
2433
2434     i = simGetValue (0xd0,'I',1);
2435     fprintf(stdout,"IP  : 0x%04X  RegisterBank %d:\nR0-7:",ctxt->addr,(i>>3)&3);
2436     for ( j = 0; j < 8 ; j++ )
2437     {
2438         val = simGetValue (j,'R',1);
2439         fprintf(stdout," 0x%02lX",val);
2440     }
2441     fprintf(stdout,"\n");
2442     val = simGetValue (0xe0,'I',1);
2443     fprintf(stdout,"ACC : 0x%02lX %lu %c\n",val,val,(isprint(val) ? (char)val : '.'));
2444     val = simGetValue (0xf0,'I',1);
2445     fprintf(stdout,"B   : 0x%02lX %lu %c\n",val,val,(isprint(val) ? (char)val : '.'));
2446     val = simGetValue (0x82,'I',2);
2447     fprintf(stdout,"DPTR: 0x%04lX %lu\n",val,val);
2448     val = simGetValue (0x81,'I',1);
2449     fprintf(stdout,"SP  : 0x%02lX (0x%04lX)\n",val,simGetValue (val-1,'B',2));
2450     fprintf(stdout,"PSW : 0x%02X | CY : %c | AC : %c | OV : %c | P : %c\n",
2451             i,(i&0x80)?'1':'0',(i&0x40)?'1':'0',(i&4)?'1':'0',(i&1)?'1':'0');
2452     if ( all )
2453     {
2454         fprintf(stdout,"Special Function Registers:\n");
2455         r = regaddrs;
2456         for ( i = 0x80 ; i < 0x100 ; i++ )
2457         {
2458             symbol *sym = NULL;
2459             if ( *r && *r == i )
2460             {
2461                 /* skip normal registers */
2462                 r++ ;
2463                 continue;
2464             }
2465             if (applyToSetFTrue(sfrsymbols,symWithAddr,i,'I',&sym))
2466             {
2467                 val = simGetValue (sym->addr,sym->addrspace,sym->size);
2468                 fprintf(stdout,"%s : 0x%02lx",sym->name,val);
2469                 if ( !(i & 0x07 ))
2470                 {
2471                     for ( j = 0 ; j < 8 ; j++ )
2472                     {
2473                         sym = NULL;
2474                         if (applyToSetFTrue(sfrsymbols,symWithAddr,i+j,'J',&sym))
2475                         {
2476                             //val = simGetValue (sym->addr,sym->addrspace,sym->size);
2477                             fprintf(stdout," %s=%c",sym->name,(val&1)? '1':'0');
2478                         }
2479                         val >>= 1;
2480                     }
2481                 }
2482                 fprintf(stdout,"\n");
2483             }
2484         }
2485     }
2486 }
2487
2488 /*-----------------------------------------------------------------*/
2489 /* infoStack - print call stack information                        */
2490 /*-----------------------------------------------------------------*/
2491 static void infoStack(context *ctxt)
2492 {
2493     function *func ;
2494     int i = 0 ;
2495     context *ctx, my_context;
2496     unsigned int bp, pc, addr = ctxt->addr;
2497     int status;
2498
2499     for (status = frameStart(&bp,&pc); status; status = frameNext(&bp, &pc)) {
2500         ctx = discoverContext(pc, NULL, &my_context);
2501         if (ctx) {
2502             func = ctx->func;
2503         Dprintf(D_break, ("break: infoStack: %s 0x%02x\n",func->sym->name, bp));
2504     
2505             fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",i++,
2506                     pc,func->sym->name,
2507                     func->mod->c_name,func->lline+1);
2508         } else {
2509             fprintf(stdout,"#%d  0x%08x\n", i++, pc);
2510         }
2511     }
2512     if ( !i )
2513         fprintf(stdout,"no stack.\n");
2514 }
2515
2516 /*-----------------------------------------------------------------*/
2517 /* cmdWhere -  where command                                       */
2518 /*-----------------------------------------------------------------*/
2519 int cmdWhere(char *s, context *cctxt)
2520 {
2521         infoStack(cctxt);
2522         return 0;
2523 }
2524
2525
2526 static int infomode = 0;
2527 /*-----------------------------------------------------------------*/
2528 /* cmdInfo - info command                                          */
2529 /*-----------------------------------------------------------------*/
2530 int cmdInfo (char *s, context *cctxt)
2531 {
2532     /* trim left and_right*/
2533     s = trim(s);
2534
2535     /* list all break points */
2536     if (strncmp(s,"break",5) == 0) {
2537         listUSERbp();
2538         return 0;
2539     }
2540
2541     /* info frame same as frame */
2542     if (strncmp(s,"frame",5) == 0) {
2543         cmdFrame (s+5,cctxt);
2544         return 0;
2545     }
2546
2547     if (strncmp(s,"line",4) == 0) {
2548         infomode=1;
2549         cmdListSrc (s+4,cctxt);
2550         return 0;
2551     }
2552     if (strncmp(s,"source",6) == 0)
2553     {
2554         module *m;
2555         if ( s[6] == 's' )
2556         {
2557             int k = 0;
2558             fprintf(stdout,"Source files for which symbols have been read in:\n\n");
2559             for (m = setFirstItem(modules); m ; m = setNextItem(modules))
2560             {
2561                 fprintf(stdout,"%s%s, %s",k ? ", ":"",m->cfullname, m->afullname);
2562                 k = 1;
2563             }
2564             fprintf(stdout,"\n");
2565         }
2566         else
2567         {
2568             if (!cctxt || !cctxt->func || !cctxt->func->mod)
2569             {
2570                 fprintf(stdout,"No source file loaded\n");
2571                 return 0;
2572             }
2573             m = cctxt->func->mod;
2574             fprintf(stdout,"Current source file is %s\n",m->c_name);
2575             fprintf(stdout,"Located in %s\n",m->cfullname);
2576             fprintf(stdout,"Contains %d lines.\nSource language is c.\n",
2577                     m->ncLines);
2578         }
2579         return 0;
2580     }
2581     if (strcmp(s,"functions") == 0)
2582     {
2583         function *f;
2584         module *m = NULL;
2585         fprintf(stdout,"All defined functions:\n");
2586         for ( f = setFirstItem(functions); f ; f = setNextItem(functions))
2587         {
2588             if ( f->mod != m )
2589             {
2590                 m = f->mod;
2591                 fprintf(stdout,"\nFile %s\n", m->c_name);
2592             }
2593             fprintf(stdout,"%s();\n",f->sym->name);
2594         }
2595         return 0;
2596     }
2597     /* info stack display call stack */
2598     if (strcmp(s,"stack") == 0) {
2599         infoStack(cctxt);
2600         showfull = 1;
2601         return 0;
2602     }
2603
2604     /* info stack display call stack */
2605     if (strcmp(s,"registers") == 0) {
2606         infoRegisters(0,cctxt);
2607             return 0;
2608     }
2609
2610     /* info stack display call stack */
2611     if (strcmp(s,"all-registers") == 0)
2612     {
2613         infoRegisters(1,cctxt);
2614         return 0;
2615     }
2616
2617     /* info stack display call stack */
2618     if (strcmp(s,"symbols") == 0) {
2619       /* dump out symbols we have read in */
2620       fprintf(stdout,"Dumping symbols...\n");
2621       infoSymbols(cctxt);
2622       return 0;
2623     }
2624
2625     if (strcmp(s,"variables") == 0) {
2626       /* dump out symbols we have read in */
2627       fprintf(stdout,"Dumping symbols...\n");
2628       infoSymbols(cctxt);
2629       return 0;
2630     }
2631
2632     fprintf(stdout,"Undefined info command: \"%s\".  Try \"help\n",s);
2633     return 0;
2634
2635 }
2636
2637 /*-----------------------------------------------------------------*/
2638 /* cmdQuit  - quit debugging                                       */
2639 /*-----------------------------------------------------------------*/
2640 int cmdQuit (char *s, context *cctxt)
2641 {
2642     if (simactive)
2643         closeSimulator();
2644     return 1;
2645 }
2646
2647 /*-----------------------------------------------------------------*/
2648 /* cmdListSrc  - list src                                          */
2649 /*-----------------------------------------------------------------*/
2650 int cmdListSrc (char *s, context *cctxt)
2651 {
2652     static int currline = 0;
2653     int i =0 ;
2654     int pline = 0;
2655     int llines = listlines;
2656     function *func = NULL;
2657
2658
2659     s = trim_left(s);
2660
2661     /* if the user has spcified line numer then the line number
2662        can be of the following formats
2663        LINE          - just line number
2664        FILE:LINE     - filename line number
2665        FILE:LINE,LASTLINE  + last line
2666        FUNCTION      - list a function
2667        FILE:FUNCTION - function in file */
2668
2669     if (*s) {
2670         /* case a) LINE */
2671         if (isdigit(*s)) {
2672             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2673               if (!list_mod) {
2674                 fprintf(stdout,"Sdcdb fails to have a proper context at %d.\n", __LINE__);
2675                 return 0;
2676               }
2677             }
2678             else
2679               list_mod = cctxt->func->mod;
2680         pline = strtol(s,&s,10) - 1;
2681         if (s && (s = strchr(s,',')))
2682         {
2683             /* LINE,LASTLINE */
2684             llines = strtol(s+1,0,10);
2685             if ( llines > 0 )
2686                 llines -= pline+1;
2687             else
2688                 llines = listlines;
2689         }
2690         }
2691         else {
2692             char *bp;
2693
2694             /* if ':' present then FILE:LINE || FILE:FUNCTION */
2695             if ((bp = strchr(s,':'))) {
2696                 *bp = '\0';
2697                 bp ++;
2698                 if (isdigit(*bp)) {
2699                     /* FILE:LINE */
2700                     list_mod=NULL;  /* bug fix 2-09-02, moduleWithCName expects mod to be null */
2701                     if (srcMode == SRC_CMODE) {
2702                         if (!applyToSet(modules,moduleWithCName,s,&list_mod)) {
2703                             fprintf (stderr,"No c source file named %s.\n",s);
2704                             return 0;
2705                         }
2706                     } else {
2707                         if (!applyToSet(modules,moduleWithAsmName,s,&list_mod)) {
2708                             fprintf (stderr,"No source file named %s.\n",s);
2709                             return 0;
2710                         }
2711                     }
2712                     pline = strtol(bp,&bp,10) - 1;
2713             if (bp && (bp = strchr(bp,',')))
2714             {
2715                 /* FILE:LINE,LASTLINE */
2716                 llines = strtol(bp+1,0,10);
2717                 if ( llines > 0 )
2718                     llines -= pline+1;
2719                 else
2720                     llines = listlines;
2721             }
2722                 } else {
2723                     /* FILE:FUCTION */
2724                     if (!applyToSet(functions,funcWithNameModule,bp,s,&func)) {
2725                         fprintf(stdout,"Function \"%s\" not defined.\n",bp);
2726                         return 0;
2727                     }
2728                     list_mod = func->mod;
2729                     if (srcMode == SRC_CMODE) {
2730                         pline = func->entryline;
2731                         llines = func->exitline - func->entryline + 1;
2732                     } else {
2733                         pline = func->aentryline;
2734                         llines = func->aexitline - func->aentryline + 1;
2735                     }
2736                 }
2737             }
2738             else {
2739                 /* FUNCTION */
2740             if (*s == '\'')
2741             {
2742                 /* 'FUNCTION' */
2743                 s++ ;
2744                 if ((bp = strrchr(s,'\'')))
2745                 {
2746                     *bp = '\0';
2747                 }
2748
2749             }
2750                 if (!applyToSet(functions,funcWithName,s,&func)) {
2751                     fprintf(stderr,"Function \"%s\" not defined.\n",s);
2752                     return 0;
2753                 }
2754                 else {
2755                     list_mod = func->mod;
2756                     if (srcMode == SRC_CMODE) {
2757                         pline = func->entryline;
2758                         llines = func->exitline - func->entryline + 1;
2759                     } else {
2760                         pline = func->aentryline;
2761                         llines = func->aexitline - func->aentryline + 1;
2762                     }
2763                 }
2764             }
2765         }
2766     } else {
2767         /* if no line specified & we had listed
2768            before then continue from that listing */
2769         if (currline)
2770             pline = currline ;
2771         else {
2772             if (!cctxt || !cctxt->func || !cctxt->func->mod) {
2773               fprintf(stdout,"Missing context at %d. Try list filename:lineno\n", __LINE__);
2774               return 0;
2775             }
2776             list_mod = cctxt->func->mod;
2777             if (srcMode == SRC_CMODE)
2778                 pline = cctxt->cline;
2779             else
2780                 pline = cctxt->asmline;
2781         }
2782     }
2783
2784     if (!list_mod) {
2785       fprintf(stdout,"Sdcdb fails to have a valid module context at %d.\n", __LINE__);
2786       return 0;
2787     }
2788
2789     if ( pline < 0 )
2790         return 0;
2791     if ( infomode )
2792     {
2793         unsigned firstaddr , lastaddr ;
2794             if ( pline  >= list_mod->ncLines )
2795             pline = cctxt->cline;
2796         firstaddr = lastaddr = list_mod->cLines[pline]->addr;
2797         if (!func && cctxt && cctxt->func )
2798             func = cctxt->func;
2799             fprintf(stdout,"Line %d of \"%s\" starts at address 0x%08x <%s+%d>",
2800                 pline+1,
2801                 list_mod->c_name, lastaddr,
2802                 func ? func->sym->name : "?",
2803                 func ? lastaddr -func->sym->addr : 0);
2804         llines = pline +1;
2805         for ( ; pline < list_mod->ncLines; pline++ )
2806         {
2807             if ( list_mod->cLines[pline]->addr > lastaddr )
2808             {
2809                 lastaddr = list_mod->cLines[pline]->addr -1;
2810                 break;
2811             }
2812         }
2813         fprintf(stdout," and ends at 0x%08x <%s+%d>.\n",
2814                 lastaddr,
2815                 func ? func->sym->name : "?",
2816                 func ? lastaddr -func->sym->addr : 0);
2817         infomode=0;
2818         if ( func )
2819             fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
2820                     canonname(func->mod->cfullname),
2821                     llines,firstaddr);
2822         else
2823             showfull=1;
2824         return 0;
2825     }
2826     for ( i = 0 ; i < llines ; i++ ) {
2827         if (srcMode == SRC_CMODE) {
2828             if ( (pline + i) >= list_mod->ncLines )
2829                 break;
2830             fprintf(stdout,"%d\t%s",pline + i,
2831                     list_mod->cLines[pline +i]->src);
2832         } else {
2833             if ( (pline + i) >= list_mod->nasmLines )
2834                 break;
2835             fprintf(stdout,"%d\t%s",pline + i,
2836                     list_mod->asmLines[pline +i]->src);
2837         }
2838     }
2839     currline = pline + i ;
2840     return 0;
2841 }
2842
2843 static unsigned long getValBasic(symbol *sym, link *type, char *val)
2844 {
2845     char *s;
2846     union
2847     {
2848         float f;
2849         unsigned long val;
2850         long         sval;
2851         struct {
2852             unsigned short    lo;
2853             unsigned short    hi;
2854         } i;
2855         unsigned char b[4];
2856     }v;
2857
2858     if (IS_FLOAT(type))
2859         v.f = strtod(val,NULL);
2860     else
2861         if (IS_PTR(type))
2862             v.val = strtol(val,NULL,0);
2863         else
2864     {
2865             if (IS_INTEGRAL(type))
2866         {
2867             link *etype;
2868             if ( type->next )
2869                 etype = type->next;
2870             else
2871                 etype = type;
2872             if (IS_CHAR(etype))
2873             {
2874                 if (( s = strchr(val,'\'')))
2875                 {
2876                     if ( s[1] == '\\' )
2877                         v.b[0] = strtol(s+2,NULL,8);
2878                     else
2879                         v.b[0] = s[1];
2880                 }
2881                 else
2882                 {
2883                     v.b[0] = strtol(val,NULL,0);
2884                 }
2885             }
2886             else
2887                 if (IS_INT(etype))
2888                     if (IS_LONG(etype))
2889                         v.val = strtol(val,NULL,0);
2890                     else
2891                         v.i.lo = strtol(val,NULL,0);
2892                 else
2893                     v.val = strtol(val,NULL,0);
2894             }
2895         else
2896             v.val = strtol(val,NULL,0);
2897     }
2898     return v.val;
2899 }
2900
2901 /*-----------------------------------------------------------------*/
2902 /* printFmtInteger - print value in bin,oct,dez or hex             */
2903 /*-----------------------------------------------------------------*/
2904 static void printFmtInteger(char *deffmt,int fmt, long val,
2905                             int sign, int size)
2906 {
2907     static char digits[] =
2908     {
2909         '0' , '1' , '2' , '3' , '4' , '5' ,
2910         '6' , '7' , '8' , '9' , 'a' , 'b' ,
2911         'c' , 'd' , 'e' , 'f' , 'g' , 'h'
2912     };
2913     static int radixOfFormat[] = { 0 , 2, 8 ,10, 16  };
2914     static int olenOfSize[]    = { 0 , 3, 6 , 8, 11  };
2915         char buf[40];
2916         char negative = 0;
2917         int charPos = 38;
2918     int radix;
2919
2920     if ( fmt == FMT_NON || fmt == FMT_DEZ )
2921     {
2922         fprintf(stdout,deffmt,val);
2923         return;
2924     }
2925     radix = radixOfFormat[fmt];
2926
2927     /*
2928     if ( sign && val < 0 )
2929         negative = 1;
2930     */
2931
2932         if (!negative)
2933             val = -val;
2934
2935         buf[39] = '\0';
2936     while (val <= -radix)
2937     {
2938             buf[charPos--] = digits[-(val % radix)];
2939             val = val / radix;
2940         }
2941         buf[charPos] = digits[-val];
2942
2943     switch ( fmt )
2944     {
2945         case FMT_OCT:
2946             radix = olenOfSize[size];
2947             break;
2948         case FMT_HEX:
2949             radix = size << 1;
2950             break;
2951         case FMT_BIN:
2952             radix = size << 3;
2953             break;
2954     }
2955
2956     while (charPos > 39 - radix )
2957     {
2958         buf[--charPos] = '0';
2959     }
2960     switch ( fmt )
2961     {
2962         case FMT_OCT:
2963             if ( buf[charPos] != '0' )
2964                 buf[--charPos] = '0';
2965             break;
2966         case FMT_HEX:
2967             buf[--charPos] = 'x';
2968             buf[--charPos] = '0';
2969             break;
2970     }
2971         if (negative) {
2972             buf[--charPos] = '-';
2973         }
2974     fputs(&buf[charPos],stdout);
2975 }
2976
2977 /*-----------------------------------------------------------------*/
2978 /* printValBasic - print value of basic types                      */
2979 /*-----------------------------------------------------------------*/
2980 static void printValBasic(symbol *sym, link *type,
2981                           char mem, unsigned addr,int size, int fmt)
2982 {
2983     union {
2984         float f;
2985         unsigned long val;
2986         long         sval;
2987         struct {
2988             unsigned short    lo;
2989             unsigned short    hi;
2990         } i;
2991         unsigned char b[4];
2992     }v;
2993
2994     v.val = simGetValue(addr,mem,size);
2995     /* if this a floating point number then */
2996     if (IS_FLOAT(type))
2997         fprintf(stdout,"%f",v.f);
2998     else
2999         if (IS_PTR(type))
3000             fprintf(stdout,"0x%0*lx",size<<1,v.val);
3001         else
3002         if (IS_INTEGRAL(type))
3003         {
3004             link *etype;
3005             if ( type->next )
3006                 etype = type->next;
3007             else
3008                 etype = type;
3009             if (IS_CHAR(etype))
3010             {
3011                 if ( isprint(v.val))
3012                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'%c'"),
3013                                     fmt,(long)v.val,0,size);
3014                 else
3015                     printFmtInteger((SPEC_USIGN(etype)?"0x%02x":"'\\%o'"),
3016                                     fmt,(long)v.val,0,size);
3017             }
3018             else
3019             {
3020                 if (IS_INT(etype))
3021                     if (IS_LONG(etype))
3022                         if (SPEC_USIGN(etype))
3023                             printFmtInteger("%u",fmt,(long)v.val,0,size);
3024                         else
3025                             printFmtInteger("%d",fmt,(long)v.sval,1,size);
3026                     else
3027                         if (SPEC_USIGN(etype))
3028                             printFmtInteger("%u",fmt,(long)v.i.lo,0,size);
3029                         else
3030                             printFmtInteger("%d",fmt,(long)v.i.lo,1,size);
3031                 else
3032                 {
3033                     if (IS_BITVAR(etype))
3034                         fprintf(stdout,"%c",(v.val?'1':'0'));
3035                     else
3036                         fprintf(stdout,"0x%0*lx",size<<1,v.val);
3037                 }
3038             }
3039             } else
3040             fprintf(stdout,"0x%0*lx",size<<1,v.val);
3041 }
3042
3043 /*-----------------------------------------------------------------*/
3044 /* printValFunc  - prints function values                          */
3045 /*-----------------------------------------------------------------*/
3046 static void printValFunc (symbol *sym, int fmt)
3047 {
3048     fprintf(stdout,"print function not yet implemented");
3049 }
3050
3051 static void
3052 do_indent(int indent) {
3053     while (indent--)
3054         fprintf(stdout, "  ");
3055
3056 }
3057
3058 /*-----------------------------------------------------------------*/
3059 /* printArrayValue - will print the values of array elements       */
3060 /*-----------------------------------------------------------------*/
3061 static void printArrayValue (symbol *sym,  link *type,
3062                              char space, unsigned int addr, int fmt,
3063                              int indent)
3064 {
3065     link *elem_type = type->next;
3066     int i;
3067     int col;
3068
3069     fprintf(stdout,"{");
3070     for (i = 0 ; i < DCL_ELEM(type) ; i++) {
3071         if (IS_AGGREGATE(elem_type)) {
3072             printValAggregates(sym,elem_type,space,addr,fmt,indent);
3073             col = 0;
3074         } else {
3075             printValBasic(sym,elem_type,space,addr,getSize(elem_type),fmt);
3076             col++;
3077         }
3078         addr += getSize(elem_type);
3079         if (i != DCL_ELEM(type) -1) {
3080             fprintf(stdout,",");
3081             if (col == 16) {
3082                 fprintf(stdout,"\n");
3083                 do_indent(indent);
3084                 col = 0;
3085             }
3086         }
3087     }
3088
3089     fprintf(stdout,"}");
3090 }
3091
3092 /*-----------------------------------------------------------------*/
3093 /* printStructValue - prints structures elements                   */
3094 /*-----------------------------------------------------------------*/
3095 static void printStructValue (symbol *sym, link *type,
3096                               char space, unsigned int addr, int fmt,
3097                               int indent)
3098 {
3099     symbol *fields = SPEC_STRUCT(type)->fields;
3100     int first = 1;
3101     do_indent (indent);
3102     fprintf(stdout,"{\n");
3103     while (fields) {
3104         do_indent(indent + 1);
3105         fprintf(stdout,"%s = ", fields->name);
3106         first = 0;
3107         if (IS_AGGREGATE(fields->type)) {
3108             printValAggregates(fields,fields->type,space, addr, fmt, indent + 1);
3109         } else {
3110             printValBasic(fields,fields->type,space,addr,getSize(fields->type), fmt);
3111         }
3112         fprintf(stdout,",\n");
3113         addr += getSize(fields->type);
3114         fields = fields->next;
3115     }
3116     do_indent(indent);
3117     fprintf(stdout,"}");
3118 }
3119
3120 /*-----------------------------------------------------------------*/
3121 /* printValAggregates - print value of aggregates                  */
3122 /*-----------------------------------------------------------------*/
3123 static void printValAggregates (symbol *sym, link *type,
3124                                 char space,unsigned int addr, int fmt,
3125                                 int indent)
3126 {
3127
3128         if (IS_ARRAY(type)) {
3129                 printArrayValue(sym, type, space, addr, fmt, indent);
3130                 return ;
3131         }
3132
3133         if (IS_STRUCT(type)) {
3134                 printStructValue(sym, type, space, addr, fmt, indent);
3135                 return;
3136         }
3137 }
3138
3139 /*-----------------------------------------------------------------*/
3140 /* printOrSetSymValue - print or set value of a symbol             */
3141 /*-----------------------------------------------------------------*/
3142 static int printOrSetSymValue (symbol *sym, context *cctxt,
3143                                 int flg, int dnum, int fmt, char *rs,
3144                                 char *val, char cmp )
3145 {
3146     static char fmtChar[] = " todx ";
3147     static int stack = 1;
3148         symbol *fields;
3149     link *type;
3150     unsigned int  addr;
3151     int size, n;
3152     char *s, *s2;
3153     char save_ch, save_ch2;
3154     int get_member = 0;
3155
3156     /* if it is on stack then compute address & fall thru */
3157     if (sym->isonstack)
3158     {
3159         symbol *bp = symLookup("bp",cctxt);
3160         if (!bp)
3161         {
3162             fprintf(stdout,"cannot determine stack frame\n");
3163             return 1;
3164         }
3165
3166         sym->addr = simGetValue(bp->addr,bp->addrspace,bp->size)
3167             + sym->offset ;
3168     }
3169
3170     /* get the value from the simulator and
3171        print it */
3172     switch (flg)
3173     {
3174         case 0:
3175         default:
3176             break;
3177         case 1:
3178             fprintf(stdout,"$%d = ",stack++);
3179             break;
3180         case 2:
3181             fprintf(stdout,"%d: ", dnum);
3182             if ( fmt != FMT_NON )
3183                 fprintf(stdout,"/%c ",fmtChar[fmt]);
3184             fprintf(stdout,"%s%s = ",sym->name,rs);
3185             break;
3186     }
3187
3188     addr = sym->addr;
3189     type = sym->type;
3190     size = sym->size;
3191
3192     while ( *rs )
3193     {
3194         if ( *rs == '[' && (IS_ARRAY(type) || IS_PTR(type)))
3195         {
3196             s = rs+1;
3197             while ( *rs && *rs != ']' ) rs++ ;
3198             save_ch = *rs;
3199             *rs = '\0' ;
3200             if ( ! isdigit(*s ))
3201             {
3202                 /* index seems a variable */
3203                 for ( s2 = s; *s2 && ( isalnum( *s2 ) || *s2 == '_'); s2++ );
3204                 save_ch2 = *s2;
3205                 if ( *s2 )
3206                     *s2 = '\0';
3207                 fields = symLookup(s,cctxt);
3208                 *s2 = save_ch2;
3209                 if ( ! fields )
3210                 {
3211                     fprintf(stdout,"Unknown variable \"%s\" for index.\n", s);
3212                     return 1;
3213                 }
3214                 /* arrays & structures first */
3215                 if (! IS_INTEGRAL(fields->type))
3216                 {
3217                     fprintf(stdout,"Wrong type of variable \"%s\" for index \n", s);
3218                     return 1;
3219                 }
3220                 n = simGetValue(fields->addr,fields->addrspace,getSize(fields->type));
3221             }
3222             else
3223             {
3224                 n = strtol(s,0,0);
3225             }
3226             if ( IS_ARRAY(type) && (n < 0 || n >= DCL_ELEM(type)))
3227             {
3228                 fprintf(stdout,"Wrong index %d.\n", n);
3229                 return 1;
3230             }
3231             if (IS_PTR(type))
3232                 addr = simGetValue(addr, sym->addrspace, size);
3233             type = type->next;
3234             size = getSize(type);
3235             addr += size * n;
3236             *rs++ = save_ch;
3237         }
3238         else if ( (*rs == '.' || get_member) && IS_STRUCT(type))
3239         {
3240             s = rs+1;
3241             /* search structure element */
3242             for ( rs = s; *rs && ( isalnum( *rs ) || *rs == '_'); rs++ );
3243             save_ch = *rs;
3244             if ( *rs )
3245                 *rs = '\0';
3246             for (fields = SPEC_STRUCT(type)->fields; fields; fields = fields->next)
3247             {
3248                 if (!(strcmp(s,fields->name)))
3249                     break;
3250             }
3251             *rs = save_ch;
3252             if ( ! fields )
3253             {
3254                 fprintf(stdout,"Unknown field \"%s\" of structure\n", s);
3255                 return 1;
3256             }
3257             type = fields->type;
3258             size = getSize(type);
3259             addr += fields->offset;
3260         }
3261         else if ( *rs == '*' && IS_PTR(type))
3262         {
3263             addr = simGetValue(addr, sym->addrspace, size);
3264             type = type->next;
3265             size = getSize(type);
3266             rs++;
3267         }
3268         else if ( rs[0] == '-' && rs[1] == '>' &&
3269                  IS_PTR(type) && IS_STRUCT(type->next))
3270         {
3271             addr = simGetValue(addr, sym->addrspace, size);
3272             type = type->next;
3273             size = getSize(type);
3274             rs++;
3275             get_member = 1;
3276             continue;
3277         }
3278         else
3279             break;
3280         get_member = 0;
3281     }
3282
3283     /* arrays & structures first */
3284     if (IS_AGGREGATE(type))
3285     {
3286             if ( val )
3287         {
3288             fprintf(stdout,"Cannot set/compare aggregate variable\n");
3289             return 1;
3290         }
3291         else
3292             printValAggregates(sym,type,sym->addrspace,addr,fmt,0);
3293     }
3294     else
3295         /* functions */
3296         if (IS_FUNC(type))
3297     {
3298             if ( !val )
3299             printValFunc(sym,fmt);
3300         else
3301             return 1;
3302     }
3303         else
3304     {
3305             if ( val )
3306         {
3307             unsigned long newval;
3308             newval = getValBasic(sym,type,val);
3309
3310             if ( cmp )
3311             {
3312                 unsigned long lval;
3313                 lval = simGetValue(addr,sym->addrspace,size);
3314                 switch ( cmp )
3315                 {
3316                     case '<' : return ( lval <  newval ? 1:0 ); break;
3317                     case '>' : return ( lval >  newval ? 1:0 ); break;
3318                     case 'l' : return ( lval <= newval ? 1:0 ); break;
3319                     case 'g' : return ( lval >= newval ? 1:0 ); break;
3320                     case '=' : return ( lval == newval ? 1:0 ); break;
3321                     case '!' : return ( lval != newval ? 1:0 ); break;
3322                 }
3323             }
3324             else
3325             {
3326                 if ( sym->addrspace == 'I' && addr == 0xb8 )
3327                 {
3328                     /* Symbol with address of IP */
3329                     if ( cctxt ) cctxt->addr = newval;
3330                     simSetPC(cctxt->addr);
3331                 }
3332                 else
3333                     simSetValue(addr,sym->addrspace,size,newval);
3334                 return 1;
3335             }
3336         }
3337         else
3338             printValBasic(sym,type,sym->addrspace,addr,size,fmt);
3339     }
3340     if ( flg > 0 ) fprintf(stdout,"\n");
3341         return 0;
3342 }
3343
3344 /*-----------------------------------------------------------------*/
3345 /* printStructInfo - print out structure information               */
3346 /*-----------------------------------------------------------------*/
3347 static void printStructInfo (structdef *sdef)
3348 {
3349     symbol *field = sdef->fields ;
3350     int i = 0 ;
3351
3352     while (field) {
3353         i += field->offset;
3354         field = field->next;
3355     }
3356
3357     fprintf(stdout,"%s %s {\n",(i ? "struct" : "union" ), sdef->tag);
3358     field = sdef->fields;
3359     while (field) {
3360         printTypeInfo (field->type);
3361         fprintf(stdout," %s ;\n",field->name);
3362         field = field->next ;
3363     }
3364
3365     fprintf(stdout,"}\n");
3366
3367 }
3368
3369 /*-----------------------------------------------------------------*/
3370 /* printTypeInfo - print out the type information                  */
3371 /*-----------------------------------------------------------------*/
3372 static void printTypeInfo(link *p)
3373 {
3374     if (!p)
3375         return ;
3376
3377     if (IS_DECL(p)) {
3378         switch (DCL_TYPE(p))  {
3379         case FUNCTION:
3380             printTypeInfo (p->next);
3381             fprintf(stdout,"()");
3382             break;
3383         case ARRAY:
3384             printTypeInfo (p->next);
3385             fprintf(stdout,"[%d]",DCL_ELEM(p));
3386             break;
3387
3388         case IPOINTER:
3389         case PPOINTER:
3390         case POINTER:
3391             printTypeInfo (p->next);
3392             fprintf(stdout,"(_near *)");
3393             break;
3394
3395         case FPOINTER:
3396             printTypeInfo (p->next);
3397             fprintf(stdout,"(_xdata *)");
3398             break;
3399
3400         case CPOINTER:
3401             printTypeInfo( p->next);
3402             fprintf(stdout,"(_code *)");
3403             break;
3404
3405         case GPOINTER:
3406             printTypeInfo( p->next);
3407             fprintf(stdout,"(_generic *)");
3408             break;
3409         }
3410     } else {
3411         switch (SPEC_NOUN(p)) { /* depending on the specifier type */
3412         case V_INT:
3413             (IS_LONG(p) ? fputs("long ",stdout) :
3414              ( IS_SHORT(p) ? fputs("short ",stdout) :
3415                fputs("int ",stdout))) ;
3416             break;
3417         case V_FLOAT:
3418              fputs("float ",stdout);
3419              break;
3420
3421         case V_CHAR:
3422             fputs ("char ",stdout);
3423             break;
3424
3425         case V_VOID:
3426             fputs("void ",stdout);
3427             break;
3428
3429         case V_STRUCT:
3430             printStructInfo (SPEC_STRUCT(p));
3431             break;
3432
3433         case V_SBIT:
3434             fputs("sbit ",stdout);
3435             break;
3436
3437         case V_BIT:
3438             fprintf(stdout,": %d" ,SPEC_BLEN(p));
3439             break;
3440         }
3441     }
3442 }
3443
3444 /*-----------------------------------------------------------------*/
3445 /* conditionIsTrue - compare variable with constant value        */
3446 /*-----------------------------------------------------------------*/
3447 int conditionIsTrue( char *s, context *cctxt)
3448 {
3449     symbol *sym = NULL;
3450     int fmt;
3451     char *rs, *dup, cmp_char;
3452     dup = s = Safe_strdup(s);
3453     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )) || !sym)
3454         fmt = 1;
3455     else if (!( s =  strpbrk(rs,"<>=!")))
3456         fmt = 1;
3457     else
3458     {
3459         cmp_char = *s;
3460         *s++ = '\0';
3461         if ( *s == '=' )
3462         {
3463             /* if <= or >= an other char is used
3464              * == or !=  not checked in switch
3465              */
3466             switch( cmp_char )
3467             {
3468                 case '>': cmp_char = 'g' ; break;
3469                 case '<': cmp_char = 'l' ; break;
3470             }
3471             s++ ;
3472         }
3473         s = trim_left(s);
3474         fmt = printOrSetSymValue(sym,cctxt,0,0,0,rs,s,cmp_char);
3475     }
3476     Safe_free(dup);
3477     return fmt;
3478 }
3479
3480 /*-----------------------------------------------------------------*/
3481 /* cmdPrint - print value of variable                              */
3482 /*-----------------------------------------------------------------*/
3483 int cmdPrint (char *s, context *cctxt)
3484 {
3485     symbol *sym ;
3486     int fmt;
3487     char *rs;
3488     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
3489         return 0;
3490
3491     if ( sym )
3492     {
3493         printOrSetSymValue(sym,cctxt,1,0,fmt,rs,NULL,'\0');
3494     }
3495     return 0;
3496 }
3497
3498 /*-----------------------------------------------------------------*/
3499 /* cmdOutput - print value of variable without number and newline  */
3500 /*-----------------------------------------------------------------*/
3501 int cmdOutput (char *s, context *cctxt)
3502 {
3503     symbol *sym ;
3504     int fmt;
3505     char *rs;
3506     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
3507         return 0;
3508
3509     if ( sym )
3510     {
3511         printOrSetSymValue(sym,cctxt,0,0,fmt,rs,NULL,'\0');
3512     }
3513     return 0;
3514 }
3515
3516 /** find display entry with this number */
3517
3518 DEFSETFUNC(dsymWithNumber)
3519 {
3520     dsymbol *dsym = item;
3521     V_ARG(int , dnum);
3522     V_ARG(dsymbol **,dsymp);
3523
3524     if ( dsym->dnum == dnum )
3525     {
3526         *dsymp = dsym;
3527         return 1;
3528     }
3529     return 0;
3530 }
3531
3532 /*-----------------------------------------------------------------*/
3533 /* displayAll  - display all valid variables                       */
3534 /*-----------------------------------------------------------------*/
3535 void displayAll(context *cctxt)
3536 {
3537     dsymbol *dsym;
3538     symbol  *sym;
3539     if ( !dispsymbols )
3540         return;
3541     for (dsym = setFirstItem(dispsymbols);
3542          dsym ;
3543          dsym = setNextItem(dispsymbols))
3544     {
3545         if ( (sym = symLookup(dsym->name,cctxt)))
3546             printOrSetSymValue(sym,cctxt,2,dsym->dnum,dsym->fmt,
3547                                dsym->rs,NULL,'\0');
3548     }
3549 }
3550
3551 /*-----------------------------------------------------------------*/
3552 /* cmdDisplay  - display value of variable                         */
3553 /*-----------------------------------------------------------------*/
3554 int cmdDisplay (char *s, context *cctxt)
3555 {
3556     static int dnum = 1;
3557     symbol *sym ;
3558     int fmt;
3559     char *rs;
3560     if ( !( rs = preparePrint(s, cctxt, &fmt, &sym )))
3561     {
3562         displayAll(cctxt);
3563         return 0;
3564     }
3565
3566     if ( sym )
3567     {
3568         dsymbol *dsym = (dsymbol *)Safe_calloc(1,sizeof(dsymbol));
3569         dsym->dnum = dnum++ ;
3570         dsym->name = sym->name;
3571         dsym->fmt  = fmt;
3572         dsym->rs   = gc_strdup(rs);
3573         addSetHead(&dispsymbols,dsym);
3574     }
3575     return 0;
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /* cmdUnDisplay  - undisplay value of variable                              */
3580 /*-----------------------------------------------------------------*/
3581 int cmdUnDisplay (char *s, context *cctxt)
3582 {
3583     dsymbol *dsym;
3584     int dnum;
3585
3586     s = trim_left(s);
3587     if (!*s)
3588     {
3589         for (dsym = setFirstItem(dispsymbols);
3590              dsym;
3591              dsym = setNextItem(dispsymbols))
3592         {
3593             Safe_free(dsym->rs);
3594             Safe_free(dsym);
3595         }
3596         deleteSet(&dispsymbols);
3597         return 0;
3598     }
3599     while ( s && *s )
3600     {
3601         dnum = strtol(s,&s,10);
3602         if (applyToSetFTrue(dispsymbols,dsymWithNumber,dnum,&dsym))
3603         {
3604             deleteSetItem(&dispsymbols,dsym);
3605             Safe_free(dsym->rs);
3606             Safe_free(dsym);
3607         }
3608         else
3609         {
3610             fprintf(stdout,"Arguments must be display numbers.\n");
3611         }
3612     }
3613     return 0;
3614 }
3615
3616 /*-----------------------------------------------------------------*/
3617 /* cmdPrintType - print type of a variable                         */
3618 /*-----------------------------------------------------------------*/
3619 int cmdPrintType (char *s, context *cctxt)
3620 {
3621     symbol *sym ;
3622
3623     /* trim left and right */
3624     s = trim(s);
3625     if (!*s) return 0;
3626
3627     if ((sym = symLookup(s,cctxt))) {
3628         printTypeInfo(sym->type);
3629         fprintf(stdout,"\n");
3630     } else {
3631         fprintf(stdout,
3632                 "No symbol \"%s\" in current context.\n",
3633                 s);
3634     }
3635     return 0;
3636 }
3637
3638 /*-----------------------------------------------------------------*/
3639 /* cmdClrUserBp - clear user break point                           */
3640 /*-----------------------------------------------------------------*/
3641 int cmdClrUserBp (char *s, context *cctxt)
3642 {
3643     char *bp ;
3644     function *func = NULL;
3645
3646     /* clear break point location specification can be of the following
3647        forms
3648        a) <nothing>        - break point at current location
3649        b) lineno           - number of the current module
3650        c) filename:lineno  - line number of the given file
3651        e) filename:function- function X in file Y (useful for static functions)
3652        f) function         - function entry point
3653     */
3654
3655     if (!cctxt) {
3656         fprintf(stdout,"No symbol table is loaded.  Use the \"file\" command.\n");
3657         return 0;
3658     }
3659
3660     /* trim left and right */
3661     s = trim(s);
3662
3663     /* case a) nothing */
3664     /* if nothing given then current location : we know
3665        the current execution location from the currentContext */
3666     if (! *s ) {
3667
3668         /* if current context is known */
3669         if (cctxt->func)
3670             /* clear the break point @ current location */
3671             clearUSERbp (cctxt->addr);
3672         else
3673             fprintf(stderr,"No default breakpoint address now.\n");
3674
3675         goto ret ;
3676     }
3677
3678     /* case b) lineno */
3679     /* check if line number */
3680     if (isdigit(*s)) {
3681         /* get the lineno */
3682         int line = atoi(s);
3683
3684         /* if current context not present then we must get the module
3685            which has main & set the break point @ line number provided
3686            of that module : if current context known then set the bp
3687            at the line number given for the current module
3688         */
3689         if (cctxt->func) {
3690             if (!cctxt->func->mod) {
3691                 if (!applyToSet(functions,funcWithName,"main"))
3692                     fprintf(stderr,"Function \"main\" not defined.\n");
3693                 else
3694                     clearBPatModLine(func->mod,line);
3695             } else
3696                 clearBPatModLine(cctxt->func->mod,line);
3697         }
3698
3699         goto ret;
3700     }
3701
3702     if ((bp = strchr(s,':'))) {
3703
3704         module *mod = NULL;
3705         *bp = '\0';
3706
3707         if (!applyToSet(modules,moduleWithCName,s,&mod)) {
3708             fprintf (stderr,"No source file named %s.\n",s);
3709             goto ret;
3710         }
3711
3712         /* case c) filename:lineno */
3713         if (isdigit(*(bp +1))) {
3714
3715             clearBPatModLine (mod,atoi(bp+1));
3716             goto ret;
3717
3718         }
3719         /* case d) filename:function */
3720         if (!applyToSet(functions,funcWithNameModule,bp+1,s,&func))
3721             fprintf(stderr,"Function \"%s\" not defined.\n",bp+1);
3722         else
3723             clearBPatModLine (mod,func->entryline);
3724
3725         goto ret;
3726     }
3727
3728     /* case e) function */
3729     if (!applyToSet(functions,funcWithName,s,&func))
3730         fprintf(stderr,"Function \"%s\" not defined.\n",s);
3731     else
3732         clearBPatModLine(func->mod,func->entryline);
3733
3734  ret:
3735     return 0;
3736 }
3737
3738 /*-----------------------------------------------------------------*/
3739 /* cmdSimulator - send command to simulator                        */
3740 /*-----------------------------------------------------------------*/
3741 int cmdSimulator (char *s, context *cctxt)
3742 {
3743   char tmpstr[82];
3744
3745     if (strlen(s) > 80) {
3746       printf("error 3A\n");
3747       exit(1);
3748     }
3749     strcpy(tmpstr, s);
3750     strcat(tmpstr, "\n");
3751     sendSim(tmpstr);
3752     waitForSim(200,NULL);
3753     fprintf(stdout,"%s",simResponse());
3754     return 0;
3755 }
3756
3757 void setMainContext()
3758 {
3759     function *func = NULL;
3760     currentFrame = 0;
3761     if (!applyToSet(functions,funcWithName,"_main",&func) &&
3762         !applyToSet(functions,funcWithName,"main",&func))
3763             return;
3764
3765     discoverContext (func->sym->addr, func, currCtxt);
3766 }
3767
3768 function *needExtraMainFunction()
3769 {
3770     function *func = NULL;
3771     if (!applyToSet(functions,funcWithName,"_main",&func))
3772     {
3773         if (applyToSet(functions,funcWithName,"main",&func))
3774         {
3775             return func;
3776         }
3777     }
3778     return NULL;
3779 }
3780
3781 static void printFrame()
3782 {
3783     int i;
3784     function *func     = NULL;
3785     function *lastfunc = NULL;
3786     context *ctx, my_context;
3787     unsigned int bp, pc;
3788     int status;
3789
3790     if ( currentFrame < 0 )
3791     {
3792         currentFrame = 0;
3793         fprintf(stdout,"Bottom (i.e., innermost) frame selected; you cannot go down.\n");
3794         return;
3795     }
3796     i = 0;
3797     for (status = frameStart(&bp, &pc); status; status = frameNext(&bp, &pc))
3798     {
3799         if (i >= currentFrame)
3800             break;
3801         i++;
3802     }
3803     if (i < currentFrame) {
3804         currentFrame = i;
3805         fprintf(stdout,"Initial frame selected; you cannot go up.\n");
3806         return;
3807     }
3808     ctx = discoverContext(pc, NULL, &my_context);
3809     if (ctx && (func = ctx->func)) {
3810         fprintf(stdout,"#%d  0x%08x in %s () at %s:%d\n",
3811                 currentFrame,pc,func->sym->name,func->mod->c_name,func->lline+1);
3812         fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
3813                 canonname(func->mod->cfullname),func->lline+1,func->laddr);
3814     } else {
3815         fprintf(stdout,"#%d  0x%08x\n",
3816                 currentFrame,pc);
3817     }
3818 }
3819
3820
3821 /*-----------------------------------------------------------------*/
3822 /* cmdUp -  Up command                                             */
3823 /*-----------------------------------------------------------------*/
3824 int cmdUp(char *s, context *cctxt)
3825 {
3826     s = trim_left(s);
3827     if ( *s )
3828         currentFrame += strtol(s,0,10);
3829     else
3830         currentFrame++ ;
3831
3832     printFrame();
3833         return 0;
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* cmdDown - down command                                          */
3838 /*-----------------------------------------------------------------*/
3839 int cmdDown(char *s, context *cctxt)
3840 {
3841     s = trim_left(s);
3842     if ( *s )
3843         currentFrame -= strtol(s,0,10);
3844     else
3845         currentFrame-- ;
3846
3847     printFrame();
3848         return 0;
3849 }
3850 /*-----------------------------------------------------------------*/
3851 /* cmdFrame - Frame command                                        */
3852 /*-----------------------------------------------------------------*/
3853 int cmdFrame (char *s, context *cctxt)
3854 {
3855     function *func = NULL;
3856     int framenr = 0;
3857
3858     s = trim_left(s);
3859     if ( *s )
3860         currentFrame = strtol(s,0,10);
3861     printFrame();
3862     return 0;
3863 }
3864
3865 /*-----------------------------------------------------------------*/
3866 /* cmdFinish - exec till end of current function                   */
3867 /*-----------------------------------------------------------------*/
3868 int cmdFinish (char *s, context *ctxt)
3869 {
3870 #if 0
3871     if (STACK_EMPTY(callStack)) {
3872         fprintf(stdout,"The program is not running.\n");
3873         return 0;
3874     }
3875 #endif
3876
3877     if (srcMode == SRC_CMODE) {
3878         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP,
3879                        stepBpCB, ctxt->func->mod->c_name,
3880                        ctxt->func->exitline);
3881     } else {
3882         setBreakPoint (ctxt->func->sym->eaddr, CODE, STEP,
3883                        stepBpCB, ctxt->func->mod->asm_name,
3884                        ctxt->func->aexitline);
3885     }
3886
3887     simGo(-1);
3888     showfull = 1;
3889     return 0;
3890
3891 }
3892
3893
3894 /*-----------------------------------------------------------------*/
3895 /* cmdShow - show command                                          */
3896 /*-----------------------------------------------------------------*/
3897 int cmdShow (char *s, context *cctxt)
3898 {
3899     /* skip white space */
3900     s = trim_left(s);
3901
3902     if (strcmp(s,"copying") == 0) {
3903         fputs(copying,stdout);
3904         return 0;
3905     }
3906
3907     if (strcmp(s,"warranty") == 0) {
3908         fputs(warranty,stdout);
3909         return 0;
3910     }
3911
3912     return 0;
3913 }
3914