aboutsummaryrefslogtreecommitdiff
path: root/src/ex_docmd.c
diff options
context:
space:
mode:
authorEliseo Martínez <eliseomarmol@gmail.com>2014-05-12 02:25:17 +0200
committerEliseo Martínez <eliseomarmol@gmail.com>2014-05-15 20:46:01 +0200
commitda51dc9cf202772f60bd2da975dbef257bd9237c (patch)
tree5c16b93238a153f55634e9323077f30c8133970c /src/ex_docmd.c
parentffe61e5ba1721340ca51d56bae3ddaca415fb5bc (diff)
downloadrneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.gz
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.bz2
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.zip
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library.
Diffstat (limited to 'src/ex_docmd.c')
-rw-r--r--src/ex_docmd.c9109
1 files changed, 0 insertions, 9109 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
deleted file mode 100644
index 87ce252434..0000000000
--- a/src/ex_docmd.c
+++ /dev/null
@@ -1,9109 +0,0 @@
-/*
- * VIM - Vi IMproved by Bram Moolenaar
- *
- * Do ":help uganda" in Vim to read copying and usage conditions.
- * Do ":help credits" in Vim to see a list of people who contributed.
- * See README.txt for an overview of the Vim source code.
- */
-
-/*
- * ex_docmd.c: functions for executing an Ex command line.
- */
-
-#include <string.h>
-
-#include "vim.h"
-#include "ex_docmd.h"
-#include "blowfish.h"
-#include "buffer.h"
-#include "charset.h"
-#include "diff.h"
-#include "digraph.h"
-#include "edit.h"
-#include "eval.h"
-#include "ex_cmds.h"
-#include "ex_cmds2.h"
-#include "ex_eval.h"
-#include "ex_getln.h"
-#include "fileio.h"
-#include "fold.h"
-#include "getchar.h"
-#include "hardcopy.h"
-#include "if_cscope.h"
-#include "main.h"
-#include "mark.h"
-#include "mbyte.h"
-#include "memline.h"
-#include "memory.h"
-#include "menu.h"
-#include "message.h"
-#include "misc1.h"
-#include "misc2.h"
-#include "keymap.h"
-#include "crypt.h"
-#include "file_search.h"
-#include "garray.h"
-#include "move.h"
-#include "normal.h"
-#include "ops.h"
-#include "option.h"
-#include "os_unix.h"
-#include "path.h"
-#include "quickfix.h"
-#include "regexp.h"
-#include "screen.h"
-#include "search.h"
-#include "spell.h"
-#include "syntax.h"
-#include "tag.h"
-#include "term.h"
-#include "ui.h"
-#include "undo.h"
-#include "version.h"
-#include "window.h"
-#include "os/os.h"
-
-static int quitmore = 0;
-static int ex_pressedreturn = FALSE;
-
-typedef struct ucmd {
- char_u *uc_name; /* The command name */
- long_u uc_argt; /* The argument type */
- char_u *uc_rep; /* The command's replacement string */
- long uc_def; /* The default value for a range/count */
- int uc_compl; /* completion type */
- scid_T uc_scriptID; /* SID where the command was defined */
- char_u *uc_compl_arg; /* completion argument if any */
-} ucmd_T;
-
-#define UC_BUFFER 1 /* -buffer: local to current buffer */
-
-static garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL};
-
-#define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
-#define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
-
-static void do_ucmd(exarg_T *eap);
-static void ex_command(exarg_T *eap);
-static void ex_delcommand(exarg_T *eap);
-static char_u *get_user_command_name(int idx);
-
-
-static char_u *do_one_cmd(char_u **, int, struct condstack *,
- char_u *(*fgetline)(int, void *, int),
- void *cookie);
-static void append_command(char_u *cmd);
-static char_u *find_command(exarg_T *eap, int *full);
-
-static void ex_abbreviate(exarg_T *eap);
-static void ex_map(exarg_T *eap);
-static void ex_unmap(exarg_T *eap);
-static void ex_mapclear(exarg_T *eap);
-static void ex_abclear(exarg_T *eap);
-static void ex_autocmd(exarg_T *eap);
-static void ex_doautocmd(exarg_T *eap);
-static void ex_bunload(exarg_T *eap);
-static void ex_buffer(exarg_T *eap);
-static void ex_bmodified(exarg_T *eap);
-static void ex_bnext(exarg_T *eap);
-static void ex_bprevious(exarg_T *eap);
-static void ex_brewind(exarg_T *eap);
-static void ex_blast(exarg_T *eap);
-static char_u *getargcmd(char_u **);
-static char_u *skip_cmd_arg(char_u *p, int rembs);
-static int getargopt(exarg_T *eap);
-
-static int check_more(int, int);
-static linenr_T get_address(char_u **, int skip, int to_other_file);
-static void get_flags(exarg_T *eap);
-# define HAVE_EX_SCRIPT_NI
-static void ex_script_ni(exarg_T *eap);
-static char_u *invalid_range(exarg_T *eap);
-static void correct_range(exarg_T *eap);
-static char_u *replace_makeprg(exarg_T *eap, char_u *p,
- char_u **cmdlinep);
-static char_u *repl_cmdline(exarg_T *eap, char_u *src, int srclen,
- char_u *repl,
- char_u **cmdlinep);
-static void ex_highlight(exarg_T *eap);
-static void ex_colorscheme(exarg_T *eap);
-static void ex_quit(exarg_T *eap);
-static void ex_cquit(exarg_T *eap);
-static void ex_quit_all(exarg_T *eap);
-static void ex_close(exarg_T *eap);
-static void ex_win_close(int forceit, win_T *win, tabpage_T *tp);
-static void ex_only(exarg_T *eap);
-static void ex_resize(exarg_T *eap);
-static void ex_stag(exarg_T *eap);
-static void ex_tabclose(exarg_T *eap);
-static void ex_tabonly(exarg_T *eap);
-static void ex_tabnext(exarg_T *eap);
-static void ex_tabmove(exarg_T *eap);
-static void ex_tabs(exarg_T *eap);
-static void ex_pclose(exarg_T *eap);
-static void ex_ptag(exarg_T *eap);
-static void ex_pedit(exarg_T *eap);
-static void ex_hide(exarg_T *eap);
-static void ex_stop(exarg_T *eap);
-static void ex_exit(exarg_T *eap);
-static void ex_print(exarg_T *eap);
-static void ex_goto(exarg_T *eap);
-static void ex_preserve(exarg_T *eap);
-static void ex_recover(exarg_T *eap);
-static void ex_mode(exarg_T *eap);
-static void ex_wrongmodifier(exarg_T *eap);
-static void ex_find(exarg_T *eap);
-static void ex_open(exarg_T *eap);
-static void ex_edit(exarg_T *eap);
-# define ex_drop ex_ni
-# define ex_gui ex_nogui
-static void ex_nogui(exarg_T *eap);
-# define ex_tearoff ex_ni
-# define ex_popup ex_ni
-# define ex_simalt ex_ni
-# define gui_mch_find_dialog ex_ni
-# define gui_mch_replace_dialog ex_ni
-# define ex_helpfind ex_ni
-static void ex_swapname(exarg_T *eap);
-static void ex_syncbind(exarg_T *eap);
-static void ex_read(exarg_T *eap);
-static void ex_pwd(exarg_T *eap);
-static void ex_equal(exarg_T *eap);
-static void ex_sleep(exarg_T *eap);
-static void do_exmap(exarg_T *eap, int isabbrev);
-static void ex_winsize(exarg_T *eap);
-static void ex_wincmd(exarg_T *eap);
-#if defined(FEAT_GUI) || defined(UNIX) || defined(MSWIN)
-static void ex_winpos(exarg_T *eap);
-#else
-# define ex_winpos ex_ni
-#endif
-static void ex_operators(exarg_T *eap);
-static void ex_put(exarg_T *eap);
-static void ex_copymove(exarg_T *eap);
-static void ex_submagic(exarg_T *eap);
-static void ex_join(exarg_T *eap);
-static void ex_at(exarg_T *eap);
-static void ex_bang(exarg_T *eap);
-static void ex_undo(exarg_T *eap);
-static void ex_wundo(exarg_T *eap);
-static void ex_rundo(exarg_T *eap);
-static void ex_redo(exarg_T *eap);
-static void ex_later(exarg_T *eap);
-static void ex_redir(exarg_T *eap);
-static void ex_redraw(exarg_T *eap);
-static void ex_redrawstatus(exarg_T *eap);
-static void close_redir(void);
-static void ex_mkrc(exarg_T *eap);
-static void ex_mark(exarg_T *eap);
-static char_u *uc_fun_cmd(void);
-static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full,
- expand_T *xp,
- int *compl);
-static void ex_normal(exarg_T *eap);
-static void ex_startinsert(exarg_T *eap);
-static void ex_stopinsert(exarg_T *eap);
-static void ex_checkpath(exarg_T *eap);
-static void ex_findpat(exarg_T *eap);
-static void ex_psearch(exarg_T *eap);
-static void ex_tag(exarg_T *eap);
-static void ex_tag_cmd(exarg_T *eap, char_u *name);
-static char_u *arg_all(void);
-static int makeopens(FILE *fd, char_u *dirnow);
-static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp,
- int current_arg_idx);
-static void ex_loadview(exarg_T *eap);
-static char_u *get_view_file(int c);
-static int did_lcd; /* whether ":lcd" was produced for a session */
-static void ex_viminfo(exarg_T *eap);
-static void ex_behave(exarg_T *eap);
-static void ex_filetype(exarg_T *eap);
-static void ex_setfiletype(exarg_T *eap);
-static void ex_digraphs(exarg_T *eap);
-static void ex_set(exarg_T *eap);
-static void ex_nohlsearch(exarg_T *eap);
-static void ex_match(exarg_T *eap);
-static void ex_X(exarg_T *eap);
-static void ex_fold(exarg_T *eap);
-static void ex_foldopen(exarg_T *eap);
-static void ex_folddo(exarg_T *eap);
-#ifndef HAVE_WORKING_LIBINTL
-# define ex_language ex_ni
-#endif
-# define ex_wsverb ex_ni
-# define ex_nbclose ex_ni
-# define ex_nbkey ex_ni
-# define ex_nbstart ex_ni
-
-
-
-
-/*
- * Declare cmdnames[].
- */
-#define DO_DECLARE_EXCMD
-#include "ex_cmds_defs.h"
-
-/*
- * Table used to quickly search for a command, based on its first character.
- */
-static cmdidx_T cmdidxs[27] =
-{
- CMD_append,
- CMD_buffer,
- CMD_change,
- CMD_delete,
- CMD_edit,
- CMD_file,
- CMD_global,
- CMD_help,
- CMD_insert,
- CMD_join,
- CMD_k,
- CMD_list,
- CMD_move,
- CMD_next,
- CMD_open,
- CMD_print,
- CMD_quit,
- CMD_read,
- CMD_substitute,
- CMD_t,
- CMD_undo,
- CMD_vglobal,
- CMD_write,
- CMD_xit,
- CMD_yank,
- CMD_z,
- CMD_bang
-};
-
-static char_u dollar_command[2] = {'$', 0};
-
-
-/* Struct for storing a line inside a while/for loop */
-typedef struct {
- char_u *line; /* command line */
- linenr_T lnum; /* sourcing_lnum of the line */
-} wcmd_T;
-
-/*
- * Structure used to store info for line position in a while or for loop.
- * This is required, because do_one_cmd() may invoke ex_function(), which
- * reads more lines that may come from the while/for loop.
- */
-struct loop_cookie {
- garray_T *lines_gap; /* growarray with line info */
- int current_line; /* last read line from growarray */
- int repeating; /* TRUE when looping a second time */
- /* When "repeating" is FALSE use "getline" and "cookie" to get lines */
- char_u *(*getline)(int, void *, int);
- void *cookie;
-};
-
-static char_u *get_loop_line(int c, void *cookie, int indent);
-static void store_loop_line(garray_T *gap, char_u *line);
-static void free_cmdlines(garray_T *gap);
-
-/* Struct to save a few things while debugging. Used in do_cmdline() only. */
-struct dbg_stuff {
- int trylevel;
- int force_abort;
- except_T *caught_stack;
- char_u *vv_exception;
- char_u *vv_throwpoint;
- int did_emsg;
- int got_int;
- int did_throw;
- int need_rethrow;
- int check_cstack;
- except_T *current_exception;
-};
-
-static void save_dbg_stuff(struct dbg_stuff *dsp);
-static void restore_dbg_stuff(struct dbg_stuff *dsp);
-
-static void save_dbg_stuff(struct dbg_stuff *dsp)
-{
- dsp->trylevel = trylevel; trylevel = 0;
- dsp->force_abort = force_abort; force_abort = FALSE;
- dsp->caught_stack = caught_stack; caught_stack = NULL;
- dsp->vv_exception = v_exception(NULL);
- dsp->vv_throwpoint = v_throwpoint(NULL);
-
- /* Necessary for debugging an inactive ":catch", ":finally", ":endtry" */
- dsp->did_emsg = did_emsg; did_emsg = FALSE;
- dsp->got_int = got_int; got_int = FALSE;
- dsp->did_throw = did_throw; did_throw = FALSE;
- dsp->need_rethrow = need_rethrow; need_rethrow = FALSE;
- dsp->check_cstack = check_cstack; check_cstack = FALSE;
- dsp->current_exception = current_exception; current_exception = NULL;
-}
-
-static void restore_dbg_stuff(struct dbg_stuff *dsp)
-{
- suppress_errthrow = FALSE;
- trylevel = dsp->trylevel;
- force_abort = dsp->force_abort;
- caught_stack = dsp->caught_stack;
- (void)v_exception(dsp->vv_exception);
- (void)v_throwpoint(dsp->vv_throwpoint);
- did_emsg = dsp->did_emsg;
- got_int = dsp->got_int;
- did_throw = dsp->did_throw;
- need_rethrow = dsp->need_rethrow;
- check_cstack = dsp->check_cstack;
- current_exception = dsp->current_exception;
-}
-
-
-/*
- * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi"
- * command is given.
- */
-void
-do_exmode (
- int improved /* TRUE for "improved Ex" mode */
-)
-{
- int save_msg_scroll;
- int prev_msg_row;
- linenr_T prev_line;
- int changedtick;
-
- if (improved)
- exmode_active = EXMODE_VIM;
- else
- exmode_active = EXMODE_NORMAL;
- State = NORMAL;
-
- /* When using ":global /pat/ visual" and then "Q" we return to continue
- * the :global command. */
- if (global_busy)
- return;
-
- save_msg_scroll = msg_scroll;
- ++RedrawingDisabled; /* don't redisplay the window */
- ++no_wait_return; /* don't wait for return */
-
- MSG(_("Entering Ex mode. Type \"visual\" to go to Normal mode."));
- while (exmode_active) {
- /* Check for a ":normal" command and no more characters left. */
- if (ex_normal_busy > 0 && typebuf.tb_len == 0) {
- exmode_active = FALSE;
- break;
- }
- msg_scroll = TRUE;
- need_wait_return = FALSE;
- ex_pressedreturn = FALSE;
- ex_no_reprint = FALSE;
- changedtick = curbuf->b_changedtick;
- prev_msg_row = msg_row;
- prev_line = curwin->w_cursor.lnum;
- if (improved) {
- cmdline_row = msg_row;
- do_cmdline(NULL, getexline, NULL, 0);
- } else
- do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT);
- lines_left = Rows - 1;
-
- if ((prev_line != curwin->w_cursor.lnum
- || changedtick != curbuf->b_changedtick) && !ex_no_reprint) {
- if (curbuf->b_ml.ml_flags & ML_EMPTY)
- EMSG(_(e_emptybuf));
- else {
- if (ex_pressedreturn) {
- /* go up one line, to overwrite the ":<CR>" line, so the
- * output doesn't contain empty lines. */
- msg_row = prev_msg_row;
- if (prev_msg_row == Rows - 1)
- msg_row--;
- }
- msg_col = 0;
- print_line_no_prefix(curwin->w_cursor.lnum, FALSE, FALSE);
- msg_clr_eos();
- }
- } else if (ex_pressedreturn && !ex_no_reprint) { /* must be at EOF */
- if (curbuf->b_ml.ml_flags & ML_EMPTY)
- EMSG(_(e_emptybuf));
- else
- EMSG(_("E501: At end-of-file"));
- }
- }
-
- --RedrawingDisabled;
- --no_wait_return;
- update_screen(CLEAR);
- need_wait_return = FALSE;
- msg_scroll = save_msg_scroll;
-}
-
-/*
- * Execute a simple command line. Used for translated commands like "*".
- */
-int do_cmdline_cmd(char_u *cmd)
-{
- return do_cmdline(cmd, NULL, NULL,
- DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
-}
-
-/*
- * do_cmdline(): execute one Ex command line
- *
- * 1. Execute "cmdline" when it is not NULL.
- * If "cmdline" is NULL, or more lines are needed, fgetline() is used.
- * 2. Split up in parts separated with '|'.
- *
- * This function can be called recursively!
- *
- * flags:
- * DOCMD_VERBOSE - The command will be included in the error message.
- * DOCMD_NOWAIT - Don't call wait_return() and friends.
- * DOCMD_REPEAT - Repeat execution until fgetline() returns NULL.
- * DOCMD_KEYTYPED - Don't reset KeyTyped.
- * DOCMD_EXCRESET - Reset the exception environment (used for debugging).
- * DOCMD_KEEPLINE - Store first typed line (for repeating with ".").
- *
- * return FAIL if cmdline could not be executed, OK otherwise
- */
-int do_cmdline(cmdline, fgetline, cookie, flags)
-char_u *cmdline;
-char_u *(*fgetline)(int, void *, int);
-void *cookie; /* argument for fgetline() */
-int flags;
-{
- char_u *next_cmdline; /* next cmd to execute */
- char_u *cmdline_copy = NULL; /* copy of cmd line */
- int used_getline = FALSE; /* used "fgetline" to obtain command */
- static int recursive = 0; /* recursive depth */
- int msg_didout_before_start = 0;
- int count = 0; /* line number count */
- int did_inc = FALSE; /* incremented RedrawingDisabled */
- int retval = OK;
- struct condstack cstack; /* conditional stack */
- garray_T lines_ga; /* keep lines for ":while"/":for" */
- int current_line = 0; /* active line in lines_ga */
- char_u *fname = NULL; /* function or script name */
- linenr_T *breakpoint = NULL; /* ptr to breakpoint field in cookie */
- int *dbg_tick = NULL; /* ptr to dbg_tick field in cookie */
- struct dbg_stuff debug_saved; /* saved things for debug mode */
- int initial_trylevel;
- struct msglist **saved_msg_list = NULL;
- struct msglist *private_msg_list;
-
- /* "fgetline" and "cookie" passed to do_one_cmd() */
- char_u *(*cmd_getline)(int, void *, int);
- void *cmd_cookie;
- struct loop_cookie cmd_loop_cookie;
- void *real_cookie;
- int getline_is_func;
- static int call_depth = 0; /* recursiveness */
-
- /* For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
- * location for storing error messages to be converted to an exception.
- * This ensures that the do_errthrow() call in do_one_cmd() does not
- * combine the messages stored by an earlier invocation of do_one_cmd()
- * with the command name of the later one. This would happen when
- * BufWritePost autocommands are executed after a write error. */
- saved_msg_list = msg_list;
- msg_list = &private_msg_list;
- private_msg_list = NULL;
-
- /* It's possible to create an endless loop with ":execute", catch that
- * here. The value of 200 allows nested function calls, ":source", etc. */
- if (call_depth == 200) {
- EMSG(_("E169: Command too recursive"));
- /* When converting to an exception, we do not include the command name
- * since this is not an error of the specific command. */
- do_errthrow((struct condstack *)NULL, (char_u *)NULL);
- msg_list = saved_msg_list;
- return FAIL;
- }
- ++call_depth;
-
- cstack.cs_idx = -1;
- cstack.cs_looplevel = 0;
- cstack.cs_trylevel = 0;
- cstack.cs_emsg_silent_list = NULL;
- cstack.cs_lflags = 0;
- ga_init(&lines_ga, (int)sizeof(wcmd_T), 10);
-
- real_cookie = getline_cookie(fgetline, cookie);
-
- /* Inside a function use a higher nesting level. */
- getline_is_func = getline_equal(fgetline, cookie, get_func_line);
- if (getline_is_func && ex_nesting_level == func_level(real_cookie))
- ++ex_nesting_level;
-
- /* Get the function or script name and the address where the next breakpoint
- * line and the debug tick for a function or script are stored. */
- if (getline_is_func) {
- fname = func_name(real_cookie);
- breakpoint = func_breakpoint(real_cookie);
- dbg_tick = func_dbg_tick(real_cookie);
- } else if (getline_equal(fgetline, cookie, getsourceline)) {
- fname = sourcing_name;
- breakpoint = source_breakpoint(real_cookie);
- dbg_tick = source_dbg_tick(real_cookie);
- }
-
- /*
- * Initialize "force_abort" and "suppress_errthrow" at the top level.
- */
- if (!recursive) {
- force_abort = FALSE;
- suppress_errthrow = FALSE;
- }
-
- /*
- * If requested, store and reset the global values controlling the
- * exception handling (used when debugging). Otherwise clear it to avoid
- * a bogus compiler warning when the optimizer uses inline functions...
- */
- if (flags & DOCMD_EXCRESET)
- save_dbg_stuff(&debug_saved);
- else
- memset(&debug_saved, 0, 1);
-
- initial_trylevel = trylevel;
-
- /*
- * "did_throw" will be set to TRUE when an exception is being thrown.
- */
- did_throw = FALSE;
- /*
- * "did_emsg" will be set to TRUE when emsg() is used, in which case we
- * cancel the whole command line, and any if/endif or loop.
- * If force_abort is set, we cancel everything.
- */
- did_emsg = FALSE;
-
- /*
- * KeyTyped is only set when calling vgetc(). Reset it here when not
- * calling vgetc() (sourced command lines).
- */
- if (!(flags & DOCMD_KEYTYPED)
- && !getline_equal(fgetline, cookie, getexline))
- KeyTyped = FALSE;
-
- /*
- * Continue executing command lines:
- * - when inside an ":if", ":while" or ":for"
- * - for multiple commands on one line, separated with '|'
- * - when repeating until there are no more lines (for ":source")
- */
- next_cmdline = cmdline;
- do {
- getline_is_func = getline_equal(fgetline, cookie, get_func_line);
-
- /* stop skipping cmds for an error msg after all endif/while/for */
- if (next_cmdline == NULL
- && !force_abort
- && cstack.cs_idx < 0
- && !(getline_is_func && func_has_abort(real_cookie))
- )
- did_emsg = FALSE;
-
- /*
- * 1. If repeating a line in a loop, get a line from lines_ga.
- * 2. If no line given: Get an allocated line with fgetline().
- * 3. If a line is given: Make a copy, so we can mess with it.
- */
-
- /* 1. If repeating, get a previous line from lines_ga. */
- if (cstack.cs_looplevel > 0 && current_line < lines_ga.ga_len) {
- /* Each '|' separated command is stored separately in lines_ga, to
- * be able to jump to it. Don't use next_cmdline now. */
- free(cmdline_copy);
- cmdline_copy = NULL;
-
- /* Check if a function has returned or, unless it has an unclosed
- * try conditional, aborted. */
- if (getline_is_func) {
- if (do_profiling == PROF_YES)
- func_line_end(real_cookie);
- if (func_has_ended(real_cookie)) {
- retval = FAIL;
- break;
- }
- } else if (do_profiling == PROF_YES
- && getline_equal(fgetline, cookie, getsourceline))
- script_line_end();
-
- /* Check if a sourced file hit a ":finish" command. */
- if (source_finished(fgetline, cookie)) {
- retval = FAIL;
- break;
- }
-
- /* If breakpoints have been added/deleted need to check for it. */
- if (breakpoint != NULL && dbg_tick != NULL
- && *dbg_tick != debug_tick) {
- *breakpoint = dbg_find_breakpoint(
- getline_equal(fgetline, cookie, getsourceline),
- fname, sourcing_lnum);
- *dbg_tick = debug_tick;
- }
-
- next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line;
- sourcing_lnum = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum;
-
- /* Did we encounter a breakpoint? */
- if (breakpoint != NULL && *breakpoint != 0
- && *breakpoint <= sourcing_lnum) {
- dbg_breakpoint(fname, sourcing_lnum);
- /* Find next breakpoint. */
- *breakpoint = dbg_find_breakpoint(
- getline_equal(fgetline, cookie, getsourceline),
- fname, sourcing_lnum);
- *dbg_tick = debug_tick;
- }
- if (do_profiling == PROF_YES) {
- if (getline_is_func)
- func_line_start(real_cookie);
- else if (getline_equal(fgetline, cookie, getsourceline))
- script_line_start();
- }
- }
-
- if (cstack.cs_looplevel > 0) {
- /* Inside a while/for loop we need to store the lines and use them
- * again. Pass a different "fgetline" function to do_one_cmd()
- * below, so that it stores lines in or reads them from
- * "lines_ga". Makes it possible to define a function inside a
- * while/for loop. */
- cmd_getline = get_loop_line;
- cmd_cookie = (void *)&cmd_loop_cookie;
- cmd_loop_cookie.lines_gap = &lines_ga;
- cmd_loop_cookie.current_line = current_line;
- cmd_loop_cookie.getline = fgetline;
- cmd_loop_cookie.cookie = cookie;
- cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len);
- } else {
- cmd_getline = fgetline;
- cmd_cookie = cookie;
- }
-
- /* 2. If no line given, get an allocated line with fgetline(). */
- if (next_cmdline == NULL) {
- /*
- * Need to set msg_didout for the first line after an ":if",
- * otherwise the ":if" will be overwritten.
- */
- if (count == 1 && getline_equal(fgetline, cookie, getexline))
- msg_didout = TRUE;
- if (fgetline == NULL || (next_cmdline = fgetline(':', cookie,
- cstack.cs_idx <
- 0 ? 0 : (cstack.cs_idx + 1) * 2
- )) == NULL) {
- /* Don't call wait_return for aborted command line. The NULL
- * returned for the end of a sourced file or executed function
- * doesn't do this. */
- if (KeyTyped && !(flags & DOCMD_REPEAT))
- need_wait_return = FALSE;
- retval = FAIL;
- break;
- }
- used_getline = TRUE;
-
- /*
- * Keep the first typed line. Clear it when more lines are typed.
- */
- if (flags & DOCMD_KEEPLINE) {
- free(repeat_cmdline);
- if (count == 0)
- repeat_cmdline = vim_strsave(next_cmdline);
- else
- repeat_cmdline = NULL;
- }
- }
- /* 3. Make a copy of the command so we can mess with it. */
- else if (cmdline_copy == NULL) {
- next_cmdline = vim_strsave(next_cmdline);
- if (next_cmdline == NULL) {
- EMSG(_(e_outofmem));
- retval = FAIL;
- break;
- }
- }
- cmdline_copy = next_cmdline;
-
- /*
- * Save the current line when inside a ":while" or ":for", and when
- * the command looks like a ":while" or ":for", because we may need it
- * later. When there is a '|' and another command, it is stored
- * separately, because we need to be able to jump back to it from an
- * :endwhile/:endfor.
- */
- if (current_line == lines_ga.ga_len
- && (cstack.cs_looplevel || has_loop_cmd(next_cmdline))) {
- store_loop_line(&lines_ga, next_cmdline);
- }
- did_endif = FALSE;
-
- if (count++ == 0) {
- /*
- * All output from the commands is put below each other, without
- * waiting for a return. Don't do this when executing commands
- * from a script or when being called recursive (e.g. for ":e
- * +command file").
- */
- if (!(flags & DOCMD_NOWAIT) && !recursive) {
- msg_didout_before_start = msg_didout;
- msg_didany = FALSE; /* no output yet */
- msg_start();
- msg_scroll = TRUE; /* put messages below each other */
- ++no_wait_return; /* don't wait for return until finished */
- ++RedrawingDisabled;
- did_inc = TRUE;
- }
- }
-
- if (p_verbose >= 15 && sourcing_name != NULL) {
- ++no_wait_return;
- verbose_enter_scroll();
-
- smsg((char_u *)_("line %" PRId64 ": %s"),
- (int64_t)sourcing_lnum, cmdline_copy);
- if (msg_silent == 0)
- msg_puts((char_u *)"\n"); /* don't overwrite this */
-
- verbose_leave_scroll();
- --no_wait_return;
- }
-
- /*
- * 2. Execute one '|' separated command.
- * do_one_cmd() will return NULL if there is no trailing '|'.
- * "cmdline_copy" can change, e.g. for '%' and '#' expansion.
- */
- ++recursive;
- next_cmdline = do_one_cmd(&cmdline_copy, flags & DOCMD_VERBOSE,
- &cstack,
- cmd_getline, cmd_cookie);
- --recursive;
-
- if (cmd_cookie == (void *)&cmd_loop_cookie)
- /* Use "current_line" from "cmd_loop_cookie", it may have been
- * incremented when defining a function. */
- current_line = cmd_loop_cookie.current_line;
-
- if (next_cmdline == NULL) {
- free(cmdline_copy);
- cmdline_copy = NULL;
- /*
- * If the command was typed, remember it for the ':' register.
- * Do this AFTER executing the command to make :@: work.
- */
- if (getline_equal(fgetline, cookie, getexline)
- && new_last_cmdline != NULL) {
- free(last_cmdline);
- last_cmdline = new_last_cmdline;
- new_last_cmdline = NULL;
- }
- } else {
- /* need to copy the command after the '|' to cmdline_copy, for the
- * next do_one_cmd() */
- STRMOVE(cmdline_copy, next_cmdline);
- next_cmdline = cmdline_copy;
- }
-
-
- /* reset did_emsg for a function that is not aborted by an error */
- if (did_emsg && !force_abort
- && getline_equal(fgetline, cookie, get_func_line)
- && !func_has_abort(real_cookie))
- did_emsg = FALSE;
-
- if (cstack.cs_looplevel > 0) {
- ++current_line;
-
- /*
- * An ":endwhile", ":endfor" and ":continue" is handled here.
- * If we were executing commands, jump back to the ":while" or
- * ":for".
- * If we were not executing commands, decrement cs_looplevel.
- */
- if (cstack.cs_lflags & (CSL_HAD_CONT | CSL_HAD_ENDLOOP)) {
- cstack.cs_lflags &= ~(CSL_HAD_CONT | CSL_HAD_ENDLOOP);
-
- /* Jump back to the matching ":while" or ":for". Be careful
- * not to use a cs_line[] from an entry that isn't a ":while"
- * or ":for": It would make "current_line" invalid and can
- * cause a crash. */
- if (!did_emsg && !got_int && !did_throw
- && cstack.cs_idx >= 0
- && (cstack.cs_flags[cstack.cs_idx]
- & (CSF_WHILE | CSF_FOR))
- && cstack.cs_line[cstack.cs_idx] >= 0
- && (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE)) {
- current_line = cstack.cs_line[cstack.cs_idx];
- /* remember we jumped there */
- cstack.cs_lflags |= CSL_HAD_LOOP;
- line_breakcheck(); /* check if CTRL-C typed */
-
- /* Check for the next breakpoint at or after the ":while"
- * or ":for". */
- if (breakpoint != NULL) {
- *breakpoint = dbg_find_breakpoint(
- getline_equal(fgetline, cookie, getsourceline),
- fname,
- ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1);
- *dbg_tick = debug_tick;
- }
- } else {
- /* can only get here with ":endwhile" or ":endfor" */
- if (cstack.cs_idx >= 0)
- rewind_conditionals(&cstack, cstack.cs_idx - 1,
- CSF_WHILE | CSF_FOR, &cstack.cs_looplevel);
- }
- }
- /*
- * For a ":while" or ":for" we need to remember the line number.
- */
- else if (cstack.cs_lflags & CSL_HAD_LOOP) {
- cstack.cs_lflags &= ~CSL_HAD_LOOP;
- cstack.cs_line[cstack.cs_idx] = current_line - 1;
- }
- }
-
- /*
- * When not inside any ":while" loop, clear remembered lines.
- */
- if (cstack.cs_looplevel == 0) {
- if (lines_ga.ga_len > 0) {
- sourcing_lnum =
- ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
- free_cmdlines(&lines_ga);
- }
- current_line = 0;
- }
-
- /*
- * A ":finally" makes did_emsg, got_int, and did_throw pending for
- * being restored at the ":endtry". Reset them here and set the
- * ACTIVE and FINALLY flags, so that the finally clause gets executed.
- * This includes the case where a missing ":endif", ":endwhile" or
- * ":endfor" was detected by the ":finally" itself.
- */
- if (cstack.cs_lflags & CSL_HAD_FINA) {
- cstack.cs_lflags &= ~CSL_HAD_FINA;
- report_make_pending(cstack.cs_pending[cstack.cs_idx]
- & (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW),
- did_throw ? (void *)current_exception : NULL);
- did_emsg = got_int = did_throw = FALSE;
- cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
- }
-
- /* Update global "trylevel" for recursive calls to do_cmdline() from
- * within this loop. */
- trylevel = initial_trylevel + cstack.cs_trylevel;
-
- /*
- * If the outermost try conditional (across function calls and sourced
- * files) is aborted because of an error, an interrupt, or an uncaught
- * exception, cancel everything. If it is left normally, reset
- * force_abort to get the non-EH compatible abortion behavior for
- * the rest of the script.
- */
- if (trylevel == 0 && !did_emsg && !got_int && !did_throw)
- force_abort = FALSE;
-
- /* Convert an interrupt to an exception if appropriate. */
- (void)do_intthrow(&cstack);
-
- }
- /*
- * Continue executing command lines when:
- * - no CTRL-C typed, no aborting error, no exception thrown or try
- * conditionals need to be checked for executing finally clauses or
- * catching an interrupt exception
- * - didn't get an error message or lines are not typed
- * - there is a command after '|', inside a :if, :while, :for or :try, or
- * looping for ":source" command or function call.
- */
- while (!((got_int
- || (did_emsg && force_abort) || did_throw
- )
- && cstack.cs_trylevel == 0
- )
- && !(did_emsg
- /* Keep going when inside try/catch, so that the error can be
- * deal with, except when it is a syntax error, it may cause
- * the :endtry to be missed. */
- && (cstack.cs_trylevel == 0 || did_emsg_syntax)
- && used_getline
- && (getline_equal(fgetline, cookie, getexmodeline)
- || getline_equal(fgetline, cookie, getexline)))
- && (next_cmdline != NULL
- || cstack.cs_idx >= 0
- || (flags & DOCMD_REPEAT)));
-
- free(cmdline_copy);
- did_emsg_syntax = FALSE;
- free_cmdlines(&lines_ga);
- ga_clear(&lines_ga);
-
- if (cstack.cs_idx >= 0) {
- /*
- * If a sourced file or executed function ran to its end, report the
- * unclosed conditional.
- */
- if (!got_int && !did_throw
- && ((getline_equal(fgetline, cookie, getsourceline)
- && !source_finished(fgetline, cookie))
- || (getline_equal(fgetline, cookie, get_func_line)
- && !func_has_ended(real_cookie)))) {
- if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY)
- EMSG(_(e_endtry));
- else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE)
- EMSG(_(e_endwhile));
- else if (cstack.cs_flags[cstack.cs_idx] & CSF_FOR)
- EMSG(_(e_endfor));
- else
- EMSG(_(e_endif));
- }
-
- /*
- * Reset "trylevel" in case of a ":finish" or ":return" or a missing
- * ":endtry" in a sourced file or executed function. If the try
- * conditional is in its finally clause, ignore anything pending.
- * If it is in a catch clause, finish the caught exception.
- * Also cleanup any "cs_forinfo" structures.
- */
- do {
- int idx = cleanup_conditionals(&cstack, 0, TRUE);
-
- if (idx >= 0)
- --idx; /* remove try block not in its finally clause */
- rewind_conditionals(&cstack, idx, CSF_WHILE | CSF_FOR,
- &cstack.cs_looplevel);
- } while (cstack.cs_idx >= 0);
- trylevel = initial_trylevel;
- }
-
- /* If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory
- * lack was reported above and the error message is to be converted to an
- * exception, do this now after rewinding the cstack. */
- do_errthrow(&cstack, getline_equal(fgetline, cookie, get_func_line)
- ? (char_u *)"endfunction" : (char_u *)NULL);
-
- if (trylevel == 0) {
- /*
-