1 /*
2 * command.c
3 *
4 * This file provides the implementation of a command definition
5 */
6 #include "private.h"
7 #include "clish/types.h"
8 #include "lub/bintree.h"
9 #include "lub/string.h"
10
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15
16 /*---------------------------------------------------------
17 * PRIVATE METHODS
18 *--------------------------------------------------------- */
19 static void
clish_command_init(clish_command_t * this,const char * name,const char * text)20 clish_command_init(clish_command_t *this, const char *name, const char *text)
21 {
22 /* initialise the node part */
23 this->name = lub_string_dup(name);
24 this->text = lub_string_dup(text);
25
26 /* Be a good binary tree citizen */
27 lub_bintree_node_init(&this->bt_node);
28
29 /* set up defaults */
30 this->link = NULL;
31 this->alias = NULL;
32 this->alias_view = NULL;
33 this->paramv = clish_paramv_new();
34 this->viewid = NULL;
35 this->viewname = NULL;
36 this->action = clish_action_new();
37 this->config = clish_config_new();
38 this->detail = NULL;
39 this->escape_chars = NULL;
40 this->regex_chars = NULL;
41 this->args = NULL;
42 this->pview = NULL;
43 this->lock = BOOL_TRUE;
44 this->interrupt = BOOL_FALSE;
45 this->dynamic = BOOL_FALSE;
46 this->internal = BOOL_FALSE;
47 this->access = NULL;
48 }
49
50 /*--------------------------------------------------------- */
clish_command_fini(clish_command_t * this)51 static void clish_command_fini(clish_command_t * this)
52 {
53 lub_string_free(this->name);
54 lub_string_free(this->text);
55
56 /* Link need not full cleanup */
57 if (this->link)
58 return;
59
60 /* finalize each of the parameter instances */
61 clish_paramv_delete(this->paramv);
62
63 clish_action_delete(this->action);
64 clish_config_delete(this->config);
65 lub_string_free(this->alias);
66 lub_string_free(this->alias_view);
67 lub_string_free(this->viewname);
68 lub_string_free(this->viewid);
69 lub_string_free(this->detail);
70 lub_string_free(this->escape_chars);
71 lub_string_free(this->regex_chars);
72 lub_string_free(this->access);
73 if (this->args)
74 clish_param_delete(this->args);
75 }
76
77 /*---------------------------------------------------------
78 * PUBLIC META FUNCTIONS
79 *--------------------------------------------------------- */
clish_command_bt_offset(void)80 size_t clish_command_bt_offset(void)
81 {
82 return offsetof(clish_command_t, bt_node);
83 }
84
85 /*--------------------------------------------------------- */
clish_command_bt_compare(const void * clientnode,const void * clientkey)86 int clish_command_bt_compare(const void *clientnode, const void *clientkey)
87 {
88 const clish_command_t *this = clientnode;
89 const char *key = clientkey;
90
91 return lub_string_nocasecmp(this->name, key);
92 }
93
94 /*--------------------------------------------------------- */
clish_command_bt_getkey(const void * clientnode,lub_bintree_key_t * key)95 void clish_command_bt_getkey(const void *clientnode, lub_bintree_key_t * key)
96 {
97 const clish_command_t *this = clientnode;
98
99 /* fill out the opaque key */
100 strcpy((char *)key, this->name);
101 }
102
103 /*--------------------------------------------------------- */
clish_command_new(const char * name,const char * help)104 clish_command_t *clish_command_new(const char *name, const char *help)
105 {
106 clish_command_t *this = malloc(sizeof(clish_command_t));
107
108 if (this)
109 clish_command_init(this, name, help);
110
111 return this;
112 }
113
114 /*--------------------------------------------------------- */
clish_command_new_link(const char * name,const char * help,const clish_command_t * ref)115 clish_command_t *clish_command_new_link(const char *name,
116 const char *help, const clish_command_t * ref)
117 {
118 if (!ref)
119 return NULL;
120
121 clish_command_t *this = malloc(sizeof(clish_command_t));
122 assert(this);
123
124 /* Copy all fields to the new command-link */
125 *this = *ref;
126 /* Initialise the name (other than original name) */
127 this->name = lub_string_dup(name);
128 /* Initialise the help (other than original help) */
129 this->text = lub_string_dup(help);
130 /* Be a good binary tree citizen */
131 lub_bintree_node_init(&this->bt_node);
132 /* It a link to command so set the link flag */
133 this->link = ref;
134
135 return this;
136 }
137
138 /*--------------------------------------------------------- */
clish_command_alias_to_link(clish_command_t * this,clish_command_t * ref)139 clish_command_t * clish_command_alias_to_link(clish_command_t *this, clish_command_t *ref)
140 {
141 clish_command_t tmp;
142
143 if (!this || !ref)
144 return NULL;
145 if (ref->alias) /* The reference is a link too */
146 return NULL;
147 memcpy(&tmp, this, sizeof(tmp));
148 *this = *ref;
149 memcpy(&this->bt_node, &tmp.bt_node, sizeof(tmp.bt_node));
150 this->name = lub_string_dup(tmp.name); /* Save an original name */
151 this->text = lub_string_dup(tmp.text); /* Save an original help */
152 this->link = ref;
153 this->pview = tmp.pview; /* Save an original parent view */
154 clish_command_fini(&tmp);
155
156 return this;
157 }
158
159 /*---------------------------------------------------------
160 * PUBLIC METHODS
161 *--------------------------------------------------------- */
clish_command_delete(clish_command_t * this)162 void clish_command_delete(clish_command_t * this)
163 {
164 clish_command_fini(this);
165 free(this);
166 }
167
168 /*--------------------------------------------------------- */
clish_command_insert_param(clish_command_t * this,clish_param_t * param)169 void clish_command_insert_param(clish_command_t * this, clish_param_t * param)
170 {
171 clish_paramv_insert(this->paramv, param);
172 }
173
174 /*--------------------------------------------------------- */
clish_command_help(const clish_command_t * this)175 int clish_command_help(const clish_command_t *this)
176 {
177 this = this; /* Happy compiler */
178
179 return 0;
180 }
181
182 /*--------------------------------------------------------- */
clish_command_choose_longest(clish_command_t * cmd1,clish_command_t * cmd2)183 clish_command_t *clish_command_choose_longest(clish_command_t * cmd1,
184 clish_command_t * cmd2)
185 {
186 unsigned len1 = (cmd1 ? strlen(clish_command__get_name(cmd1)) : 0);
187 unsigned len2 = (cmd2 ? strlen(clish_command__get_name(cmd2)) : 0);
188
189 if (len2 < len1) {
190 return cmd1;
191 } else if (len1 < len2) {
192 return cmd2;
193 } else {
194 /* let local view override */
195 return cmd1;
196 }
197 }
198
199 /*--------------------------------------------------------- */
clish_command_diff(const clish_command_t * cmd1,const clish_command_t * cmd2)200 int clish_command_diff(const clish_command_t * cmd1,
201 const clish_command_t * cmd2)
202 {
203 if (NULL == cmd1) {
204 if (NULL != cmd2)
205 return 1;
206 else
207 return 0;
208 }
209 if (NULL == cmd2)
210 return -1;
211
212 return lub_string_nocasecmp(clish_command__get_name(cmd1),
213 clish_command__get_name(cmd2));
214 }
215
216 /*---------------------------------------------------------
217 * PUBLIC ATTRIBUTES
218 *--------------------------------------------------------- */
clish_command__get_name(const clish_command_t * this)219 const char *clish_command__get_name(const clish_command_t * this)
220 {
221 if (!this)
222 return NULL;
223 return this->name;
224 }
225
226 /*--------------------------------------------------------- */
clish_command__get_text(const clish_command_t * this)227 const char *clish_command__get_text(const clish_command_t * this)
228 {
229 return this->text;
230 }
231
232 /*--------------------------------------------------------- */
clish_command__get_detail(const clish_command_t * this)233 const char *clish_command__get_detail(const clish_command_t * this)
234 {
235 return this->detail;
236 }
237
238 /*--------------------------------------------------------- */
clish_command__set_detail(clish_command_t * this,const char * detail)239 void clish_command__set_detail(clish_command_t * this, const char *detail)
240 {
241 assert(NULL == this->detail);
242 this->detail = lub_string_dup(detail);
243 }
244
245 /*--------------------------------------------------------- */
clish_command__get_action(const clish_command_t * this)246 clish_action_t *clish_command__get_action(const clish_command_t *this)
247 {
248 return this->action;
249 }
250
251 /*--------------------------------------------------------- */
clish_command__get_config(const clish_command_t * this)252 clish_config_t *clish_command__get_config(const clish_command_t *this)
253 {
254 return this->config;
255 }
256
257 /*--------------------------------------------------------- */
clish_command__set_viewname(clish_command_t * this,const char * viewname)258 void clish_command__set_viewname(clish_command_t * this, const char *viewname)
259 {
260 assert(NULL == this->viewname);
261 clish_command__force_viewname(this, viewname);
262 }
263
264 /*--------------------------------------------------------- */
clish_command__force_viewname(clish_command_t * this,const char * viewname)265 void clish_command__force_viewname(clish_command_t * this, const char *viewname)
266 {
267 if (this->viewname)
268 lub_string_free(this->viewname);
269 this->viewname = lub_string_dup(viewname);
270 }
271
272 /*--------------------------------------------------------- */
clish_command__get_viewname(const clish_command_t * this)273 char *clish_command__get_viewname(const clish_command_t * this)
274 {
275 return this->viewname;
276 }
277
278 /*--------------------------------------------------------- */
clish_command__set_viewid(clish_command_t * this,const char * viewid)279 void clish_command__set_viewid(clish_command_t * this, const char *viewid)
280 {
281 assert(NULL == this->viewid);
282 clish_command__force_viewid(this, viewid);
283 }
284
285 /*--------------------------------------------------------- */
clish_command__force_viewid(clish_command_t * this,const char * viewid)286 void clish_command__force_viewid(clish_command_t * this, const char *viewid)
287 {
288 if (this->viewid)
289 lub_string_free(this->viewid);
290 this->viewid = lub_string_dup(viewid);
291 }
292
293 /*--------------------------------------------------------- */
clish_command__get_viewid(const clish_command_t * this)294 char *clish_command__get_viewid(const clish_command_t * this)
295 {
296 return this->viewid;
297 }
298
299 /*--------------------------------------------------------- */
clish_command__get_param(const clish_command_t * this,unsigned index)300 const clish_param_t *clish_command__get_param(const clish_command_t * this,
301 unsigned index)
302 {
303 return clish_paramv__get_param(this->paramv, index);
304 }
305
306 /*--------------------------------------------------------- */
clish_command__get_suffix(const clish_command_t * this)307 const char *clish_command__get_suffix(const clish_command_t * this)
308 {
309 return lub_string_suffix(this->name);
310 }
311
312 /*--------------------------------------------------------- */
313 void
clish_command__set_escape_chars(clish_command_t * this,const char * escape_chars)314 clish_command__set_escape_chars(clish_command_t * this,
315 const char *escape_chars)
316 {
317 assert(!this->escape_chars);
318 this->escape_chars = lub_string_dup(escape_chars);
319 }
320
321 /*--------------------------------------------------------- */
clish_command__get_escape_chars(const clish_command_t * this)322 const char *clish_command__get_escape_chars(const clish_command_t * this)
323 {
324 return this->escape_chars;
325 }
326
327 /*--------------------------------------------------------- */
clish_command__set_regex_chars(clish_command_t * this,const char * escape_chars)328 void clish_command__set_regex_chars(clish_command_t *this,
329 const char *escape_chars)
330 {
331 assert(!this->regex_chars);
332 this->regex_chars = lub_string_dup(escape_chars);
333 }
334
335 /*--------------------------------------------------------- */
clish_command__get_regex_chars(const clish_command_t * this)336 const char *clish_command__get_regex_chars(const clish_command_t *this)
337 {
338 return this->regex_chars;
339 }
340
341 /*--------------------------------------------------------- */
clish_command__set_args(clish_command_t * this,clish_param_t * args)342 void clish_command__set_args(clish_command_t * this, clish_param_t * args)
343 {
344 assert(NULL == this->args);
345 this->args = args;
346 }
347
348 /*--------------------------------------------------------- */
clish_command__get_args(const clish_command_t * this)349 clish_param_t *clish_command__get_args(const clish_command_t * this)
350 {
351 return this->args;
352 }
353
354 /*--------------------------------------------------------- */
clish_command__get_param_count(const clish_command_t * this)355 unsigned int clish_command__get_param_count(const clish_command_t * this)
356 {
357 return clish_paramv__get_count(this->paramv);
358 }
359
360 /*--------------------------------------------------------- */
clish_command__get_paramv(const clish_command_t * this)361 clish_paramv_t *clish_command__get_paramv(const clish_command_t * this)
362 {
363 return this->paramv;
364 }
365
366 /*--------------------------------------------------------- */
clish_command__set_pview(clish_command_t * this,clish_view_t * view)367 void clish_command__set_pview(clish_command_t * this, clish_view_t * view)
368 {
369 this->pview = view;
370 }
371
372 /*--------------------------------------------------------- */
clish_command__get_pview(const clish_command_t * this)373 clish_view_t *clish_command__get_pview(const clish_command_t * this)
374 {
375 return this->pview;
376 }
377
378 /*--------------------------------------------------------- */
clish_command__get_depth(const clish_command_t * this)379 int clish_command__get_depth(const clish_command_t * this)
380 {
381 if (!this->pview)
382 return 0;
383 return clish_view__get_depth(this->pview);
384 }
385
386 /*--------------------------------------------------------- */
clish_command__get_restore(const clish_command_t * this)387 clish_view_restore_e clish_command__get_restore(const clish_command_t * this)
388 {
389 if (!this->pview)
390 return CLISH_RESTORE_NONE;
391 return clish_view__get_restore(this->pview);
392 }
393
394 /*--------------------------------------------------------- */
clish_command__get_orig(const clish_command_t * this)395 const clish_command_t * clish_command__get_orig(const clish_command_t * this)
396 {
397 if (this->link)
398 return clish_command__get_orig(this->link);
399 return this;
400 }
401
402 /*--------------------------------------------------------- */
clish_command__get_lock(const clish_command_t * this)403 bool_t clish_command__get_lock(const clish_command_t * this)
404 {
405 return this->lock;
406 }
407
408 /*--------------------------------------------------------- */
clish_command__set_lock(clish_command_t * this,bool_t lock)409 void clish_command__set_lock(clish_command_t * this, bool_t lock)
410 {
411 this->lock = lock;
412 }
413
414 /*--------------------------------------------------------- */
clish_command__set_alias(clish_command_t * this,const char * alias)415 void clish_command__set_alias(clish_command_t * this, const char * alias)
416 {
417 if (this->alias)
418 lub_string_free(this->alias);
419 this->alias = lub_string_dup(alias);
420 }
421
422 /*--------------------------------------------------------- */
clish_command__get_alias(const clish_command_t * this)423 const char * clish_command__get_alias(const clish_command_t * this)
424 {
425 return this->alias;
426 }
427
428 /*--------------------------------------------------------- */
clish_command__set_alias_view(clish_command_t * this,const char * alias_view)429 void clish_command__set_alias_view(clish_command_t *this,
430 const char *alias_view)
431 {
432 if (this->alias_view)
433 lub_string_free(this->alias_view);
434 this->alias_view = lub_string_dup(alias_view);
435 }
436
437 /*--------------------------------------------------------- */
clish_command__get_alias_view(const clish_command_t * this)438 const char * clish_command__get_alias_view(const clish_command_t * this)
439 {
440 return this->alias_view;
441 }
442
443 /*--------------------------------------------------------- */
clish_command__set_dynamic(clish_command_t * this,bool_t dynamic)444 void clish_command__set_dynamic(clish_command_t * this, bool_t dynamic)
445 {
446 this->dynamic = dynamic;
447 }
448
449 /*--------------------------------------------------------- */
clish_command__get_dynamic(const clish_command_t * this)450 bool_t clish_command__get_dynamic(const clish_command_t * this)
451 {
452 return this->dynamic;
453 }
454
455 /*--------------------------------------------------------- */
clish_command__set_internal(clish_command_t * this,bool_t internal)456 void clish_command__set_internal(clish_command_t * this, bool_t internal)
457 {
458 this->internal = internal;
459 }
460
461 /*--------------------------------------------------------- */
clish_command__get_internal(const clish_command_t * this)462 bool_t clish_command__get_internal(const clish_command_t * this)
463 {
464 return this->internal;
465 }
466
467 /*--------------------------------------------------------- */
clish_command__get_cmd(const clish_command_t * this)468 const clish_command_t * clish_command__get_cmd(const clish_command_t * this)
469 {
470 if (!this->dynamic)
471 return this;
472 if (this->link)
473 return clish_command__get_cmd(this->link);
474 return NULL;
475 }
476
477 /*--------------------------------------------------------- */
clish_command__get_interrupt(const clish_command_t * this)478 bool_t clish_command__get_interrupt(const clish_command_t * this)
479 {
480 return this->interrupt;
481 }
482
483 /*--------------------------------------------------------- */
clish_command__set_interrupt(clish_command_t * this,bool_t interrupt)484 void clish_command__set_interrupt(clish_command_t * this, bool_t interrupt)
485 {
486 this->interrupt = interrupt;
487 }
488
489 /*--------------------------------------------------------- */
clish_command__set_access(clish_command_t * this,const char * access)490 void clish_command__set_access(clish_command_t *this, const char *access)
491 {
492 if (this->access)
493 lub_string_free(this->access);
494 this->access = lub_string_dup(access);
495 }
496
497 /*--------------------------------------------------------- */
clish_command__get_access(const clish_command_t * this)498 char *clish_command__get_access(const clish_command_t *this)
499 {
500 return this->access;
501 }
502