1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
#pragma once
#include <stdbool.h>
#include "nvim/eval/typval_defs.h"
#include "nvim/pos_defs.h"
/// A list used for saving values of "emsg_silent". Used by ex_try() to save the
/// value of "emsg_silent" if it was non-zero. When this is done, the CSF_SILENT
/// flag below is set.
typedef struct eslist_elem eslist_T;
struct eslist_elem {
int saved_emsg_silent; ///< saved value of "emsg_silent"
eslist_T *next; ///< next element on the list
};
enum {
/// For conditional commands a stack is kept of nested conditionals.
/// When cs_idx < 0, there is no conditional command.
CSTACK_LEN = 50,
};
typedef struct {
int cs_flags[CSTACK_LEN]; ///< CSF_ flags
char cs_pending[CSTACK_LEN]; ///< CSTP_: what's pending in ":finally"
union {
void *csp_rv[CSTACK_LEN]; ///< return typeval for pending return
void *csp_ex[CSTACK_LEN]; ///< exception for pending throw
} cs_pend;
void *cs_forinfo[CSTACK_LEN]; ///< info used by ":for"
int cs_line[CSTACK_LEN]; ///< line nr of ":while"/":for" line
int cs_idx; ///< current entry, or -1 if none
int cs_looplevel; ///< nr of nested ":while"s and ":for"s
int cs_trylevel; ///< nr of nested ":try"s
eslist_T *cs_emsg_silent_list; ///< saved values of "emsg_silent"
int cs_lflags; ///< loop flags: CSL_ flags
} cstack_T;
#define cs_rettv cs_pend.csp_rv
#define cs_exception cs_pend.csp_ex
/// There is no CSF_IF, the lack of CSF_WHILE, CSF_FOR and CSF_TRY means ":if"
/// was used.
enum {
CSF_TRUE = 0x0001, ///< condition was TRUE
CSF_ACTIVE = 0x0002, ///< current state is active
CSF_ELSE = 0x0004, ///< ":else" has been passed
CSF_WHILE = 0x0008, ///< is a ":while"
CSF_FOR = 0x0010, ///< is a ":for"
CSF_TRY = 0x0100, ///< is a ":try"
CSF_FINALLY = 0x0200, ///< ":finally" has been passed
CSF_THROWN = 0x0800, ///< exception thrown to this try conditional
CSF_CAUGHT = 0x1000, ///< exception caught by this try conditional
CSF_FINISHED = 0x2000, ///< CSF_CAUGHT was handled by finish_exception()
CSF_SILENT = 0x4000, ///< "emsg_silent" reset by ":try"
};
// Note that CSF_ELSE is only used when CSF_TRY and CSF_WHILE are unset
// (an ":if"), and CSF_SILENT is only used when CSF_TRY is set.
/// What's pending for being reactivated at the ":endtry" of this try
/// conditional:
enum {
CSTP_NONE = 0, ///< nothing pending in ":finally" clause
CSTP_ERROR = 1, ///< an error is pending
CSTP_INTERRUPT = 2, ///< an interrupt is pending
CSTP_THROW = 4, ///< a throw is pending
CSTP_BREAK = 8, ///< ":break" is pending
CSTP_CONTINUE = 16, ///< ":continue" is pending
CSTP_RETURN = 24, ///< ":return" is pending
CSTP_FINISH = 32, ///< ":finish" is pending
};
/// Flags for the cs_lflags item in cstack_T.
enum {
CSL_HAD_LOOP = 1, ///< just found ":while" or ":for"
CSL_HAD_ENDLOOP = 2, ///< just found ":endwhile" or ":endfor"
CSL_HAD_CONT = 4, ///< just found ":continue"
CSL_HAD_FINA = 8, ///< just found ":finally"
};
/// A list of error messages that can be converted to an exception. "throw_msg"
/// is only set in the first element of the list. Usually, it points to the
/// original message stored in that element, but sometimes it points to a later
/// message in the list. See cause_errthrow().
typedef struct msglist msglist_T;
struct msglist {
msglist_T *next; ///< next of several messages in a row
char *msg; ///< original message, allocated
char *throw_msg; ///< msg to throw: usually original one
char *sfile; ///< value from estack_sfile(), allocated
linenr_T slnum; ///< line number for "sfile"
bool multiline; ///< whether this is a multiline message
};
/// The exception types.
typedef enum {
ET_USER, ///< exception caused by ":throw" command
ET_ERROR, ///< error exception
ET_INTERRUPT, ///< interrupt exception triggered by Ctrl-C
} except_type_T;
/// Structure describing an exception.
/// (don't use "struct exception", it's used by the math library).
typedef struct vim_exception except_T;
struct vim_exception {
except_type_T type; ///< exception type
char *value; ///< exception value
msglist_T *messages; ///< message(s) causing error exception
char *throw_name; ///< name of the throw point
linenr_T throw_lnum; ///< line number of the throw point
list_T *stacktrace; ///< stacktrace
except_T *caught; ///< next exception on the caught stack
};
/// Structure to save the error/interrupt/exception state between calls to
/// enter_cleanup() and leave_cleanup(). Must be allocated as an automatic
/// variable by the (common) caller of these functions.
typedef struct cleanup_stuff cleanup_T;
struct cleanup_stuff {
int pending; ///< error/interrupt/exception state
except_T *exception; ///< exception value
};
/// Exception state that is saved and restored when calling timer callback
/// functions and deferred functions.
typedef struct exception_state_S exception_state_T;
struct exception_state_S {
except_T *estate_current_exception;
bool estate_did_throw;
bool estate_need_rethrow;
int estate_trylevel;
int estate_did_emsg;
};
|