home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / gdbinit.C < prev    next >
C/C++ Source or Header  |  1998-11-12  |  9KB  |  369 lines

  1. // $Id: gdbinit.C,v 1.30 1998/11/12 19:41:54 zeller Exp $ -*- C++ -*-
  2. // GDB initialization
  3.  
  4. // Copyright (C) 1996 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char gdbinit_rcsid[] = 
  30.     "$Id: gdbinit.C,v 1.30 1998/11/12 19:41:54 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "gdbinit.h"
  37.  
  38. #include <X11/Intrinsic.h>
  39. #include <iostream.h>
  40. #include <fstream.h>
  41. #include <ctype.h>
  42.  
  43. #include "assert.h"
  44. #include "filetype.h"
  45. #include "shell.h"
  46. #include "string-fun.h"
  47. #include "ddd.h"
  48. #include "TimeOut.h"
  49.  
  50. static void InvokeGDBFromShellHP(Agent *source, void *client_data, 
  51.                  void *call_data);
  52.  
  53. //-----------------------------------------------------------------------------
  54. // Create new GDB interface
  55. //-----------------------------------------------------------------------------
  56.  
  57. GDBAgent *new_gdb(DebuggerType type,
  58.           const AppData& app_data,
  59.           XtAppContext app_context,
  60.           int argc, char *argv[])
  61. {
  62.     // Build call
  63.     static string gdb_call = app_data.debugger_command;
  64.  
  65.     if (app_data.play_log != 0)
  66.     {
  67.     gdb_call += string(" --PLAY ") + app_data.play_log;
  68.     }
  69.     else
  70.     {
  71.     switch(type)
  72.     {
  73.     case GDB:
  74.         // Do not issue introductiory messages; output full file names.
  75.         gdb_call += " -q -fullname";
  76.         break;
  77.  
  78.     case DBX:
  79.         // Nothing special.  (Anyway, every DBX has its own sets of
  80.         // options, so there is not much we could do here.)
  81.         break;
  82.  
  83.     case JDB:
  84.         // Nothing special.
  85.         break;
  86.  
  87.     case PERL:
  88.         // Be sure to invoke the debugger.
  89.         gdb_call += " -d";
  90.         break;
  91.  
  92.     case PYDB:
  93.         // Nothing special.
  94.         break;
  95.  
  96.     case XDB:
  97.         // Enable line mode.
  98.         gdb_call += " -L";
  99.         break;
  100.     }
  101.     }
  102.  
  103.     for (int i = 1; i < argc; i++) 
  104.     {
  105.     string arg = argv[i];
  106.     gdb_call += " " + sh_quote(arg);
  107.     }
  108.  
  109.     if (type == PERL && argc <= 1)
  110.     {
  111.     // Invoked without args.  Add a dummy `eval' arg.
  112.     gdb_call += " -e 42";
  113.     }
  114.  
  115.     GDBAgent *gdb;
  116.     if (app_data.debugger_rhost == 0 || app_data.debugger_rhost[0] == '\0')
  117.     {
  118.     // Use direct invocation
  119.     gdb_call = sh_command("exec " + gdb_call);
  120.     gdb = new GDBAgent(app_context, gdb_call, type);
  121.     }
  122.     else
  123.     {
  124.     // Use interactive rsh
  125.     gdb = new GDBAgent(app_context, sh_command(), type);
  126.     gdb_call = 
  127.         "exec " + _sh_command("exec " + gdb_call, true, true) + "\n";
  128.     gdb->addHandler(Input, InvokeGDBFromShellHP, (void *)&gdb_call);
  129.     }
  130.  
  131.     // Set up Agent resources
  132.     switch (app_data.block_tty_input)
  133.     {
  134.     case On:
  135.     gdb->block_tty_input(true);
  136.     break;
  137.  
  138.     case Off:
  139.     gdb->block_tty_input(false);
  140.     break;
  141.  
  142.     case Auto:
  143.     // Leave default setting unchanged
  144.     break;
  145.     }
  146.  
  147.     return gdb;
  148. }
  149.  
  150. // Show call in output window
  151. static void EchoTextCB(XtPointer client_data, XtIntervalId *)
  152. {
  153.     const string& gdb_call = *((string *)client_data);
  154.     _gdb_out(gdb_call);
  155. }
  156.  
  157. // Invoke GDB upon rlogin
  158. static void InvokeGDBFromShellHP(Agent *source, void *client_data, 
  159.                  void *call_data)
  160. {
  161.     DataLength *d = (DataLength *)call_data;
  162.  
  163.     bool at_shell_prompt = false;
  164.     if (d->length >= 1 && d->data[d->length - 1] == '>')
  165.     {
  166.     // We got input ending in `>' - probably a prompt.
  167.     at_shell_prompt = true;
  168.     }
  169.     else if (d->length >= 2
  170.          && d->data[d->length - 1] == ' '
  171.          && ispunct(d->data[d->length - 2]))
  172.     {
  173.     // We got input ending in a punctuation character, followed by
  174.     // a single space - probably a prompt.
  175.     at_shell_prompt = true;
  176.     }
  177.     else
  178.     {
  179.     // (Any other prompt choices out there?  -AZ)
  180.     }
  181.  
  182.     if (at_shell_prompt)
  183.     {
  184.     GDBAgent *gdb = ptr_cast(GDBAgent, source);
  185.     static bool init_sent = false;
  186.  
  187.     if (!init_sent)
  188.     {
  189.         // Send the initialization string.
  190.         if (app_data.rhost_init_commands != 0 
  191.         && app_data.rhost_init_commands[0] != '\0')
  192.         {
  193.         string init = string(app_data.rhost_init_commands) + "\n";
  194.         gdb->write(init, init.length());
  195.         }
  196.  
  197.         init_sent = true;
  198.     }
  199.     else
  200.     {
  201.         // Invoke GDB...
  202.         const string& gdb_call = *((string *)client_data);
  203.         gdb->write(gdb_call, gdb_call.length());
  204.  
  205.         // Echoing should be disabled by now.  Echo call manually...
  206.         XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 
  207.                 0, EchoTextCB, (XtPointer)client_data);
  208.  
  209.         // ... and don't get called again.
  210.         gdb->removeHandler(Input, InvokeGDBFromShellHP, client_data);
  211.     }
  212.     }
  213. }
  214.  
  215.  
  216.  
  217. //-----------------------------------------------------------------------------
  218. // Guess inferior debugger type
  219. //-----------------------------------------------------------------------------
  220.  
  221. static bool have_cmd(const string& cmd)
  222. {
  223.     return cmd_file(cmd).contains('/', 0);
  224. }
  225.  
  226. // Return an appropriate debugger type from ARGC/ARGV.
  227. // Set SURE if debugger type could be deduced from args.
  228. DebuggerType guess_debugger_type(int argc, char *argv[], bool& sure)
  229. {
  230.     DebuggerType fallback = DebuggerType(-1);
  231.     get_debugger_type(app_data.debugger, fallback);
  232.  
  233.     sure = true;
  234.  
  235.     static bool have_perl   = (fallback == PERL || have_cmd("perl"));
  236.     static bool have_python = (fallback == PYDB || have_cmd("python"));
  237.  
  238.     // Check for Perl and Python scripts
  239.     int i;
  240.     for (i = 1; i < argc; i++)
  241.     {
  242.     string arg = argv[i];
  243.  
  244.     if (arg.contains('-', 0))
  245.         continue;        // Option
  246.  
  247.     if (have_perl && is_perl_file(arg))
  248.         return PERL;
  249.  
  250.     if (have_python && is_python_file(arg))
  251.         return PYDB;
  252.     }
  253.  
  254.     // Check for executables.
  255.     static bool have_gdb = (fallback == GDB || have_cmd("gdb"));
  256.     static bool have_dbx = (fallback == DBX || have_cmd("dbx"));
  257.     static bool have_xdb = (fallback == XDB || have_cmd("xdb"));
  258.  
  259.     for (i = 1; i < argc; i++)
  260.     {
  261.     string arg = argv[i];
  262.  
  263.     if (arg.contains('-', 0))
  264.         continue;        // Option
  265.  
  266.     if (is_exec_file(arg))
  267.     {
  268.         if (fallback == GDB || fallback == DBX || fallback == XDB)
  269.         return fallback;
  270.  
  271.         if (have_gdb)
  272.         return GDB;
  273.  
  274.         if (have_dbx)
  275.         return DBX;
  276.  
  277.         if (have_xdb)
  278.         return XDB;
  279.     }
  280.     }
  281.  
  282.     // Search class path for Java classes.
  283.     static bool have_jdb = (fallback == JDB || have_cmd("jdb"));
  284.     if (have_jdb)
  285.     {
  286.     for (i = 1; i < argc; i++)
  287.     {
  288.         string arg = argv[i];
  289.  
  290.         if (arg.contains('-', 0))
  291.         continue;        // Option
  292.         if (arg.contains('/', 0))
  293.         continue;        // File
  294.  
  295.         string classpath = 
  296.         getenv("CLASSPATH") != 0 ? getenv("CLASSPATH") : ".";
  297.         while (classpath != "")
  298.         {
  299.         string dir;
  300.         if (classpath.contains(':'))
  301.             dir = classpath.before(':');
  302.         else
  303.             dir = classpath;
  304.         classpath = classpath.after(':');
  305.  
  306.         if (dir == "")
  307.             dir = ".";
  308.         if (!dir.contains('/', -1))
  309.             dir += '/';
  310.  
  311.         if (is_regular_file(dir + arg + ".java"))
  312.             return JDB;
  313.  
  314.         if (is_regular_file(dir + arg + ".class"))
  315.             return JDB;
  316.         }
  317.     }
  318.     }
  319.  
  320.     sure = false;
  321.  
  322.     // Use fallback
  323.     if (fallback != DebuggerType(-1))
  324.     return fallback;
  325.  
  326.     // All fails - use GDB
  327.     return GDB;
  328. }
  329.  
  330. static struct table {
  331.     DebuggerType type;
  332.     char *cmd;
  333. } debuggers[] =
  334. {
  335.     { GDB,  "gdb"  },
  336.     { DBX,  "dbx"  },
  337.     { XDB,  "xdb"  },
  338.     { JDB,  "jdb"  },
  339.     { PYDB, "pydb" },
  340.     { PERL, "perl" }
  341. };
  342.  
  343. // Determine debugger type from DEBUGGER_NAME
  344. bool get_debugger_type(const string& debugger_name, DebuggerType& type)
  345. {
  346.     for (int i = 0; i < int(XtNumber(debuggers)); i++)
  347.     if (debugger_name.contains(debuggers[i].cmd))
  348.     {
  349.         // Found
  350.         type = debuggers[i].type;
  351.         return true;
  352.     }
  353.         
  354.  
  355.     // Failed
  356.     return false;
  357. }
  358.  
  359. char *default_debugger(DebuggerType type)
  360. {
  361.     for (int i = 0; i < int(XtNumber(debuggers)); i++)
  362.     if (type == debuggers[i].type)
  363.         return debuggers[i].cmd;
  364.  
  365.     // This can't happen.
  366.     assert(0);
  367.     return "false";
  368. }
  369.