home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / sybase / starbuck / java.z / TTY.java < prev    next >
Text File  |  1996-05-03  |  43KB  |  1,448 lines

  1. /*
  2.  * @(#)TTY.java    1.68 96/04/21
  3.  *
  4.  * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package sun.tools.ttydebug;
  21. import sun.tools.debug.*;
  22. import java.util.*;
  23. import java.io.*;
  24. import java.net.*;
  25.  
  26. public class TTY implements DebuggerCallback {
  27.     RemoteDebugger debugger;
  28.     RemoteThread currentThread;
  29.     RemoteThreadGroup currentThreadGroup;
  30.     PrintStream out = null;
  31.     PrintStream console = null;
  32.  
  33.     private String lastArgs = null;
  34.     
  35.     private RemoteThread indexToThread(int index) throws Exception {
  36.     setDefaultThreadGroup();
  37.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  38.     if (index == 0 || index > list.length) {
  39.         return null;
  40.     }
  41.     return list[index-1];
  42.     }
  43.  
  44.     private int parseThreadId(String idToken) throws Exception {
  45.     if (idToken.startsWith("t@")) {
  46.         idToken = idToken.substring(2);
  47.     }
  48.  
  49.     int threadId;
  50.     try {
  51.         threadId = Integer.valueOf(idToken).intValue();
  52.     } catch (NumberFormatException e) {
  53.         threadId = 0;
  54.     }
  55.     if (indexToThread(threadId) == null) {
  56.         out.println("\"" + idToken +
  57.                    "\" is not a valid thread id.");
  58.         return 0;
  59.     }
  60.     return threadId;
  61.     }
  62.  
  63.     private void printPrompt() throws Exception {
  64.         if (currentThread == null) {
  65.             out.print("> ");
  66.         } else {
  67.             out.print(currentThread.getName() + "[" +
  68.                       (currentThread.getCurrentFrameIndex() + 1)
  69.                       + "] ");
  70.         }
  71.         out.flush();
  72.     }
  73.  
  74.     public synchronized void printToConsole(String text) throws Exception {
  75.         console.print(text);
  76.         console.flush();
  77.     }
  78.  
  79.     public void breakpointEvent(RemoteThread t) throws Exception {
  80.     out.print("\nBreakpoint hit: ");
  81.  
  82.     RemoteStackFrame[] stack = t.dumpStack();
  83.     if (stack.length > 0) {
  84.         out.println(stack[0].toString());
  85.             currentThread = t;
  86.     } else {
  87.         out.println("Invalid thread specified in breakpoint.");
  88.     }
  89.         printPrompt();
  90.     }
  91.  
  92.     public void exceptionEvent(RemoteThread t, String errorText) 
  93.       throws Exception {
  94.     out.println("\n" + errorText);
  95.     t.setCurrentFrameIndex(0);
  96.     currentThread = t;
  97.         printPrompt();
  98.     }
  99.  
  100.     public void threadDeathEvent(RemoteThread t) throws Exception {
  101.     out.println("\n" + t.getName() + " died.");
  102.         if (t == currentThread) {
  103.             currentThread = null;
  104.         }
  105.         printPrompt();
  106.     }
  107.  
  108.     public void quitEvent() throws Exception {
  109.         String msg = null;
  110.         if (lastArgs != null) {
  111.             StringTokenizer t = new StringTokenizer(lastArgs);
  112.             if (t.hasMoreTokens()) {
  113.                 msg = new String("\n" + t.nextToken() + " exited");
  114.             }
  115.         }
  116.         if (msg == null) {
  117.             msg = new String("\nThe application exited");
  118.         }
  119.         out.println(msg);
  120.         currentThread = null;
  121.         System.exit(0);
  122.     }
  123.  
  124.     void classes() throws Exception {
  125.     RemoteClass list[] = debugger.listClasses();
  126.  
  127.     out.println("** classes list **");
  128.     for (int i = 0 ; i < list.length ; i++) {
  129.         out.println(list[i].description());
  130.     }
  131.     }
  132.  
  133.     void methods(StringTokenizer t) throws Exception {
  134.     if (!t.hasMoreTokens()) {
  135.         out.println("No class specified.");
  136.         return;
  137.     }
  138.  
  139.     String idClass = t.nextToken();
  140.     try {
  141.         RemoteClass cls = getClassFromToken(idClass);
  142.  
  143.         RemoteField methods[] = cls.getMethods();
  144.         for (int i = 0; i < methods.length; i++) {
  145.         out.println(methods[i].getTypedName());
  146.         }
  147.     } catch (IllegalArgumentException e) {
  148.         out.println("\"" + idClass +
  149.                    "\" is not a valid id or class name.");
  150.     }
  151.     }
  152.  
  153.     int printThreadGroup(RemoteThreadGroup tg, int iThread) throws Exception {
  154.     out.println("Group " + tg.getName() + ":");
  155.     RemoteThread tlist[] = tg.listThreads(false);
  156.  
  157.     int maxId = 0;
  158.     int maxName = 0;
  159.     for (int i = 0 ; i < tlist.length ; i++) {
  160.         int len = tlist[i].description().length();
  161.         if (len > maxId)
  162.         maxId = len;
  163.         String name = tlist[i].getName();
  164.         int iDot = name.lastIndexOf('.');
  165.         if (iDot >= 0 && name.length() > iDot) {
  166.         name = name.substring(iDot + 1);
  167.         }
  168.         if (name.length() > maxName)
  169.         maxName = name.length();
  170.     }
  171.  
  172.     for (int i = 0 ; i < tlist.length ; i++) {
  173.         char buf[] = new char[80];
  174.         for (int j = 0; j < 79; j++) {
  175.         buf[j] = ' ';
  176.         }
  177.         buf[79] = '\0';
  178.         StringBuffer sbOut = new StringBuffer();
  179.         sbOut.append(buf);
  180.  
  181.         sbOut.insert(((i + iThread + 1) < 10) ? 1 : 0, (i + iThread + 1));
  182.         sbOut.insert(2, ".");
  183.         int iBuf = 4;
  184.         sbOut.insert(iBuf, tlist[i].description());
  185.         iBuf += maxId + 1;
  186.         String name = tlist[i].getName();
  187.         int iDot = name.lastIndexOf('.');
  188.         if (iDot >= 0 && name.length() > iDot) {
  189.         name = name.substring(iDot + 1);
  190.         }
  191.         sbOut.insert(iBuf, name);
  192.         iBuf += maxName + 1;
  193.         sbOut.insert(iBuf, tlist[i].getStatus());
  194.         sbOut.setLength(79);
  195.         out.println(sbOut.toString());
  196.     }
  197.  
  198.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(tg);
  199.     for (int ig = 0; ig < tglist.length; ig++) {
  200.         if (tg != tglist[ig]) {
  201.         iThread += printThreadGroup(tglist[ig], iThread + tlist.length);
  202.         }
  203.     }
  204.     return tlist.length;
  205.     }
  206.  
  207.     private void setDefaultThreadGroup() throws Exception {
  208.     if (currentThreadGroup == null) {
  209.         RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  210.         currentThreadGroup = tglist[0];    // system threadgroup
  211.     }
  212.     }
  213.     
  214.     void threads(StringTokenizer t) throws Exception {
  215.     if (!t.hasMoreTokens()) {
  216.         setDefaultThreadGroup();
  217.         printThreadGroup(currentThreadGroup, 0);
  218.         return;
  219.     }
  220.     String name = t.nextToken();
  221.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  222.     for (int i = 0; i < tglist.length; i++) {
  223.         if (name.equals(tglist[i].getName())) {
  224.         printThreadGroup(tglist[i], 0);
  225.         return;
  226.         }
  227.     }
  228.     out.println(name + " is not a valid threadgroup name.");
  229.     }
  230.  
  231.     void threadGroups() throws Exception {
  232.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  233.     for (int i = 0; i < tglist.length; i++) {
  234.         out.println(new Integer(i+1).toString() + ". " +
  235.                    tglist[i].description() + " " +
  236.                    tglist[i].getName());
  237.     }
  238.     }
  239.  
  240.     void setThread(int threadId) throws Exception {
  241.     setDefaultThreadGroup();
  242.     RemoteThread thread = indexToThread(threadId);
  243.     if (thread == null) {
  244.         out.println("\"" + threadId +
  245.                    "\" is not a valid thread id.");
  246.         return;
  247.     }
  248.     currentThread = thread;
  249.     }
  250.     
  251.     void thread(StringTokenizer t) throws Exception {
  252.     if (!t.hasMoreTokens()) {
  253.         out.println("Thread number not specified.");
  254.         return;
  255.     }
  256.     int threadId = parseThreadId(t.nextToken());
  257.     if (threadId == 0) {
  258.         return;
  259.     }
  260.     setThread(threadId);
  261.     }
  262.     
  263.     void threadGroup(StringTokenizer t) throws Exception {
  264.     if (!t.hasMoreTokens()) {
  265.         out.println("Threadgroup name not specified.");
  266.         return;
  267.     }
  268.     String name = t.nextToken();
  269.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  270.     for (int i = 0; i < tglist.length; i++) {
  271.         if (name.equals(tglist[i].getName())) {
  272.         currentThreadGroup = tglist[i];
  273.         return;
  274.         }
  275.     }
  276.     out.println(name + " is not a valid threadgroup name.");
  277.     }
  278.     
  279.     void run(StringTokenizer t) throws Exception {
  280.     String argv[] = new String[100];
  281.     int argc = 0;
  282.  
  283.     if (!t.hasMoreTokens() && lastArgs != null) {
  284.         t = new StringTokenizer(lastArgs);
  285.         out.println("run " + lastArgs);
  286.     }
  287.     while (t.hasMoreTokens()) {
  288.         argv[argc++] = t.nextToken();
  289.             if (argc == 1) {
  290.                 // Expand name, if necessary.
  291.                 RemoteClass cls = debugger.findClass(argv[0]);
  292.                 if (cls == null) {
  293.                     out.println("Could not load the " + argv[0] + " class.");
  294.                     return;
  295.                 }
  296.                 argv[0] = cls.getName();
  297.             }
  298.     }
  299.  
  300.     if (argc > 0) {
  301.         RemoteThreadGroup newGroup = debugger.run(argc, argv);
  302.         if (newGroup != null) {
  303.         currentThreadGroup = newGroup;
  304.         setThread(1);
  305.         out.println("running ...");
  306.         } else {
  307.         out.println(argv[0] + " failed.");
  308.         }
  309.     } else {
  310.         out.println("No class name specified.");
  311.     }
  312.     }
  313.  
  314.     void load(StringTokenizer t) throws Exception {
  315.     if (!t.hasMoreTokens()) {
  316.         out.println("Class name not specified.");
  317.         return;
  318.     }
  319.     String idToken = t.nextToken();
  320.     RemoteClass cls = debugger.findClass(idToken);
  321.     if (cls == null) {
  322.         out.print(idToken + " not found");
  323.         out.println((idToken.indexOf('.') > 0) ?
  324.                    " (try the full name)" : "");
  325.     } else {
  326.         out.println(cls.toString());
  327.     }
  328.     }
  329.  
  330.     void suspend(StringTokenizer t) throws Exception {
  331.     if (!t.hasMoreTokens()) {
  332.         setDefaultThreadGroup();
  333.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  334.         for (int i = 0; i < list.length; i++) {
  335.         list[i].suspend();
  336.         }
  337.         out.println("All (non-system) threads suspended.");
  338.     } else {
  339.         while (t.hasMoreTokens()) {
  340.         String idToken = t.nextToken();
  341.         int threadId;
  342.         try {
  343.             threadId = Integer.valueOf(idToken).intValue();
  344.         } catch (NumberFormatException e) {
  345.             threadId = 0;
  346.         }
  347.         RemoteThread thread = indexToThread(threadId);
  348.         if (thread == null) {
  349.             out.println("\"" + idToken +
  350.                        "\" is not a valid thread id.");
  351.             continue;
  352.         }
  353.         thread.suspend();
  354.         }
  355.     }
  356.     }
  357.  
  358.     void resume(StringTokenizer t) throws Exception {
  359.      if (!t.hasMoreTokens()) {
  360.         setDefaultThreadGroup();
  361.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  362.         for (int i = 0; i < list.length; i++) {
  363.         list[i].resume();
  364.         }
  365.         if (currentThread != null) {
  366.         currentThread.resetCurrentFrameIndex();
  367.         }
  368.          out.println("All threads resumed.");
  369.      } else {
  370.          while (t.hasMoreTokens()) {
  371.          String idToken = t.nextToken();
  372.          int threadId;
  373.          try {
  374.              threadId = Integer.valueOf(idToken).intValue();
  375.          } catch (NumberFormatException e) {
  376.              threadId = 0;
  377.          }
  378.         RemoteThread thread = indexToThread(threadId);
  379.         if (thread == null) {
  380.              out.println("\"" + idToken +
  381.                        "\" is not a valid thread id.");
  382.              continue;
  383.          }
  384.          thread.resume();
  385.          if (thread == currentThread) {
  386.              currentThread.resetCurrentFrameIndex();
  387.          }
  388.           }
  389.     }
  390.     }
  391.  
  392.     void cont() throws Exception {
  393.     if (currentThread == null) {
  394.         out.println("Nothing suspended.");
  395.         return;
  396.     }
  397.     setDefaultThreadGroup();
  398.     RemoteThread list[] = currentThreadGroup.listThreads(true);
  399.     for (int i = 0; i < list.length; i++) {
  400.         list[i].cont();
  401.     }
  402.     currentThread.resetCurrentFrameIndex();
  403.     }
  404.  
  405.     void step() throws Exception {
  406.     if (currentThread == null) {
  407.         out.println("Nothing suspended.");
  408.         return;
  409.     }
  410.     try {
  411.         currentThread.step(true);
  412.     } catch (IllegalAccessError e) {
  413.         out.println("Current thread is not at breakpoint.");
  414.     }
  415.     }
  416.  
  417.     void next() throws Exception {
  418.     if (currentThread == null) {
  419.         out.println("Nothing suspended.");
  420.         return;
  421.     }
  422.     try {
  423.         currentThread.next();
  424.     } catch (IllegalAccessError e) {
  425.         out.println("Current thread is not at breakpoint.");
  426.     }
  427.     }
  428.  
  429.     void kill(StringTokenizer t) throws Exception {
  430.      if (!t.hasMoreTokens()) {
  431.         out.println("Usage: kill <threadgroup name> or <thread id>");
  432.         return;
  433.     }
  434.     while (t.hasMoreTokens()) {
  435.         String idToken = t.nextToken();
  436.         int threadId;
  437.         try {
  438.         threadId = Integer.valueOf(idToken).intValue();
  439.         } catch (NumberFormatException e) {
  440.         threadId = 0;
  441.         }
  442.         RemoteThread thread = indexToThread(threadId);
  443.         if (thread != null) {
  444.                 out.println("killing thread: " + thread.getName());
  445.         thread.stop();
  446.                 return;
  447.         } else {
  448.         /* Check for threadgroup name, skipping "system". */
  449.         RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  450.         tglist = debugger.listThreadGroups(tglist[0]);
  451.         for (int i = 0; i < tglist.length; i++) {
  452.             if (tglist[i].getName().equals(idToken)) {
  453.                         out.println("killing threadgroup: " + idToken);
  454.             tglist[i].stop();
  455.             return;
  456.             }
  457.         }
  458.         
  459.         out.println("\"" + idToken +
  460.                    "\" is not a valid threadgroup or id.");
  461.         }
  462.     }
  463.     }
  464.  
  465.     void catchException(StringTokenizer t) throws Exception {
  466.      if (!t.hasMoreTokens()) {
  467.         String exceptionList[] = debugger.getExceptionCatchList();
  468.         for (int i = 0; i < exceptionList.length; i++) {
  469.         out.print("  " + exceptionList[i]);
  470.         if ((i & 4) == 3 || (i == exceptionList.length - 1)) {
  471.             out.println();
  472.         }
  473.         }
  474.     } else {
  475.         String idClass = t.nextToken();
  476.         try {
  477.         RemoteClass cls = getClassFromToken(idClass);
  478.         cls.catchExceptions();
  479.         } catch (Exception e) {
  480.         out.println("Invalid exception class name: " + idClass);
  481.         }
  482.     }
  483.     }
  484.     
  485.     void ignoreException(StringTokenizer t) throws Exception {
  486.      if (!t.hasMoreTokens()) {
  487.         String exceptionList[] = debugger.getExceptionCatchList();
  488.         for (int i = 0; i < exceptionList.length; i++) {
  489.         out.print("  " + exceptionList[i]);
  490.         if ((i & 4) == 3 || (i == exceptionList.length - 1)) {
  491.             out.println();
  492.         }
  493.         }
  494.     } else {
  495.         String idClass = t.nextToken();
  496.         try {
  497.         RemoteClass cls = getClassFromToken(idClass);
  498.         cls.ignoreExceptions();
  499.         } catch (Exception e) {
  500.         out.println("Invalid exception class name: " + idClass);
  501.         }
  502.     }
  503.     }
  504.     
  505.     void up(StringTokenizer t) throws Exception {
  506.     if (currentThread == null) {
  507.         out.println("Current thread not set.");
  508.         return;
  509.     }
  510.  
  511.     int nLevels = 1;
  512.     if (t.hasMoreTokens()) {
  513.         String idToken = t.nextToken();
  514.         int n;
  515.         try {
  516.         n = Integer.valueOf(idToken).intValue();
  517.         } catch (NumberFormatException e) {
  518.         n = 0;
  519.         }
  520.         if (n == 0) {
  521.         out.println("Usage: up [n frames]");
  522.         return;
  523.         }
  524.         nLevels = n;
  525.     }
  526.  
  527.     try {
  528.         currentThread.up(nLevels);
  529.     } catch (IllegalAccessError e) {
  530.         out.println("Thread isn't suspended.");
  531.     } catch (ArrayIndexOutOfBoundsException e) {
  532.         out.println("End of stack.");
  533.     }
  534.     }
  535.  
  536.     void down(StringTokenizer t) throws Exception {
  537.     if (currentThread == null) {
  538.         out.println("Current thread not set.");
  539.         return;
  540.     }
  541.  
  542.     int nLevels = 1;
  543.     if (t.hasMoreTokens()) {
  544.         String idToken = t.nextToken();
  545.         int n;
  546.         try {
  547.         n = Integer.valueOf(idToken).intValue();
  548.         } catch (NumberFormatException e) {
  549.         n = 0;
  550.         }
  551.         if (n == 0) {
  552.         out.println("usage: down [n frames]");
  553.         return;
  554.         }
  555.         nLevels = n;
  556.     }
  557.  
  558.     try {
  559.         currentThread.down(nLevels);
  560.     } catch (IllegalAccessError e) {
  561.         out.println("Thread isn't suspended.");
  562.     } catch (ArrayIndexOutOfBoundsException e) {
  563.         out.println("End of stack.");
  564.     }
  565.     }
  566.  
  567.     void dumpStack(RemoteThread thread) throws Exception {
  568.     RemoteStackFrame[] stack = thread.dumpStack();
  569.     if (stack.length == 0) {
  570.         out.println("Thread is not running (no stack).");
  571.     } else {
  572.         int nFrames = stack.length;
  573.         for (int i = thread.getCurrentFrameIndex(); i < nFrames; i++) {
  574.         out.print("  [" + (i + 1) + "] ");
  575.         out.println(stack[i].toString());
  576.         }
  577.     }
  578.     }
  579.  
  580.     void where(StringTokenizer t) throws Exception {
  581.     if (!t.hasMoreTokens()) {
  582.         if (currentThread == null) {
  583.         out.println("No thread specified.");
  584.         return;
  585.         }
  586.         dumpStack(currentThread);
  587.     } else {
  588.         String token = t.nextToken();
  589.         if (token.toLowerCase().equals("all")) {
  590.         setDefaultThreadGroup();
  591.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  592.         for (int i = 0; i < list.length; i++) {
  593.             out.println(list[i].getName() + ": ");
  594.             dumpStack(list[i]);
  595.         }
  596.         } else {
  597.         int threadId = parseThreadId(token);
  598.         if (threadId == 0) {
  599.             return;
  600.         }
  601.         dumpStack(indexToThread(threadId));
  602.         }
  603.     }
  604.     }
  605.  
  606.     void trace(String cmd, StringTokenizer t) throws Exception {
  607.     if (!t.hasMoreTokens()) {
  608.         out.println("(i)trace < \"on\" | \"off\" >");
  609.         return;
  610.     }
  611.     
  612.     String v = t.nextToken();
  613.     boolean traceOn;
  614.     if (v.equals("on")) {
  615.         traceOn = true;
  616.     } else if (v.equals("off")) {
  617.         traceOn = false;
  618.     } else {
  619.         out.println("(i)trace < \"on\" | \"off\" >");
  620.         return;
  621.     }
  622.  
  623.     if (cmd.equals("trace")) {
  624.         debugger.trace(traceOn);
  625.     } else {
  626.         debugger.itrace(traceOn);
  627.     }
  628.     }
  629.  
  630.     void memory() throws Exception {
  631.     out.println("Free: " + debugger.freeMemory() + ", total: " +
  632.                debugger.totalMemory());
  633.     }
  634.  
  635.     void gc() throws Exception {
  636.         RemoteObject[] save_list = new RemoteObject[2];
  637.         save_list[0] = currentThread;
  638.         save_list[1] = currentThreadGroup;
  639.         debugger.gc(save_list);
  640.     }
  641.  
  642.     private RemoteClass getClassFromToken(String idToken) throws Exception {
  643.     RemoteObject obj;
  644.     if (idToken.startsWith("0x") ||
  645.         Character.isDigit(idToken.charAt(0))) {
  646.         /* It's an object id. */
  647.         int id;
  648.         try {
  649.         id = RemoteObject.fromHex(idToken);
  650.         } catch (NumberFormatException e) {
  651.         id = 0;
  652.         }
  653.         if (id == 0 || (obj = debugger.get(new Integer(id))) == null) {
  654.         throw new IllegalArgumentException();
  655.         } else if (!(obj instanceof RemoteClass)) {
  656.         throw new IllegalArgumentException();
  657.         }
  658.     } else {
  659.         /* It's a class */
  660.         obj = debugger.findClass(idToken);
  661.         if (obj == null) {
  662.         throw new IllegalArgumentException();
  663.         }
  664.     }
  665.     return (RemoteClass)obj;
  666.     }
  667.  
  668.     void listBreakpoints() throws Exception {
  669.         String bkptList[] = debugger.listBreakpoints();
  670.     if (bkptList.length > 0) {
  671.             out.println("Current breakpoints set:");
  672.             for(int i = 0; i < bkptList.length; i++) {
  673.                 out.println("\t" + bkptList[i]);
  674.             }
  675.     } else {
  676.         out.println("No breakpoints set.");
  677.     }
  678.     }
  679.  
  680.     void stop(StringTokenizer t) throws Exception {
  681.     if (!t.hasMoreTokens()) {
  682.         listBreakpoints();
  683.         return;
  684.     }
  685.     
  686.     String idClass = null;
  687.     try {
  688.         String modifier = t.nextToken();
  689.         boolean stopAt;
  690.         if (modifier.equals("at")) {
  691.         stopAt = true;
  692.         } else if (modifier.equals("in")) {
  693.         stopAt = false;
  694.         } else {
  695.         out.println("Usage: stop at <class>:<line_number> or");
  696.         out.println("       stop in <class>.<method_name>");
  697.         return;
  698.         }
  699.  
  700.         if (modifier.equals("at")) {
  701.         idClass = t.nextToken(": \t\n\r");
  702.         RemoteClass cls = getClassFromToken(idClass);
  703.  
  704.         String idLine = t.nextToken();
  705.         int lineno = Integer.valueOf(idLine).intValue();
  706.  
  707.         String err = cls.setBreakpointLine(lineno);
  708.         if (err.length() > 0) {
  709.             out.println(err);
  710.         } else {
  711.             out.println("Breakpoint set at " + cls.getName() +
  712.                        ":" + lineno);
  713.         }
  714.         } else {
  715.         idClass = t.nextToken(": \t\n\r");
  716.                 RemoteClass cls = null;
  717.                 String idMethod = null;
  718.  
  719.                 try {
  720.                     cls = getClassFromToken(idClass);
  721.                 } catch (IllegalArgumentException e) {
  722.                     // Try stripping method from class.method token.
  723.                     int idot = idClass.lastIndexOf(".");
  724.                     if (idot == -1) {
  725.                         out.println("\"" + idClass +
  726.                             "\" is not a valid id or class name.");
  727.                         return;
  728.                     }
  729.                     idMethod = idClass.substring(idot + 1);
  730.                     idClass = idClass.substring(0, idot);
  731.                     cls = getClassFromToken(idClass);
  732.                 }
  733.  
  734.                 if (idMethod == null) {
  735.                     idMethod = t.nextToken();
  736.                 }
  737.                 RemoteField method;
  738.                 try {
  739.                     method = cls.getMethod(idMethod);
  740.                 } catch (NoSuchMethodException nsme) {
  741.             out.println("Class " + cls.getName() +
  742.                        " doesn't have a method " + idMethod);
  743.             return;
  744.         }
  745.         String err = cls.setBreakpointMethod(method);
  746.         if (err.length() > 0) {
  747.             out.println(err);
  748.         } else {
  749.             out.println("Breakpoint set in " + cls.getName() +
  750.                        "." + idMethod);
  751.         }
  752.         }
  753.     } catch (NoSuchElementException e) {
  754.         out.println("Usage: stop at <class>:<line_number> or");
  755.         out.println("       stop in <class>.<method_name>");
  756.     } catch (NumberFormatException e) {
  757.         out.println("Invalid line number.");
  758.     } catch (IllegalArgumentException e) {
  759.         out.println("\"" + idClass +
  760.                    "\" is not a valid id or class name.");
  761.     }
  762.     }
  763.  
  764.     void clear(StringTokenizer t) throws Exception {
  765.     if (!t.hasMoreTokens()) {
  766.         listBreakpoints();
  767.         return;
  768.     }
  769.     
  770.     String idClass = null;
  771.     String idMethod = null;
  772.     RemoteClass cls = null;
  773.     try {
  774.         idClass = t.nextToken(": \t\n\r");
  775.         try {
  776.             cls = getClassFromToken(idClass);
  777.             } catch (IllegalArgumentException e) {
  778.                 // Try stripping method from class.method token.
  779.                 int idot = idClass.lastIndexOf(".");
  780.                 if (idot == -1) {
  781.                     out.println("\"" + idClass +
  782.                         "\" is not a valid id or class name.");
  783.                     return;
  784.                 }
  785.                 idMethod = idClass.substring(idot + 1);
  786.                 idClass = idClass.substring(0, idot);
  787.                 cls = getClassFromToken(idClass);
  788.                 RemoteField method;
  789.                 try {
  790.                     method = cls.getMethod(idMethod);
  791.                 } catch (NoSuchMethodException nsme) {
  792.             out.println("\"" + idMethod + 
  793.                 "\" is not a valid method name of class " +
  794.                 cls.getName());
  795.             return;
  796.         }
  797.         String err = cls.clearBreakpointMethod(method);
  798.             if (err.length() > 0) {
  799.             out.println(err);
  800.             } else {
  801.             out.println("Breakpoint cleared at " + 
  802.                 cls.getName() + "." + idMethod);
  803.         }
  804.         return;
  805.             }
  806.  
  807.         String idLine = t.nextToken();
  808.         int lineno = Integer.valueOf(idLine).intValue();
  809.  
  810.         String err = cls.clearBreakpointLine(lineno);
  811.         if (err.length() > 0) {
  812.         out.println(err);
  813.         } else {
  814.         out.println("Breakpoint cleared at " + cls.getName() +
  815.                    ": " + lineno);
  816.         }
  817.     } catch (NoSuchElementException e) {
  818.         out.println("Usage: clear <class>:<line_number>");
  819.         out.println("   or: clear <class>.<method>");
  820.     } catch (NumberFormatException e) {
  821.         out.println("Usage: clear <class>:<line_number>");
  822.         out.println("   or: clear <class>.<method>");
  823.     } catch (IllegalArgumentException e) {
  824.         out.println("\"" + idClass +
  825.                    "\" is not a valid id or class name.");
  826.     }
  827.     }
  828.  
  829.     void list(StringTokenizer t) throws Exception {
  830.     RemoteStackFrame frame = null;
  831.     if (currentThread == null) {
  832.         out.println("No thread specified.");
  833.         return;
  834.     }
  835.     try {
  836.         frame = currentThread.getCurrentFrame();
  837.     } catch (IllegalAccessError e) {
  838.         out.println("Current thread isn't suspended.");
  839.         return;
  840.     } catch (ArrayIndexOutOfBoundsException e) {
  841.         out.println("Thread is not running (no stack).");
  842.         return;
  843.     }
  844.     
  845.     int lineno;
  846.     if (t.hasMoreTokens()) {
  847.         String id = t.nextToken();
  848.  
  849.             // See if token is a line number.
  850.             try {
  851.                 lineno = Integer.valueOf(id).intValue();
  852.             } catch (NumberFormatException nfe) {
  853.                 // It isn't -- see if it's a method name.
  854.                 try {
  855.                     lineno = frame.getRemoteClass().getMethodLineNumber(id);
  856.                 } catch (NoSuchMethodException iobe) {
  857.                     out.println(id + " is not a valid line number or " +
  858.                                 "method name for class " + 
  859.                                 frame.getRemoteClass().getName());
  860.                     return;
  861.                 } catch (NoSuchLineNumberException nse) {
  862.                     out.println("Line number information not found in " +
  863.                                 frame.getRemoteClass().getName());
  864.                     return;
  865.                 }
  866.             }
  867.     } else {
  868.         lineno = frame.getLineNumber();
  869.     }
  870.     int startLine = (lineno > 4) ? lineno - 4 : 1;
  871.     int endLine = startLine + 9;
  872.  
  873.     InputStream rawSourceFile = frame.getRemoteClass().getSourceFile();
  874.     if (rawSourceFile == null) {
  875.         out.println("Unable to find " + 
  876.                         frame.getRemoteClass().getSourceFileName());
  877.         return;
  878.     }
  879.  
  880.     DataInputStream sourceFile = new DataInputStream(rawSourceFile);
  881.     String sourceLine = null;
  882.  
  883.     /* Skip through file to desired window. */
  884.     for (int i = 1; i <= startLine; i++) {
  885.         sourceLine = sourceFile.readLine();
  886.     }
  887.     if (sourceLine == null) {
  888.         out.println(new Integer(lineno).toString() +
  889.                         " is an invalid line number for the file " +
  890.                         frame.getRemoteClass().getSourceFileName());
  891.     }
  892.  
  893.     /* Print lines */
  894.     for (int i = startLine; i < endLine && sourceLine != null; i++) {
  895.         out.print(new Integer(i).toString() + "\t" +
  896.                  ((i == lineno) ? "=> " : "   "));
  897.         out.println(sourceLine);
  898.         sourceLine = sourceFile.readLine();
  899.     }
  900.         
  901.     }
  902.  
  903.     /* Get or set the source file path list. */
  904.     void use(StringTokenizer t) throws Exception {
  905.     if (!t.hasMoreTokens()) {
  906.         out.println(debugger.getSourcePath());
  907.     } else {
  908.         debugger.setSourcePath(t.nextToken());
  909.     }
  910.     }
  911.  
  912.     /* Print all local variables in current stack frame. */
  913.     void locals() throws Exception {
  914.     if (currentThread == null) {
  915.         out.println("No default thread specified: " +
  916.                    "use the \"thread\" command first.");
  917.         return;
  918.     }
  919.     RemoteStackVariable rsv[] = currentThread.getStackVariables();
  920.     if (rsv == null || rsv.length == 0) {
  921.         out.println("No local variables: try compiling with -g");
  922.         return;
  923.     }
  924.     out.println("Method arguments:");
  925.     for (int i = 0; i < rsv.length; i++) {
  926.         if (rsv[i].methodArgument()) {
  927.                 out.print("  " + rsv[i].getName());
  928.                 if (rsv[i].inScope()) {
  929.                     out.println(" = " + rsv[i].getValue().toString());
  930.                 } else {
  931.                     out.println(" is not in scope (WHAT???)");
  932.                 }
  933.         }
  934.     }
  935.     out.println("Local variables:");
  936.     for (int i = 0; i < rsv.length; i++) {
  937.         if (!rsv[i].methodArgument()) {
  938.                 out.print("  " + rsv[i].getName());
  939.                 if (rsv[i].inScope()) {
  940.                     out.println(" = " + rsv[i].getValue().toString());
  941.                 } else {
  942.                     out.println(" is not in scope.");
  943.                 }
  944.             }
  945.     }
  946.     return;
  947.     }
  948.  
  949.     /* Print a specified reference.  Returns success in resolving reference. */
  950.     boolean print(StringTokenizer t, boolean dumpObject, boolean recursing) throws Exception {
  951.     if (!t.hasMoreTokens()) {
  952.         out.println("No objects specified.");
  953.         return false;
  954.     }
  955.  
  956.     while (t.hasMoreTokens()) {
  957.         int id;
  958.         RemoteValue obj = null;
  959.  
  960.         String delimiters = ".[(";
  961.         String expr = t.nextToken();
  962.         StringTokenizer pieces =
  963.         new StringTokenizer(expr, delimiters, true);
  964.  
  965.         String idToken = pieces.nextToken(); // There will be at least one.
  966.         String varName = expr;
  967.         if (idToken.startsWith("t@")) {
  968.         /* It's a thread */
  969.         setDefaultThreadGroup();
  970.         RemoteThread tlist[] = currentThreadGroup.listThreads(true);
  971.         try {
  972.             id = Integer.valueOf(idToken.substring(2)).intValue();
  973.         } catch (NumberFormatException e) {
  974.             id = 0;
  975.         }
  976.         if (id <= 0 || id > tlist.length) {
  977.             out.println("\"" + idToken +
  978.                        "\" is not a valid thread id.");
  979.             return false;
  980.         }
  981.         obj = tlist[id - 1];
  982.  
  983.         } else if (idToken.startsWith("$s")) {
  984.         int slotnum;
  985.         try {
  986.             slotnum = Integer.valueOf(idToken.substring(2)).intValue();
  987.         } catch (NumberFormatException e) {
  988.             out.println("\"" + idToken +
  989.                        "\" is not a valid slot.");
  990.             return false;
  991.         }
  992.         if (currentThread != null) {
  993.             RemoteStackVariable rsv[] = currentThread.getStackVariables();
  994.             if (rsv == null || slotnum >= rsv.length) {
  995.             out.println("\"" + idToken +
  996.                        "\" is not a valid slot.");
  997.             return false;
  998.             }
  999.             obj = rsv[slotnum].getValue();
  1000.         }
  1001.         
  1002.         } else if (idToken.startsWith("0x") ||
  1003.                Character.isDigit(idToken.charAt(0))) {
  1004.         /* It's an object id. */
  1005.         try {
  1006.             id = RemoteObject.fromHex(idToken);
  1007.         } catch (NumberFormatException e) {
  1008.             id = 0;
  1009.         }
  1010.         if (id == 0 || (obj = debugger.get(new Integer(id))) == null) {
  1011.             out.println("\"" + idToken +
  1012.                        "\" is not a valid id.");
  1013.             return false;
  1014.         }
  1015.         } else {
  1016.         /* See if it's a local stack variable */
  1017.         if (currentThread != null) {
  1018.             RemoteStackVariable rsv =
  1019.             currentThread.getStackVariable(idToken);
  1020.             if (rsv != null && !rsv.inScope()) {
  1021.                 out.println(idToken + " is not in scope.");
  1022.             return false;
  1023.             }
  1024.             obj = (rsv == null) ? null : rsv.getValue();
  1025.         }
  1026.         if (obj == null) {
  1027.             if (idToken.equals("this") == false) {
  1028.             /* See if it's an instance variable */
  1029.             String instanceStr = "this." + idToken;
  1030.             if (print(new StringTokenizer(instanceStr),
  1031.                   dumpObject, true))
  1032.                 return true;
  1033.             }
  1034.             
  1035.             /* It's a class */
  1036.             obj = debugger.findClass(idToken);
  1037.             if (obj == null) {
  1038.             if (!recursing) {
  1039.                 out.println("\"" + expr + "\" is not a " +
  1040.                            "valid id or class name.");
  1041.             }
  1042.             return false;
  1043.             }
  1044.         }
  1045.         }
  1046.  
  1047.         RemoteInt noValue = new RemoteInt(-1);
  1048.         RemoteValue rv = noValue;
  1049.         String lastField = "";
  1050.         idToken = pieces.hasMoreTokens() ? pieces.nextToken() : null;
  1051.         while (idToken != null) {
  1052.  
  1053.         if (idToken.equals(".")) {
  1054.             if (pieces.hasMoreTokens() == false) {
  1055.             out.println("\"" + expr +
  1056.                        "\" is not a valid expression.");
  1057.             return false;
  1058.             }
  1059.             idToken = pieces.nextToken();
  1060.  
  1061.             if (rv != noValue) {
  1062.             /* attempt made to get a field on a non-object */
  1063.             out.println("\"" + lastField +
  1064.                        "\" is not an object.");
  1065.             return false;
  1066.             }
  1067.             lastField = idToken;
  1068.             
  1069.             rv = ((RemoteObject)obj).getFieldValue(idToken);
  1070.             if (rv == null) {
  1071.             out.println("\"" + idToken +
  1072.                        "\" is not a valid field of " +
  1073.                        obj.description());
  1074.             return false;
  1075.             }
  1076.             if (rv.isObject()) {
  1077.             obj = rv;
  1078.             rv = noValue;
  1079.             }
  1080.             idToken =
  1081.             pieces.hasMoreTokens() ? pieces.nextToken() : null;
  1082.  
  1083.         } else if (idToken.equals("[")) {
  1084.             if (pieces.hasMoreTokens() == false) {
  1085.             out.println("\"" + expr +
  1086.                        "\" is not a valid expression.");
  1087.             return false;
  1088.             }
  1089.             idToken = pieces.nextToken("]");
  1090.             try {
  1091.             int index = Integer.valueOf(idToken).intValue();
  1092.             rv = ((RemoteArray)rv).getElement(index);
  1093.             } catch (NumberFormatException e) {
  1094.             out.println("\"" + idToken +
  1095.                        "\" is not a valid decimal number.");
  1096.             return false;
  1097.             } catch (ArrayIndexOutOfBoundsException e) {
  1098.             out.println(idToken + " is out of bounds for " +
  1099.                        obj.description());
  1100.             return false;
  1101.             }
  1102.             if (rv != null && rv.isObject()) {
  1103.             obj = rv;
  1104.             rv = noValue;
  1105.             }
  1106.             if (pieces.hasMoreTokens() == false ||
  1107.             (idToken = pieces.nextToken()).equals("]") == false) {
  1108.             out.println("\"" + expr +
  1109.                        "\" is not a valid expression.");
  1110.             return false;
  1111.             }
  1112.             idToken = pieces.hasMoreTokens() ?
  1113.             pieces.nextToken(delimiters) : null;
  1114.  
  1115.         } else if (idToken.equals("(")) {
  1116.             out.println("print <method> not supported yet.");
  1117.             return false;
  1118.         } else {
  1119.             /* Should never get here. */
  1120.             out.println("invalid expression");
  1121.             return false;
  1122.         }
  1123.         }
  1124.  
  1125.         out.print(varName + " = ");
  1126.         if (rv != noValue) {
  1127.         out.println((rv == null) ? "null" : rv.description());
  1128.         } else if (dumpObject && obj instanceof RemoteObject) {
  1129.         out.println(obj.description() + " {");
  1130.  
  1131.         if (obj instanceof RemoteClass) {
  1132.             RemoteClass cls = (RemoteClass)obj;
  1133.  
  1134.             out.print("    superclass = ");
  1135.             RemoteClass superClass = cls.getSuperclass();
  1136.             out.println((superClass == null) ?
  1137.                        "null" : superClass.description());
  1138.  
  1139.             out.print("    loader = ");
  1140.             RemoteObject loader = cls.getClassLoader();
  1141.             out.println((loader == null) ?
  1142.                        "null" : loader.description());
  1143.  
  1144.             RemoteClass interfaces[] = cls.getInterfaces();
  1145.             if (interfaces != null && interfaces.length > 0) {
  1146.             out.println("    interfaces:");
  1147.             for (int i = 0; i < interfaces.length; i++) {
  1148.                 out.println("        " + interfaces[i]);
  1149.             }
  1150.             }
  1151.         }
  1152.  
  1153.         RemoteField fields[] = ((RemoteObject)obj).getFields();
  1154.         if (obj instanceof RemoteClass && fields.length > 0) {
  1155.             out.println();
  1156.         }
  1157.         for (int i = 0; i < fields.length; i++) {
  1158.             String name = fields[i].getTypedName();
  1159.             String modifiers = fields[i].getModifiers();
  1160.             out.print("    " + modifiers + name + " = ");
  1161.             RemoteValue v = ((RemoteObject)obj).getFieldValue(i);
  1162.             out.println((v == null) ? "null" : v.description());
  1163.         }
  1164.         out.println("}");
  1165.         } else {
  1166.         out.println(obj.toString());
  1167.         }
  1168.     }
  1169.     return true;
  1170.     }
  1171.  
  1172.     void help
  1173.     () {
  1174.         out.println("** command list **");
  1175.         out.println("threads [threadgroup]     -- list threads");
  1176.         out.println("thread <thread id>        -- set default thread");
  1177.         out.println("suspend [thread id(s)]    -- suspend threads (default: all)");
  1178.         out.println("resume [thread id(s)]     -- resume threads (default: all)");
  1179.         out.println("where [thread id] | all   -- dump a thread's stack");
  1180.         out.println("threadgroups              -- list threadgroups");
  1181.         out.println("threadgroup <name>        -- set current threadgroup\n");
  1182.         out.println("print <id> [id(s)]        -- print object or field");
  1183.         out.println("dump <id> [id(s)]         -- print all object information\n");
  1184.         out.println("locals                    -- print all local variables in current stack frame\n");
  1185.         out.println("classes                   -- list currently known classes");
  1186.         out.println("methods <class id>        -- list a class's methods\n");
  1187.         out.println("stop in <class id>.<method> -- set a breakpoint in a method");
  1188.         out.println("stop at <class id>:<line> -- set a breakpoint at a line");
  1189.         out.println("up [n frames]             -- move up a thread's stack");
  1190.         out.println("down [n frames]           -- move down a thread's stack");
  1191.         out.println("clear <class id>:<line>   -- clear a breakpoint");
  1192.         out.println("step                      -- execute current line");
  1193.         out.println("cont                      -- continue execution from breakpoint\n");
  1194.         out.println("catch <class id>          -- break for the specified exception");
  1195.         out.println("ignore <class id>         -- ignore when the specified exception\n");
  1196.         out.println("list [line number|method] -- print source code");
  1197.         out.println("use [source file path]    -- display or change the source path\n");
  1198.         out.println("memory                    -- report memory usage");
  1199.         out.println("gc                        -- free unused objects\n");
  1200.         out.println("load classname            -- load Java class to be debugged");
  1201.         out.println("run <class> [args]        -- start execution of a loaded Java class");
  1202. //        out.println("kill <thread(group)>      -- kill a thread or threadgroup\n");
  1203.         out.println("!!                        -- repeat last command");
  1204.         out.println("help (or ?)               -- list commands");
  1205.         out.println("exit (or quit)            -- exit debugger");
  1206.     }
  1207.  
  1208.     void executeCommand(StringTokenizer t) {
  1209.     String cmd = t.nextToken().toLowerCase();
  1210.  
  1211.     try {
  1212.         if (cmd.equals("print")) {
  1213.         print(t, false, false);
  1214.         } else if (cmd.equals("dump")) {
  1215.         print(t, true, false);
  1216.         } else if (cmd.equals("locals")) {
  1217.         locals();
  1218.         } else if (cmd.equals("classes")) {
  1219.         classes();
  1220.         } else if (cmd.equals("methods")) {
  1221.         methods(t);
  1222.         } else if (cmd.equals("threads")) {
  1223.         threads(t);
  1224.         } else if (cmd.equals("thread")) {
  1225.         thread(t);
  1226.         } else if (cmd.equals("suspend")) {
  1227.         suspend(t);
  1228.         } else if (cmd.equals("resume")) {
  1229.         resume(t);
  1230.         } else if (cmd.equals("threadgroups")) {
  1231.         threadGroups();
  1232.         } else if (cmd.equals("threadgroup")) {
  1233.         threadGroup(t);
  1234.         } else if (cmd.equals("catch")) {
  1235.         catchException(t);
  1236.         } else if (cmd.equals("ignore")) {
  1237.         ignoreException(t);
  1238.         } else if (cmd.equals("cont")) {
  1239.         cont();
  1240.         } else if (cmd.equals("step")) {
  1241.         step();
  1242.         } else if (cmd.equals("next")) {
  1243.         next();
  1244.             } else if (cmd.equals("kill")) {
  1245.                 kill(t);
  1246.         } else if (cmd.equals("where")) {
  1247.         where(t);
  1248.         } else if (cmd.equals("up")) {
  1249.         up(t);
  1250.         } else if (cmd.equals("down")) {
  1251.         down(t);
  1252.         } else if (cmd.equals("load")) {
  1253.         load(t);
  1254.         } else if (cmd.equals("run")) {
  1255.         run(t);
  1256.         } else if (cmd.equals("memory")) {
  1257.         memory();
  1258.             } else if (cmd.equals("gc")) {
  1259.                 gc();
  1260.         } else if (cmd.equals("trace") || cmd.equals("itrace")) {
  1261.         trace(cmd, t);
  1262.         } else if (cmd.equals("stop")) {
  1263.         stop(t);
  1264.         } else if (cmd.equals("clear")) {
  1265.         clear(t);
  1266.         } else if (cmd.equals("list")) {
  1267.         list(t);
  1268.         } else if (cmd.equals("use")) {
  1269.         use(t);
  1270.         } else if (cmd.equals("help") || cmd.equals("?")) {
  1271.         help();
  1272.         } else if (cmd.equals("quit") || cmd.equals("exit")) {
  1273.         debugger.close();
  1274.         System.exit(0);
  1275.         } else {
  1276.         out.println("huh? Try help...");
  1277.         }
  1278.     } catch (Exception e) {
  1279.         out.println("Internal exception:");
  1280.         out.flush();
  1281.         e.printStackTrace();
  1282.     }
  1283.     }
  1284.  
  1285.     void readCommandFile(File f) {
  1286.     try {
  1287.         if (f.canRead()) {
  1288.         // Process initial commands.
  1289.         DataInputStream inFile = 
  1290.             new DataInputStream(new FileInputStream(f));
  1291.         String ln;
  1292.         while ((ln = inFile.readLine()) != null) {
  1293.             StringTokenizer t = new StringTokenizer(ln);
  1294.             if (t.hasMoreTokens()) {
  1295.             executeCommand(t);
  1296.             }
  1297.         }
  1298.         }
  1299.     } catch (IOException e) {}
  1300.     }
  1301.  
  1302.     public TTY(String host, String password, String javaArgs, String args, 
  1303.                PrintStream outStream, PrintStream consoleStream,
  1304.                boolean verbose) throws Exception {
  1305.         System.out.println("Initializing jdb...");
  1306.     out = outStream;
  1307.     console = consoleStream;
  1308.         if (password == null) {
  1309.             debugger = new RemoteDebugger(javaArgs, this, verbose);
  1310.         } else {
  1311.             debugger = new RemoteDebugger(host, password, this, verbose);
  1312.         }
  1313.     DataInputStream in = new DataInputStream(System.in);
  1314.     String lastLine = null;
  1315.  
  1316.     if (args != null && args.length() > 0) {
  1317.         StringTokenizer t = new StringTokenizer(args);
  1318.         load(t);
  1319.         lastArgs = args;
  1320.     }
  1321.  
  1322.     Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
  1323.  
  1324.     // Try reading user's startup file.
  1325.     File f = new File(System.getProperty("user.home") + 
  1326.         System.getProperty("file.separator") + "jdb.ini");
  1327.         if (!f.canRead()) {
  1328.             // Try opening $HOME/jdb.ini
  1329.             f = new File(System.getProperty("user.home") + 
  1330.                          System.getProperty("file.separator") + ".jdbrc");
  1331.         }
  1332.         readCommandFile(f);
  1333.  
  1334.     // Try opening local jdb.ini
  1335.     f = new File(System.getProperty("user.dir") + 
  1336.         System.getProperty("file.separator") + "startup.jdb");
  1337.         readCommandFile(f);
  1338.  
  1339.     // Process interactive commands.
  1340.     while (true) {
  1341.             printPrompt();
  1342.         String ln = in.readLine();
  1343.         if (ln == null) {
  1344.         out.println("Input stream closed.");
  1345.         return;
  1346.         }
  1347.  
  1348.         if (ln.startsWith("!!") && lastLine != null) {
  1349.         ln = lastLine + ln.substring(2);
  1350.         out.println(ln);
  1351.         }
  1352.  
  1353.         StringTokenizer t = new StringTokenizer(ln);
  1354.         if (t.hasMoreTokens()) {
  1355.         lastLine = ln;
  1356.         executeCommand(t);
  1357.         }
  1358.     }
  1359.     }
  1360.  
  1361.     public static void main(String argv[]) {
  1362.     // Get host attribute, if any.
  1363.     String localhost;
  1364.     try {
  1365.         localhost = InetAddress.getLocalHost().getHostName();
  1366.     } catch (Exception ex) {
  1367.         localhost = null;
  1368.     }    
  1369.     if (localhost == null) {
  1370.         localhost = "localhost";
  1371.     }
  1372.     String host = null;
  1373.     String password = null;
  1374.     String classArgs = "";
  1375.     String javaArgs = "";
  1376.         boolean verbose = false;
  1377.     
  1378.     for (int i = 0; i < argv.length; i++) {
  1379.         String token = argv[i];
  1380.         if (token.equals("-dbgtrace")) {
  1381.         verbose = true;
  1382.         } else if (token.equals("-cs") || token.equals("-checksource") ||
  1383.                token.equals("-noasyncgc") || token.equals("-prof") ||
  1384.                token.equals("-v") || token.equals("-verbose") ||
  1385.                token.equals("-verify") || token.equals("-noverify") ||
  1386.                token.equals("-verifyremote") ||
  1387.                token.equals("-verbosegc") ||
  1388.                token.startsWith("-ms") || token.startsWith("-mx") ||
  1389.                token.startsWith("-ss") || token.startsWith("-oss") ||
  1390.                token.startsWith("-D")) {
  1391.         javaArgs += token + " ";
  1392.         } else if (token.equals("-classpath")) {
  1393.         if (i == (argv.length - 1)) {
  1394.             System.out.println("No classpath specified.");
  1395.             System.exit(1);
  1396.         }
  1397.         javaArgs += token + " " + argv[++i] + " ";
  1398.         } else if (token.equals("-host")) {
  1399.         if (i == (argv.length - 1)) {
  1400.             System.out.println("No host specified.");
  1401.             System.exit(1);
  1402.         }
  1403.         host = argv[++i];
  1404.         } else if (token.equals("-password")) {
  1405.         if (i == (argv.length - 1)) {
  1406.             System.out.println("No password specified.");
  1407.             System.exit(1);
  1408.         }
  1409.         password = argv[++i];
  1410.         } else {
  1411.         classArgs += token + " ";
  1412.         }
  1413.     }
  1414.     if (host != null && password == null) {
  1415.         System.out.println("A debug password must be specified for " +
  1416.                    "remote debugging.");
  1417.         System.exit(1);
  1418.     }
  1419.     if (host == null) {
  1420.         host = localhost;
  1421.     }
  1422.  
  1423.     try {
  1424.         if (!host.equals(localhost) && password.length() == 0) {
  1425.         System.out.println(
  1426.             "No password supplied for accessing remote " +
  1427.             "Java interpreter.");
  1428.         System.out.println(
  1429.             "The password is reported by the remote interpreter" +
  1430.             "when it is started.");
  1431.                 System.exit(1);
  1432.             }
  1433.             new TTY(host, password, javaArgs, classArgs, 
  1434.                     System.out, System.out, verbose);
  1435.     } catch(SocketException se) {
  1436.         System.out.println("Failed accessing debugging session on " +
  1437.                    host + ": invalid password.");
  1438.     } catch(NumberFormatException ne) {
  1439.         System.out.println("Failed accessing debugging session on " +
  1440.                    host + ": invalid password.");
  1441.     } catch(Exception e) {        
  1442.         System.out.print("Internal exception:  ");
  1443.         System.out.flush();
  1444.         e.printStackTrace();
  1445.     }
  1446.     }
  1447. }
  1448.