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