📄 main.c
字号:
return; /* Set the instream to 0, indicating execution of a user-defined function. */ old_chain = make_cleanup (source_cleanup, instream); instream = (FILE *) 0; while (cmdlines) { execute_command (cmdlines->line, 0); cmdlines = cmdlines->next; } do_cleanups (old_chain);}/* ARGSUSED */static voidcommand_loop_marker (foo) int foo;{}/* Read commands from `instream' and execute them until end of file or error reading instream. */static voidcommand_loop (){ struct cleanup *old_chain; register int toplevel = (instream == stdin); register int interactive = (toplevel && ISATTY(stdin)); while (!feof(instream)) { register char *cmd_line; quit_flag = 0; if (interactive) reinitialize_more_filter (); old_chain = make_cleanup (command_loop_marker, 0); cmd_line = command_line_input (toplevel ? masterprompt : 0, toplevel); if (cmd_line == 0) { do_cleanups (old_chain); return; } execute_command (cmd_line, toplevel); /* Do any commands attached to breakpoint we stopped at. */ bpstat_do_actions (&stop_bpstat); do_cleanups (old_chain); }}/* Read a line from the stream "instream" without command line editing. It prints PROMPT once at the start. Action is compatible with "readline", e.g. space for the result is malloc'd and should be freed by the caller. A NULL return means end of file. */char *gdb_readline (prompt) char *prompt;{ int c; char *result; int input_index = 0; int result_size = 80; if (prompt) { /* Don't use a _filtered function here. It causes the assumed character position to be off, since the newline we read from the user is not accounted for. */ fputs (prompt, stdout); fflush (stdout); } result = (char *) xmalloc (result_size); while (1) { /* Read from stdin if we are executing a user defined command. This is the right thing for prompt_for_continue, at least. */ c = fgetc (instream ? instream : stdin); if (c == EOF) { free (result); return NULL; } if (c == '\n') break; result[input_index++] = c; while (input_index >= result_size) { result_size *= 2; result = (char *) xrealloc (result, result_size); } } result[input_index++] = '\0'; return result;}/* Variables which control command line editing and history substitution. These variables are given default values at the end of this file. */static int write_history_p;static unsigned int history_size;static char *history_filename;/* Variables which are necessary for fancy command line editing. */char *gdb_completer_word_break_characters = " \t\n!@#$%^&*()+=|~`}{[]\"';?/>.<,-";/* When completing on command names, we remove '-' from the list of word break characters, since we use it in command names. If the readline library sees one in any of the current completion strings, it thinks that the string needs to be quoted and automatically supplies a leading quote. */char *gdb_completer_command_word_break_characters = " \t\n!@#$%^&*()+=|~`}{[]\"';?/>.<,";/* Characters that can be used to quote completion strings. Note that we can't include '"' because the gdb C parser treats such quoted sequences as strings. */char *gdb_completer_quote_characters = "'";/* Functions that are used as part of the fancy command line editing. *//* This can be used for functions which don't want to complete on symbols but don't want to complete on anything else either. *//* ARGSUSED */char **noop_completer (text) char *text;{ return NULL;}/* Generate symbol names one by one for the completer. Each time we are called return another potential completion to the caller. TEXT is what we expect the symbol to start with. MATCHES is the number of matches that have currently been collected from calling this completion function. When zero, then we need to initialize, otherwise the initialization has already taken place and we can just return the next potential completion string. Returns NULL if there are no more completions, else a pointer to a string which is a possible completion. RL_LINE_BUFFER is available to be looked at; it contains the entire text of the line. RL_POINT is the offset in that line of the cursor. You should pretend that the line ends at RL_POINT. */ static char *symbol_completion_function (text, matches) char *text; int matches;{ static char **list = (char **)NULL; /* Cache of completions */ static int index; /* Next cached completion */ char *output = NULL; char *tmp_command, *p; struct cmd_list_element *c, *result_list; extern char *rl_line_buffer; extern int rl_point; if (matches == 0) { /* The caller is beginning to accumulate a new set of completions, so we need to find all of them now, and cache them for returning one at a time on future calls. */ if (list) { /* Free the storage used by LIST, but not by the strings inside. This is because rl_complete_internal () frees the strings. */ free ((PTR)list); } list = 0; index = 0; /* Choose the default set of word break characters to break completions. If we later find out that we are doing completions on command strings (as opposed to strings supplied by the individual command completer functions, which can be any string) then we will switch to the special word break set for command strings, which leaves out the '-' character used in some commands. */ rl_completer_word_break_characters = gdb_completer_word_break_characters; /* Decide whether to complete on a list of gdb commands or on symbols. */ tmp_command = (char *) alloca (rl_point + 1); p = tmp_command; strncpy (tmp_command, rl_line_buffer, rl_point); tmp_command[rl_point] = '\0'; if (rl_point == 0) { /* An empty line we want to consider ambiguous; that is, it could be any command. */ c = (struct cmd_list_element *) -1; result_list = 0; } else { c = lookup_cmd_1 (&p, cmdlist, &result_list, 1); } /* Move p up to the next interesting thing. */ while (*p == ' ' || *p == '\t') { p++; } if (!c) { /* He's typed something unrecognizable. Sigh. */ list = NULL; } else if (c == (struct cmd_list_element *) -1) { /* If we didn't recognize everything up to the thing that needs completing, and we don't know what command it is yet, we are in trouble. */ if (p + strlen(text) != tmp_command + rl_point) { /* This really should not produce an error. Better would be to pretend to hit RETURN here; this would produce a response like "Ambiguous command: foo, foobar, etc", and leave the line available for re-entry with ^P. Instead, this error blows away the user's typed input without any way to get it back. */ error (" Unrecognized command."); } /* He's typed something ambiguous. This is easier. */ if (result_list) { list = complete_on_cmdlist (*result_list->prefixlist, text); } else { list = complete_on_cmdlist (cmdlist, text); } rl_completer_word_break_characters = gdb_completer_command_word_break_characters; } else { /* If we've gotten this far, gdb has recognized a full command. There are several possibilities: 1) We need to complete on the command. 2) We need to complete on the possibilities coming after the command. 2) We need to complete the text of what comes after the command. */ if (!*p && *text) { /* Always (might be longer versions of thie command). */ list = complete_on_cmdlist (result_list, text); rl_completer_word_break_characters = gdb_completer_command_word_break_characters; } else if (!*p && !*text) { if (c->prefixlist) { list = complete_on_cmdlist (*c->prefixlist, ""); rl_completer_word_break_characters = gdb_completer_command_word_break_characters; } else { list = (*c->completer) (""); } } else { if (c->prefixlist && !c->allow_unknown) { /* Something like "info adsfkdj". But error() is not the proper response; just return no completions instead. */ list = NULL; } else { list = (*c->completer) (text); } } } } /* If we found a list of potential completions during initialization then dole them out one at a time. The vector of completions is NULL terminated, so after returning the last one, return NULL (and continue to do so) each time we are called after that, until a new list is available. */ if (list) { output = list[index]; if (output) { index++; } } return (output);}/* Skip over a possibly quoted word (as defined by the quote characters and word break characters the completer uses). Returns pointer to the location after the "word". */char *skip_quoted (str) char *str;{ char quote_char = '\0'; char *scan; for (scan = str; *scan != '\0'; scan++) { if (quote_char != '\0') { /* Ignore everything until the matching close quote char */ if (*scan == quote_char) { /* Found matching close quote. */ scan++; break; } } else if (strchr (gdb_completer_quote_characters, *scan)) { /* Found start of a quoted string. */ quote_char = *scan; } else if (strchr (gdb_completer_word_break_characters, *scan)) { break; } } return (scan);}#ifdef STOP_SIGNALstatic voidstop_sig (signo)int signo;{#if STOP_SIGNAL == SIGTSTP signal (SIGTSTP, SIG_DFL); sigsetmask (0); kill (getpid (), SIGTSTP); signal (SIGTSTP, stop_sig);#else signal (STOP_SIGNAL, stop_sig);#endif printf ("%s", masterprompt); fflush (stdout); /* Forget about any previous command -- null line now will do nothing. */ dont_repeat ();}#endif /* STOP_SIGNAL *//* Initialize signal handlers. */static voiddo_nothing (signo)int signo;{}static void suspend_sig ();static voidinit_signals (){ signal (SIGINT, request_quit); /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get passed to the inferior, which we don't want. It would be possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but on BSD4.3 systems using vfork, that will (apparently) affect the GDB process as well as the inferior (the signal handling tables being shared between the two, apparently). Since we establish a handler for SIGQUIT, when we call exec it will set the signal to SIG_DFL for us. */ signal (SIGQUIT, do_nothing); if (signal (SIGHUP, do_nothing) != SIG_IGN) signal (SIGHUP, disconnect); signal (SIGFPE, float_handler);#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) signal (SIGWINCH, SIGWINCH_HANDLER);#endif init_term(fileno(stdin)); signal(SIGTSTP, suspend_sig);}/* Execute the line P as a command. Pass FROM_TTY as second argument to the defining function. */voidexecute_command (p, from_tty) char *p; int from_tty;{ register struct cmd_list_element *c; register struct command_line *cmdlines; register enum language flang; static const struct language_defn *saved_language = 0; static int warned = 0; free_all_values (); /* This can happen when command_line_input hits end of file. */ if (p == NULL) return; while (*p == ' ' || *p == '\t') p++; if (*p) { char *arg; c = lookup_cmd(&p, cmdlist, "", 0, 1); /* Pass null arg rather than an empty one. */ arg = *p ? p : 0; if (c->function.cfunc == 0) error("That is not a command, just a help topic."); else if (c->class == (int) class_user) { extern struct cleanup *setup_user_args(); struct cleanup *old_chain = setup_user_args(p); if (c->user_commands != 0) (void)execute_command_lines(c->user_commands); do_cleanups(old_chain); } else if (c->type == set_cmd || c->type == show_cmd) do_setshow_command (arg, from_tty & caution, c); else if (c->function.cfunc == NO_FUNCTION) error ("That is not a command, just a help topic."); else (*c->function.cfunc) (arg, from_tty & caution); } /* Tell the user if the language has changed (except first time). */ if (current_language != saved_language) { if (language_mode == language_mode_auto) { if (saved_language) language_info (1); } saved_language = current_language; warned = 0; } /* Warn the user if the working language does not match the language of the current frame. Only warn the user if we are actually running the program, i.e. there is a stack. */ /* FIXME: This should be cacheing the frame and only running when the frame changes. */ if (target_has_stack) { flang = get_frame_language (); if (!warned && flang != language_unknown && flang != current_language->la_language) { printf_filtered ("%s\n", lang_frame_mismatch_warn); warned = 1; } }}/* Add an element to the list of info subcommands. */voidadd_info (name, fun, doc) char *name;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -