home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 August / PCO0897.ISO / filesbbs / os2 / plnk065.arj / PLNK065.ZIP / pilot-link.0.6.5 / pilot-debug.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-23  |  49.8 KB  |  1,826 lines

  1. /* pilot-debug.c:  Pilot debugging console, with optional graphics support
  2.  *
  3.  * This is free software, licensed under the GNU Public License V2.
  4.  * See the file COPYING for details.
  5.  *
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. #include <signal.h>
  12. #include <sys/time.h>
  13. #include <sys/types.h>
  14. #include "pi-source.h"
  15. #include "pi-socket.h"
  16. #include "pi-dlp.h"
  17. #include "pi-syspkt.h"
  18.  
  19. /* Definitions for functions in pd-tty.c */
  20.  
  21. extern void do_readline(void);
  22.  
  23. /* Display text asynchronously, and make sure it doesn't interfere with
  24.    the current prompt */
  25. extern void display(char * text, char * tag, int type);
  26.  
  27. #ifndef LIBDIR
  28. # define LIBDIR "."
  29. #endif
  30.  
  31. #ifdef TK
  32. int usetk;
  33. # include "tk.h"
  34. #else
  35. # include "tcl.h"
  36. #endif
  37.  
  38. #ifndef TCL_ACTIVE
  39. # define TCL_ACTIVE TCL_READABLE
  40. #endif
  41.  
  42. /*
  43.  * The following variable is a special hack that is needed in order for
  44.  * Sun shared libraries to be used for Tcl.
  45.  */
  46.  
  47. extern int matherr();
  48. int *tclDummyMathPtr = (int *) matherr;
  49.  
  50. int done = 0;
  51.  
  52. int Interactive = 1;
  53.  
  54. Tcl_Interp * interp;        
  55. struct Pilot_state state;
  56.  
  57. int debugger = 0; /* If non-zero, then debugger is thought to be active */
  58. int console = 0;  /* If non-zero, then console is thought to be active 
  59.                      Note: if both console and debugger are thought to be
  60.                            active, only the debugger will be usable. If
  61.                            execution is continued, the console be
  62.                            be usable again. */
  63. int stalestate = 1; /* If non-zero, then the current Pilot state (in particular the registers)
  64.                        should be assumed out-of-date */
  65.                        
  66. int port = 0;
  67.  
  68.  
  69. int tty;            /* Non-zero means standard input is a
  70.                  * terminal-like device.  Zero means it's*/
  71.  
  72.  
  73. /* Misc utility */
  74. void SetLabel(const char * label, const char * value)
  75. {
  76. #ifdef TK
  77.   if (usetk)
  78.     Tcl_VarEval(interp, label, " configure -text \"", value, "\"",NULL);
  79. #endif
  80. }
  81.  
  82. char * itoa(int val) {
  83.   static char buf[20];
  84.   sprintf(buf,"%d",val);
  85.   return buf;
  86. }
  87.  
  88. char * htoa(int val) {
  89.   static char buf[9];
  90.   sprintf(buf,"%8.8X",val);
  91.   return buf;
  92. }
  93.  
  94. char * h4toa(int val) {
  95.   static char buf[5];
  96.   sprintf(buf,"%4.4X",val);
  97.   return buf;
  98. }
  99.  
  100. int SayInteractive(char * text)
  101. {
  102.     Tcl_DString d;
  103.     
  104.     if (!Interactive)
  105.       return 0;
  106.     
  107.     Tcl_DStringInit(&d);
  108.  
  109. #ifdef TK
  110.     if (usetk) {
  111.         Tcl_DStringAppendElement(&d, ".f.t");
  112.         Tcl_DStringAppendElement(&d, "insert");
  113.         Tcl_DStringAppendElement(&d, "insert");
  114.         Tcl_DStringAppendElement(&d, text);
  115.         Tcl_Eval(interp, Tcl_DStringValue(&d));
  116.         Tcl_DStringFree(&d);
  117.         Tcl_DStringAppendElement(&d, ".f.t");    
  118.         Tcl_DStringAppendElement(&d, "see");
  119.         Tcl_DStringAppendElement(&d, "insert");
  120.         Tcl_Eval(interp, Tcl_DStringValue(&d));
  121.         Tcl_DStringFree(&d);
  122.     } else {
  123. #endif
  124.         Tcl_DStringAppendElement(&d, "puts");
  125.         Tcl_DStringAppendElement(&d, text);
  126.         Tcl_Eval(interp, Tcl_DStringValue(&d));
  127.         Tcl_DStringFree(&d);
  128.  
  129. #ifdef TK
  130.     }
  131. #endif
  132.     Tcl_Eval(interp, Tcl_DStringValue(&d));
  133.     Tcl_DStringFree(&d);
  134.     
  135.     return 0;
  136. }
  137.  
  138. int Say(char * text)
  139. {
  140.     Tcl_DString d;
  141.     
  142.     if (Interactive) {
  143.         Tcl_DStringInit(&d);
  144. #ifdef TK
  145.         if (usetk) {
  146.             Tcl_DStringAppendElement(&d, ".f.t");
  147.             Tcl_DStringAppendElement(&d, "insert");
  148.             Tcl_DStringAppendElement(&d, "insert");
  149.             Tcl_DStringAppendElement(&d, text);
  150.             Tcl_Eval(interp, Tcl_DStringValue(&d));
  151.             Tcl_DStringFree(&d);
  152.             Tcl_DStringAppendElement(&d, ".f.t");    
  153.             Tcl_DStringAppendElement(&d, "see");
  154.             Tcl_DStringAppendElement(&d, "insert");
  155.             Tcl_Eval(interp, Tcl_DStringValue(&d));
  156.             Tcl_DStringFree(&d);
  157.         } else {
  158. #endif
  159.             Tcl_DStringAppendElement(&d, "puts");
  160.             Tcl_DStringAppendElement(&d, text);
  161.             Tcl_Eval(interp, Tcl_DStringValue(&d));
  162.             Tcl_DStringFree(&d);
  163.  
  164. #ifdef TK
  165.         }
  166. #endif
  167.     } else 
  168.             Tcl_AppendResult(interp, text, NULL);
  169.     
  170.     return 0;
  171. }
  172.  
  173. int Error(char * text)
  174. {
  175.     Tcl_SetResult(interp, text, TCL_STATIC);
  176.     return TCL_ERROR;
  177. }
  178.  
  179. void SetModeLabel(void)
  180. {
  181.   SetLabel(".state.halted",debugger ? "Debugger" :
  182.                            console ? "Console" :
  183.                            "None");
  184. }
  185.  
  186.  
  187. /* Workhorse function to read input from the Pilot. Called both via Tcl event loop on serial input,
  188.    and explicitly by any function has thinks there should be a packet ready. */
  189.    
  190. void Read_Pilot(ClientData clientData, int mask) {
  191.   unsigned char buf[4096];
  192.   int l;
  193.   
  194.   memset(buf,0,4096);
  195.   l = pi_read(port, buf, 4096);
  196.   
  197.   if (l < 6)
  198.     return;
  199.  
  200.   /*puts("From Pilot:");
  201.   dumpdata((unsigned char *)buf, l);*/
  202.   
  203.   if(buf[2] == 0) { /* SysPkt command */
  204.     if(buf[0] == 2) { /* UI */
  205.       if ((!console) || debugger) {
  206.               Say("Console active\n");
  207.           console = 1;
  208.           debugger = 0;
  209.           SetModeLabel();
  210.           Tcl_VarEval(interp, "checkin 25",NULL);
  211.       }
  212.       if(buf[4] == 0x0c) { /* Screen update */
  213. #ifdef TK
  214.     if (usetk) {
  215.           int i, x1, y1, sx, sy, w, h, bytes;
  216.           int y,x;
  217.           char buffer[8192];
  218.         Tk_PhotoImageBlock block;
  219.         Tk_PhotoHandle handle;
  220.           
  221.           bytes = get_short(buf+6);
  222.           y1 = get_short(buf+8);
  223.           x1 = get_short(buf+10);
  224.           sy = get_short(buf+12);
  225.           sx = get_short(buf+14);
  226.           h = get_short(buf+16);
  227.           w = get_short(buf+18);
  228.           
  229.         block.width = w+x1;
  230.         block.height =h;
  231.         block.pitch = w+x1;
  232.         block.pixelSize = 1;
  233.         block.offset[0] = 0;
  234.         block.offset[1] = 0;
  235.         block.offset[2] = 0; 
  236.         block.pixelPtr = buffer;
  237.    
  238.         handle = Tk_FindPhoto("Case");
  239.  
  240.         i = 0;
  241.         l = 0;
  242.         for (y=0;y<h;y++) {
  243.           l = 20 + (y*bytes);
  244.           for(x=0;x<(w+x1);x++) {
  245.             int mask = 1<<(7-(x%8));
  246.             buffer[i++] = (buf[x/8+l] & mask) ? 0 : 0xff;
  247.           }
  248.         }
  249.       
  250.         /*for(i=0;i<((l-20)*8);i++) {
  251.              int p = i/8+20;
  252.              int b = 1<<(7-(i%8));
  253.               buffer[i] = (buf[p] & b) ? 0 : 0xff;
  254.         }*/
  255.         Tk_PhotoPutBlock(handle, &block, 32+sx-x1, 33+sy-y1, w+x1, h);
  256.       
  257.         /*Tcl_VarEval(interp, "global show; set show(.remote) 1; update", NULL); */
  258.         }
  259. #endif           
  260.     return;
  261.       }
  262.       
  263.     } else if(buf[0] == 1) { /* Console */
  264.       if(buf[4] == 0x7f) { /* Message from Pilot */
  265.           int i;
  266.         
  267.           for(i=6;i<l;i++)
  268.             if(buf[i] == '\r')
  269.               buf[i] = '\n';          
  270.         /* Insert message into both debug and console windows */        
  271. #ifdef TK
  272.     if (usetk) {
  273.           Tcl_VarEval(interp,".console.t insert end \"",buf+6,"\"",NULL);
  274.           Tcl_VarEval(interp,".console.t mark set insert end",NULL);
  275.           Tcl_VarEval(interp,".console.t see insert",NULL);
  276.         }
  277. #endif
  278.     display(buf+6, "Console: ", 2);
  279.  
  280.         return;
  281.       }
  282.     } else if (buf[0] == 0) { /* Debug */
  283.       if (!debugger) {
  284.            debugger = 1;
  285.            SetModeLabel();
  286.        Tcl_VarEval(interp, "checkin 25",NULL);
  287.       }
  288.         if (buf[4] == 0x7f) { /* Message */
  289.           int i;
  290.           for(i=6;i<l;i++)
  291.               if(buf[i] == '\r')
  292.                 buf[i] = '\n';          
  293.  
  294.     display(buf+6, "Debug: ", 1);
  295.           
  296.           return;
  297.         }
  298.         else if (buf[4] == 0x8c) { /* Breakpoints set */
  299.            Say("Breakpoint set\n");
  300.            return;
  301.         }
  302.         else if (buf[4] == 0x80) { /* State response */
  303.         
  304.            sys_UnpackState(buf+6,&state);
  305.            
  306.            if (stalestate) {
  307.                char buffer[40];
  308.                sprintf(buffer, "Pilot halted at %8.8lX (function %s) with exception %d\n",
  309.                    state.regs.PC, state.func_name, state.exception);
  310.                display(buffer, "Debug: ", 1);
  311.                stalestate = 0;
  312.            }
  313.            
  314.            SetLabel(".state.exception",itoa(state.exception));
  315.            SetLabel(".state.funcname",state.func_name);
  316.            SetLabel(".state.funcstart",htoa(state.func_start));
  317.            SetLabel(".state.funcend",htoa(state.func_end));
  318.            SetLabel(".state.d0",htoa(state.regs.D[0]));
  319.            SetLabel(".state.a0",htoa(state.regs.A[0]));
  320.            SetLabel(".state.d1",htoa(state.regs.D[1]));
  321.            SetLabel(".state.a1",htoa(state.regs.A[1]));
  322.            SetLabel(".state.d2",htoa(state.regs.D[2]));
  323.            SetLabel(".state.a2",htoa(state.regs.A[2]));
  324.            SetLabel(".state.d3",htoa(state.regs.D[3]));
  325.            SetLabel(".state.a3",htoa(state.regs.A[3]));
  326.            SetLabel(".state.d4",htoa(state.regs.D[4]));
  327.            SetLabel(".state.a4",htoa(state.regs.A[4]));
  328.            SetLabel(".state.d5",htoa(state.regs.D[5]));
  329.            SetLabel(".state.a5",htoa(state.regs.A[5]));
  330.            SetLabel(".state.d6",htoa(state.regs.D[6]));
  331.            SetLabel(".state.a6",htoa(state.regs.A[6]));
  332.            SetLabel(".state.d7",htoa(state.regs.D[7]));
  333.  
  334.            SetLabel(".state.ssp",htoa(state.regs.SSP));
  335.            SetLabel(".state.usp",htoa(state.regs.USP));
  336.            SetLabel(".state.sr",h4toa(state.regs.SR));
  337.            SetLabel(".state.pc",htoa(state.regs.PC));
  338.  
  339.            SetLabel(".state.reset",state.reset ? "Yes" : "No");
  340.  
  341.            SetLabel(".state.b1",htoa(state.breakpoint[0].address));
  342.            SetLabel(".state.b1a",(state.breakpoint[0].enabled) ? "Yes" : "No");
  343.            SetLabel(".state.b2",htoa(state.breakpoint[1].address));
  344.            SetLabel(".state.b2a",(state.breakpoint[1].enabled) ? "Yes" : "No");
  345.            SetLabel(".state.b3",htoa(state.breakpoint[2].address));
  346.            SetLabel(".state.b3a",(state.breakpoint[2].enabled) ? "Yes" : "No");
  347.            SetLabel(".state.b4",htoa(state.breakpoint[3].address));
  348.            SetLabel(".state.b4a",(state.breakpoint[3].enabled) ? "Yes" : "No");
  349.            SetLabel(".state.b5",htoa(state.breakpoint[4].address));
  350.            SetLabel(".state.b5a",(state.breakpoint[4].enabled) ? "Yes" : "No");
  351.            SetLabel(".state.b6",htoa(state.breakpoint[5].address));
  352.            SetLabel(".state.b6a",(state.breakpoint[5].enabled) ? "Yes" : "No");
  353.            
  354.            /* Show the state window if it is hidden */
  355.            Tcl_VarEval(interp, "set show(.state) 1", NULL); 
  356.            return;
  357.         }
  358.     }
  359.   }
  360. }
  361.  
  362.  
  363.  
  364. /* Workhorse function to turn an address string into a numeric value. Ideally, it should
  365.    also know about traps, function names, etc. As it is, it just assumed the text is
  366.    a hexadecimal number, with or with '0x' prefix. */
  367. unsigned long ParseAddress(char * address) {
  368.     return strtoul(address, 0, 16);
  369. }
  370.  
  371. /* Utility function to modify breakpoint table */
  372. int SetBreakpoint(int bp, unsigned long address, int enabled) {
  373.  
  374.     state.breakpoint[bp].address = address;
  375.     state.breakpoint[bp].enabled = enabled;
  376.  
  377.         SetLabel(".state.b1",htoa(state.breakpoint[0].address));
  378.         SetLabel(".state.b1a",(state.breakpoint[0].enabled) ? "Yes" : "No");
  379.         SetLabel(".state.b2",htoa(state.breakpoint[1].address));
  380.         SetLabel(".state.b2a",(state.breakpoint[1].enabled) ? "Yes" : "No");
  381.         SetLabel(".state.b3",htoa(state.breakpoint[2].address));
  382.         SetLabel(".state.b3a",(state.breakpoint[2].enabled) ? "Yes" : "No");
  383.         SetLabel(".state.b4",htoa(state.breakpoint[3].address));
  384.         SetLabel(".state.b4a",(state.breakpoint[3].enabled) ? "Yes" : "No");
  385.         SetLabel(".state.b5",htoa(state.breakpoint[4].address));
  386.         SetLabel(".state.b5a",(state.breakpoint[4].enabled) ? "Yes" : "No");
  387.         SetLabel(".state.b6",htoa(state.breakpoint[5].address));
  388.         SetLabel(".state.b6a",(state.breakpoint[5].enabled) ? "Yes" : "No");
  389.         
  390.     
  391.     sys_SetBreakpoints(port, &state.breakpoint[0]);
  392.     
  393.     Read_Pilot(0, 0);
  394.     
  395.     return 0;
  396. }
  397.  
  398. /* Attempt to verify a connection to either the debugger or console */
  399. int DbgAttach(int verify)
  400. {
  401.   struct RPC_params p;
  402.   
  403.   if (!port) {
  404.     Error("No serial port selected, use 'port' command to choose one.\n");
  405.     return 0;
  406.   }
  407.  
  408. again:  
  409.   if (verify || (!debugger && !console)) {
  410.     int old = debugger;
  411.     sys_QueryState(port);
  412.     debugger = 0;
  413.     Read_Pilot(0,0);
  414.     if (debugger && !old)
  415.       if (verify > 1)
  416.         Say("Attaching to Pilot debugger\n");
  417.       else
  418.         SayInteractive("(attaching to Pilot debugger)\n");
  419.   }
  420.   
  421.   if (!debugger && (verify || !console)) {
  422.     int err;
  423.     int old = console;
  424.      console = 0;
  425.     PackRPC(&p, 0xA09E, RPC_IntReply, RPC_End); /* TaskID, a harmless call */
  426.     DoRPC(port, 1, &p, &err);
  427.     if (err == 0)
  428.       console = 1;
  429.     else 
  430.       console = 0;
  431.     if (console && !old)
  432.       if (verify > 1)
  433.         Say("Attaching to Pilot console\n");
  434.       else
  435.         SayInteractive("(attaching to Pilot console)\n");
  436.     
  437.   }
  438.   
  439.   if (!debugger && !console && !verify) {
  440.     verify = 1;
  441.     goto again;
  442.   }
  443.   
  444.   SetModeLabel();
  445.  
  446.   return (debugger || console);
  447. }
  448.  
  449. int DbgAttachDebugger(int verify)
  450. {
  451.   if (!port) {
  452.     Error("No serial port selected, use 'port' command to choose one.\n");
  453.     return 0;
  454.   }
  455.   
  456.   if (!debugger || verify) {
  457.     int old = debugger;
  458.     debugger = 0;
  459.     sys_QueryState(port);
  460.     Read_Pilot(0,0);
  461.     SetModeLabel();
  462.     if (debugger && !old)
  463.       SayInteractive("(attaching to Pilot debugger)\n");
  464.   }
  465.   
  466.   if (!debugger) {
  467.     Error("Unable to attach to debugger on Pilot. Is the Pilot connected and in debugging mode?\n");
  468.   }
  469.   return debugger;
  470. }
  471.  
  472. int DbgAttachConsole(int verify)
  473. {
  474.   int err;
  475.   struct RPC_params p;
  476.  
  477.   if (!port) {
  478.     Error("No serial port selected, use 'port' command to choose one.\n");
  479.     return 0;
  480.   }
  481.     
  482.   if (verify || debugger || !console) {
  483.     int old = console && !debugger;
  484.     PackRPC(&p, 0xA09E, RPC_IntReply, RPC_End); /* TaskID, a harmless call */
  485.     DoRPC(port, 1, &p, &err);
  486.     if (err == 0) {
  487.        console = 1;
  488.        debugger = 0;
  489.        SetModeLabel();
  490.     } else {
  491.       if (!debugger)
  492.         console = 0;
  493.     }
  494.     if ((console && !debugger) && !old)
  495.       SayInteractive("(attaching to Pilot console)\n");
  496.   }
  497.   
  498.   if (!console || debugger) {
  499.     Error("Unable to attach to console on Pilot. Is the Pilot connected, in console mode, and not in debugger mode?\n");
  500.   }
  501.   
  502.   return console;
  503. }
  504.  
  505. unsigned long DbgRPC(struct RPC_params * p, int * error)
  506. {
  507.     unsigned long result = 0;
  508.     int err = -1;
  509.  
  510.   if (!port) {
  511.     Error("No serial port selected, use 'port' command to choose one.\n");
  512.     return 0;
  513.   }
  514.       
  515.     if (p->reply == RPC_NoReply) {
  516.       /* If the RPC call will normally generate no reply (as in a call that reboots the machine)
  517.          then we need to do some special work to verify that the connection is active */
  518.       DbgAttach(1);
  519.       if (!debugger && !console) {
  520.         if (error)
  521.           *error = -1;
  522.         Error("Unable to invoke RPC on Pilot. Is the Pilot connected and in debugging or console mode?\n");
  523.         return 0;
  524.       }
  525.     }
  526.  
  527.     if (debugger) {
  528.         result = DoRPC(port, 0, p, &err);
  529.         if ((err < 0) && (p->reply != RPC_NoReply)) /* Failure, assume no response */ {
  530.             debugger = 0;
  531.             SetModeLabel();
  532.         }
  533.     } else if (console) {
  534.         result = DoRPC(port, 1, p, &err);
  535.         if ((err < 0) && (p->reply != RPC_NoReply)) /* Failure, assume no response */ {
  536.             console = 0;
  537.             SetModeLabel();
  538.         }
  539.     }/* else {
  540.         Say("(attaching to Pilot)\n");
  541.     }*/
  542.     
  543.     if (!console && !debugger) {
  544.         DbgAttach(0);
  545.         if (debugger) {
  546.             result = DoRPC(port, 0, p, &err);
  547.         } else if (console) {
  548.             result = DoRPC(port, 1, p, &err);
  549.         } else {
  550.             /* complete failure to attach */
  551.             Error("Unable to invoke RPC on Pilot. Is the Pilot connected and in debugging or console mode?\n");
  552.         }
  553.     }
  554.     
  555.     if (error)
  556.         *error = err;
  557.         
  558.     return result;
  559. }
  560.  
  561. unsigned char buffer[0xffff];
  562.  
  563.  
  564. /* Go, restart execution */
  565. int proc_g(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  566. {
  567.   /* Use verify since the sys_Continue command produces no return value */
  568.      
  569.   if (!DbgAttachDebugger(1))
  570.     return TCL_ERROR;
  571.  
  572.   if (argc==2) {
  573.     /* argv[1] is address to start execution at */
  574.     state.regs.PC = ParseAddress(argv[1]);
  575.     SetLabel(".state.pc",htoa(state.regs.PC));
  576.     
  577.     /*SetBreakpoint(port, 5, ParseAddress(argv[1]), 1);*/
  578.   }
  579.   
  580.   sys_Continue(port, &state.regs, 0);
  581.   
  582.   Say("Resuming execution\n");
  583.   
  584.   /* Assume the Pilot is no longer halted */
  585.   
  586.   debugger = 0;
  587.   console = 0;
  588.   stalestate = 1;
  589.   SetModeLabel();
  590.  
  591.   Tcl_VarEval(interp, "checkupin 25",NULL);
  592.   Tcl_ResetResult(interp);
  593.  
  594.   return TCL_OK;
  595. }
  596.  
  597. /* Till, restart execution */
  598. int proc_t(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  599. {
  600.   /* Use verify since the sys_Continue command produces no return value */
  601.      
  602.   if (!DbgAttachDebugger(1))
  603.     return TCL_ERROR;
  604.  
  605.   if (argc>=2) {
  606.     /* argv[1] is address to stop execution at */
  607.     SetBreakpoint(5, ParseAddress(argv[1]), 1);
  608.   }
  609.    
  610.   if (argc>=3) {
  611.     /* argv[2] is address to start execution at */
  612.     state.regs.PC = ParseAddress(argv[2]);
  613.     SetLabel(".state.pc",htoa(state.regs.PC));
  614.   }
  615.   
  616.   sys_Continue(port, &state.regs, 0);
  617.   
  618.   Say("Resuming execution\n");
  619.   
  620.   /* Assume the Pilot is no longer halted */
  621.   
  622.   debugger = 0;
  623.   console = 0;
  624.   stalestate = 1;
  625.   SetModeLabel();
  626.  
  627.   Tcl_VarEval(interp, "checkupin 25",NULL);
  628.   Tcl_ResetResult(interp);
  629.  
  630.   return TCL_OK;
  631. }
  632.  
  633. /* Attach to a Pilot that has already crashed into the debugger without notifying us */
  634. int proc_attach(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  635. {
  636.   DbgAttach(2); /* Two means explicit verify, as opposed to implicit */
  637.   
  638.   if (!debugger && !console) {
  639.      Say("Unable to attach to to Pilot. Is the Pilot connected and in debugging or console mode?\n");
  640.   }
  641.  
  642.   return TCL_OK;
  643. }
  644.  
  645. int proc_sendscreen(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  646. {
  647.   struct RPC_params p;
  648.  
  649.   PackRPC(&p, 0xA0F1, RPC_IntReply, RPC_Short(0), RPC_Short(0), RPC_Short(160), RPC_Short(160), RPC_End);
  650.   DbgRPC(&p, 0);
  651.   
  652.   return TCL_OK;
  653. }
  654.  
  655. int proc_coldboot(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  656. {
  657.   struct RPC_params p;
  658.  
  659.   PackRPC(&p, 0xA08B, RPC_NoReply, RPC_Long(0),RPC_Long(0),RPC_Long(0),RPC_Long(0), RPC_End);
  660.   DbgRPC(&p, 0);
  661.   
  662.   /* And sever attachment */
  663.   debugger = 0;
  664.   console = 0;
  665.   stalestate = 1;
  666.   SetModeLabel();
  667.  
  668.   Tcl_VarEval(interp, "checkupin 25",NULL);
  669.   Tcl_ResetResult(interp);
  670.  
  671.   return TCL_OK;
  672. }
  673.  
  674. int proc_warmboot(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  675. {
  676.   struct RPC_params p;
  677.  
  678.   PackRPC(&p, 0xA08C, RPC_NoReply, RPC_End);
  679.   DbgRPC(&p, 0);
  680.   
  681.   /* And sever attachment */
  682.   debugger = 0;
  683.   console = 0;
  684.   stalestate = 1;
  685.   SetModeLabel();
  686.   
  687.   Tcl_VarEval(interp, "checkupin 25",NULL);
  688.   Tcl_ResetResult(interp);
  689.  
  690.   return TCL_OK;
  691. }
  692.  
  693. int proc_battery(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  694. {
  695.             int err;
  696.             int warn, critical, maxTicks;
  697.             int v, kind, pluggedin;
  698.             char buffer[30];
  699.       struct RPC_params p;
  700.  
  701.   if (!DbgAttach(0))
  702.     return TCL_ERROR;
  703.  
  704.             warn = 0x1234;
  705.             critical = 0x2345;
  706.             maxTicks = 0x3456;
  707.             kind = 2;
  708.             pluggedin = 3;
  709.   
  710.         PackRPC(&p,0xA0B6, RPC_IntReply,
  711.             RPC_Byte(0), RPC_ShortPtr(&warn), RPC_ShortPtr(&critical),
  712.             RPC_ShortPtr(&maxTicks), RPC_BytePtr(&kind), RPC_BytePtr(&pluggedin), RPC_End);
  713.             
  714.      
  715.  
  716.       v =  DbgRPC(&p, &err);
  717.       
  718.      if (err)
  719.        return TCL_ERROR;
  720.       
  721. /*        printf("Volts = %f, crit = %f, warn = %f, ticks = %d, kind = %d, pluggedin= %d, err = %d\n",
  722.             (float)v/100, (float)critical/100, (float)warn/100,
  723.             maxTicks, kind, pluggedin, err);*/
  724.     
  725.     sprintf(buffer,"%.2f %s%s", (float)v/100, (kind == 0) ? "Alkaline" :
  726.                                               (kind == 1) ? "NiCd" :
  727.                                               (kind == 2) ? "Lithium" :
  728.                                               "",
  729.                                               pluggedin ? " Ext" : "" );
  730.     
  731.     Say(buffer);
  732.     
  733.     SetLabel(".state.battery",buffer);
  734.     
  735.     
  736. #ifdef TK
  737.     if (usetk) 
  738.         Tcl_VarEval(interp,".state.battery configure -fg ", (v <= critical) ? "red" :
  739.                                                             (v <= warn) ? "darkred" :
  740.                                                             "blue" , NULL);
  741. #endif    
  742.  
  743.     Say((v <= critical) ? " power critical!\n" : (v <= warn) ? " power low\n" : "\n");
  744.     
  745.     return TCL_OK;
  746. }
  747.  
  748. int proc_mirror(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  749. {
  750.   struct RPC_params p;
  751.   unsigned long addr;
  752.   int e1,e2;
  753.   int active;
  754.  
  755.   if (!DbgAttachConsole(0))
  756.     return TCL_ERROR;
  757.     
  758.   
  759.   /* Fetch scrGlobals ptr */
  760.  PackRPC(&p,0xA026, RPC_IntReply, RPC_LongPtr(&addr), RPC_Long(356), RPC_Long(4), RPC_End);
  761.   e1=DbgRPC(&p, &e2);
  762.   
  763.   /* Fetch current drawnotify setting */
  764.  PackRPC(&p,0xA026, RPC_IntReply, RPC_BytePtr(&active), RPC_Long(addr+18), RPC_Long(1), RPC_End);
  765.   e1=DbgRPC(&p, &e2);
  766.  
  767.   /*printf("addr=%d\nactive=%d\n", addr, active);*/
  768.  
  769.   /* Change setting */
  770.   if (argc<2)
  771.     active = !active;
  772.   else
  773.    if (Tcl_GetBoolean(interp, argv[1], &active)!=TCL_OK)
  774.      return TCL_ERROR;
  775.   
  776.   /* Put it back */
  777.  PackRPC(&p,0xA026, RPC_IntReply, RPC_Long(addr+18), RPC_BytePtr(&active), RPC_Long(1), RPC_End);
  778.   e1=DbgRPC(&p, &e2);
  779.  
  780.   if (Interactive) {
  781.     if (active)
  782.       Say("Mirroring is active.\n");
  783.     else
  784.       Say("Mirroring is inactive.\n");
  785.   }
  786.  
  787.   if (active) {
  788.     /* Try to prod Pilot into immediately giving us a screen update */
  789.     PackRPC(&p,0xA0F1, RPC_IntReply, RPC_Short(0), RPC_Short(0), RPC_Short(160), RPC_Short(160), RPC_End);
  790.     e1=DbgRPC(&p, &e2);
  791.   }
  792.   
  793.   return TCL_OK;  
  794. }
  795.  
  796. #define DB 0xFFFF0000
  797. #define LSSA 0xFA00  
  798.  
  799. int proc_getdisplay(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  800. {
  801. #ifndef TK
  802.   Say("getdisplay is not available due to pilot-debug being compiled without Tk support");
  803.   return TCL_ERROR;
  804.  
  805. #else  
  806.   char buffer[0xffff];
  807.   char buffer2[0xffff];
  808.   Tk_PhotoImageBlock block;
  809.   Tk_PhotoHandle handle;
  810.   struct RPC_params p;
  811.   unsigned long addr;
  812.   int e1,e2;
  813.   int l;
  814.  
  815.  
  816.   if (!usetk) {
  817.     Say("getdisplay is not usable when graphical display is disabled");
  818.     return TCL_ERROR;
  819.   }
  820.   
  821.   if (!DbgAttach(0))
  822.     return TCL_ERROR;
  823.     
  824.   
  825.   if (debugger) {
  826.       l = sys_ReadMemory(port, DB+LSSA, 4, buffer);
  827.       addr = get_long(buffer);
  828.       l = sys_ReadMemory(port, addr, 160*160/8, buffer);
  829.   } else {
  830.       PackRPC(&p,0xA026, RPC_IntReply, RPC_LongPtr(&addr), RPC_Long(DB+LSSA), RPC_Long(4), RPC_End);
  831.       e1=DbgRPC(&p, &e2);
  832.       for (l=0;l<160*160/8;l+=64) {
  833.           PackRPC(&p,0xA026, RPC_IntReply, RPC_Ptr(buffer+l, 128), RPC_Long(addr+l), RPC_Long(128), RPC_End);
  834.           e1=DbgRPC(&p, &e2);
  835.       }
  836.   }
  837.   
  838.   block.width = 160;
  839.   block.height = 160;
  840.   block.pitch = 160;
  841.   block.pixelSize = 1;
  842.   block.offset[0] = 0;
  843.   block.offset[1] = 0;
  844.   block.offset[2] = 0; 
  845.   
  846.   handle = Tk_FindPhoto("Case");
  847.  
  848.   for(l=0;l<160*160;l++) {
  849.       int p = l/8;
  850.       int b = 1<<(7-(l%8));
  851.       buffer2[l] = (buffer[p] & b) ? 0 : 0xff;
  852.   }
  853.   block.pixelPtr = buffer2;
  854.   Tk_PhotoPutBlock(handle, &block, 32, 33, 160, 160);
  855.   
  856.   return TCL_OK;  
  857. #endif
  858. }
  859.  
  860. int proc_transmit(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  861. {
  862.   if (argc < 2)
  863.     return TCL_OK;
  864.   
  865.   if (!DbgAttachConsole(0))
  866.     return TCL_ERROR;
  867.     
  868.   buffer[0] = 1;
  869.   buffer[1] = 1;
  870.   buffer[2] = 0;
  871.   buffer[3] = 0;
  872.   buffer[4] = 0x7f;
  873.   buffer[5] = 0;
  874.   strcpy(buffer+6, argv[1]);
  875.   strcat(buffer+6, "\n");
  876.   
  877.   pi_write(port, buffer, 6+strlen(argv[1])+2);
  878.   
  879.   return TCL_OK;  
  880. }
  881.  
  882. int proc_pushbutton(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  883. {
  884.   struct RPC_params p;
  885.   unsigned int key=0, scan=0, mod=0;
  886.   
  887.   if (!DbgAttachConsole(0))
  888.     return TCL_ERROR;
  889.   
  890.   sys_RPCerror = 0;
  891.   switch(atoi(argv[1])) {
  892.     case 1: /* Power */
  893.         key = 0x0208;
  894.         mod = 0x08;
  895.         break;
  896.  
  897.     case 2: /* Datebook */
  898.         key = 0x0204;
  899.         mod = 0x08;
  900.         break;
  901.     case 3: /* Address */
  902.         key = 0x0205;
  903.         mod = 0x08;
  904.         break;
  905.     case 6: /* ToDo */
  906.         key = 0x0206;
  907.         mod = 0x08;
  908.         break;
  909.     case 7: /* Memo */
  910.         key = 0x0207;
  911.         mod = 0x08;
  912.         break;
  913.  
  914.     case 4: /* Page Up */
  915.         key = 0x000b;
  916.         mod = 0;
  917.         break;
  918.     case 5: /* Page Down */
  919.         key = 0x000c;
  920.         mod = 0;
  921.         break;
  922.     default:
  923.         return Error("Button number out of range (1-7)");
  924.   }
  925.  
  926.   PackRPC(&p, 0xA12D, RPC_IntReply, RPC_Short(key),RPC_Short(scan),RPC_Short(mod), RPC_End);
  927.   
  928.   DbgRPC(&p, 0);
  929.   
  930.   return TCL_OK;
  931. }
  932.  
  933. /* Tcl procedure to simulate a pen tap -- primarily used by Remote UI bindings */
  934. int proc_pen(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  935. {
  936.   int x = atoi(argv[1])-32, y = atoi(argv[2])-33, pen = atoi(argv[3]);
  937.   
  938.   /* Transmit Pen event to Pilot */
  939.   
  940.  /*printf("Pen %d, %d, %d\n", x, y, pen);*/
  941.   
  942.  if (!DbgAttachConsole(0))
  943.     return TCL_ERROR;
  944.   
  945.   sys_RemoteEvent(port, pen, x, y, 0, 0,0,0);
  946.   
  947.   return TCL_OK;
  948. }
  949.  
  950. /* Tcl procedure to simulate a key press -- primarily used by Remote UI bindings */
  951. int proc_key(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  952. {
  953.   /*struct RPC_params p;*/
  954.   int key = argv[1][0];
  955.   
  956.   /* Transmit ASCII key to Pilot */
  957.  
  958.   /*printf("Key %d\n", key);*/
  959.   
  960.   /*PackRPC(&p, 0xA12D, RPC_IntReply, RPC_Short(key),RPC_Short(0),RPC_Short(0x0), RPC_End);
  961.  
  962.   if (key != 0)
  963.     DbgRPC(&p, 0);*/
  964.  
  965.  if (!DbgAttachConsole(0))
  966.     return TCL_ERROR;
  967.  
  968.  sys_RemoteEvent(port, 0, 0, 0, 1, 0, key, 0);
  969.   
  970. /*  int sd, int penDown, int x, int y, int keypressed,
  971.                          int keymod, int keyasc, int keycode)*/
  972.                          
  973.   
  974.   return TCL_OK;
  975. }
  976.  
  977. int proc_port(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  978. {
  979.   static struct pi_sockaddr laddr;
  980.   static Tcl_Channel channel;
  981.   int fd;
  982.   
  983.   if (argc<2) {
  984.       if(port)
  985.         Tcl_SetResult(interp, laddr.pi_device, TCL_STATIC);
  986.     return TCL_OK;
  987.   }
  988.   
  989.   if (port) {
  990.     Tcl_DeleteChannelHandler(channel, Read_Pilot, (ClientData)port);
  991.     Tcl_UnregisterChannel(interp, channel);
  992.     pi_close(port);
  993.     port = 0;
  994.   }
  995.   
  996.   if (strcmp(argv[1],"close")==0) {
  997.       return TCL_OK;
  998.   }
  999.   
  1000.   port = pi_socket(PI_AF_SLP, PI_SOCK_RAW, PI_PF_SLP);
  1001.   
  1002.   laddr.pi_family = PI_AF_SLP;
  1003.   strcpy(laddr.pi_device,argv[1]);
  1004.   
  1005.   if (pi_bind(port, &laddr, sizeof(laddr))==-1) {
  1006.     Say("Unable to open port '");
  1007.     Say(argv[1]);
  1008.     Say("': ");
  1009.     Say(Tcl_ErrnoMsg(errno));
  1010.     Say("\n");
  1011.     port = 0;
  1012.     return TCL_ERROR;
  1013.   }
  1014.   
  1015.   fd = port;
  1016.                         
  1017.   channel = Tcl_MakeFileChannel((ClientData)fd, 0, TCL_READABLE);
  1018.   Tcl_RegisterChannel(interp, channel); /* And register it to TCL */
  1019.   Tcl_CreateChannelHandler(channel, TCL_READABLE, Read_Pilot, (ClientData)port);
  1020.   
  1021.   Tcl_SetResult(interp, laddr.pi_device, TCL_STATIC);
  1022.   return TCL_OK;
  1023. }
  1024.  
  1025. int proc_inittkdbg(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  1026. {
  1027. #ifndef TK
  1028.   Say("This executable does not contain Tk support!\n");
  1029.   return TCL_ERROR;
  1030. #else
  1031.   static int created = 0;
  1032.   if (created) {
  1033.     Say("Graphical debugger already initialized.\n");
  1034.     return TCL_OK;
  1035.   }
  1036.  
  1037.   Tcl_VarEval(interp,"\
  1038.  
  1039. ###  /*** Generate remote UI window ***/
  1040.  
  1041. set tkdbg 1
  1042.  
  1043. toplevel .remote
  1044. wm title .remote {Pilot Remote UI}
  1045.  
  1046. catch {
  1047.     if {[file exists {pix/case.gif}]} {
  1048.         set dir {pix}
  1049.     } elseif {[file exists {",LIBDIR,"/pix/case.gif}]} {
  1050.         set dir {",LIBDIR,"/pix}
  1051.     } else {
  1052.         error {No pix}
  1053.     }
  1054.     image create photo Case -format gif -file \"$dir/case.gif\"
  1055.     image create photo B1 -format gif -file \"$dir/b1.gif\"
  1056.     image create photo B2 -format gif -file \"$dir/b2.gif\"
  1057.     image create photo B3 -format gif -file \"$dir/b3.gif\"
  1058.     image create photo B4 -format gif -file \"$dir/b4.gif\"
  1059.     image create photo B5 -format gif -file \"$dir/b5.gif\"
  1060.     image create photo B6 -format gif -file \"$dir/b6.gif\"
  1061.     image create photo B7 -format gif -file \"$dir/b7.gif\"
  1062. }
  1063.  
  1064. canvas .remote.c -width 221 -height 337
  1065.  
  1066. .remote.c create rectangle 27 29 196 260 -outline {red} -tag screen -fill {blue}
  1067. .remote.c create rectangle 0 280 18 306 -outline {red} -tag button1 -fill {blue}
  1068. .remote.c create oval 23 276 52 307 -outline {red} -tag button2 -fill {blue}
  1069. .remote.c create oval 63 276 92 307 -outline {red} -tag button3 -fill {blue}
  1070. .remote.c create rectangle 97 277 127 294 -outline {red} -tag button4 -fill {blue}
  1071. .remote.c create rectangle 97 300 127 317 -outline {red} -tag button5 -fill {blue}
  1072. .remote.c create oval 133 276 162 307 -outline {red} -tag button6 -fill {blue}
  1073. .remote.c create oval 171 276 200 307 -outline {red} -tag button7 -fill {blue}
  1074.  
  1075. .remote.c create rectangle 33 32 187 253 -outline black -tag screen
  1076. .remote.c create rectangle 33 200 61 225 -outline black -tag screen
  1077. .remote.c create rectangle 33 225 61 253 -outline black -tag screen
  1078. .remote.c create rectangle 160 200 187 225 -outline black -tag screen
  1079. .remote.c create rectangle 160 225 187 253 -outline black -tag screen
  1080. .remote.c create rectangle 62 200 159 253 -outline black -tag screen
  1081.  
  1082. .remote.c bind button1 <ButtonPress-1> {.remote.c itemconfigure button1 -fill green; update; pushbutton 1}
  1083. .remote.c bind button1 <ButtonRelease-1> {.remote.c itemconfigure button1 -fill blue}
  1084.  
  1085. .remote.c bind button2 <ButtonPress-1> {.remote.c itemconfigure button2 -fill green; update; pushbutton 2}
  1086. .remote.c bind button2 <ButtonRelease-1> {.remote.c itemconfigure button2 -fill blue}
  1087.  
  1088. .remote.c bind button3 <ButtonPress-1> {.remote.c itemconfigure button3 -fill green; update; pushbutton 3}
  1089. .remote.c bind button3 <ButtonRelease-1> {.remote.c itemconfigure button3 -fill blue}
  1090.  
  1091. .remote.c bind button4 <ButtonPress-1> {.remote.c itemconfigure button4 -fill green; update; pushbutton 4}
  1092. .remote.c bind button4 <ButtonRelease-1> {.remote.c itemconfigure button4 -fill blue}
  1093.  
  1094. .remote.c bind button5 <ButtonPress-1> {.remote.c itemconfigure button5 -fill green; update; pushbutton 5}
  1095. .remote.c bind button5 <ButtonRelease-1> {.remote.c itemconfigure button5 -fill blue}
  1096.  
  1097. .remote.c bind button6 <ButtonPress-1> {.remote.c itemconfigure button6 -fill green; update; pushbutton 6}
  1098. .remote.c bind button6 <ButtonRelease-1> {.remote.c itemconfigure button6 -fill blue}
  1099.  
  1100. .remote.c bind button7 <ButtonPress-1> {.remote.c itemconfigure button7 -fill green; update; pushbutton 7}
  1101. .remote.c bind button7 <ButtonRelease-1> {.remote.c itemconfigure button7 -fill blue}
  1102.  
  1103. catch {
  1104.     .remote.c create image 0 282 -image B1 -anchor nw -tag downbutton1
  1105.     .remote.c create image 22 274 -image B2 -anchor nw -tag downbutton2
  1106.     .remote.c create image 60 275 -image B3 -anchor nw -tag downbutton3
  1107.     .remote.c create image 93 278 -image B4 -anchor nw -tag downbutton4
  1108.     .remote.c create image 95 298 -image B5 -anchor nw -tag downbutton5
  1109.     .remote.c create image 131 275 -image B6 -anchor nw -tag downbutton6
  1110.     .remote.c create image 169 274 -image B7 -anchor nw -tag downbutton7
  1111.  
  1112.     .remote.c create image 0 0 -image Case -anchor nw
  1113.  
  1114.     .remote.c bind button1 <ButtonPress-1> {.remote.c raise downbutton1; update; pushbutton 1}
  1115.     .remote.c bind button1 <ButtonRelease-1> {.remote.c lower downbutton1}
  1116.  
  1117.     .remote.c bind button2 <ButtonPress-1> {.remote.c raise downbutton2; update; pushbutton 2}
  1118.     .remote.c bind button2 <ButtonRelease-1> {.remote.c lower downbutton2}
  1119.  
  1120.     .remote.c bind button3 <ButtonPress-1> {.remote.c raise downbutton3; update; pushbutton 3}
  1121.     .remote.c bind button3 <ButtonRelease-1> {.remote.c lower downbutton3}
  1122.  
  1123.     .remote.c bind button4 <ButtonPress-1> {.remote.c raise downbutton4; update; pushbutton 4}
  1124.     .remote.c bind button4 <ButtonRelease-1> {.remote.c lower downbutton4}
  1125.  
  1126.     .remote.c bind button5 <ButtonPress-1> {.remote.c raise downbutton5; update; pushbutton 5}
  1127.     .remote.c bind button5 <ButtonRelease-1> {.remote.c lower downbutton5}
  1128.  
  1129.     .remote.c bind button6 <ButtonPress-1> {.remote.c raise downbutton6; update; pushbutton 6}
  1130.     .remote.c bind button6 <ButtonRelease-1> {.remote.c lower downbutton6}
  1131.  
  1132.     .remote.c bind button7 <ButtonPress-1> {.remote.c raise downbutton7; update; pushbutton 7}
  1133.     .remote.c bind button7 <ButtonRelease-1> {.remote.c lower downbutton7}
  1134.     
  1135.     
  1136.     .remote.c itemconfigure button1 -outline {} -fill {}
  1137.     .remote.c raise button1
  1138.     .remote.c itemconfigure button2 -outline {} -fill {}
  1139.     .remote.c raise button2
  1140.     .remote.c itemconfigure button3 -outline {} -fill {}
  1141.     .remote.c raise button3
  1142.     .remote.c itemconfigure button4 -outline {} -fill {}
  1143.     .remote.c raise button4
  1144.     .remote.c itemconfigure button5 -outline {} -fill {}
  1145.     .remote.c raise button5
  1146.     .remote.c itemconfigure button6 -outline {} -fill {}
  1147.     .remote.c raise button6
  1148.     .remote.c itemconfigure button7 -outline {} -fill {}
  1149.     .remote.c raise button7
  1150.     .remote.c itemconfigure screen -outline {} -fill {}
  1151.     .remote.c raise screen
  1152. }
  1153.  
  1154. pack .remote.c -side top
  1155.  
  1156. .remote.c bind screen <ButtonPress-1> {pen %x %y 1}
  1157. .remote.c bind screen <B1-Motion> {pen %x %y 1}
  1158. .remote.c bind screen <ButtonRelease-1> {pen %x %y 0}
  1159.  
  1160. bind .remote <KeyPress> {key %A}
  1161.  
  1162. #####  /*** Generate remote console window ***/
  1163.  
  1164. toplevel .console
  1165. wm title .console \"Pilot Remote Console\"
  1166. scrollbar .console.y -orient vertical -command {.console.t yview}
  1167. text .console.t -yscrollcommand {.console.y set}
  1168. pack .console.t -fill both -expand yes -side left
  1169. pack .console.y -fill y -side right
  1170. focus .console.t
  1171.  
  1172. ####  /*** Generate pilot state window ***/
  1173.  
  1174. toplevel .state
  1175. wm title .state {Pilot State}
  1176. label .state.l1 -text {Active mode:}
  1177. label .state.l1x -text {Battery:}
  1178. label .state.l2 -text {Exception:}
  1179. label .state.l25 -text {Reset:}
  1180. label .state.l3 -text {Function:}
  1181. label .state.l4 -text {F-start:}
  1182. label .state.l5 -text {F-end:}
  1183. label .state.l6 -text {D0:}
  1184. label .state.l7 -text {A0:}
  1185. label .state.l8 -text {D1:}
  1186. label .state.l9 -text {A1:}
  1187. label .state.l10 -text {D2:}
  1188. label .state.l11 -text {A2:}
  1189. label .state.l12 -text {D3:}
  1190. label .state.l13 -text {A3:}
  1191. label .state.l14 -text {D4:}
  1192. label .state.l15 -text {A4:}
  1193. label .state.l16 -text {D5:}
  1194. label .state.l17 -text {A5:}
  1195. label .state.l18 -text {D6:}
  1196. label .state.l19 -text {A6:}
  1197. label .state.l20 -text {D7:}
  1198.  
  1199. label .state.l21 -text {PC:}
  1200. label .state.l22 -text {SR:}
  1201. label .state.l23 -text {USP:}
  1202. label .state.l24 -text {SSP:}
  1203.  
  1204. label .state.halted -text {None}
  1205. label .state.battery -text {Unknown}
  1206. label .state.exception -text {0}
  1207. label .state.reset -text {No}
  1208. label .state.funcname -text {}
  1209. label .state.funcstart -text {00000000}
  1210. label .state.funcend -text {00000000}
  1211. label .state.d0 -text {00000000}
  1212. label .state.a0 -text {00000000}
  1213. label .state.d1 -text {00000000}
  1214. label .state.a1 -text {00000000}
  1215. label .state.d2 -text {00000000}
  1216. label .state.a2 -text {00000000}
  1217. label .state.d3 -text {00000000}
  1218. label .state.a3 -text {00000000}
  1219. label .state.d4 -text {00000000}
  1220. label .state.a4 -text {00000000}
  1221. label .state.d5 -text {00000000}
  1222. label .state.a5 -text {00000000}
  1223. label .state.d6 -text {00000000}
  1224. label .state.a6 -text {00000000}
  1225. label .state.d7 -text {00000000}
  1226. label .state.pc -text {00000000}
  1227. label .state.sr -text {0000}
  1228. label .state.usp -text {00000000}
  1229. label .state.ssp -text {00000000}
  1230.  
  1231. grid .state.l1 -column 0 -row 0 -sticky e -columnspan 2
  1232. grid .state.halted -column 2 -row 0 -sticky w -columnspan 2
  1233.  
  1234. grid .state.l1x -column 0 -row 1 -sticky e -columnspan 2
  1235. grid .state.battery -column 2 -row 1 -sticky w -columnspan 2
  1236.  
  1237. grid .state.l2 -column 0 -row 2 -sticky e -columnspan 2
  1238. grid .state.exception -column 2 -row 2 -sticky w -columnspan 2
  1239.  
  1240. grid .state.l25 -column 0 -row 3 -sticky e -columnspan 2
  1241. grid .state.reset -column 2 -row 3 -sticky w -columnspan 2
  1242.  
  1243. grid .state.l3 -column 0 -row 4 -sticky e -columnspan 2 
  1244. grid .state.funcname -column 2 -row 4 -sticky w -columnspan 2
  1245.  
  1246. grid .state.l4 -column 0 -row 5 -sticky e -columnspan 2 
  1247. grid .state.funcstart -column 2 -row 5 -sticky w -columnspan 2
  1248.  
  1249. grid .state.l5 -column 0 -row 6 -sticky e -columnspan 2 
  1250. grid .state.funcend -column 2 -row 6 -sticky w -columnspan 2
  1251.  
  1252. frame .state.rule1 -relief raised -bd 2 -height 4
  1253. grid .state.rule1 -column 0 -row 7 -columnspan 4 -sticky ew
  1254.  
  1255. grid .state.l6 -column 0 -row 8 -sticky e 
  1256. grid .state.d0 -column 1 -row 8 -sticky w
  1257. grid .state.l7 -column 2 -row 8 -sticky e 
  1258. grid .state.a0 -column 3 -row 8 -sticky w
  1259.  
  1260. grid .state.l8 -column 0 -row 9 -sticky e 
  1261. grid .state.d1 -column 1 -row 9 -sticky w
  1262. grid .state.l9 -column 2 -row 9 -sticky e 
  1263. grid .state.a1 -column 3 -row 9 -sticky w
  1264.  
  1265. grid .state.l10 -column 0 -row 10 -sticky e 
  1266. grid .state.d2 -column 1 -row 10 -sticky w
  1267. grid .state.l11 -column 2 -row 10 -sticky e 
  1268. grid .state.a2 -column 3 -row 10 -sticky w
  1269.  
  1270. grid .state.l12 -column 0 -row 11 -sticky e 
  1271. grid .state.d3 -column 1 -row 11 -sticky w
  1272. grid .state.l13 -column 2 -row 11 -sticky e 
  1273. grid .state.a3 -column 3 -row 11 -sticky w
  1274.  
  1275. grid .state.l14 -column 0 -row 12 -sticky e 
  1276. grid .state.d4 -column 1 -row 12 -sticky w
  1277. grid .state.l15 -column 2 -row 12 -sticky e 
  1278. grid .state.a4 -column 3 -row 12 -sticky w
  1279.  
  1280. grid .state.l16 -column 0 -row 13 -sticky e 
  1281. grid .state.d5 -column 1 -row 13 -sticky w
  1282. grid .state.l17 -column 2 -row 13 -sticky e 
  1283. grid .state.a5 -column 3 -row 13 -sticky w
  1284.  
  1285. grid .state.l18 -column 0 -row 14 -sticky e 
  1286. grid .state.d6 -column 1 -row 14 -sticky w
  1287. grid .state.l19 -column 2 -row 14 -sticky e 
  1288. grid .state.a6 -column 3 -row 14 -sticky w
  1289.  
  1290. grid .state.l20 -column 0 -row 15 -sticky e 
  1291. grid .state.d7 -column 1 -row 15 -sticky w
  1292.  
  1293. grid .state.l21 -column 0 -row 16 -sticky e 
  1294. grid .state.pc -column 1 -row 16 -sticky w
  1295. grid .state.l22 -column 2 -row 16 -sticky e 
  1296. grid .state.sr -column 3 -row 16 -sticky w
  1297.  
  1298. grid .state.l23 -column 0 -row 17 -sticky e 
  1299. grid .state.usp -column 1 -row 17 -sticky w
  1300. grid .state.l24 -column 2 -row 17 -sticky e 
  1301. grid .state.ssp -column 3 -row 17 -sticky w
  1302.  
  1303. label .state.bl2 -text {B1:}
  1304. label .state.bl4 -text {B2:}
  1305. label .state.bl6 -text {B3:}
  1306. label .state.bl8 -text {B4:}
  1307. label .state.bl10 -text {B5:}
  1308. label .state.bl12 -text {B6:}
  1309.  
  1310. label .state.b1 -text {00000000}
  1311. label .state.b1a -text {Off}
  1312. label .state.b2 -text {00000000}
  1313. label .state.b2a -text {Off}
  1314. label .state.b3 -text {00000000}
  1315. label .state.b3a -text {Off}
  1316. label .state.b4 -text {00000000}
  1317. label .state.b4a  -text {Off}
  1318. label .state.b5 -text {00000000}
  1319. label .state.b5a -text {Off}
  1320. label .state.b6 -text {00000000}
  1321. label .state.b6a -text {Off}
  1322.  
  1323. frame .state.rule2 -relief raised -bd 2 -height 4
  1324. grid .state.rule2 -column 0 -row 18 -columnspan 4 -sticky ew
  1325.  
  1326. grid .state.bl2 -column 0 -row 19 -sticky e
  1327. grid .state.b1 -column 1 -row 19 -sticky w
  1328. grid .state.b1a -column 2 -row 19 -sticky w 
  1329.  
  1330. grid .state.bl4 -column 0 -row 20 -sticky e
  1331. grid .state.b2 -column 1 -row 20 -sticky w
  1332. grid .state.b2a -column 2 -row 20 -sticky w 
  1333.  
  1334. grid .state.bl6 -column 0 -row 21 -sticky e
  1335. grid .state.b3 -column 1 -row 21 -sticky w
  1336. grid .state.b3a -column 2 -row 21 -sticky w 
  1337.  
  1338. grid .state.bl8 -column 0 -row 22 -sticky e
  1339. grid .state.b4 -column 1 -row 22 -sticky w
  1340. grid .state.b4a -column 2 -row 22 -sticky w 
  1341.  
  1342. grid .state.bl10 -column 0 -row 23 -sticky e
  1343. grid .state.b5 -column 1 -row 23 -sticky w
  1344. grid .state.b5a -column 2 -row 23 -sticky w 
  1345.  
  1346. grid .state.bl12 -column 0 -row 24 -sticky e
  1347. grid .state.b6 -column 1 -row 24 -sticky w
  1348. grid .state.b6a -column 2 -row 24 -sticky w 
  1349.  
  1350. ###  /*** Generate debugger console window ***/
  1351.  
  1352. wm title . \"Pilot Debugger Console\"
  1353. catch {
  1354.     wm iconbitmap . {@pix/case.xbm}
  1355.     wm iconbitmap .remote {@pix/case.xbm}
  1356.     wm iconbitmap .console {@pix/case.xbm}
  1357.     wm iconbitmap .state {@pix/case.xbm}
  1358.     #wm iconmask . {@pix/casemask.xbm}
  1359. }
  1360.  
  1361. frame .m -relief raised
  1362. frame .f
  1363. scrollbar .f.y -orient vertical -command {.f.t yview}
  1364. text .f.t -yscrollcommand {.f.y set} -wrap word
  1365. pack .f.t -fill both -expand yes -side left
  1366. pack .f.y -fill y -side right
  1367. pack [menubutton .m.file -text {File} -menu .m.file.m] -side left
  1368. #pack [menubutton .m.edit -text {Edit} -menu .m.edit.m] -side left
  1369. pack [menubutton .m.windows -text {Windows} -menu .m.windows.m] -side left
  1370. #pack [menubutton .m.help -text {Help} -menu .m.help.m] -side right
  1371.  
  1372. menu .m.file.m
  1373. menu .m.windows.m
  1374. #menu .m.edit.m
  1375. #menu .m.help.m
  1376.  
  1377. #wm iconify .remote
  1378. #wm iconify .console
  1379. #wm iconify .state
  1380.  
  1381.  
  1382. proc ShowWindow {name1 name2 op} {
  1383.   global show
  1384.   if {$show($name2)} {
  1385.     if {[wm state $name2] != \"normal\"} {
  1386.       wm deiconify $name2
  1387.     }
  1388.   } else {
  1389.     if {[wm state $name2] == \"normal\"} {
  1390.       wm withdraw $name2
  1391.     }
  1392.   }
  1393. }
  1394.  
  1395.  
  1396. trace variable show w {ShowWindow}
  1397.  
  1398. bind .remote <Unmap> { set show(.remote) 0 }
  1399. bind .console <Unmap> { set show(.console) 0 }
  1400. bind .state <Unmap> { set show(.state) 0 }
  1401.  
  1402. bind .remote <Map> { set show(.remote) 1 }
  1403. bind .console <Map> { set show(.console) 1 }
  1404. bind .state <Map> { set show(.state) 1 }
  1405.  
  1406. wm protocol .remote WM_DELETE_WINDOW { set show(.remote) 0 }
  1407. wm protocol .console WM_DELETE_WINDOW { set show(.console) 0 }
  1408. wm protocol .state WM_DELETE_WINDOW { set show(.state) 0 }
  1409.  
  1410. set show(.remote) 0
  1411. set show(.console) 0
  1412. set show(.state) 0
  1413.  
  1414.  
  1415. .m.file.m add command -label {Exit} -command {exit}
  1416.  
  1417. .m.windows.m add checkbutton -label {Remote UI} -var show(.remote)
  1418. .m.windows.m add checkbutton -label {Remote Console} -var show(.console)
  1419. .m.windows.m add checkbutton -label {Remote State} -var show(.state)
  1420.  
  1421. pack .m -side top -fill x
  1422. pack .f -side top -fill both -expand yes
  1423. focus .f.t
  1424.  
  1425. ###  /*** Configure console bindings ***/
  1426.  
  1427. bind .console.t <Shift-KeyPress-Return> {tkTextInsert .console.t \"\\n\" ; break}
  1428. bind .f.t <Shift-KeyPress-Return> {tkTextInsert .f.t \"\\n\" ; break}
  1429.  
  1430. bind .console.t <Control-KeyPress-Return> {tkTextInsert .console.t \"\\n\" ; break}
  1431. bind .f.t <Control-KeyPress-Return> {tkTextInsert .f.t \"\\n\" ; break}
  1432.  
  1433. bind .console.t <KeyPress-Return> {Console [.console.t get {insert linestart} {insert lineend}] ; break}
  1434. bind .f.t <KeyPress-Return> {
  1435.     set line [.f.t get {insert linestart} {insert lineend}]
  1436.     set f [string first \">\" $line]
  1437.     incr f
  1438.     set line [string range $line $f end]
  1439.     .f.t mark set insert {insert lineend}
  1440.     .f.t insert insert \\n
  1441.     Debugger $line
  1442.     if {[.f.t compare insert != {insert linestart}]} {
  1443.         .f.t insert insert \"\\n\"
  1444.     }
  1445.     .f.t insert insert \"pilot-debug> \"
  1446.     .f.t see insert
  1447.     break
  1448. }
  1449.  
  1450. proc Console {cmd} {
  1451.     .console.t mark set insert {insert lineend}
  1452.     tkTextInsert .console.t \\n
  1453.     transmit $cmd
  1454. }
  1455.  
  1456. proc Debugger {cmd} {
  1457.     #.f.t mark set insert {insert lineend}
  1458.     #tkTextInsert .f.t \\n
  1459.     if {[string length [string trim $cmd]]!=0} {
  1460.         set code [catch {eval $cmd} message]
  1461.         if {[string length $message]} {
  1462.             set message [string trimright $message]
  1463.             Say \"$message\\n\"
  1464.             #if {[.f.t compare insert != {insert linestart}]} {
  1465.             #    Say \"\\\n\"
  1466.             #}
  1467.         }
  1468.     }
  1469. }
  1470.  
  1471. proc Say {text} {
  1472.     global Interactive
  1473.     if {$Interactive} {
  1474.       .f.t insert insert \"$text\"
  1475.       .f.t see insert
  1476.     } else {
  1477.       upvar result result
  1478.       set result \"$result$text\"
  1479.     }
  1480. }
  1481.  
  1482. ", NULL);
  1483.   puts(interp->result);
  1484.   
  1485.   created = 1;
  1486.   usetk = 1;
  1487.  
  1488.   return TCL_OK;
  1489. #endif
  1490. }
  1491.  
  1492. int proc_help(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  1493. {
  1494.   Say("\
  1495. --- Help ---\n\
  1496. g [<addr>]\tGo: Resume execution (if address is supplied, will start at that point)\n\
  1497. t <addr1> [<addr2>}\tTill: Resume execution until addr1 (if addr2 is supplied, will start at that point)\n\
  1498. coldboot\n\
  1499. warmboot\n\
  1500. pushbutton <button number>\tSimulate button push\n\
  1501. mirror [bool]\tContinually view the Pilot's screen in the Remote UI window (if bool supplied, can turn on or off mirroring, otherwise toggles)\n\
  1502. getdisplay\tShow the Pilot's display in the Remote UI window\n\
  1503. ");
  1504.   return TCL_OK;
  1505. }
  1506.  
  1507. struct { char * name; Tcl_CmdProc * proc; } cmds[] = {
  1508.     { "coldboot",    proc_coldboot },
  1509.     { "warmboot",    proc_warmboot },
  1510.     { "sendscreen",    proc_sendscreen },
  1511.     { "pushbutton",    proc_pushbutton },
  1512.     { "pen",    proc_pen },
  1513.     { "key",    proc_key },
  1514.     { "g",        proc_g },
  1515.     { "t",        proc_t },
  1516.     { "attach",    proc_attach },
  1517.     { "transmit",    proc_transmit },
  1518.     { "getdisplay",    proc_getdisplay },
  1519.     { "mirror",     proc_mirror },
  1520.     { "battery",    proc_battery },
  1521.     { "port",    proc_port },
  1522.     { "help",    proc_help },
  1523.     { "inittkdbg",  proc_inittkdbg },
  1524.     { 0, 0}
  1525. };
  1526.  
  1527. int
  1528. Tcl_AppInit(myinterp)
  1529.     Tcl_Interp *myinterp;        /* Interpreter for application. */
  1530. {
  1531.     int i;
  1532.     
  1533.     interp=myinterp;
  1534.   
  1535.     if (Tcl_Init(interp) == TCL_ERROR) {
  1536.     return TCL_ERROR;
  1537.     }
  1538. #ifdef TK
  1539.     if (usetk) {    
  1540.         if (Tk_Init(interp) == TCL_ERROR) {
  1541.           return TCL_ERROR;
  1542.         }
  1543.         Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
  1544.     }
  1545. #endif
  1546.  
  1547.   /*** Load custom Tcl procedures ***/
  1548.  
  1549.  
  1550.   for (i=0;cmds[i].name;i++) {
  1551.     Tcl_CreateCommand(interp, cmds[i].name, cmds[i].proc, 0, NULL);
  1552.   }
  1553.   
  1554.   Tcl_VarEval(interp,"\
  1555. proc Say {text} {
  1556.     global Interactive
  1557.     if {$Interactive} {
  1558.       puts \"$text\"
  1559.     } else {
  1560.       upvar result result
  1561.       set result \"$result$text\"
  1562.     }
  1563. }
  1564.  
  1565. proc interactive {args} {
  1566.     global Interactive
  1567.     global errorInfo
  1568.     set hold $Interactive
  1569.     set Interactive 1
  1570.     set code [catch $args message]
  1571.     set Interactive $hold
  1572.     error $message $errorInfo $code
  1573. }
  1574.  
  1575. proc noninteractive {args} {
  1576.     global Interactive
  1577.     global errorInfo
  1578.     set hold $Interactive
  1579.     set Interactive 0
  1580.     set code [catch $args message]
  1581.     set Interactive $hold
  1582.     error $message $errorInfo $code
  1583. }
  1584.  
  1585. set Interactive 1
  1586.  
  1587.  
  1588. proc bgerror {msg} {
  1589.     Say $msg
  1590. }
  1591.  
  1592. proc checkup {} {
  1593.     catch {noninteractive battery}
  1594.     after 10000 checkup
  1595. }
  1596.  
  1597. after 1000 checkup
  1598.  
  1599. proc checkupin {time} {
  1600.     after $time {catch {noninteractive battery}}
  1601. }
  1602.  
  1603. ",NULL);     
  1604.  
  1605.   Tcl_LinkVar(interp, "Interactive", (char*)&Interactive, TCL_LINK_INT);
  1606.  
  1607.  
  1608. #ifdef TK  
  1609.   if (usetk)
  1610.     Tcl_VarEval(interp,"inittkdbg",NULL);
  1611.   else
  1612.     Tcl_VarEval(interp,"set tkdbg 0", NULL);
  1613. #endif
  1614.  
  1615.   Say("\tWelcome to pilot-debug!\n\nType 'help' for further information.\n\n");
  1616.   
  1617. #if 0
  1618.   Say("\tWelcome to pilot-debug!\n\n\
  1619. Please connect your Pilot and start console or debugging mode.\n\n(Console mode is a background \
  1620. task that can respond to a few commands, most importantly RPC which lets any function on the \
  1621. Pilot be invoked. The Pilot operates as usual while console mode is active, except that \
  1622. since the serial port is help open, HotSync and other applications that use the serial port \
  1623. will not work. Debug mode is activated on demand or when the Pilot crashes. In debug mode, the \
  1624. CPU is halted, and no commands may be executed, except via a debugging console like this one.)\n\n\
  1625. In the absence of special utilities, the console can be started by \
  1626. the \".2\" shortcut, and debugging via \".1\". To clear either mode, \
  1627. reboot via the reset button. If console mode is active, you may \
  1628. also reboot via the \"coldboot\" or \"warmboot\" commands.\n\n\
  1629. The Remote UI window lets you manipulate the Pilot if console mode is active. By clicking the \
  1630. mouse button on the screen or buttons, you can simulate pen taps, and if you type anything \
  1631. while the window has the focus, the Pilot will receive the keystrokes.\n\n \
  1632. The Remote Console window is specifically for the transmission and reception of console \
  1633. packets. Pressing Return on a line will transmit it, and any incoming packets will be \
  1634. displayed here in addition to the Debug Console.\n\n\
  1635. The Remote State window shows the current Pilot CPU state. It is only updated on request or \
  1636. when the Pilot halts.\n\n\
  1637. The Debugging Console window is the primary interface for pilot-debug. Pressing Return on a \
  1638. line that contains text will execute that line as a Tcl command. (Try 'expr 3+4'.) All of \
  1639. the usual Tcl and Tk commands are available, as well as some special-purpose ones, including \
  1640. 'help', 'coldboot', 'warmboot', 'attach', 't', and 'g', (the last one continues after the Pilot halts.)\n\n\
  1641. Execute 'help' for the list of commands currently implemented.\n\
  1642. ");
  1643. #endif
  1644.  
  1645.     /*
  1646.      * Specify a user-specific startup file to invoke if the application
  1647.      * is run interactively.  Typically the startup file is "~/.apprc"
  1648.      * where "app" is the name of the application.  If this line is deleted
  1649.      * then no user-specific startup file will be run under any conditions.
  1650.      */
  1651.  
  1652.     Tcl_SetVar(interp, "tcl_rcFileName", "~/.pdebugrc", TCL_GLOBAL_ONLY);
  1653.  
  1654.     Tcl_VarEval(interp,"\
  1655.       set tcl_prompt1 myprompt
  1656.       proc myprompt {} {
  1657.         puts -nonewline \"pilot-debug> \"
  1658.       }
  1659.       
  1660.     ",NULL);
  1661.  
  1662.     /* Deal with command-line arguments */
  1663.  
  1664.     Tcl_VarEval(interp,"\
  1665.       if {$argc > 0} {
  1666.         set p [lindex $argv 0]
  1667.         set argv [lrange $argv 1 end]
  1668.         port $p
  1669.       } else {
  1670.         Say \"As you have not entered a serial port on the command like, you might like to \
  1671. set one with 'port /dev/something'\\n\\n\"
  1672.       }
  1673.     ",NULL);
  1674.         
  1675.     return TCL_OK;
  1676. }
  1677.  
  1678. int main(int argc, char *argv[])
  1679. {
  1680.     char *args, *fileName;
  1681.     char buf[20];
  1682.     int code;
  1683.     size_t length;
  1684.     int exitCode = 0;
  1685.     Tcl_Channel errChannel;
  1686.  
  1687.     Tcl_FindExecutable(argv[0]);
  1688.     interp = Tcl_CreateInterp();
  1689.  
  1690.     fileName = NULL;
  1691.     if (argc > 2) {
  1692.     length = strlen(argv[1]);
  1693.     if ((length >= 2) && (strncmp(argv[1], "-file", length) == 0)) {
  1694.         fileName = argv[2];
  1695.         argc-=2;
  1696.         argv+=2;
  1697.     }
  1698.     }
  1699.  
  1700. #ifdef TK    
  1701.     usetk = 1;
  1702. #endif
  1703.     
  1704.     if (argc > 1) {
  1705.         length = strlen(argv[1]);
  1706.         if ((length >= 2) && (strncmp(argv[1], "-notk", length) == 0)) {
  1707. #ifdef TK
  1708.              usetk = 0;
  1709. #endif
  1710.              argc--;
  1711.              argv++;
  1712.         }
  1713.     }
  1714.  
  1715.     /*
  1716.      * Make command-line arguments available in the Tcl variables "argc"
  1717.      * and "argv".
  1718.      */
  1719.  
  1720.     args = Tcl_Merge(argc-1, argv+1);
  1721.     Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
  1722.     ckfree(args);
  1723.     sprintf(buf, "%d", argc-1);
  1724.     Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
  1725.     Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0],
  1726.         TCL_GLOBAL_ONLY);
  1727.  
  1728.     /*
  1729.      * Set the "tcl_interactive" variable.
  1730.      */
  1731.  
  1732.     tty = isatty(0);
  1733.     Tcl_SetVar(interp, "tcl_interactive",
  1734.         ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY);
  1735.  
  1736.  
  1737. #ifdef TK
  1738.     if (!getenv("DISPLAY") || (strlen(getenv("DISPLAY"))==0))
  1739.         usetk = 0;
  1740. #endif
  1741.  
  1742.     /*
  1743.      * Invoke application-specific initialization.
  1744.      */
  1745.  
  1746.     if (Tcl_AppInit(interp) != TCL_OK) {
  1747.     errChannel = Tcl_GetStdChannel(TCL_STDERR);
  1748.     if (errChannel) {
  1749.         Tcl_Write(errChannel,
  1750.             "application-specific initialization failed: ", -1);
  1751.         Tcl_Write(errChannel, interp->result, -1);
  1752.         Tcl_Write(errChannel, "\n", 1);
  1753.     }
  1754.     }
  1755.  
  1756.     /*
  1757.      * Invoke the script specified on the command line, if any.
  1758.      */
  1759.  
  1760.     if (fileName != NULL) {
  1761.     code = Tcl_EvalFile(interp, fileName);
  1762.     if (code != TCL_OK) {
  1763.         errChannel = Tcl_GetStdChannel(TCL_STDERR);
  1764.         if (errChannel) {
  1765.         /*
  1766.          * The following statement guarantees that the errorInfo
  1767.          * variable is set properly.
  1768.          */
  1769.  
  1770.         Tcl_AddErrorInfo(interp, "");
  1771.         Tcl_Write(errChannel,
  1772.             Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY), -1);
  1773.         Tcl_Write(errChannel, "\n", 1);
  1774.         }
  1775.         exitCode = 1;
  1776.     }
  1777.     goto done;
  1778.     }
  1779.  
  1780.    /* Tcl 7.5 did not support this command */
  1781. #if (TCL_MAJOR_VERSION > 7) || (TCL_MINOR_VERSION > 5)
  1782.  
  1783.     /*
  1784.      * We're running interactively.  Source a user-specific startup
  1785.      * file if the application specified one and if the file exists.
  1786.      */
  1787.  
  1788.     Tcl_SourceRCFile(interp);
  1789. #endif
  1790.     
  1791.     /*
  1792.      * Loop infinitely, waiting for commands to execute.  When there
  1793.      * are no windows left, Tk_MainLoop returns and we exit.
  1794.      */
  1795.      
  1796. #ifdef TK
  1797.     if (!usetk) {     
  1798. #endif
  1799.  
  1800.     /*
  1801.      * Process commands from stdin until there's an end-of-file.  Note
  1802.      * that we need to fetch the standard channels again after every
  1803.      * eval, since they may have been changed.
  1804.      */
  1805.  
  1806.     do_readline();
  1807.  
  1808.      
  1809. #ifdef TK
  1810.     }
  1811. #endif
  1812.  
  1813. done:
  1814.  
  1815. #ifdef TK
  1816.     if (usetk) {
  1817.         Tcl_VarEval(interp, ".f.t insert end {pilot-debug> }; .f.t set mark insert end",0);
  1818.         Tk_MainLoop();
  1819.         Tcl_DeleteInterp(interp);
  1820.         Tcl_Exit(0);
  1821.     }
  1822. #endif
  1823.     return 0;
  1824. }
  1825.  
  1826.