1 | // This is an open source non-commercial project. Dear PVS-Studio, please check |
2 | // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com |
3 | |
4 | // TODO(ZyX-I): move to eval/executor |
5 | |
6 | /// @file ex_eval.c |
7 | /// |
8 | /// Functions for Ex command line for the +eval feature. |
9 | #include <assert.h> |
10 | #include <stdbool.h> |
11 | #include <inttypes.h> |
12 | #include <limits.h> |
13 | |
14 | #include "nvim/vim.h" |
15 | #include "nvim/ascii.h" |
16 | #include "nvim/ex_eval.h" |
17 | #include "nvim/charset.h" |
18 | #include "nvim/eval.h" |
19 | #include "nvim/eval/typval.h" |
20 | #include "nvim/ex_cmds2.h" |
21 | #include "nvim/ex_docmd.h" |
22 | #include "nvim/message.h" |
23 | #include "nvim/memory.h" |
24 | #include "nvim/regexp.h" |
25 | #include "nvim/strings.h" |
26 | |
27 | #ifdef INCLUDE_GENERATED_DECLARATIONS |
28 | # include "ex_eval.c.generated.h" |
29 | #endif |
30 | |
31 | // Exception handling terms: |
32 | // |
33 | // :try ":try" command ─┐ |
34 | // ... try block │ |
35 | // :catch RE ":catch" command │ |
36 | // ... catch clause ├─ try conditional |
37 | // :finally ":finally" command │ |
38 | // ... finally clause │ |
39 | // :endtry ":endtry" command ─┘ |
40 | // |
41 | // The try conditional may have any number of catch clauses and at most one |
42 | // finally clause. A ":throw" command can be inside the try block, a catch |
43 | // clause, the finally clause, or in a function called or script sourced from |
44 | // there or even outside the try conditional. Try conditionals may be nested. |
45 | |
46 | // Configuration whether an exception is thrown on error or interrupt. When |
47 | // the preprocessor macros below evaluate to FALSE, an error (did_emsg) or |
48 | // interrupt (got_int) under an active try conditional terminates the script |
49 | // after the non-active finally clauses of all active try conditionals have been |
50 | // executed. Otherwise, errors and/or interrupts are converted into catchable |
51 | // exceptions, which terminate the script only if not caught. For user |
52 | // exceptions, only current_exception is set. (Note: got_int can be set |
53 | // asynchronously afterwards by a SIGINT, so current_exception && got_int is not |
54 | // a reliant test that the exception currently being thrown is an interrupt |
55 | // exception. Similarly, did_emsg can be set afterwards on an error in an |
56 | // (unskipped) conditional command inside an inactive conditional, so |
57 | // current_exception && did_emsg is not a reliant test that the exception |
58 | // currently being thrown is an error exception.) - The macros can be defined |
59 | // as expressions checking for a variable that is allowed to be changed during |
60 | // execution of a script. |
61 | |
62 | // Values used for the Vim release. |
63 | #define THROW_ON_ERROR true |
64 | #define THROW_ON_ERROR_TRUE |
65 | #define THROW_ON_INTERRUPT true |
66 | #define THROW_ON_INTERRUPT_TRUE |
67 | |
68 | // Don't do something after an error, interrupt, or throw, or when |
69 | // there is a surrounding conditional and it was not active. |
70 | #define CHECK_SKIP \ |
71 | (did_emsg \ |
72 | || got_int \ |
73 | || current_exception \ |
74 | || (cstack->cs_idx > 0 \ |
75 | && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE))) |
76 | |
77 | #define discard_pending_return(p) tv_free((typval_T *)(p)) |
78 | |
79 | /* |
80 | * When several errors appear in a row, setting "force_abort" is delayed until |
81 | * the failing command returned. "cause_abort" is set to TRUE meanwhile, in |
82 | * order to indicate that situation. This is useful when "force_abort" was set |
83 | * during execution of a function call from an expression: the aborting of the |
84 | * expression evaluation is done without producing any error messages, but all |
85 | * error messages on parsing errors during the expression evaluation are given |
86 | * (even if a try conditional is active). |
87 | */ |
88 | static int cause_abort = FALSE; |
89 | |
90 | /* |
91 | * Return TRUE when immediately aborting on error, or when an interrupt |
92 | * occurred or an exception was thrown but not caught. Use for ":{range}call" |
93 | * to check whether an aborted function that does not handle a range itself |
94 | * should be called again for the next line in the range. Also used for |
95 | * cancelling expression evaluation after a function call caused an immediate |
96 | * abort. Note that the first emsg() call temporarily resets "force_abort" |
97 | * until the throw point for error messages has been reached. That is, during |
98 | * cancellation of an expression evaluation after an aborting function call or |
99 | * due to a parsing error, aborting() always returns the same value. |
100 | */ |
101 | int aborting(void) |
102 | { |
103 | return (did_emsg && force_abort) || got_int || current_exception; |
104 | } |
105 | |
106 | /* |
107 | * The value of "force_abort" is temporarily reset by the first emsg() call |
108 | * during an expression evaluation, and "cause_abort" is used instead. It might |
109 | * be necessary to restore "force_abort" even before the throw point for the |
110 | * error message has been reached. update_force_abort() should be called then. |
111 | */ |
112 | void update_force_abort(void) |
113 | { |
114 | if (cause_abort) |
115 | force_abort = TRUE; |
116 | } |
117 | |
118 | /* |
119 | * Return TRUE if a command with a subcommand resulting in "retcode" should |
120 | * abort the script processing. Can be used to suppress an autocommand after |
121 | * execution of a failing subcommand as long as the error message has not been |
122 | * displayed and actually caused the abortion. |
123 | */ |
124 | int should_abort(int retcode) |
125 | { |
126 | return (retcode == FAIL && trylevel != 0 && !emsg_silent) || aborting(); |
127 | } |
128 | |
129 | /* |
130 | * Return TRUE if a function with the "abort" flag should not be considered |
131 | * ended on an error. This means that parsing commands is continued in order |
132 | * to find finally clauses to be executed, and that some errors in skipped |
133 | * commands are still reported. |
134 | */ |
135 | int aborted_in_try(void) |
136 | { |
137 | /* This function is only called after an error. In this case, "force_abort" |
138 | * determines whether searching for finally clauses is necessary. */ |
139 | return force_abort; |
140 | } |
141 | |
142 | /* |
143 | * cause_errthrow(): Cause a throw of an error exception if appropriate. |
144 | * Return TRUE if the error message should not be displayed by emsg(). |
145 | * Sets "ignore", if the emsg() call should be ignored completely. |
146 | * |
147 | * When several messages appear in the same command, the first is usually the |
148 | * most specific one and used as the exception value. The "severe" flag can be |
149 | * set to TRUE, if a later but severer message should be used instead. |
150 | */ |
151 | int cause_errthrow(char_u *mesg, int severe, int *ignore) |
152 | { |
153 | struct msglist *elem; |
154 | struct msglist **plist; |
155 | |
156 | /* |
157 | * Do nothing when displaying the interrupt message or reporting an |
158 | * uncaught exception (which has already been discarded then) at the top |
159 | * level. Also when no exception can be thrown. The message will be |
160 | * displayed by emsg(). |
161 | */ |
162 | if (suppress_errthrow) |
163 | return FALSE; |
164 | |
165 | /* |
166 | * If emsg() has not been called previously, temporarily reset |
167 | * "force_abort" until the throw point for error messages has been |
168 | * reached. This ensures that aborting() returns the same value for all |
169 | * errors that appear in the same command. This means particularly that |
170 | * for parsing errors during expression evaluation emsg() will be called |
171 | * multiply, even when the expression is evaluated from a finally clause |
172 | * that was activated due to an aborting error, interrupt, or exception. |
173 | */ |
174 | if (!did_emsg) { |
175 | cause_abort = force_abort; |
176 | force_abort = FALSE; |
177 | } |
178 | |
179 | /* |
180 | * If no try conditional is active and no exception is being thrown and |
181 | * there has not been an error in a try conditional or a throw so far, do |
182 | * nothing (for compatibility of non-EH scripts). The message will then |
183 | * be displayed by emsg(). When ":silent!" was used and we are not |
184 | * currently throwing an exception, do nothing. The message text will |
185 | * then be stored to v:errmsg by emsg() without displaying it. |
186 | */ |
187 | if (((trylevel == 0 && !cause_abort) || emsg_silent) && !current_exception) { |
188 | return false; |
189 | } |
190 | |
191 | /* |
192 | * Ignore an interrupt message when inside a try conditional or when an |
193 | * exception is being thrown or when an error in a try conditional or |
194 | * throw has been detected previously. This is important in order that an |
195 | * interrupt exception is catchable by the innermost try conditional and |
196 | * not replaced by an interrupt message error exception. |
197 | */ |
198 | if (mesg == (char_u *)_(e_interr)) { |
199 | *ignore = TRUE; |
200 | return TRUE; |
201 | } |
202 | |
203 | /* |
204 | * Ensure that all commands in nested function calls and sourced files |
205 | * are aborted immediately. |
206 | */ |
207 | cause_abort = TRUE; |
208 | |
209 | /* |
210 | * When an exception is being thrown, some commands (like conditionals) are |
211 | * not skipped. Errors in those commands may affect what of the subsequent |
212 | * commands are regarded part of catch and finally clauses. Catching the |
213 | * exception would then cause execution of commands not intended by the |
214 | * user, who wouldn't even get aware of the problem. Therefor, discard the |
215 | * exception currently being thrown to prevent it from being caught. Just |
216 | * execute finally clauses and terminate. |
217 | */ |
218 | if (current_exception) { |
219 | // When discarding an interrupt exception, reset got_int to prevent the |
220 | // same interrupt being converted to an exception again and discarding |
221 | // the error exception we are about to throw here. |
222 | if (current_exception->type == ET_INTERRUPT) { |
223 | got_int = false; |
224 | } |
225 | discard_current_exception(); |
226 | } |
227 | |
228 | #ifdef THROW_TEST |
229 | if (!THROW_ON_ERROR) { |
230 | /* |
231 | * Print error message immediately without searching for a matching |
232 | * catch clause; just finally clauses are executed before the script |
233 | * is terminated. |
234 | */ |
235 | return FALSE; |
236 | } else |
237 | #endif |
238 | { |
239 | /* |
240 | * Prepare the throw of an error exception, so that everything will |
241 | * be aborted (except for executing finally clauses), until the error |
242 | * exception is caught; if still uncaught at the top level, the error |
243 | * message will be displayed and the script processing terminated |
244 | * then. - This function has no access to the conditional stack. |
245 | * Thus, the actual throw is made after the failing command has |
246 | * returned. - Throw only the first of several errors in a row, except |
247 | * a severe error is following. |
248 | */ |
249 | if (msg_list != NULL) { |
250 | plist = msg_list; |
251 | while (*plist != NULL) |
252 | plist = &(*plist)->next; |
253 | |
254 | elem = xmalloc(sizeof(struct msglist)); |
255 | elem->msg = vim_strsave(mesg); |
256 | elem->next = NULL; |
257 | elem->throw_msg = NULL; |
258 | *plist = elem; |
259 | if (plist == msg_list || severe) { |
260 | char_u *tmsg; |
261 | |
262 | /* Skip the extra "Vim " prefix for message "E458". */ |
263 | tmsg = elem->msg; |
264 | if (STRNCMP(tmsg, "Vim E" , 5) == 0 |
265 | && ascii_isdigit(tmsg[5]) |
266 | && ascii_isdigit(tmsg[6]) |
267 | && ascii_isdigit(tmsg[7]) |
268 | && tmsg[8] == ':' |
269 | && tmsg[9] == ' ') |
270 | (*msg_list)->throw_msg = &tmsg[4]; |
271 | else |
272 | (*msg_list)->throw_msg = tmsg; |
273 | } |
274 | } |
275 | return TRUE; |
276 | } |
277 | } |
278 | |
279 | /* |
280 | * Free a "msg_list" and the messages it contains. |
281 | */ |
282 | static void free_msglist(struct msglist *l) |
283 | { |
284 | struct msglist *messages, *next; |
285 | |
286 | messages = l; |
287 | while (messages != NULL) { |
288 | next = messages->next; |
289 | xfree(messages->msg); |
290 | xfree(messages); |
291 | messages = next; |
292 | } |
293 | } |
294 | |
295 | /* |
296 | * Free global "*msg_list" and the messages it contains, then set "*msg_list" |
297 | * to NULL. |
298 | */ |
299 | void free_global_msglist(void) |
300 | { |
301 | free_msglist(*msg_list); |
302 | *msg_list = NULL; |
303 | } |
304 | |
305 | /* |
306 | * Throw the message specified in the call to cause_errthrow() above as an |
307 | * error exception. If cstack is NULL, postpone the throw until do_cmdline() |
308 | * has returned (see do_one_cmd()). |
309 | */ |
310 | void do_errthrow(struct condstack *cstack, char_u *cmdname) |
311 | { |
312 | /* |
313 | * Ensure that all commands in nested function calls and sourced files |
314 | * are aborted immediately. |
315 | */ |
316 | if (cause_abort) { |
317 | cause_abort = FALSE; |
318 | force_abort = TRUE; |
319 | } |
320 | |
321 | /* If no exception is to be thrown or the conversion should be done after |
322 | * returning to a previous invocation of do_one_cmd(), do nothing. */ |
323 | if (msg_list == NULL || *msg_list == NULL) |
324 | return; |
325 | |
326 | if (throw_exception(*msg_list, ET_ERROR, cmdname) == FAIL) |
327 | free_msglist(*msg_list); |
328 | else { |
329 | if (cstack != NULL) |
330 | do_throw(cstack); |
331 | else |
332 | need_rethrow = TRUE; |
333 | } |
334 | *msg_list = NULL; |
335 | } |
336 | |
337 | /* |
338 | * do_intthrow(): Replace the current exception by an interrupt or interrupt |
339 | * exception if appropriate. Return TRUE if the current exception is discarded, |
340 | * FALSE otherwise. |
341 | */ |
342 | int do_intthrow(struct condstack *cstack) |
343 | { |
344 | // If no interrupt occurred or no try conditional is active and no exception |
345 | // is being thrown, do nothing (for compatibility of non-EH scripts). |
346 | if (!got_int || (trylevel == 0 && !current_exception)) { |
347 | return false; |
348 | } |
349 | |
350 | #ifdef THROW_TEST // avoid warning for condition always true |
351 | if (!THROW_ON_INTERRUPT) { |
352 | // The interrupt aborts everything except for executing finally clauses. |
353 | // Discard any user or error or interrupt exception currently being |
354 | // thrown. |
355 | if (current_exception) { |
356 | discard_current_exception(); |
357 | } |
358 | } else { |
359 | #endif |
360 | // Throw an interrupt exception, so that everything will be aborted |
361 | // (except for executing finally clauses), until the interrupt exception |
362 | // is caught; if still uncaught at the top level, the script processing |
363 | // will be terminated then. - If an interrupt exception is already |
364 | // being thrown, do nothing. |
365 | |
366 | if (current_exception) { |
367 | if (current_exception->type == ET_INTERRUPT) { |
368 | return false; |
369 | } |
370 | |
371 | // An interrupt exception replaces any user or error exception. |
372 | discard_current_exception(); |
373 | } |
374 | if (throw_exception("Vim:Interrupt" , ET_INTERRUPT, NULL) != FAIL) { |
375 | do_throw(cstack); |
376 | } |
377 | #ifdef THROW_TEST |
378 | } |
379 | #endif |
380 | |
381 | return true; |
382 | } |
383 | |
384 | // Get an exception message that is to be stored in current_exception->value. |
385 | char_u *get_exception_string(void *value, except_type_T type, char_u *cmdname, |
386 | int *should_free) |
387 | { |
388 | char_u *ret, *mesg; |
389 | char_u *p, *val; |
390 | |
391 | if (type == ET_ERROR) { |
392 | *should_free = true; |
393 | mesg = ((struct msglist *)value)->throw_msg; |
394 | if (cmdname != NULL && *cmdname != NUL) { |
395 | size_t cmdlen = STRLEN(cmdname); |
396 | ret = vim_strnsave((char_u *)"Vim(" , 4 + cmdlen + 2 + STRLEN(mesg)); |
397 | STRCPY(&ret[4], cmdname); |
398 | STRCPY(&ret[4 + cmdlen], "):" ); |
399 | val = ret + 4 + cmdlen + 2; |
400 | } else { |
401 | ret = vim_strnsave((char_u *)"Vim:" , 4 + STRLEN(mesg)); |
402 | val = ret + 4; |
403 | } |
404 | |
405 | /* msg_add_fname may have been used to prefix the message with a file |
406 | * name in quotes. In the exception value, put the file name in |
407 | * parentheses and move it to the end. */ |
408 | for (p = mesg;; p++) { |
409 | if (*p == NUL |
410 | || (*p == 'E' |
411 | && ascii_isdigit(p[1]) |
412 | && (p[2] == ':' |
413 | || (ascii_isdigit(p[2]) |
414 | && (p[3] == ':' |
415 | || (ascii_isdigit(p[3]) |
416 | && p[4] == ':')))))) { |
417 | if (*p == NUL || p == mesg) { |
418 | STRCAT(val, mesg); // 'E123' missing or at beginning |
419 | } else { |
420 | // '"filename" E123: message text' |
421 | if (mesg[0] != '"' || p-2 < &mesg[1] |
422 | || p[-2] != '"' || p[-1] != ' ') { |
423 | // "E123:" is part of the file name. |
424 | continue; |
425 | } |
426 | |
427 | STRCAT(val, p); |
428 | p[-2] = NUL; |
429 | sprintf((char *)(val + STRLEN(p)), " (%s)" , &mesg[1]); |
430 | p[-2] = '"'; |
431 | } |
432 | break; |
433 | } |
434 | } |
435 | } else { |
436 | *should_free = FALSE; |
437 | ret = (char_u *) value; |
438 | } |
439 | |
440 | return ret; |
441 | } |
442 | |
443 | |
444 | // Throw a new exception. Return FAIL when out of memory or it was tried to |
445 | // throw an illegal user exception. "value" is the exception string for a |
446 | // user or interrupt exception, or points to a message list in case of an |
447 | // error exception. |
448 | static int throw_exception(void *value, except_type_T type, char_u *cmdname) |
449 | { |
450 | except_T *excp; |
451 | int should_free; |
452 | |
453 | /* |
454 | * Disallow faking Interrupt or error exceptions as user exceptions. They |
455 | * would be treated differently from real interrupt or error exceptions |
456 | * when no active try block is found, see do_cmdline(). |
457 | */ |
458 | if (type == ET_USER) { |
459 | if (STRNCMP((char_u *)value, "Vim" , 3) == 0 |
460 | && (((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':' |
461 | || ((char_u *)value)[3] == '(')) { |
462 | EMSG(_("E608: Cannot :throw exceptions with 'Vim' prefix" )); |
463 | goto fail; |
464 | } |
465 | } |
466 | |
467 | excp = xmalloc(sizeof(except_T)); |
468 | |
469 | if (type == ET_ERROR) |
470 | /* Store the original message and prefix the exception value with |
471 | * "Vim:" or, if a command name is given, "Vim(cmdname):". */ |
472 | excp->messages = (struct msglist *)value; |
473 | |
474 | excp->value = get_exception_string(value, type, cmdname, &should_free); |
475 | if (excp->value == NULL && should_free) |
476 | goto nomem; |
477 | |
478 | excp->type = type; |
479 | excp->throw_name = vim_strsave(sourcing_name == NULL |
480 | ? (char_u *)"" : sourcing_name); |
481 | excp->throw_lnum = sourcing_lnum; |
482 | |
483 | if (p_verbose >= 13 || debug_break_level > 0) { |
484 | int save_msg_silent = msg_silent; |
485 | |
486 | if (debug_break_level > 0) |
487 | msg_silent = FALSE; /* display messages */ |
488 | else |
489 | verbose_enter(); |
490 | ++no_wait_return; |
491 | if (debug_break_level > 0 || *p_vfile == NUL) |
492 | msg_scroll = TRUE; /* always scroll up, don't overwrite */ |
493 | |
494 | smsg(_("Exception thrown: %s" ), excp->value); |
495 | msg_puts("\n" ); // don't overwrite this either |
496 | |
497 | if (debug_break_level > 0 || *p_vfile == NUL) |
498 | cmdline_row = msg_row; |
499 | --no_wait_return; |
500 | if (debug_break_level > 0) |
501 | msg_silent = save_msg_silent; |
502 | else |
503 | verbose_leave(); |
504 | } |
505 | |
506 | current_exception = excp; |
507 | return OK; |
508 | |
509 | nomem: |
510 | xfree(excp); |
511 | suppress_errthrow = TRUE; |
512 | EMSG(_(e_outofmem)); |
513 | fail: |
514 | current_exception = NULL; |
515 | return FAIL; |
516 | } |
517 | |
518 | /* |
519 | * Discard an exception. "was_finished" is set when the exception has been |
520 | * caught and the catch clause has been ended normally. |
521 | */ |
522 | static void discard_exception(except_T *excp, int was_finished) |
523 | { |
524 | char_u *saved_IObuff; |
525 | |
526 | if (excp == NULL) { |
527 | internal_error("discard_exception()" ); |
528 | return; |
529 | } |
530 | |
531 | if (p_verbose >= 13 || debug_break_level > 0) { |
532 | int save_msg_silent = msg_silent; |
533 | |
534 | saved_IObuff = vim_strsave(IObuff); |
535 | if (debug_break_level > 0) |
536 | msg_silent = FALSE; /* display messages */ |
537 | else |
538 | verbose_enter(); |
539 | ++no_wait_return; |
540 | if (debug_break_level > 0 || *p_vfile == NUL) |
541 | msg_scroll = TRUE; /* always scroll up, don't overwrite */ |
542 | smsg(was_finished ? _("Exception finished: %s" ) |
543 | : _("Exception discarded: %s" ), |
544 | excp->value); |
545 | msg_puts("\n" ); // don't overwrite this either |
546 | if (debug_break_level > 0 || *p_vfile == NUL) { |
547 | cmdline_row = msg_row; |
548 | } |
549 | no_wait_return--; |
550 | if (debug_break_level > 0) { |
551 | msg_silent = save_msg_silent; |
552 | } else { |
553 | verbose_leave(); |
554 | } |
555 | xstrlcpy((char *)IObuff, (const char *)saved_IObuff, IOSIZE); |
556 | xfree(saved_IObuff); |
557 | } |
558 | if (excp->type != ET_INTERRUPT) |
559 | xfree(excp->value); |
560 | if (excp->type == ET_ERROR) |
561 | free_msglist(excp->messages); |
562 | xfree(excp->throw_name); |
563 | xfree(excp); |
564 | } |
565 | |
566 | /* |
567 | * Discard the exception currently being thrown. |
568 | */ |
569 | void discard_current_exception(void) |
570 | { |
571 | if (current_exception != NULL) { |
572 | discard_exception(current_exception, false); |
573 | current_exception = NULL; |
574 | } |
575 | // Note: all globals manipulated here should be saved/restored in |
576 | // try_enter/try_leave. |
577 | need_rethrow = false; |
578 | } |
579 | |
580 | /* |
581 | * Put an exception on the caught stack. |
582 | */ |
583 | static void catch_exception(except_T *excp) |
584 | { |
585 | excp->caught = caught_stack; |
586 | caught_stack = excp; |
587 | set_vim_var_string(VV_EXCEPTION, (char *) excp->value, -1); |
588 | if (*excp->throw_name != NUL) { |
589 | if (excp->throw_lnum != 0) { |
590 | vim_snprintf((char *)IObuff, IOSIZE, _("%s, line %" PRId64), |
591 | excp->throw_name, (int64_t)excp->throw_lnum); |
592 | } else { |
593 | vim_snprintf((char *)IObuff, IOSIZE, "%s" , excp->throw_name); |
594 | } |
595 | set_vim_var_string(VV_THROWPOINT, (char *) IObuff, -1); |
596 | } else { |
597 | // throw_name not set on an exception from a command that was typed. |
598 | set_vim_var_string(VV_THROWPOINT, NULL, -1); |
599 | } |
600 | |
601 | if (p_verbose >= 13 || debug_break_level > 0) { |
602 | int save_msg_silent = msg_silent; |
603 | |
604 | if (debug_break_level > 0) |
605 | msg_silent = FALSE; /* display messages */ |
606 | else |
607 | verbose_enter(); |
608 | ++no_wait_return; |
609 | if (debug_break_level > 0 || *p_vfile == NUL) |
610 | msg_scroll = TRUE; /* always scroll up, don't overwrite */ |
611 | |
612 | smsg(_("Exception caught: %s" ), excp->value); |
613 | msg_puts("\n" ); // don't overwrite this either |
614 | |
615 | if (debug_break_level > 0 || *p_vfile == NUL) |
616 | cmdline_row = msg_row; |
617 | --no_wait_return; |
618 | if (debug_break_level > 0) |
619 | msg_silent = save_msg_silent; |
620 | else |
621 | verbose_leave(); |
622 | } |
623 | } |
624 | |
625 | /* |
626 | * Remove an exception from the caught stack. |
627 | */ |
628 | static void finish_exception(except_T *excp) |
629 | { |
630 | if (excp != caught_stack) { |
631 | internal_error("finish_exception()" ); |
632 | } |
633 | caught_stack = caught_stack->caught; |
634 | if (caught_stack != NULL) { |
635 | set_vim_var_string(VV_EXCEPTION, (char *) caught_stack->value, -1); |
636 | if (*caught_stack->throw_name != NUL) { |
637 | if (caught_stack->throw_lnum != 0) { |
638 | vim_snprintf((char *)IObuff, IOSIZE, |
639 | _("%s, line %" PRId64), caught_stack->throw_name, |
640 | (int64_t)caught_stack->throw_lnum); |
641 | } else { |
642 | vim_snprintf((char *)IObuff, IOSIZE, "%s" , |
643 | caught_stack->throw_name); |
644 | } |
645 | set_vim_var_string(VV_THROWPOINT, (char *) IObuff, -1); |
646 | } else { |
647 | // throw_name not set on an exception from a command that was |
648 | // typed. |
649 | set_vim_var_string(VV_THROWPOINT, NULL, -1); |
650 | } |
651 | } else { |
652 | set_vim_var_string(VV_EXCEPTION, NULL, -1); |
653 | set_vim_var_string(VV_THROWPOINT, NULL, -1); |
654 | } |
655 | |
656 | /* Discard the exception, but use the finish message for 'verbose'. */ |
657 | discard_exception(excp, TRUE); |
658 | } |
659 | |
660 | /* |
661 | * Flags specifying the message displayed by report_pending. |
662 | */ |
663 | #define RP_MAKE 0 |
664 | #define RP_RESUME 1 |
665 | #define RP_DISCARD 2 |
666 | |
667 | /* |
668 | * Report information about something pending in a finally clause if required by |
669 | * the 'verbose' option or when debugging. "action" tells whether something is |
670 | * made pending or something pending is resumed or discarded. "pending" tells |
671 | * what is pending. "value" specifies the return value for a pending ":return" |
672 | * or the exception value for a pending exception. |
673 | */ |
674 | static void report_pending(int action, int pending, void *value) |
675 | { |
676 | char *mesg; |
677 | char *s; |
678 | int save_msg_silent; |
679 | |
680 | assert(value || !(pending & CSTP_THROW)); |
681 | |
682 | switch (action) { |
683 | case RP_MAKE: |
684 | mesg = _("%s made pending" ); |
685 | break; |
686 | case RP_RESUME: |
687 | mesg = _("%s resumed" ); |
688 | break; |
689 | /* case RP_DISCARD: */ |
690 | default: |
691 | mesg = _("%s discarded" ); |
692 | break; |
693 | } |
694 | |
695 | switch (pending) { |
696 | case CSTP_NONE: |
697 | return; |
698 | |
699 | case CSTP_CONTINUE: |
700 | s = ":continue" ; |
701 | break; |
702 | case CSTP_BREAK: |
703 | s = ":break" ; |
704 | break; |
705 | case CSTP_FINISH: |
706 | s = ":finish" ; |
707 | break; |
708 | case CSTP_RETURN: |
709 | /* ":return" command producing value, allocated */ |
710 | s = (char *)get_return_cmd(value); |
711 | break; |
712 | |
713 | default: |
714 | if (pending & CSTP_THROW) { |
715 | vim_snprintf((char *)IObuff, IOSIZE, |
716 | mesg, _("Exception" )); |
717 | mesg = (char *)concat_str(IObuff, (char_u *)": %s" ); |
718 | s = (char *)((except_T *)value)->value; |
719 | } else if ((pending & CSTP_ERROR) && (pending & CSTP_INTERRUPT)) |
720 | s = _("Error and interrupt" ); |
721 | else if (pending & CSTP_ERROR) |
722 | s = _("Error" ); |
723 | else /* if (pending & CSTP_INTERRUPT) */ |
724 | s = _("Interrupt" ); |
725 | } |
726 | |
727 | save_msg_silent = msg_silent; |
728 | if (debug_break_level > 0) |
729 | msg_silent = FALSE; /* display messages */ |
730 | ++no_wait_return; |
731 | msg_scroll = TRUE; /* always scroll up, don't overwrite */ |
732 | smsg(mesg, s); |
733 | msg_puts("\n" ); // don't overwrite this either |
734 | cmdline_row = msg_row; |
735 | --no_wait_return; |
736 | if (debug_break_level > 0) |
737 | msg_silent = save_msg_silent; |
738 | |
739 | if (pending == CSTP_RETURN) |
740 | xfree(s); |
741 | else if (pending & CSTP_THROW) |
742 | xfree(mesg); |
743 | } |
744 | |
745 | /* |
746 | * If something is made pending in a finally clause, report it if required by |
747 | * the 'verbose' option or when debugging. |
748 | */ |
749 | void report_make_pending(int pending, void *value) |
750 | { |
751 | if (p_verbose >= 14 || debug_break_level > 0) { |
752 | if (debug_break_level <= 0) |
753 | verbose_enter(); |
754 | report_pending(RP_MAKE, pending, value); |
755 | if (debug_break_level <= 0) |
756 | verbose_leave(); |
757 | } |
758 | } |
759 | |
760 | /* |
761 | * If something pending in a finally clause is resumed at the ":endtry", report |
762 | * it if required by the 'verbose' option or when debugging. |
763 | */ |
764 | void report_resume_pending(int pending, void *value) |
765 | { |
766 | if (p_verbose >= 14 || debug_break_level > 0) { |
767 | if (debug_break_level <= 0) |
768 | verbose_enter(); |
769 | report_pending(RP_RESUME, pending, value); |
770 | if (debug_break_level <= 0) |
771 | verbose_leave(); |
772 | } |
773 | } |
774 | |
775 | /* |
776 | * If something pending in a finally clause is discarded, report it if required |
777 | * by the 'verbose' option or when debugging. |
778 | */ |
779 | void report_discard_pending(int pending, void *value) |
780 | { |
781 | if (p_verbose >= 14 || debug_break_level > 0) { |
782 | if (debug_break_level <= 0) |
783 | verbose_enter(); |
784 | report_pending(RP_DISCARD, pending, value); |
785 | if (debug_break_level <= 0) |
786 | verbose_leave(); |
787 | } |
788 | } |
789 | |
790 | |
791 | /* |
792 | * ":if". |
793 | */ |
794 | void ex_if(exarg_T *eap) |
795 | { |
796 | int skip; |
797 | int result; |
798 | struct condstack *cstack = eap->cstack; |
799 | |
800 | if (cstack->cs_idx == CSTACK_LEN - 1) |
801 | eap->errmsg = (char_u *)N_("E579: :if nesting too deep" ); |
802 | else { |
803 | ++cstack->cs_idx; |
804 | cstack->cs_flags[cstack->cs_idx] = 0; |
805 | |
806 | skip = CHECK_SKIP; |
807 | |
808 | bool error; |
809 | result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); |
810 | |
811 | if (!skip && !error) { |
812 | if (result) |
813 | cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE; |
814 | } else |
815 | /* set TRUE, so this conditional will never get active */ |
816 | cstack->cs_flags[cstack->cs_idx] = CSF_TRUE; |
817 | } |
818 | } |
819 | |
820 | /* |
821 | * ":endif". |
822 | */ |
823 | void ex_endif(exarg_T *eap) |
824 | { |
825 | did_endif = TRUE; |
826 | if (eap->cstack->cs_idx < 0 |
827 | || (eap->cstack->cs_flags[eap->cstack->cs_idx] |
828 | & (CSF_WHILE | CSF_FOR | CSF_TRY))) |
829 | eap->errmsg = (char_u *)N_("E580: :endif without :if" ); |
830 | else { |
831 | /* |
832 | * When debugging or a breakpoint was encountered, display the debug |
833 | * prompt (if not already done). This shows the user that an ":endif" |
834 | * is executed when the ":if" or a previous ":elseif" was not TRUE. |
835 | * Handle a ">quit" debug command as if an interrupt had occurred before |
836 | * the ":endif". That is, throw an interrupt exception if appropriate. |
837 | * Doing this here prevents an exception for a parsing error being |
838 | * discarded by throwing the interrupt exception later on. |
839 | */ |
840 | if (!(eap->cstack->cs_flags[eap->cstack->cs_idx] & CSF_TRUE) |
841 | && dbg_check_skipped(eap)) |
842 | (void)do_intthrow(eap->cstack); |
843 | |
844 | --eap->cstack->cs_idx; |
845 | } |
846 | } |
847 | |
848 | /* |
849 | * ":else" and ":elseif". |
850 | */ |
851 | void ex_else(exarg_T *eap) |
852 | { |
853 | int skip; |
854 | int result; |
855 | struct condstack *cstack = eap->cstack; |
856 | |
857 | skip = CHECK_SKIP; |
858 | |
859 | if (cstack->cs_idx < 0 |
860 | || (cstack->cs_flags[cstack->cs_idx] |
861 | & (CSF_WHILE | CSF_FOR | CSF_TRY))) { |
862 | if (eap->cmdidx == CMD_else) { |
863 | eap->errmsg = (char_u *)N_("E581: :else without :if" ); |
864 | return; |
865 | } |
866 | eap->errmsg = (char_u *)N_("E582: :elseif without :if" ); |
867 | skip = TRUE; |
868 | } else if (cstack->cs_flags[cstack->cs_idx] & CSF_ELSE) { |
869 | if (eap->cmdidx == CMD_else) { |
870 | eap->errmsg = (char_u *)N_("E583: multiple :else" ); |
871 | return; |
872 | } |
873 | eap->errmsg = (char_u *)N_("E584: :elseif after :else" ); |
874 | skip = TRUE; |
875 | } |
876 | |
877 | /* if skipping or the ":if" was TRUE, reset ACTIVE, otherwise set it */ |
878 | if (skip || cstack->cs_flags[cstack->cs_idx] & CSF_TRUE) { |
879 | if (eap->errmsg == NULL) |
880 | cstack->cs_flags[cstack->cs_idx] = CSF_TRUE; |
881 | skip = TRUE; /* don't evaluate an ":elseif" */ |
882 | } else |
883 | cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE; |
884 | |
885 | /* |
886 | * When debugging or a breakpoint was encountered, display the debug prompt |
887 | * (if not already done). This shows the user that an ":else" or ":elseif" |
888 | * is executed when the ":if" or previous ":elseif" was not TRUE. Handle |
889 | * a ">quit" debug command as if an interrupt had occurred before the |
890 | * ":else" or ":elseif". That is, set "skip" and throw an interrupt |
891 | * exception if appropriate. Doing this here prevents that an exception |
892 | * for a parsing errors is discarded when throwing the interrupt exception |
893 | * later on. |
894 | */ |
895 | if (!skip && dbg_check_skipped(eap) && got_int) { |
896 | (void)do_intthrow(cstack); |
897 | skip = TRUE; |
898 | } |
899 | |
900 | if (eap->cmdidx == CMD_elseif) { |
901 | bool error; |
902 | result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); |
903 | /* When throwing error exceptions, we want to throw always the first |
904 | * of several errors in a row. This is what actually happens when |
905 | * a conditional error was detected above and there is another failure |
906 | * when parsing the expression. Since the skip flag is set in this |
907 | * case, the parsing error will be ignored by emsg(). */ |
908 | |
909 | if (!skip && !error) { |
910 | if (result) |
911 | cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE; |
912 | else |
913 | cstack->cs_flags[cstack->cs_idx] = 0; |
914 | } else if (eap->errmsg == NULL) |
915 | /* set TRUE, so this conditional will never get active */ |
916 | cstack->cs_flags[cstack->cs_idx] = CSF_TRUE; |
917 | } else |
918 | cstack->cs_flags[cstack->cs_idx] |= CSF_ELSE; |
919 | } |
920 | |
921 | /* |
922 | * Handle ":while" and ":for". |
923 | */ |
924 | void ex_while(exarg_T *eap) |
925 | { |
926 | bool error; |
927 | int skip; |
928 | int result; |
929 | struct condstack *cstack = eap->cstack; |
930 | |
931 | if (cstack->cs_idx == CSTACK_LEN - 1) |
932 | eap->errmsg = (char_u *)N_("E585: :while/:for nesting too deep" ); |
933 | else { |
934 | /* |
935 | * The loop flag is set when we have jumped back from the matching |
936 | * ":endwhile" or ":endfor". When not set, need to initialise this |
937 | * cstack entry. |
938 | */ |
939 | if ((cstack->cs_lflags & CSL_HAD_LOOP) == 0) { |
940 | ++cstack->cs_idx; |
941 | ++cstack->cs_looplevel; |
942 | cstack->cs_line[cstack->cs_idx] = -1; |
943 | } |
944 | cstack->cs_flags[cstack->cs_idx] = |
945 | eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR; |
946 | |
947 | skip = CHECK_SKIP; |
948 | if (eap->cmdidx == CMD_while) { |
949 | /* |
950 | * ":while bool-expr" |
951 | */ |
952 | result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); |
953 | } else { |
954 | void *fi; |
955 | |
956 | /* |
957 | * ":for var in list-expr" |
958 | */ |
959 | if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) { |
960 | /* Jumping here from a ":continue" or ":endfor": use the |
961 | * previously evaluated list. */ |
962 | fi = cstack->cs_forinfo[cstack->cs_idx]; |
963 | error = FALSE; |
964 | } else { |
965 | /* Evaluate the argument and get the info in a structure. */ |
966 | fi = eval_for_line(eap->arg, &error, &eap->nextcmd, skip); |
967 | cstack->cs_forinfo[cstack->cs_idx] = fi; |
968 | } |
969 | |
970 | /* use the element at the start of the list and advance */ |
971 | if (!error && fi != NULL && !skip) |
972 | result = next_for_item(fi, eap->arg); |
973 | else |
974 | result = FALSE; |
975 | |
976 | if (!result) { |
977 | free_for_info(fi); |
978 | cstack->cs_forinfo[cstack->cs_idx] = NULL; |
979 | } |
980 | } |
981 | |
982 | /* |
983 | * If this cstack entry was just initialised and is active, set the |
984 | * loop flag, so do_cmdline() will set the line number in cs_line[]. |
985 | * If executing the command a second time, clear the loop flag. |
986 | */ |
987 | if (!skip && !error && result) { |
988 | cstack->cs_flags[cstack->cs_idx] |= (CSF_ACTIVE | CSF_TRUE); |
989 | cstack->cs_lflags ^= CSL_HAD_LOOP; |
990 | } else { |
991 | cstack->cs_lflags &= ~CSL_HAD_LOOP; |
992 | /* If the ":while" evaluates to FALSE or ":for" is past the end of |
993 | * the list, show the debug prompt at the ":endwhile"/":endfor" as |
994 | * if there was a ":break" in a ":while"/":for" evaluating to |
995 | * TRUE. */ |
996 | if (!skip && !error) |
997 | cstack->cs_flags[cstack->cs_idx] |= CSF_TRUE; |
998 | } |
999 | } |
1000 | } |
1001 | |
1002 | /* |
1003 | * ":continue" |
1004 | */ |
1005 | void ex_continue(exarg_T *eap) |
1006 | { |
1007 | int idx; |
1008 | struct condstack *cstack = eap->cstack; |
1009 | |
1010 | if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) |
1011 | eap->errmsg = (char_u *)N_("E586: :continue without :while or :for" ); |
1012 | else { |
1013 | /* Try to find the matching ":while". This might stop at a try |
1014 | * conditional not in its finally clause (which is then to be executed |
1015 | * next). Therefor, inactivate all conditionals except the ":while" |
1016 | * itself (if reached). */ |
1017 | idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE); |
1018 | assert(idx >= 0); |
1019 | if (cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR)) { |
1020 | rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); |
1021 | |
1022 | /* |
1023 | * Set CSL_HAD_CONT, so do_cmdline() will jump back to the |
1024 | * matching ":while". |
1025 | */ |
1026 | cstack->cs_lflags |= CSL_HAD_CONT; /* let do_cmdline() handle it */ |
1027 | } else { |
1028 | /* If a try conditional not in its finally clause is reached first, |
1029 | * make the ":continue" pending for execution at the ":endtry". */ |
1030 | cstack->cs_pending[idx] = CSTP_CONTINUE; |
1031 | report_make_pending(CSTP_CONTINUE, NULL); |
1032 | } |
1033 | } |
1034 | } |
1035 | |
1036 | /* |
1037 | * ":break" |
1038 | */ |
1039 | void ex_break(exarg_T *eap) |
1040 | { |
1041 | int idx; |
1042 | struct condstack *cstack = eap->cstack; |
1043 | |
1044 | if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) |
1045 | eap->errmsg = (char_u *)N_("E587: :break without :while or :for" ); |
1046 | else { |
1047 | /* Inactivate conditionals until the matching ":while" or a try |
1048 | * conditional not in its finally clause (which is then to be |
1049 | * executed next) is found. In the latter case, make the ":break" |
1050 | * pending for execution at the ":endtry". */ |
1051 | idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, TRUE); |
1052 | if (idx >= 0 && !(cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR))) { |
1053 | cstack->cs_pending[idx] = CSTP_BREAK; |
1054 | report_make_pending(CSTP_BREAK, NULL); |
1055 | } |
1056 | } |
1057 | } |
1058 | |
1059 | /* |
1060 | * ":endwhile" and ":endfor" |
1061 | */ |
1062 | void ex_endwhile(exarg_T *eap) |
1063 | { |
1064 | struct condstack *cstack = eap->cstack; |
1065 | int idx; |
1066 | char_u *err; |
1067 | int csf; |
1068 | int fl; |
1069 | |
1070 | if (eap->cmdidx == CMD_endwhile) { |
1071 | err = e_while; |
1072 | csf = CSF_WHILE; |
1073 | } else { |
1074 | err = e_for; |
1075 | csf = CSF_FOR; |
1076 | } |
1077 | |
1078 | if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) |
1079 | eap->errmsg = err; |
1080 | else { |
1081 | fl = cstack->cs_flags[cstack->cs_idx]; |
1082 | if (!(fl & csf)) { |
1083 | /* If we are in a ":while" or ":for" but used the wrong endloop |
1084 | * command, do not rewind to the next enclosing ":for"/":while". */ |
1085 | if (fl & CSF_WHILE) |
1086 | eap->errmsg = (char_u *)_("E732: Using :endfor with :while" ); |
1087 | else if (fl & CSF_FOR) |
1088 | eap->errmsg = (char_u *)_("E733: Using :endwhile with :for" ); |
1089 | } |
1090 | if (!(fl & (CSF_WHILE | CSF_FOR))) { |
1091 | if (!(fl & CSF_TRY)) |
1092 | eap->errmsg = e_endif; |
1093 | else if (fl & CSF_FINALLY) |
1094 | eap->errmsg = e_endtry; |
1095 | /* Try to find the matching ":while" and report what's missing. */ |
1096 | for (idx = cstack->cs_idx; idx > 0; --idx) { |
1097 | fl = cstack->cs_flags[idx]; |
1098 | if ((fl & CSF_TRY) && !(fl & CSF_FINALLY)) { |
1099 | /* Give up at a try conditional not in its finally clause. |
1100 | * Ignore the ":endwhile"/":endfor". */ |
1101 | eap->errmsg = err; |
1102 | return; |
1103 | } |
1104 | if (fl & csf) |
1105 | break; |
1106 | } |
1107 | /* Cleanup and rewind all contained (and unclosed) conditionals. */ |
1108 | (void)cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE); |
1109 | rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); |
1110 | } |
1111 | /* |
1112 | * When debugging or a breakpoint was encountered, display the debug |
1113 | * prompt (if not already done). This shows the user that an |
1114 | * ":endwhile"/":endfor" is executed when the ":while" was not TRUE or |
1115 | * after a ":break". Handle a ">quit" debug command as if an |
1116 | * interrupt had occurred before the ":endwhile"/":endfor". That is, |
1117 | * throw an interrupt exception if appropriate. Doing this here |
1118 | * prevents that an exception for a parsing error is discarded when |
1119 | * throwing the interrupt exception later on. |
1120 | */ |
1121 | else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE |
1122 | && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE) |
1123 | && dbg_check_skipped(eap)) |
1124 | (void)do_intthrow(cstack); |
1125 | |
1126 | /* |
1127 | * Set loop flag, so do_cmdline() will jump back to the matching |
1128 | * ":while" or ":for". |
1129 | */ |
1130 | cstack->cs_lflags |= CSL_HAD_ENDLOOP; |
1131 | } |
1132 | } |
1133 | |
1134 | |
1135 | /* |
1136 | * ":throw expr" |
1137 | */ |
1138 | void ex_throw(exarg_T *eap) |
1139 | { |
1140 | const char *arg = (const char *)eap->arg; |
1141 | char *value; |
1142 | |
1143 | if (*arg != NUL && *arg != '|' && *arg != '\n') { |
1144 | value = eval_to_string_skip(arg, (const char **)&eap->nextcmd, |
1145 | (bool)eap->skip); |
1146 | } else { |
1147 | EMSG(_(e_argreq)); |
1148 | value = NULL; |
1149 | } |
1150 | |
1151 | // On error or when an exception is thrown during argument evaluation, do |
1152 | // not throw. |
1153 | if (!eap->skip && value != NULL) { |
1154 | if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) { |
1155 | xfree(value); |
1156 | } else { |
1157 | do_throw(eap->cstack); |
1158 | } |
1159 | } |
1160 | } |
1161 | |
1162 | /* |
1163 | * Throw the current exception through the specified cstack. Common routine |
1164 | * for ":throw" (user exception) and error and interrupt exceptions. Also |
1165 | * used for rethrowing an uncaught exception. |
1166 | */ |
1167 | void do_throw(struct condstack *cstack) |
1168 | { |
1169 | int idx; |
1170 | int inactivate_try = FALSE; |
1171 | |
1172 | /* |
1173 | * Cleanup and inactivate up to the next surrounding try conditional that |
1174 | * is not in its finally clause. Normally, do not inactivate the try |
1175 | * conditional itself, so that its ACTIVE flag can be tested below. But |
1176 | * if a previous error or interrupt has not been converted to an exception, |
1177 | * inactivate the try conditional, too, as if the conversion had been done, |
1178 | * and reset the did_emsg or got_int flag, so this won't happen again at |
1179 | * the next surrounding try conditional. |
1180 | */ |
1181 | #ifndef THROW_ON_ERROR_TRUE |
1182 | if (did_emsg && !THROW_ON_ERROR) { |
1183 | inactivate_try = TRUE; |
1184 | did_emsg = FALSE; |
1185 | } |
1186 | #endif |
1187 | #ifndef THROW_ON_INTERRUPT_TRUE |
1188 | if (got_int && !THROW_ON_INTERRUPT) { |
1189 | inactivate_try = TRUE; |
1190 | got_int = FALSE; |
1191 | } |
1192 | #endif |
1193 | idx = cleanup_conditionals(cstack, 0, inactivate_try); |
1194 | if (idx >= 0) { |
1195 | /* |
1196 | * If this try conditional is active and we are before its first |
1197 | * ":catch", set THROWN so that the ":catch" commands will check |
1198 | * whether the exception matches. When the exception came from any of |
1199 | * the catch clauses, it will be made pending at the ":finally" (if |
1200 | * present) and rethrown at the ":endtry". This will also happen if |
1201 | * the try conditional is inactive. This is the case when we are |
1202 | * throwing an exception due to an error or interrupt on the way from |
1203 | * a preceding ":continue", ":break", ":return", ":finish", error or |
1204 | * interrupt (not converted to an exception) to the finally clause or |
1205 | * from a preceding throw of a user or error or interrupt exception to |
1206 | * the matching catch clause or the finally clause. |
1207 | */ |
1208 | if (!(cstack->cs_flags[idx] & CSF_CAUGHT)) { |
1209 | if (cstack->cs_flags[idx] & CSF_ACTIVE) |
1210 | cstack->cs_flags[idx] |= CSF_THROWN; |
1211 | else |
1212 | /* THROWN may have already been set for a catchable exception |
1213 | * that has been discarded. Ensure it is reset for the new |
1214 | * exception. */ |
1215 | cstack->cs_flags[idx] &= ~CSF_THROWN; |
1216 | } |
1217 | cstack->cs_flags[idx] &= ~CSF_ACTIVE; |
1218 | cstack->cs_exception[idx] = current_exception; |
1219 | } |
1220 | } |
1221 | |
1222 | /* |
1223 | * ":try" |
1224 | */ |
1225 | void ex_try(exarg_T *eap) |
1226 | { |
1227 | int skip; |
1228 | struct condstack *cstack = eap->cstack; |
1229 | |
1230 | if (cstack->cs_idx == CSTACK_LEN - 1) |
1231 | eap->errmsg = (char_u *)N_("E601: :try nesting too deep" ); |
1232 | else { |
1233 | ++cstack->cs_idx; |
1234 | ++cstack->cs_trylevel; |
1235 | cstack->cs_flags[cstack->cs_idx] = CSF_TRY; |
1236 | cstack->cs_pending[cstack->cs_idx] = CSTP_NONE; |
1237 | |
1238 | skip = CHECK_SKIP; |
1239 | |
1240 | if (!skip) { |
1241 | /* Set ACTIVE and TRUE. TRUE means that the corresponding ":catch" |
1242 | * commands should check for a match if an exception is thrown and |
1243 | * that the finally clause needs to be executed. */ |
1244 | cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE; |
1245 | |
1246 | /* |
1247 | * ":silent!", even when used in a try conditional, disables |
1248 | * displaying of error messages and conversion of errors to |
1249 | * exceptions. When the silent commands again open a try |
1250 | * conditional, save "emsg_silent" and reset it so that errors are |
1251 | * again converted to exceptions. The value is restored when that |
1252 | * try conditional is left. If it is left normally, the commands |
1253 | * following the ":endtry" are again silent. If it is left by |
1254 | * a ":continue", ":break", ":return", or ":finish", the commands |
1255 | * executed next are again silent. If it is left due to an |
1256 | * aborting error, an interrupt, or an exception, restoring |
1257 | * "emsg_silent" does not matter since we are already in the |
1258 | * aborting state and/or the exception has already been thrown. |
1259 | * The effect is then just freeing the memory that was allocated |
1260 | * to save the value. |
1261 | */ |
1262 | if (emsg_silent) { |
1263 | eslist_T *elem = xmalloc(sizeof(struct eslist_elem)); |
1264 | elem->saved_emsg_silent = emsg_silent; |
1265 | elem->next = cstack->cs_emsg_silent_list; |
1266 | cstack->cs_emsg_silent_list = elem; |
1267 | cstack->cs_flags[cstack->cs_idx] |= CSF_SILENT; |
1268 | emsg_silent = 0; |
1269 | } |
1270 | } |
1271 | |
1272 | } |
1273 | } |
1274 | |
1275 | /* |
1276 | * ":catch /{pattern}/" and ":catch" |
1277 | */ |
1278 | void ex_catch(exarg_T *eap) |
1279 | { |
1280 | int idx = 0; |
1281 | int give_up = FALSE; |
1282 | int skip = FALSE; |
1283 | int caught = FALSE; |
1284 | char_u *end; |
1285 | char_u save_char = 0; |
1286 | char_u *save_cpo; |
1287 | regmatch_T regmatch; |
1288 | int prev_got_int; |
1289 | struct condstack *cstack = eap->cstack; |
1290 | char_u *pat; |
1291 | |
1292 | if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) { |
1293 | eap->errmsg = (char_u *)N_("E603: :catch without :try" ); |
1294 | give_up = TRUE; |
1295 | } else { |
1296 | if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) { |
1297 | /* Report what's missing if the matching ":try" is not in its |
1298 | * finally clause. */ |
1299 | eap->errmsg = get_end_emsg(cstack); |
1300 | skip = TRUE; |
1301 | } |
1302 | for (idx = cstack->cs_idx; idx > 0; --idx) |
1303 | if (cstack->cs_flags[idx] & CSF_TRY) |
1304 | break; |
1305 | if (cstack->cs_flags[idx] & CSF_FINALLY) { |
1306 | /* Give up for a ":catch" after ":finally" and ignore it. |
1307 | * Just parse. */ |
1308 | eap->errmsg = (char_u *)N_("E604: :catch after :finally" ); |
1309 | give_up = TRUE; |
1310 | } else |
1311 | rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, |
1312 | &cstack->cs_looplevel); |
1313 | } |
1314 | |
1315 | if (ends_excmd(*eap->arg)) { /* no argument, catch all errors */ |
1316 | pat = (char_u *)".*" ; |
1317 | end = NULL; |
1318 | eap->nextcmd = find_nextcmd(eap->arg); |
1319 | } else { |
1320 | pat = eap->arg + 1; |
1321 | end = skip_regexp(pat, *eap->arg, TRUE, NULL); |
1322 | } |
1323 | |
1324 | if (!give_up) { |
1325 | /* |
1326 | * Don't do something when no exception has been thrown or when the |
1327 | * corresponding try block never got active (because of an inactive |
1328 | * surrounding conditional or after an error or interrupt or throw). |
1329 | */ |
1330 | if (!current_exception || !(cstack->cs_flags[idx] & CSF_TRUE)) { |
1331 | skip = true; |
1332 | } |
1333 | |
1334 | /* |
1335 | * Check for a match only if an exception is thrown but not caught by |
1336 | * a previous ":catch". An exception that has replaced a discarded |
1337 | * exception is not checked (THROWN is not set then). |
1338 | */ |
1339 | if (!skip && (cstack->cs_flags[idx] & CSF_THROWN) |
1340 | && !(cstack->cs_flags[idx] & CSF_CAUGHT)) { |
1341 | if (end != NULL && *end != NUL && !ends_excmd(*skipwhite(end + 1))) { |
1342 | EMSG(_(e_trailing)); |
1343 | return; |
1344 | } |
1345 | |
1346 | /* When debugging or a breakpoint was encountered, display the |
1347 | * debug prompt (if not already done) before checking for a match. |
1348 | * This is a helpful hint for the user when the regular expression |
1349 | * matching fails. Handle a ">quit" debug command as if an |
1350 | * interrupt had occurred before the ":catch". That is, discard |
1351 | * the original exception, replace it by an interrupt exception, |
1352 | * and don't catch it in this try block. */ |
1353 | if (!dbg_check_skipped(eap) || !do_intthrow(cstack)) { |
1354 | /* Terminate the pattern and avoid the 'l' flag in 'cpoptions' |
1355 | * while compiling it. */ |
1356 | if (end != NULL) { |
1357 | save_char = *end; |
1358 | *end = NUL; |
1359 | } |
1360 | save_cpo = p_cpo; |
1361 | p_cpo = (char_u *)"" ; |
1362 | // Disable error messages, it will make current exception |
1363 | // invalid |
1364 | emsg_off++; |
1365 | regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); |
1366 | emsg_off--; |
1367 | regmatch.rm_ic = false; |
1368 | if (end != NULL) { |
1369 | *end = save_char; |
1370 | } |
1371 | p_cpo = save_cpo; |
1372 | if (regmatch.regprog == NULL) { |
1373 | EMSG2(_(e_invarg2), pat); |
1374 | } else { |
1375 | // |
1376 | // Save the value of got_int and reset it. We don't want |
1377 | // a previous interruption cancel matching, only hitting |
1378 | // CTRL-C while matching should abort it. |
1379 | // |
1380 | prev_got_int = got_int; |
1381 | got_int = FALSE; |
1382 | caught = vim_regexec_nl(®match, current_exception->value, |
1383 | (colnr_T)0); |
1384 | got_int |= prev_got_int; |
1385 | vim_regfree(regmatch.regprog); |
1386 | } |
1387 | } |
1388 | } |
1389 | |
1390 | if (caught) { |
1391 | /* Make this ":catch" clause active and reset did_emsg and got_int. |
1392 | * Put the exception on the caught stack. */ |
1393 | cstack->cs_flags[idx] |= CSF_ACTIVE | CSF_CAUGHT; |
1394 | did_emsg = got_int = false; |
1395 | catch_exception((except_T *)cstack->cs_exception[idx]); |
1396 | /* It's mandatory that the current exception is stored in the cstack |
1397 | * so that it can be discarded at the next ":catch", ":finally", or |
1398 | * ":endtry" or when the catch clause is left by a ":continue", |
1399 | * ":break", ":return", ":finish", error, interrupt, or another |
1400 | * exception. */ |
1401 | if (cstack->cs_exception[cstack->cs_idx] != current_exception) { |
1402 | internal_error("ex_catch()" ); |
1403 | } |
1404 | // Discarding current_exceptions happens based on what is stored in |
1405 | // cstack->cs_exception, *all* calls to discard_current_exception() are |
1406 | // (and must be) guarded by current_exception check. |
1407 | current_exception = NULL; |
1408 | } else { |
1409 | /* |
1410 | * If there is a preceding catch clause and it caught the exception, |
1411 | * finish the exception now. This happens also after errors except |
1412 | * when this ":catch" was after the ":finally" or not within |
1413 | * a ":try". Make the try conditional inactive so that the |
1414 | * following catch clauses are skipped. On an error or interrupt |
1415 | * after the preceding try block or catch clause was left by |
1416 | * a ":continue", ":break", ":return", or ":finish", discard the |
1417 | * pending action. |
1418 | */ |
1419 | cleanup_conditionals(cstack, CSF_TRY, TRUE); |
1420 | } |
1421 | } |
1422 | |
1423 | if (end != NULL) |
1424 | eap->nextcmd = find_nextcmd(end); |
1425 | } |
1426 | |
1427 | /* |
1428 | * ":finally" |
1429 | */ |
1430 | void ex_finally(exarg_T *eap) |
1431 | { |
1432 | int idx; |
1433 | int skip = FALSE; |
1434 | int pending = CSTP_NONE; |
1435 | struct condstack *cstack = eap->cstack; |
1436 | |
1437 | if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) |
1438 | eap->errmsg = (char_u *)N_("E606: :finally without :try" ); |
1439 | else { |
1440 | if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) { |
1441 | eap->errmsg = get_end_emsg(cstack); |
1442 | for (idx = cstack->cs_idx - 1; idx > 0; --idx) |
1443 | if (cstack->cs_flags[idx] & CSF_TRY) |
1444 | break; |
1445 | /* Make this error pending, so that the commands in the following |
1446 | * finally clause can be executed. This overrules also a pending |
1447 | * ":continue", ":break", ":return", or ":finish". */ |
1448 | pending = CSTP_ERROR; |
1449 | } else |
1450 | idx = cstack->cs_idx; |
1451 | |
1452 | if (cstack->cs_flags[idx] & CSF_FINALLY) { |
1453 | /* Give up for a multiple ":finally" and ignore it. */ |
1454 | eap->errmsg = (char_u *)N_("E607: multiple :finally" ); |
1455 | return; |
1456 | } |
1457 | rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, |
1458 | &cstack->cs_looplevel); |
1459 | |
1460 | /* |
1461 | * Don't do something when the corresponding try block never got active |
1462 | * (because of an inactive surrounding conditional or after an error or |
1463 | * interrupt or throw) or for a ":finally" without ":try" or a multiple |
1464 | * ":finally". After every other error (did_emsg or the conditional |
1465 | * errors detected above) or after an interrupt (got_int) or an |
1466 | * exception (current_exception), the finally clause must be executed. |
1467 | */ |
1468 | skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); |
1469 | |
1470 | if (!skip) { |
1471 | /* When debugging or a breakpoint was encountered, display the |
1472 | * debug prompt (if not already done). The user then knows that the |
1473 | * finally clause is executed. */ |
1474 | if (dbg_check_skipped(eap)) { |
1475 | /* Handle a ">quit" debug command as if an interrupt had |
1476 | * occurred before the ":finally". That is, discard the |
1477 | * original exception and replace it by an interrupt |
1478 | * exception. */ |
1479 | (void)do_intthrow(cstack); |
1480 | } |
1481 | |
1482 | /* |
1483 | * If there is a preceding catch clause and it caught the exception, |
1484 | * finish the exception now. This happens also after errors except |
1485 | * when this is a multiple ":finally" or one not within a ":try". |
1486 | * After an error or interrupt, this also discards a pending |
1487 | * ":continue", ":break", ":finish", or ":return" from the preceding |
1488 | * try block or catch clause. |
1489 | */ |
1490 | cleanup_conditionals(cstack, CSF_TRY, FALSE); |
1491 | |
1492 | /* |
1493 | * Make did_emsg, got_int, current_exception pending. If set, they |
1494 | * overrule a pending ":continue", ":break", ":return", or ":finish". |
1495 | * Then we have particularly to discard a pending return value (as done |
1496 | * by the call to cleanup_conditionals() above when did_emsg or |
1497 | * got_int is set). The pending values are restored by the |
1498 | * ":endtry", except if there is a new error, interrupt, exception, |
1499 | * ":continue", ":break", ":return", or ":finish" in the following |
1500 | * finally clause. A missing ":endwhile", ":endfor" or ":endif" |
1501 | * detected here is treated as if did_emsg and current_exception had |
1502 | * already been set, respectively in case that the error is not |
1503 | * converted to an exception, current_exception had already been unset. |
1504 | * We must not set did_emsg here since that would suppress the |
1505 | * error message. |
1506 | */ |
1507 | if (pending == CSTP_ERROR || did_emsg || got_int || current_exception) { |
1508 | if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN) { |
1509 | report_discard_pending(CSTP_RETURN, |
1510 | cstack->cs_rettv[cstack->cs_idx]); |
1511 | discard_pending_return(cstack->cs_rettv[cstack->cs_idx]); |
1512 | } |
1513 | if (pending == CSTP_ERROR && !did_emsg) { |
1514 | pending |= (THROW_ON_ERROR ? CSTP_THROW : 0); |
1515 | } else { |
1516 | pending |= (current_exception ? CSTP_THROW : 0); |
1517 | } |
1518 | pending |= did_emsg ? CSTP_ERROR : 0; |
1519 | pending |= got_int ? CSTP_INTERRUPT : 0; |
1520 | assert(pending >= CHAR_MIN && pending <= CHAR_MAX); |
1521 | cstack->cs_pending[cstack->cs_idx] = (char)pending; |
1522 | |
1523 | /* It's mandatory that the current exception is stored in the |
1524 | * cstack so that it can be rethrown at the ":endtry" or be |
1525 | * discarded if the finally clause is left by a ":continue", |
1526 | * ":break", ":return", ":finish", error, interrupt, or another |
1527 | * exception. When emsg() is called for a missing ":endif" or |
1528 | * a missing ":endwhile"/":endfor" detected here, the |
1529 | * exception will be discarded. */ |
1530 | if (current_exception |
1531 | && cstack->cs_exception[cstack->cs_idx] != current_exception) { |
1532 | internal_error("ex_finally()" ); |
1533 | } |
1534 | } |
1535 | |
1536 | /* |
1537 | * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg, |
1538 | * got_int, and current_exception and make the finally clause active. |
1539 | * This will happen after emsg() has been called for a missing |
1540 | * ":endif" or a missing ":endwhile"/":endfor" detected here, so |
1541 | * that the following finally clause will be executed even then. |
1542 | */ |
1543 | cstack->cs_lflags |= CSL_HAD_FINA; |
1544 | } |
1545 | } |
1546 | } |
1547 | |
1548 | /* |
1549 | * ":endtry" |
1550 | */ |
1551 | void ex_endtry(exarg_T *eap) |
1552 | { |
1553 | int idx; |
1554 | int skip; |
1555 | int rethrow = FALSE; |
1556 | int pending = CSTP_NONE; |
1557 | void *rettv = NULL; |
1558 | struct condstack *cstack = eap->cstack; |
1559 | |
1560 | if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) { |
1561 | eap->errmsg = (char_u *)N_("E602: :endtry without :try" ); |
1562 | } else { |
1563 | // Don't do something after an error, interrupt or throw in the try |
1564 | // block, catch clause, or finally clause preceding this ":endtry" or |
1565 | // when an error or interrupt occurred after a ":continue", ":break", |
1566 | // ":return", or ":finish" in a try block or catch clause preceding this |
1567 | // ":endtry" or when the try block never got active (because of an |
1568 | // inactive surrounding conditional or after an error or interrupt or |
1569 | // throw) or when there is a surrounding conditional and it has been |
1570 | // made inactive by a ":continue", ":break", ":return", or ":finish" in |
1571 | // the finally clause. The latter case need not be tested since then |
1572 | // anything pending has already been discarded. |
1573 | skip = (did_emsg || got_int || current_exception |
1574 | || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE)); |
1575 | |
1576 | if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) { |
1577 | eap->errmsg = get_end_emsg(cstack); |
1578 | /* Find the matching ":try" and report what's missing. */ |
1579 | idx = cstack->cs_idx; |
1580 | do |
1581 | --idx; |
1582 | while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY)); |
1583 | rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, |
1584 | &cstack->cs_looplevel); |
1585 | skip = TRUE; |
1586 | |
1587 | /* |
1588 | * If an exception is being thrown, discard it to prevent it from |
1589 | * being rethrown at the end of this function. It would be |
1590 | * discarded by the error message, anyway. Resets current_exception. |
1591 | * This does not affect the script termination due to the error |
1592 | * since "trylevel" is decremented after emsg() has been called. |
1593 | */ |
1594 | if (current_exception) { |
1595 | discard_current_exception(); |
1596 | } |
1597 | } else { |
1598 | idx = cstack->cs_idx; |
1599 | |
1600 | /* |
1601 | * If we stopped with the exception currently being thrown at this |
1602 | * try conditional since we didn't know that it doesn't have |
1603 | * a finally clause, we need to rethrow it after closing the try |
1604 | * conditional. |
1605 | */ |
1606 | if (current_exception |
1607 | && (cstack->cs_flags[idx] & CSF_TRUE) |
1608 | && !(cstack->cs_flags[idx] & CSF_FINALLY)) { |
1609 | rethrow = true; |
1610 | } |
1611 | } |
1612 | |
1613 | /* If there was no finally clause, show the user when debugging or |
1614 | * a breakpoint was encountered that the end of the try conditional has |
1615 | * been reached: display the debug prompt (if not already done). Do |
1616 | * this on normal control flow or when an exception was thrown, but not |
1617 | * on an interrupt or error not converted to an exception or when |
1618 | * a ":break", ":continue", ":return", or ":finish" is pending. These |
1619 | * actions are carried out immediately. |
1620 | */ |
1621 | if ((rethrow || (!skip |
1622 | && !(cstack->cs_flags[idx] & CSF_FINALLY) |
1623 | && !cstack->cs_pending[idx])) |
1624 | && dbg_check_skipped(eap)) { |
1625 | /* Handle a ">quit" debug command as if an interrupt had occurred |
1626 | * before the ":endtry". That is, throw an interrupt exception and |
1627 | * set "skip" and "rethrow". */ |
1628 | if (got_int) { |
1629 | skip = TRUE; |
1630 | (void)do_intthrow(cstack); |
1631 | // The do_intthrow() call may have reset current_exception or |
1632 | // cstack->cs_pending[idx]. |
1633 | rethrow = false; |
1634 | if (current_exception && !(cstack->cs_flags[idx] & CSF_FINALLY)) { |
1635 | rethrow = true; |
1636 | } |
1637 | } |
1638 | } |
1639 | |
1640 | /* |
1641 | * If a ":return" is pending, we need to resume it after closing the |
1642 | * try conditional; remember the return value. If there was a finally |
1643 | * clause making an exception pending, we need to rethrow it. Make it |
1644 | * the exception currently being thrown. |
1645 | */ |
1646 | if (!skip) { |
1647 | pending = cstack->cs_pending[idx]; |
1648 | cstack->cs_pending[idx] = CSTP_NONE; |
1649 | if (pending == CSTP_RETURN) |
1650 | rettv = cstack->cs_rettv[idx]; |
1651 | else if (pending & CSTP_THROW) |
1652 | current_exception = cstack->cs_exception[idx]; |
1653 | } |
1654 | |
1655 | /* |
1656 | * Discard anything pending on an error, interrupt, or throw in the |
1657 | * finally clause. If there was no ":finally", discard a pending |
1658 | * ":continue", ":break", ":return", or ":finish" if an error or |
1659 | * interrupt occurred afterwards, but before the ":endtry" was reached. |
1660 | * If an exception was caught by the last of the catch clauses and there |
1661 | * was no finally clause, finish the exception now. This happens also |
1662 | * after errors except when this ":endtry" is not within a ":try". |
1663 | * Restore "emsg_silent" if it has been reset by this try conditional. |
1664 | */ |
1665 | (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); |
1666 | |
1667 | --cstack->cs_idx; |
1668 | --cstack->cs_trylevel; |
1669 | |
1670 | if (!skip) { |
1671 | report_resume_pending(pending, |
1672 | (pending == CSTP_RETURN) ? rettv : |
1673 | (pending & CSTP_THROW) ? (void *)current_exception : NULL); |
1674 | switch (pending) { |
1675 | case CSTP_NONE: |
1676 | break; |
1677 | |
1678 | /* Reactivate a pending ":continue", ":break", ":return", |
1679 | * ":finish" from the try block or a catch clause of this try |
1680 | * conditional. This is skipped, if there was an error in an |
1681 | * (unskipped) conditional command or an interrupt afterwards |
1682 | * or if the finally clause is present and executed a new error, |
1683 | * interrupt, throw, ":continue", ":break", ":return", or |
1684 | * ":finish". */ |
1685 | case CSTP_CONTINUE: |
1686 | ex_continue(eap); |
1687 | break; |
1688 | case CSTP_BREAK: |
1689 | ex_break(eap); |
1690 | break; |
1691 | case CSTP_RETURN: |
1692 | do_return(eap, FALSE, FALSE, rettv); |
1693 | break; |
1694 | case CSTP_FINISH: |
1695 | do_finish(eap, FALSE); |
1696 | break; |
1697 | |
1698 | // When the finally clause was entered due to an error, |
1699 | // interrupt or throw (as opposed to a ":continue", ":break", |
1700 | // ":return", or ":finish"), restore the pending values of |
1701 | // did_emsg, got_int, and current_exception. This is skipped, if there |
1702 | // was a new error, interrupt, throw, ":continue", ":break", |
1703 | // ":return", or ":finish". in the finally clause. |
1704 | default: |
1705 | if (pending & CSTP_ERROR) { |
1706 | did_emsg = true; |
1707 | } |
1708 | if (pending & CSTP_INTERRUPT) { |
1709 | got_int = true; |
1710 | } |
1711 | if (pending & CSTP_THROW) { |
1712 | rethrow = true; |
1713 | } |
1714 | break; |
1715 | } |
1716 | } |
1717 | |
1718 | if (rethrow) { |
1719 | // Rethrow the current exception (within this cstack). |
1720 | do_throw(cstack); |
1721 | } |
1722 | } |
1723 | } |
1724 | |
1725 | /* |
1726 | * enter_cleanup() and leave_cleanup() |
1727 | * |
1728 | * Functions to be called before/after invoking a sequence of autocommands for |
1729 | * cleanup for a failed command. (Failure means here that a call to emsg() |
1730 | * has been made, an interrupt occurred, or there is an uncaught exception |
1731 | * from a previous autocommand execution of the same command.) |
1732 | * |
1733 | * Call enter_cleanup() with a pointer to a cleanup_T and pass the same |
1734 | * pointer to leave_cleanup(). The cleanup_T structure stores the pending |
1735 | * error/interrupt/exception state. |
1736 | */ |
1737 | |
1738 | /* |
1739 | * This function works a bit like ex_finally() except that there was not |
1740 | * actually an extra try block around the part that failed and an error or |
1741 | * interrupt has not (yet) been converted to an exception. This function |
1742 | * saves the error/interrupt/ exception state and prepares for the call to |
1743 | * do_cmdline() that is going to be made for the cleanup autocommand |
1744 | * execution. |
1745 | */ |
1746 | void enter_cleanup(cleanup_T *csp) |
1747 | { |
1748 | int pending = CSTP_NONE; |
1749 | |
1750 | /* |
1751 | * Postpone did_emsg, got_int, current_exception. The pending values will be |
1752 | * restored by leave_cleanup() except if there was an aborting error, |
1753 | * interrupt, or uncaught exception after this function ends. |
1754 | */ |
1755 | if (did_emsg || got_int || current_exception || need_rethrow) { |
1756 | csp->pending = (did_emsg ? CSTP_ERROR : 0) |
1757 | | (got_int ? CSTP_INTERRUPT : 0) |
1758 | | (current_exception ? CSTP_THROW : 0) |
1759 | | (need_rethrow ? CSTP_THROW : 0); |
1760 | |
1761 | /* If we are currently throwing an exception, save it as well. On an error |
1762 | * not yet converted to an exception, update "force_abort" and reset |
1763 | * "cause_abort" (as do_errthrow() would do). This is needed for the |
1764 | * do_cmdline() call that is going to be made for autocommand execution. We |
1765 | * need not save *msg_list because there is an extra instance for every call |
1766 | * of do_cmdline(), anyway. |
1767 | */ |
1768 | if (current_exception || need_rethrow) { |
1769 | csp->exception = current_exception; |
1770 | current_exception = NULL; |
1771 | } else { |
1772 | csp->exception = NULL; |
1773 | if (did_emsg) { |
1774 | force_abort |= cause_abort; |
1775 | cause_abort = FALSE; |
1776 | } |
1777 | } |
1778 | did_emsg = got_int = need_rethrow = false; |
1779 | current_exception = NULL; |
1780 | |
1781 | /* Report if required by the 'verbose' option or when debugging. */ |
1782 | report_make_pending(pending, csp->exception); |
1783 | } else { |
1784 | csp->pending = CSTP_NONE; |
1785 | csp->exception = NULL; |
1786 | } |
1787 | } |
1788 | |
1789 | /* |
1790 | * See comment above enter_cleanup() for how this function is used. |
1791 | * |
1792 | * This function is a bit like ex_endtry() except that there was not actually |
1793 | * an extra try block around the part that failed and an error or interrupt |
1794 | * had not (yet) been converted to an exception when the cleanup autocommand |
1795 | * sequence was invoked. |
1796 | * |
1797 | * This function has to be called with the address of the cleanup_T structure |
1798 | * filled by enter_cleanup() as an argument; it restores the error/interrupt/ |
1799 | * exception state saved by that function - except there was an aborting |
1800 | * error, an interrupt or an uncaught exception during execution of the |
1801 | * cleanup autocommands. In the latter case, the saved error/interrupt/ |
1802 | * exception state is discarded. |
1803 | */ |
1804 | void leave_cleanup(cleanup_T *csp) |
1805 | { |
1806 | int pending = csp->pending; |
1807 | |
1808 | if (pending == CSTP_NONE) /* nothing to do */ |
1809 | return; |
1810 | |
1811 | /* If there was an aborting error, an interrupt, or an uncaught exception |
1812 | * after the corresponding call to enter_cleanup(), discard what has been |
1813 | * made pending by it. Report this to the user if required by the |
1814 | * 'verbose' option or when debugging. */ |
1815 | if (aborting() || need_rethrow) { |
1816 | if (pending & CSTP_THROW) |
1817 | /* Cancel the pending exception (includes report). */ |
1818 | discard_exception(csp->exception, FALSE); |
1819 | else |
1820 | report_discard_pending(pending, NULL); |
1821 | |
1822 | /* If an error was about to be converted to an exception when |
1823 | * enter_cleanup() was called, free the message list. */ |
1824 | if (msg_list != NULL) |
1825 | free_global_msglist(); |
1826 | } |
1827 | /* |
1828 | * If there was no new error, interrupt, or throw between the calls |
1829 | * to enter_cleanup() and leave_cleanup(), restore the pending |
1830 | * error/interrupt/exception state. |
1831 | */ |
1832 | else { |
1833 | /* |
1834 | * If there was an exception being thrown when enter_cleanup() was |
1835 | * called, we need to rethrow it. Make it the exception currently |
1836 | * being thrown. |
1837 | */ |
1838 | if (pending & CSTP_THROW) |
1839 | current_exception = csp->exception; |
1840 | |
1841 | /* |
1842 | * If an error was about to be converted to an exception when |
1843 | * enter_cleanup() was called, let "cause_abort" take the part of |
1844 | * "force_abort" (as done by cause_errthrow()). |
1845 | */ |
1846 | else if (pending & CSTP_ERROR) { |
1847 | cause_abort = force_abort; |
1848 | force_abort = FALSE; |
1849 | } |
1850 | |
1851 | // Restore the pending values of did_emsg, got_int, and current_exception. |
1852 | if (pending & CSTP_ERROR) { |
1853 | did_emsg = true; |
1854 | } |
1855 | if (pending & CSTP_INTERRUPT) { |
1856 | got_int = true; |
1857 | } |
1858 | if (pending & CSTP_THROW) { |
1859 | need_rethrow = true; // current_exception will be set by do_one_cmd() |
1860 | } |
1861 | |
1862 | // Report if required by the 'verbose' option or when debugging. |
1863 | report_resume_pending( |
1864 | pending, ((pending & CSTP_THROW) ? (void *)current_exception : NULL)); |
1865 | } |
1866 | } |
1867 | |
1868 | |
1869 | /* |
1870 | * Make conditionals inactive and discard what's pending in finally clauses |
1871 | * until the conditional type searched for or a try conditional not in its |
1872 | * finally clause is reached. If this is in an active catch clause, finish |
1873 | * the caught exception. |
1874 | * Return the cstack index where the search stopped. |
1875 | * Values used for "searched_cond" are (CSF_WHILE | CSF_FOR) or CSF_TRY or 0, |
1876 | * the latter meaning the innermost try conditional not in its finally clause. |
1877 | * "inclusive" tells whether the conditional searched for should be made |
1878 | * inactive itself (a try conditional not in its finally clause possibly find |
1879 | * before is always made inactive). If "inclusive" is TRUE and |
1880 | * "searched_cond" is CSF_TRY|CSF_SILENT, the saved former value of |
1881 | * "emsg_silent", if reset when the try conditional finally reached was |
1882 | * entered, is restored (used by ex_endtry()). This is normally done only |
1883 | * when such a try conditional is left. |
1884 | */ |
1885 | int cleanup_conditionals(struct condstack *cstack, int searched_cond, int inclusive) |
1886 | { |
1887 | int idx; |
1888 | int stop = FALSE; |
1889 | |
1890 | for (idx = cstack->cs_idx; idx >= 0; --idx) { |
1891 | if (cstack->cs_flags[idx] & CSF_TRY) { |
1892 | /* |
1893 | * Discard anything pending in a finally clause and continue the |
1894 | * search. There may also be a pending ":continue", ":break", |
1895 | * ":return", or ":finish" before the finally clause. We must not |
1896 | * discard it, unless an error or interrupt occurred afterwards. |
1897 | */ |
1898 | if (did_emsg || got_int || (cstack->cs_flags[idx] & CSF_FINALLY)) { |
1899 | switch (cstack->cs_pending[idx]) { |
1900 | case CSTP_NONE: |
1901 | break; |
1902 | |
1903 | case CSTP_CONTINUE: |
1904 | case CSTP_BREAK: |
1905 | case CSTP_FINISH: |
1906 | report_discard_pending(cstack->cs_pending[idx], NULL); |
1907 | cstack->cs_pending[idx] = CSTP_NONE; |
1908 | break; |
1909 | |
1910 | case CSTP_RETURN: |
1911 | report_discard_pending(CSTP_RETURN, |
1912 | cstack->cs_rettv[idx]); |
1913 | discard_pending_return(cstack->cs_rettv[idx]); |
1914 | cstack->cs_pending[idx] = CSTP_NONE; |
1915 | break; |
1916 | |
1917 | default: |
1918 | if (cstack->cs_flags[idx] & CSF_FINALLY) { |
1919 | if (cstack->cs_pending[idx] & CSTP_THROW) { |
1920 | /* Cancel the pending exception. This is in the |
1921 | * finally clause, so that the stack of the |
1922 | * caught exceptions is not involved. */ |
1923 | discard_exception((except_T *) |
1924 | cstack->cs_exception[idx], |
1925 | FALSE); |
1926 | } else |
1927 | report_discard_pending(cstack->cs_pending[idx], |
1928 | NULL); |
1929 | cstack->cs_pending[idx] = CSTP_NONE; |
1930 | } |
1931 | break; |
1932 | } |
1933 | } |
1934 | |
1935 | /* |
1936 | * Stop at a try conditional not in its finally clause. If this try |
1937 | * conditional is in an active catch clause, finish the caught |
1938 | * exception. |
1939 | */ |
1940 | if (!(cstack->cs_flags[idx] & CSF_FINALLY)) { |
1941 | if ((cstack->cs_flags[idx] & CSF_ACTIVE) |
1942 | && (cstack->cs_flags[idx] & CSF_CAUGHT)) |
1943 | finish_exception((except_T *)cstack->cs_exception[idx]); |
1944 | /* Stop at this try conditional - except the try block never |
1945 | * got active (because of an inactive surrounding conditional |
1946 | * or when the ":try" appeared after an error or interrupt or |
1947 | * throw). */ |
1948 | if (cstack->cs_flags[idx] & CSF_TRUE) { |
1949 | if (searched_cond == 0 && !inclusive) |
1950 | break; |
1951 | stop = TRUE; |
1952 | } |
1953 | } |
1954 | } |
1955 | |
1956 | /* Stop on the searched conditional type (even when the surrounding |
1957 | * conditional is not active or something has been made pending). |
1958 | * If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT, |
1959 | * check first whether "emsg_silent" needs to be restored. */ |
1960 | if (cstack->cs_flags[idx] & searched_cond) { |
1961 | if (!inclusive) |
1962 | break; |
1963 | stop = TRUE; |
1964 | } |
1965 | cstack->cs_flags[idx] &= ~CSF_ACTIVE; |
1966 | if (stop && searched_cond != (CSF_TRY | CSF_SILENT)) |
1967 | break; |
1968 | |
1969 | /* |
1970 | * When leaving a try conditional that reset "emsg_silent" on its |
1971 | * entry after saving the original value, restore that value here and |
1972 | * free the memory used to store it. |
1973 | */ |
1974 | if ((cstack->cs_flags[idx] & CSF_TRY) |
1975 | && (cstack->cs_flags[idx] & CSF_SILENT)) { |
1976 | eslist_T *elem; |
1977 | |
1978 | elem = cstack->cs_emsg_silent_list; |
1979 | cstack->cs_emsg_silent_list = elem->next; |
1980 | emsg_silent = elem->saved_emsg_silent; |
1981 | xfree(elem); |
1982 | cstack->cs_flags[idx] &= ~CSF_SILENT; |
1983 | } |
1984 | if (stop) |
1985 | break; |
1986 | } |
1987 | return idx; |
1988 | } |
1989 | |
1990 | /* |
1991 | * Return an appropriate error message for a missing endwhile/endfor/endif. |
1992 | */ |
1993 | static char_u *get_end_emsg(struct condstack *cstack) |
1994 | { |
1995 | if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) |
1996 | return e_endwhile; |
1997 | if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR) |
1998 | return e_endfor; |
1999 | return e_endif; |
2000 | } |
2001 | |
2002 | |
2003 | /* |
2004 | * Rewind conditionals until index "idx" is reached. "cond_type" and |
2005 | * "cond_level" specify a conditional type and the address of a level variable |
2006 | * which is to be decremented with each skipped conditional of the specified |
2007 | * type. |
2008 | * Also free "for info" structures where needed. |
2009 | */ |
2010 | void rewind_conditionals(struct condstack *cstack, int idx, int cond_type, int *cond_level) |
2011 | { |
2012 | while (cstack->cs_idx > idx) { |
2013 | if (cstack->cs_flags[cstack->cs_idx] & cond_type) |
2014 | --*cond_level; |
2015 | if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR) |
2016 | free_for_info(cstack->cs_forinfo[cstack->cs_idx]); |
2017 | --cstack->cs_idx; |
2018 | } |
2019 | } |
2020 | |
2021 | /* |
2022 | * ":endfunction" when not after a ":function" |
2023 | */ |
2024 | void ex_endfunction(exarg_T *eap) |
2025 | { |
2026 | EMSG(_("E193: :endfunction not inside a function" )); |
2027 | } |
2028 | |
2029 | /* |
2030 | * Return TRUE if the string "p" looks like a ":while" or ":for" command. |
2031 | */ |
2032 | int has_loop_cmd(char_u *p) |
2033 | { |
2034 | int len; |
2035 | |
2036 | /* skip modifiers, white space and ':' */ |
2037 | for (;; ) { |
2038 | while (*p == ' ' || *p == '\t' || *p == ':') |
2039 | ++p; |
2040 | len = modifier_len(p); |
2041 | if (len == 0) |
2042 | break; |
2043 | p += len; |
2044 | } |
2045 | if ((p[0] == 'w' && p[1] == 'h') |
2046 | || (p[0] == 'f' && p[1] == 'o' && p[2] == 'r')) |
2047 | return TRUE; |
2048 | return FALSE; |
2049 | } |
2050 | |
2051 | |