1 #ifndef R2_CMD_H
2 #define R2_CMD_H
3
4 #include <r_types.h>
5 #include <r_util.h>
6 #include <r_bind.h>
7
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11
12 typedef struct r_core_t RCore;
13
14 //R_LIB_VERSION_HEADER (r_cmd);
15
16 #define MACRO_LIMIT 1024
17 #define MACRO_LABELS 20
18 #define R_CMD_MAXLEN 4096
19
20 typedef enum r_cmd_status_t {
21 R_CMD_STATUS_OK = 0, // command handler exited in the right way
22 R_CMD_STATUS_WRONG_ARGS, // command handler could not handle the arguments passed to it
23 R_CMD_STATUS_ERROR, // command handler had issues while running (e.g. allocation error, etc.)
24 R_CMD_STATUS_INVALID, // command could not be executed (e.g. shell level error, not existing command, bad expression, etc.)
25 R_CMD_STATUS_EXIT, // command handler asks to exit the prompt loop
26 } RCmdStatus;
27
28 typedef int (*RCmdCb) (void *user, const char *input);
29 typedef RCmdStatus (*RCmdArgvCb) (RCore *core, int argc, const char **argv);
30 typedef int (*RCmdNullCb) (void *user);
31
32 typedef struct r_cmd_parsed_args_t {
33 int argc;
34 char **argv;
35 bool has_space_after_cmd;
36 } RCmdParsedArgs;
37
38 typedef struct r_cmd_macro_label_t {
39 char name[80];
40 char *ptr;
41 } RCmdMacroLabel;
42
43 typedef struct r_cmd_macro_item_t {
44 char *name;
45 char *args;
46 char *code;
47 int codelen;
48 int nargs;
49 } RCmdMacroItem;
50
51 typedef struct r_cmd_macro_t {
52 int counter;
53 ut64 *brk_value;
54 ut64 _brk_value;
55 int brk;
56 // int (*cmd)(void *user, const char *cmd);
57 RCoreCmd cmd;
58 PrintfCallback cb_printf;
59 void *user;
60 RNum *num;
61 int labels_n;
62 RCmdMacroLabel labels[MACRO_LABELS];
63 RList *macros;
64 } RCmdMacro;
65
66 typedef struct r_cmd_item_t {
67 char cmd[64];
68 RCmdCb callback;
69 } RCmdItem;
70
71 typedef struct r_cmd_alias_t {
72 int count;
73 char **keys;
74 char **values;
75 int *remote;
76 } RCmdAlias;
77
78 typedef struct r_cmd_desc_example_t {
79 const char *example;
80 const char *comment;
81 } RCmdDescExample;
82
83 /**
84 * Define how the command looks like in the help.
85 */
86 typedef struct r_cmd_desc_help_t {
87 /**
88 * Short-sentence explaining what the command does.
89 * This is shown, for example, when the list of sub-commands is printed
90 * and each sub-command has a very short description on the right,
91 * explaining what it does.
92 */
93 const char *summary;
94 /**
95 * Long description of what the command does. It can be as long as you
96 * want and it should explain well how the command behaves.
97 * This is shown, for example, when `??` is appended on command or `?`
98 * is appended and the command has no children to show. In that case,
99 * the short summary is extended with this longer description.
100 *
101 * Optional.
102 */
103 const char *description;
104 /**
105 * String used to identify the arguments. This usually comes together
106 * with the summary.
107 * TODO: explain how to differentiate between required and optional arguments
108 */
109 const char *args_str;
110 /**
111 * String that overrides the name+args_str usually used to describe the
112 * command.
113 *
114 * Optional.
115 */
116 const char *usage;
117 /**
118 * String to use as sub-commands suggestions instead of the
119 * auto-generated one (e.g. [abcd] or [?] that you can see near command
120 * names when doing `w?`). If not provided, the options will be
121 * auto-generated.
122 *
123 * Optional.
124 */
125 const char *options;
126 /**
127 * List of examples used to better explain how to use the command. This
128 * is shown together with the long description.
129 *
130 * Optional.
131 */
132 const RCmdDescExample *examples;
133 } RCmdDescHelp;
134
135 typedef enum {
136 // for old handlers that parse their own input and accept a single string
137 R_CMD_DESC_TYPE_OLDINPUT = 0,
138 // for handlers that accept argc/argv
139 R_CMD_DESC_TYPE_ARGV,
140 // for cmd descriptors that are just used to group together related
141 // sub-commands. Do not use this if the command can be used by itself or
142 // if it's necessary to show its help, because this descriptor is not
143 // stored in the hashtable and cannot be retrieved except by listing the
144 // children of its parent.
145 R_CMD_DESC_TYPE_INNER,
146 // for cmd descriptors that are parent of other sub-commands but that
147 // may also have a sub-command with the same name. For example, `wc` is
148 // both the parent of `wci`, `wc*`, etc. but there is also `wc` as a
149 // sub-command.
150 R_CMD_DESC_TYPE_GROUP,
151 } RCmdDescType;
152
153 typedef struct r_cmd_desc_t {
154 RCmdDescType type;
155 char *name;
156 struct r_cmd_desc_t *parent;
157 int n_children;
158 RPVector children;
159 const RCmdDescHelp *help;
160
161 union {
162 struct {
163 RCmdCb cb;
164 } oldinput_data;
165 struct {
166 RCmdArgvCb cb;
167 } argv_data;
168 struct {
169 struct r_cmd_desc_t *exec_cd;
170 } group_data;
171 } d;
172 } RCmdDesc;
173
174 typedef struct r_cmd_t {
175 void *data;
176 RCmdNullCb nullcallback;
177 RCmdItem *cmds[UT8_MAX];
178 RCmdMacro macro;
179 RList *lcmds;
180 RList *plist;
181 RCmdAlias aliases;
182 void *language; // used to store TSLanguage *
183 HtUP *ts_symbols_ht;
184 RCmdDesc *root_cmd_desc;
185 HtPP *ht_cmds;
186 } RCmd;
187
188 // TODO: remove this once transitioned to RCmdDesc
189 typedef struct r_cmd_descriptor_t {
190 const char *cmd;
191 const char **help_msg;
192 const char **help_detail;
193 const char **help_detail2;
194 struct r_cmd_descriptor_t *sub[127];
195 } RCmdDescriptor;
196
197 // TODO: move into r_core.h
198 typedef struct r_core_plugin_t {
199 const char *name;
200 const char *desc;
201 const char *license;
202 const char *author;
203 const char *version;
204 RCmdCb call; // returns true if command was handled, false otherwise.
205 RCmdCb init;
206 RCmdCb fini;
207 } RCorePlugin;
208
209 #define DEFINE_CMD_ARGV_DESC_DETAIL(core, name, c_name, parent, handler, help) \
210 RCmdDesc *c_name##_cd = r_cmd_desc_argv_new (core->rcmd, parent, #name, handler, help); \
211 r_warn_if_fail (c_name##_cd)
212 #define DEFINE_CMD_ARGV_DESC_SPECIAL(core, name, c_name, parent) \
213 DEFINE_CMD_ARGV_DESC_DETAIL (core, name, c_name, parent, c_name##_handler, &c_name##_help)
214 #define DEFINE_CMD_ARGV_DESC_INNER(core, name, c_name, parent) \
215 RCmdDesc *c_name##_cd = r_cmd_desc_inner_new (core->rcmd, parent, #name, &c_name##_help); \
216 r_warn_if_fail (c_name##_cd)
217 #define DEFINE_CMD_ARGV_GROUP_WITH_CHILD(core, name, parent) \
218 RCmdDesc *name##_cd = r_cmd_desc_group_new (core->rcmd, parent, #name, name##_handler, &name##_help, &name##_group_help); \
219 r_warn_if_fail (name##_cd)
220 #define DEFINE_CMD_ARGV_DESC(core, name, parent) \
221 DEFINE_CMD_ARGV_DESC_SPECIAL (core, name, name, parent)
222 #define DEFINE_CMD_OLDINPUT_DESC(core, name, parent) \
223 RCmdDesc *name##_cd = r_cmd_desc_oldinput_new (core->rcmd, parent, #name, name##_handler_old, &name##_help); \
224 r_warn_if_fail (name##_cd)
225
226 #ifdef R_API
227 R_API bool r_core_plugin_init(RCmd *cmd);
228 R_API bool r_core_plugin_add(RCmd *cmd, RCorePlugin *plugin);
229 R_API bool r_core_plugin_check(RCmd *cmd, const char *a0);
230 R_API bool r_core_plugin_fini(RCmd *cmd);
231
232 R_API RCmd *r_cmd_new(void);
233 R_API RCmd *r_cmd_free(RCmd *cmd);
234 R_API void r_cmd_set_data(RCmd *cmd, void *data);
235 R_API bool r_cmd_add(RCmd *cmd, const char *command, RCmdCb callback);
236 R_API bool r_core_del(RCmd *cmd, const char *command);
237 R_API int r_cmd_call(RCmd *cmd, const char *command);
238 R_API RCmdStatus r_cmd_call_parsed_args(RCmd *cmd, RCmdParsedArgs *args);
239 R_API RCmdDesc *r_cmd_get_root(RCmd *cmd);
240 R_API RCmdDesc *r_cmd_get_desc(RCmd *cmd, const char *cmd_identifier);
241 R_API char *r_cmd_get_help(RCmd *cmd, RCmdParsedArgs *args, bool use_color);
242
r_cmd_int2status(int v)243 static inline RCmdStatus r_cmd_int2status(int v) {
244 if (v == -2) {
245 return R_CMD_STATUS_EXIT;
246 } else if (v < 0) {
247 return R_CMD_STATUS_ERROR;
248 } else {
249 return R_CMD_STATUS_OK;
250 }
251 }
252
r_cmd_status2int(RCmdStatus s)253 static inline int r_cmd_status2int(RCmdStatus s) {
254 switch (s) {
255 case R_CMD_STATUS_OK:
256 return 0;
257 case R_CMD_STATUS_ERROR:
258 case R_CMD_STATUS_WRONG_ARGS:
259 case R_CMD_STATUS_INVALID:
260 return -1;
261 case R_CMD_STATUS_EXIT:
262 default:
263 return -2;
264 }
265 }
266
267 /* RCmdDescriptor */
268 R_API RCmdDesc *r_cmd_desc_argv_new(RCmd *cmd, RCmdDesc *parent, const char *name, RCmdArgvCb cb, const RCmdDescHelp *help);
269 R_API RCmdDesc *r_cmd_desc_inner_new(RCmd *cmd, RCmdDesc *parent, const char *name, const RCmdDescHelp *help);
270 R_API RCmdDesc *r_cmd_desc_group_new(RCmd *cmd, RCmdDesc *parent, const char *name, RCmdArgvCb cb, const RCmdDescHelp *help, const RCmdDescHelp *group_help);
271 R_API RCmdDesc *r_cmd_desc_oldinput_new(RCmd *cmd, RCmdDesc *parent, const char *name, RCmdCb cb, const RCmdDescHelp *help);
272 R_API RCmdDesc *r_cmd_desc_parent(RCmdDesc *cd);
273 R_API bool r_cmd_desc_has_handler(RCmdDesc *cd);
274 R_API bool r_cmd_desc_remove(RCmd *cmd, RCmdDesc *cd);
275
276 #define r_cmd_desc_children_foreach(root, it_cd) r_pvector_foreach (&root->children, it_cd)
277
278 /* RCmdParsedArgs */
279 R_API RCmdParsedArgs *r_cmd_parsed_args_new(const char *cmd, int n_args, char **args);
280 R_API RCmdParsedArgs *r_cmd_parsed_args_newcmd(const char *cmd);
281 R_API RCmdParsedArgs *r_cmd_parsed_args_newargs(int n_args, char **args);
282 R_API void r_cmd_parsed_args_free(RCmdParsedArgs *args);
283 R_API bool r_cmd_parsed_args_setargs(RCmdParsedArgs *arg, int n_args, char **args);
284 R_API bool r_cmd_parsed_args_setcmd(RCmdParsedArgs *arg, const char *cmd);
285 R_API char *r_cmd_parsed_args_argstr(RCmdParsedArgs *arg);
286 R_API char *r_cmd_parsed_args_execstr(RCmdParsedArgs *arg);
287 R_API const char *r_cmd_parsed_args_cmd(RCmdParsedArgs *arg);
288
289 #define r_cmd_parsed_args_foreach_arg(args, i, arg) for ((i) = 1; (i) < (args->argc) && ((arg) = (args)->argv[i]); (i)++)
290
291 /* r_cmd_macro */
292 R_API RCmdMacroItem *r_cmd_macro_item_new(void);
293 R_API void r_cmd_macro_item_free(RCmdMacroItem *item);
294 R_API void r_cmd_macro_init(RCmdMacro *mac);
295 R_API bool r_cmd_macro_add(RCmdMacro *mac, const char *name);
296 R_API bool r_cmd_macro_rm(RCmdMacro *mac, const char *_name);
297 R_API void r_cmd_macro_list(RCmdMacro *mac);
298 R_API void r_cmd_macro_meta(RCmdMacro *mac);
299 R_API int r_cmd_macro_call(RCmdMacro *mac, const char *name);
300 R_API int r_cmd_macro_break(RCmdMacro *mac, const char *value);
301
302 R_API bool r_cmd_alias_del(RCmd *cmd, const char *k);
303 R_API char **r_cmd_alias_keys(RCmd *cmd, int *sz);
304 R_API int r_cmd_alias_set(RCmd *cmd, const char *k, const char *v, int remote);
305 R_API const char *r_cmd_alias_get(RCmd *cmd, const char *k, int remote);
306 R_API void r_cmd_alias_free(RCmd *cmd);
307 R_API void r_cmd_macro_fini(RCmdMacro *mac);
308
309 #ifdef __cplusplus
310 }
311 #endif
312
313 #endif
314 #endif
315