コード例 #1
0
/**
 * Process the commands that were created by the client
 *
 * \param tgdb
 * The TGDB context
 *
 * \return
 * -1 on error, 0 on success
 */
int Ctgdb::Process_client_commands()
{
	struct tgdb_list *client_command_list;
	tgdb_list_iterator *iterator;
	struct tgdb_command *command;

	client_command_list = tgdb_client_get_client_commands (tcc);
	iterator = tgdb_list_get_first (client_command_list);

	while (iterator)
	{
		command = (struct tgdb_command *) tgdb_list_get_item (iterator);

		if (Run_or_queue_command(command) == -1)
		{
			Logger_write_pos( __FILE__, __LINE__,
					"Run_or_queue_command failed");
			return -1;
		}

		iterator = tgdb_list_next (iterator);
	}

	/* free the list of client commands */
	tgdb_list_clear (client_command_list);

	return 0;
}
コード例 #2
0
ファイル: rline.c プロジェクト: rsenn/cgdb
int 
rline_rl_complete (struct rline *rline, struct tgdb_list *list, display_callback display_cb)
{
  int size;
  int key;
  rl_command_func_t *compare_func = NULL;

  if (!rline)
    return -1;

  /* Currently, if readline output's the tab completion to rl_outstream, it will fill
   * the pty between it and CGDB and will cause CGDB to hang. */
  if (!display_cb)
    return -1;

  size = tgdb_list_size (list);

  if (size == 0) {
    rl_completion_word_break_hook = NULL;
    rl_completion_entry_function = NULL;
  } else {
    rl_completion_word_break_hook = rline_rl_cpvfunc_t;
    rl_completion_entry_function = rline_rl_completion_entry_function;
  }

  rl_completion_display_matches_hook = display_cb;

  rline_local_iter = tgdb_list_get_first (list);

  /* This is probably a hack, however it works for now.
   *
   * Basically, rl_complete is working fine. After the call to rl_complete,
   * rl_line_buffer contains the proper data. However, the CGDB main loop
   * always call rline_rl_forced_update_display, which in the case of tab 
   * completion does this, (gdb) b ma(gdb) b main
   *
   * Normally, this works fine because the user hits '\n', which puts the prompt
   * on the next line. In this case, the user hit's \t.
   *
   * In order work around this problem, simply putting the \r should work 
   * for now.
   *
   * This obviously shouldn't be done when readline is doing 
   *    `?' means list the possible completions.
   * style completion. Because that actuall does list all of the values on
   * a different line. In this situation the \r goes after the completion
   * is done, since only the current prompt is on that line.
   */

  /* Another confusing comparison. This checks to see if the last
   * readline function and the current readline function and the 
   * tab completion callback are all the same. This ensures that this
   * is the second time the user hit \t in a row. Instead of simply
   * calling rl_complete_internal, it's better to call, rl_completion_mode
   * because this checks to see what kind of completion should be done.
   */
  if (rline->rline_rl_last_func == rline->tab_completion &&
      rline->rline_rl_last_func == rl_last_func)
    compare_func = rline->tab_completion;
  
  key = rl_completion_mode (compare_func);

  if (key == TAB)
    fprintf (rline->output, "\r");

  rl_complete_internal (key);

  if (key != TAB)
    fprintf (rline->output, "\r");

  return 0;
}
コード例 #3
0
/**
 * This function does most of the dirty work in TGDB. It is capable of 
 * processing the output of the debugger, to either satisfy a previously 
 * made request, or to simply get console output for the caller to have.
 *
 * The data returned from this function is the console output of the 
 * debugger.
 * 
 * \param tgdb
 * An instance of the tgdb library to operate on.
 *
 * \param buf
 * The output of the debugger will be returned in this buffer.
 * The buffer passed back will not exceed N in size.
 *
 * \param n
 * Tells libtgdb how large the buffer BUF is that the client passed in.
 *
 * \param is_finished
 * If this is passed in as NULL, it is not set.
 *
 * If it is non-null, it will be set to 1 if TGDB finished processing the
 * current request. Otherwise, it will be set to 0 if TGDB needs more input
 * in order to finish processing the current requested command.
 *
 * @return
 * The number of valid bytes in BUF on success, or -1 on error.
 */
size_t Ctgdb::Process(char *buf, size_t n, int *is_finished, ITarget** target)
{

	char local_buf[10 * n];
	ssize_t size;
	size_t buf_size = 0;
	int is_busy;

	/* make the queue empty */
	Delete_responses();
	*target = m_target;
	/* TODO: This is kind of a hack.
	 * Since I know that I didn't do a read yet, the next select loop will
	 * get me back here. This probably shouldn't return, however, I have to
	 * re-write a lot of this function. Also, I think this function should
	 * return a malloc'd string, not a static buffer.
	 *
	 * Currently, I see it as a bigger hack to try to just append this to the
	 * beggining of buf.
	 */
	if (last_gui_command != NULL)
	{
		int ret;

		if (IsBusy( &is_busy) == -1)
		{
			Logger_write_pos( __FILE__, __LINE__, 
					"tgdb_is_busy failed");
			return -1;
		}
		*is_finished = !is_busy;

		if (show_gui_commands)
		{
			strcpy (buf, last_gui_command);
			ret = strlen (last_gui_command);
		}
		else
		{
			strcpy (buf, "\n");
			ret = 1;
		}

		free (last_gui_command);
		last_gui_command = NULL;
		return ret;
	}

	if (has_sigchld_recv)
	{
		int tgdb_will_quit;
		/* tgdb_get_quit_command will return right away, it's asynchrounous.
		 * We call it to determine if it was GDB that died.
		 * If GDB didn't die, things will work like normal. ignore this.
		 * If GDB did die, this get's the quit command and add's it to the list. It's
		 * OK that the rest of this function get's executed, since the read will simply
		 * return EOF.
		 */
		int val = Get_quit_command(&tgdb_will_quit);
		if (val == -1)
		{
			Logger_write_pos( __FILE__, __LINE__,
					"tgdb_get_quit_command error");
			return -1;
		}
		has_sigchld_recv = 0;
		if (tgdb_will_quit)
			goto tgdb_finish;
	}

	/* set buf to null for debug reasons */
	memset (buf, '\0', n);

	/* 1. read all the data possible from gdb that is ready. */
	if ((size = io_read (debugger_stdout, local_buf, n)) < 0)
	{
		Logger_write_pos( __FILE__, __LINE__,
				"could not read from masterfd");
		buf_size = -1;
		Add_quit_command();
		goto tgdb_finish;
	}
	else if (size == 0)
	{				/* EOF */
		Add_quit_command();
		goto tgdb_finish;
	}

	local_buf[size] = '\0';

	/* 2. At this point local_buf has everything new from this read.
	 * Basically this function is responsible for seperating the annotations
	 * that gdb writes from the data. 
	 *
	 * buf and buf_size are the data to be returned from the user.
	 */
	{
		/* unused for now */
		char *infbuf = NULL;
		size_t infbuf_size;
		int result;
		result = tgdb_client_parse_io (tcc,
				local_buf, size,
				buf, &buf_size,
				infbuf, &infbuf_size, command_list);

		Process_client_commands();

		if (result == 0)
		{
			/* success, and more to parse, ss isn't done */
		}
		else if (result == 1)
		{
			/* success, and finished command */
			IS_SUBSYSTEM_READY_FOR_NEXT_COMMAND = 1;	
		}
		else if (result == -1)
		{
			Logger_write_pos( __FILE__, __LINE__,
					"tgdb_client_parse_io failed");
		}
	}

	/* 3. if ^c has been sent, clear the buffers.
	 *        If a signal has been recieved, clear the queue and return
	 */
	Handle_signals();
	
	/* 4. runs the users buffered command if any exists */
	if (Has_command_to_run ())
		Unqueue_and_deliver_command();

tgdb_finish:

	/* Set the iterator to the beggining. So when the user
	 * calls tgdb_get_command it, it will be in the right spot.
	 */
	command_list_iterator = tgdb_list_get_first(command_list);

	if (IsBusy (&is_busy) == -1)
	{
		Logger_write_pos( __FILE__, __LINE__, "tgdb_is_busy failed");
		return -1;
	}
	*is_finished = !is_busy;

	return buf_size;
}
コード例 #4
0
ファイル: cgdb.c プロジェクト: i4fumi/cgdb
static void process_commands(struct tgdb *tgdb)
{
    struct tgdb_response *item;

    while ((item = tgdb_get_response(tgdb)) != NULL) {
        switch (item->header) {
                /* This updates all the breakpoints */
            case TGDB_UPDATE_BREAKPOINTS:
            {
                struct sviewer *sview = if_get_sview();
                char *file;
                struct tgdb_list *list =
                        item->choice.update_breakpoints.breakpoint_list;
                tgdb_list_iterator *iterator;
                struct tgdb_breakpoint *tb;

                source_clear_breaks(if_get_sview());
                iterator = tgdb_list_get_first(list);

                while (iterator) {
                    /* For each breakpoint */
                    tb = (struct tgdb_breakpoint *)
                            tgdb_list_get_item(iterator);

                    file = tb->file;

                    if (tb->enabled)
                        source_enable_break(sview, file, tb->line);
                    else
                        source_disable_break(sview, file, tb->line);

                    iterator = tgdb_list_next(iterator);
                }

                if_show_file(NULL, 0);
                break;
            }

                /* This means a source file or line number changed */
            case TGDB_UPDATE_FILE_POSITION:
            {
                struct tgdb_file_position *tfp;

                tfp = item->choice.update_file_position.file_position;

                /* Update the file */
                source_reload(if_get_sview(), tfp->absolute_path, 0);

                if_show_file(tfp->absolute_path, tfp->line_number);

                source_set_relative_path(if_get_sview(),
                        tfp->absolute_path, tfp->relative_path);

                break;
            }

                /* This is a list of all the source files */
            case TGDB_UPDATE_SOURCE_FILES:
            {
                struct tgdb_list *list =
                        item->choice.update_source_files.source_files;
                tgdb_list_iterator *i = tgdb_list_get_first(list);
                char *s;

                if_clear_filedlg();

                while (i) {
                    s = tgdb_list_get_item(i);
                    if_add_filedlg_choice(s);
                    i = tgdb_list_next(i);
                }

                if_set_focus(FILE_DLG);
                kui_input_acceptable = 1;
                break;
            }

                /* The user is trying to get a list of source files that make up
                 * the debugged program but libtgdb is claiming that gdb knows
                 * none. */
            case TGDB_SOURCES_DENIED:
                if_display_message("Error:", 0,
                        " No sources available! Was the program compiled with debug?");
                kui_input_acceptable = 1;
                break;

                /* This is the absolute path to the last file the user requested */
            case TGDB_FILENAME_PAIR:
            {
                const char *apath = item->choice.filename_pair.absolute_path;
                const char *rpath = item->choice.filename_pair.relative_path;

                if_show_file((char *) apath, 1);
                source_set_relative_path(if_get_sview(), apath, rpath);
                break;
            }

                /* The source file requested does not exist */
            case TGDB_ABSOLUTE_SOURCE_DENIED:
            {
                struct tgdb_source_file *file =
                        item->choice.absolute_source_denied.source_file;
                if_show_file(NULL, 0);
                /* com can be NULL when tgdb orig requests main file */
                if (file->absolute_path != NULL)
                    if_display_message("No such file:", 0, " %s",
                            file->absolute_path);
                break;
            }
            case TGDB_INFERIOR_EXITED:
            {
                /*
                 * int *status = item->data;
                 * This could eventually go here, but for now, the update breakpoint 
                 * display function makes the status bar go back to the name of the file.
                 *
                 * if_display_message ( "Program exited with value", 0, " %d", *status );
                 */

                /* Clear the cache */
                break;
            }
            case TGDB_UPDATE_COMPLETIONS:
            {
                struct tgdb_list *list =
                        item->choice.update_completions.completion_list;
                do_tab_completion(list);
                break;
            }
            case TGDB_UPDATE_CONSOLE_PROMPT_VALUE:
            {
                const char *new_prompt =
                        item->choice.update_console_prompt_value.prompt_value;
                change_prompt(new_prompt);
                break;
            }
            case TGDB_QUIT:
                cleanup();
                exit(0);
                break;
                /* Default */
            default:
                break;
        }
    }
}