9
0
Fork 0

improve complete support

The following patch serie improve the complete support
 by adding a complete framework to aalow commands complete support.
 
 The add also car complete support for eval and setting and executable
 file support
 
 This also include an update of the stringlist API to support asprintf
 API
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJPnohsAAoJEOrjwV5ZMRf2qeIQAIC7WrIao0mB2pIB+51MqeU+
 sof7GLxUl0MWXFFc3OFEHDcY5grC867mBmB9+uDG1mvcxa/bUpw+jMRMrki5j4Kg
 mjaHQ2UCvDjMHqQi7ISc/WTyJb09mtduFIceP0EftAmG8Mb5n9XOMaKwL9r/UQHB
 ps9MijnI/QeFqbrmBZcuaCp59QsPvipYw8NMJITBu2VvWrpKTIox33qPfNATDuEV
 SzMoLwz+uD7W7dEAM/A1uFdo4K5fLyZruDVGQoQ8CRS+zW3E6rr/EakpN5mhr/66
 dVZYO1xWppBaefIJQ1RD6bvwlFvesuuvQmMtDxsCsp07fyBolEWfFzblrwdkbueY
 NPwWExV5nzbRdAKKSyhU/nHiQ2edOQQZtHDAbnM4zh5e6lK7YLrzVklzT4Dfhzn0
 GRdnjCmiQiaZdmAEHe8wte2nr3Lc01fTsj/EFVA+LYP3a9by1iG2Zn3/ChieVcN4
 R+o/2lMBdhxsTszcmwMOemdqVPlt/0VmEXrKGtjTIZEViuQyyhY8ZtEaf4C0zeln
 Jf60t0ZvkehAJc0Lo4UOygjzvErqcKoHMk7utAjP+bi1KcMgF3Q+HmtCnJJs2FHw
 c40FZj1WcLPStEiS1way7miBakxOy2zPumKi1OXx+140L25C1nvQPYu8ilOZHEyU
 opNlo+wQ8h5sG/054kYL
 =rYfw
 -----END PGP SIGNATURE-----

Merge tag 'complete_update_support' of git://git.jcrosoft.org/barebox into next

improve complete support

The following patch serie improve the complete support
by adding a complete framework to allow commands complete support.

The add also car complete support for eval and setting and executable
file support

This also include an update of the stringlist API to support asprintf
API
This commit is contained in:
Sascha Hauer 2012-05-01 21:41:59 +02:00
commit e4e3fbd22b
30 changed files with 312 additions and 34 deletions

View File

@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#define CPU_ARCH_UNKNOWN 0
#define CPU_ARCH_ARMv3 1
@ -181,5 +182,6 @@ static int do_cpuinfo(int argc, char *argv[])
BAREBOX_CMD_START(cpuinfo)
.cmd = do_cpuinfo,
.usage = "Show info about CPU",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -24,6 +24,7 @@
#include <asm-generic/div64.h>
#include <common.h>
#include <command.h>
#include <complete.h>
#include <mach/clock.h>
/*
@ -80,5 +81,6 @@ static int do_clocks(int argc, char *argv[])
BAREBOX_CMD_START(dump_clocks)
.cmd = do_clocks,
.usage = "show clock frequencies",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -19,6 +19,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
extern void imx_dump_clocks(void);
@ -32,4 +33,5 @@ static int do_clocks(int argc, char *argv[])
BAREBOX_CMD_START(dump_clocks)
.cmd = do_clocks,
.usage = "show clock frequencies",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <readkey.h>
static int do_clear(int argc, char *argv[])
@ -39,4 +40,5 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(clear)
.cmd = do_clear,
.usage = "clear screen",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
static int do_false(int argc, char *argv[])
{
@ -32,5 +33,6 @@ static int do_false(int argc, char *argv[])
BAREBOX_CMD_START(false)
.cmd = do_false,
.usage = "do nothing, unsuccessfully",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -25,6 +25,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <fs.h>
#include <fcntl.h>
#include <linux/ctype.h>
@ -91,4 +92,5 @@ BAREBOX_CMD_START(go)
.cmd = do_go,
.usage = "start application at address or file",
BAREBOX_CMD_HELP(cmd_go_help)
BAREBOX_CMD_COMPLETE(cammand_var_complete)
BAREBOX_CMD_END

View File

@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
/*
* Use puts() instead of printf() to avoid printf buffer overflow
@ -68,5 +69,6 @@ BAREBOX_CMD_START(help)
.aliases = help_aliases,
.usage = "print online help",
BAREBOX_CMD_HELP(cmd_help_help)
BAREBOX_CMD_COMPLETE(command_complete)
BAREBOX_CMD_END

View File

@ -20,6 +20,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <password.h>
#include <getopt.h>
@ -80,4 +81,5 @@ BAREBOX_CMD_START(login)
.cmd = do_login,
.usage = "login",
BAREBOX_CMD_HELP(cmd_login_help)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -1,5 +1,6 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <module.h>
static int do_lsmod(int argc, char *argv[])
@ -15,4 +16,5 @@ static int do_lsmod(int argc, char *argv[])
BAREBOX_CMD_START(lsmod)
.cmd = do_lsmod,
.usage = "list modules",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -21,6 +21,7 @@
*/
#include <common.h>
#include <command.h>
#include <complete.h>
#include <malloc.h>
static int do_meminfo(int argc, char *argv[])
@ -33,4 +34,5 @@ static int do_meminfo(int argc, char *argv[])
BAREBOX_CMD_START(meminfo)
.cmd = do_meminfo,
.usage = "print info about memory usage",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -28,6 +28,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <environment.h>
#include <driver.h>
#include <net.h>
@ -96,5 +97,6 @@ BAREBOX_CMD_START(ethact)
.cmd = do_ethact,
.usage = "set current ethernet device",
BAREBOX_CMD_HELP(cmd_ethact_help)
BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_END

View File

@ -32,6 +32,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <driver.h>
#include <malloc.h>
#include <partition.h>
@ -225,5 +226,6 @@ BAREBOX_CMD_START(delpart)
.cmd = do_delpart,
.usage = "delete partition(s)",
BAREBOX_CMD_HELP(cmd_delpart_help)
BAREBOX_CMD_COMPLETE(devfs_partition_complete)
BAREBOX_CMD_END

View File

@ -20,6 +20,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <password.h>
#include <errno.h>
@ -95,4 +96,5 @@ BAREBOX_CMD_START(passwd)
.cmd = do_passwd,
.usage = "passwd",
BAREBOX_CMD_HELP(cmd_passwd_help)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -21,6 +21,7 @@
*/
#include <common.h>
#include <command.h>
#include <complete.h>
#include <fs.h>
static int do_pwd(int argc, char *argv[])
@ -32,4 +33,5 @@ static int do_pwd(int argc, char *argv[])
BAREBOX_CMD_START(pwd)
.cmd = do_pwd,
.usage = "print working directory",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
static int do_reginfo(int argc, char *argv[])
{
@ -32,4 +33,5 @@ static int do_reginfo(int argc, char *argv[])
BAREBOX_CMD_START(reginfo)
.cmd = do_reginfo,
.usage = "print register information",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
static int cmd_reset(int argc, char *argv[])
{
@ -34,4 +35,5 @@ static int cmd_reset(int argc, char *argv[])
BAREBOX_CMD_START(reset)
.cmd = cmd_reset,
.usage = "Perform RESET of the CPU",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <clock.h>
static int do_sleep(int argc, char *argv[])
@ -46,4 +47,5 @@ static int do_sleep(int argc, char *argv[])
BAREBOX_CMD_START(sleep)
.cmd = do_sleep,
.usage = "delay execution for n seconds",
BAREBOX_CMD_COMPLETE(cammand_var_complete)
BAREBOX_CMD_END

View File

@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
static int do_true(int argc, char *argv[])
{
@ -32,5 +33,6 @@ static int do_true(int argc, char *argv[])
BAREBOX_CMD_START(true)
.cmd = do_true,
.usage = "do nothing, successfully",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -21,6 +21,7 @@
*/
#include <common.h>
#include <command.h>
#include <complete.h>
#include <usb/usb.h>
#include <getopt.h>
@ -56,4 +57,5 @@ BAREBOX_CMD_START(usb)
.cmd = do_usb,
.usage = "(re-)detect USB devices",
BAREBOX_CMD_HELP(cmd_usb_help)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
static int do_version(int argc, char *argv[])
{
@ -33,5 +34,6 @@ static int do_version(int argc, char *argv[])
BAREBOX_CMD_START(version)
.cmd = do_version,
.usage = "print monitor version",
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END

View File

@ -20,16 +20,13 @@
#include <common.h>
#include <complete.h>
#include <xfuncs.h>
#include <linux/list.h>
#include <malloc.h>
#include <fs.h>
#include <linux/stat.h>
#include <libgen.h>
#include <command.h>
#include <stringlist.h>
#include <environment.h>
static int file_complete(struct string_list *sl, char *instr)
static int file_complete(struct string_list *sl, char *instr, int exec)
{
char *path = strdup(instr);
struct stat s;
@ -49,15 +46,20 @@ static int file_complete(struct string_list *sl, char *instr)
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (!strncmp(base, d->d_name, strlen(base))) {
strcpy(tmp, instr);
strcat(tmp, d->d_name + strlen(base));
if (!stat(tmp, &s) && S_ISDIR(s.st_mode))
strcat(tmp, "/");
else
strcat(tmp, " ");
string_list_add_sorted(sl, tmp);
if (strncmp(base, d->d_name, strlen(base)))
continue;
strcpy(tmp, instr);
strcat(tmp, d->d_name + strlen(base));
if (!stat(tmp, &s) && S_ISDIR(s.st_mode)) {
strcat(tmp, "/");
} else {
if (exec && !S_ISREG(s.st_mode))
continue;
strcat(tmp, " ");
}
string_list_add_sorted(sl, tmp);
}
closedir(dir);
@ -131,17 +133,128 @@ static int path_command_complete(struct string_list *sl, char *instr)
return 0;
}
static int command_complete(struct string_list *sl, char *instr)
int command_complete(struct string_list *sl, char *instr)
{
struct command *cmdtp;
char cmd[128];
if (!instr)
instr = "";
for_each_command(cmdtp) {
if (!strncmp(instr, cmdtp->name, strlen(instr))) {
strcpy(cmd, cmdtp->name);
cmd[strlen(cmdtp->name)] = ' ';
cmd[strlen(cmdtp->name) + 1] = 0;
string_list_add(sl, cmd);
if (strncmp(instr, cmdtp->name, strlen(instr)))
continue;
string_list_add_asprintf(sl, "%s ", cmdtp->name);
}
return 0;
}
int device_complete(struct string_list *sl, char *instr)
{
struct device_d *dev;
int len;
if (!instr)
instr = "";
len = strlen(instr);
for_each_device(dev) {
if (strncmp(instr, dev_name(dev), len))
continue;
string_list_add_asprintf(sl, "%s ", dev_name(dev));
}
return COMPLETE_CONTINUE;
}
static int device_param_complete(char *begin, struct device_d *dev,
struct string_list *sl, char *instr)
{
struct param_d *param;
int len;
if (!instr)
instr = "";
len = strlen(instr);
list_for_each_entry(param, &dev->parameters, list) {
if (strncmp(instr, param->name, len))
continue;
string_list_add_asprintf(sl, "%s%s.%s%c",
begin ? begin : "", dev_name(dev), param->name,
begin ? ' ' : '=');
}
return 0;
}
int empty_complete(struct string_list *sl, char *instr)
{
return COMPLETE_END;
}
int cammand_var_complete(struct string_list *sl, char *instr)
{
return COMPLETE_CONTINUE;
}
static int env_param_complete(struct string_list *sl, char *instr, int eval)
{
struct device_d *dev;
struct variable_d *var;
struct env_context *c, *current_c;
char *instr_param;
int len;
char end = '=';
char *begin = "";
if (!instr)
instr = "";
if (eval) {
begin = "$";
end = ' ';
}
instr_param = strrchr(instr, '.');
len = strlen(instr);
current_c = get_current_context();
for(var = current_c->local->next; var; var = var->next) {
if (strncmp(instr, var_name(var), len))
continue;
string_list_add_asprintf(sl, "%s%s%c",
begin, var_name(var), end);
}
for (c = get_current_context(); c; c = c->parent) {
for (var = c->global->next; var; var = var->next) {
if (strncmp(instr, var_name(var), len))
continue;
string_list_add_asprintf(sl, "%s%s%c",
begin, var_name(var), end);
}
}
if (instr_param) {
len = (instr_param - instr);
instr_param++;
} else {
len = strlen(instr);
instr_param = "";
}
for_each_device(dev) {
if (!strncmp(instr, dev_name(dev), len)) {
if (eval)
device_param_complete("$", dev, sl, instr_param);
else
device_param_complete(NULL, dev, sl, instr_param);
}
}
@ -155,6 +268,32 @@ void complete_reset(void)
tab_pressed = 0;
}
static char* cmd_complete_lookup(struct string_list *sl, char *instr)
{
struct command *cmdtp;
int len;
int ret = 1;
char *res = NULL;
for_each_command(cmdtp) {
len = strlen(cmdtp->name);
if (!strncmp(instr, cmdtp->name, len) && instr[len] == ' ') {
instr += len + 1;
if (cmdtp->complete) {
ret = cmdtp->complete(sl, instr);
res = instr;
}
goto end;
}
}
end:
if (ret == COMPLETE_CONTINUE && *instr == '$')
env_param_complete(sl, instr + 1, 1);
return res;
}
int complete(char *instr, char **outstr)
{
struct string_list sl, *entry, *first_entry;
@ -178,16 +317,24 @@ int complete(char *instr, char **outstr)
while (*t == ' ')
t++;
instr = t;
/* get the completion possibilities */
if ((t = strrchr(t, ' '))) {
t++;
file_complete(&sl, t);
instr = cmd_complete_lookup(&sl, t);
if (!instr) {
instr = t;
} else {
command_complete(&sl, instr);
path_command_complete(&sl, instr);
if (t && (t[0] == '/' || !strncmp(t, "./", 2))) {
file_complete(&sl, t, 1);
instr = t;
} else if ((t = strrchr(t, ' '))) {
t++;
file_complete(&sl, t, 0);
instr = t;
} else {
command_complete(&sl, instr);
path_command_complete(&sl, instr);
env_param_complete(&sl, instr, 0);
}
if (*instr == '$')
env_param_complete(&sl, instr + 1, 1);
}
pos = strlen(instr);

View File

@ -33,6 +33,7 @@
#include <errno.h>
#include <fs.h>
#include <linux/list.h>
#include <complete.h>
LIST_HEAD(device_list);
EXPORT_SYMBOL(device_list);
@ -443,6 +444,7 @@ BAREBOX_CMD_START(devinfo)
.cmd = do_devinfo,
.usage = "Show information about devices and drivers.",
BAREBOX_CMD_HELP(cmd_devinfo_help)
BAREBOX_CMD_COMPLETE(device_complete)
BAREBOX_CMD_END
#endif

View File

@ -18,6 +18,7 @@
/* #define VERBOSE_DEBUG */
#include <common.h>
#include <complete.h>
#include <usb/cdc.h>
#include <kfifo.h>
#include <clock.h>
@ -502,6 +503,7 @@ static int do_mycdev(int argc, char *argv[])
BAREBOX_CMD_START(mycdev)
.cmd = do_mycdev,
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
/**

View File

@ -20,6 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <common.h>
#include <complete.h>
#include <driver.h>
#include <errno.h>
#include <malloc.h>
@ -29,6 +30,24 @@
LIST_HEAD(cdev_list);
#ifdef CONFIG_AUTO_COMPLETE
int devfs_partition_complete(struct string_list *sl, char *instr)
{
struct cdev *cdev;
int len;
len = strlen(instr);
list_for_each_entry(cdev, &cdev_list, list) {
if (cdev->flags & DEVFS_IS_PARTITION &&
!strncmp(instr, cdev->name, len)) {
string_list_add_asprintf(sl, "%s ", cdev->name);
}
}
return COMPLETE_CONTINUE;
}
#endif
struct cdev *cdev_by_name(const char *filename)
{
struct cdev *cdev;

View File

@ -40,6 +40,8 @@ extern struct list_head command_list;
#define for_each_command(cmd) list_for_each_entry(cmd, &command_list, list)
struct string_list;
/*
* Monitor Command Table
*/
@ -48,6 +50,7 @@ struct command {
const char **aliases;
/* Implementation function */
int (*cmd)(int, char *[]);
int (*complete)(struct string_list *sl, char *instr);
const char *usage; /* Usage message (short) */
struct list_head list; /* List of commands */
@ -88,6 +91,11 @@ const struct command __barebox_cmd_##_name \
#define BAREBOX_CMD_END \
};
#ifdef CONFIG_AUTO_COMPLETE
#define BAREBOX_CMD_COMPLETE(_cpt) .complete = _cpt,
#else
#define BAREBOX_CMD_COMPLETE(_cpt)
#endif
#define BAREBOX_CMD_HELP_START(_name) \
static const __maybe_unused char cmd_##_name##_help[] =

View File

@ -2,9 +2,21 @@
#define __COMPLETE_
#include <linux/list.h>
#include <malloc.h>
#include <stringlist.h>
#define COMPLETE_END 0
#define COMPLETE_CONTINUE 1
int complete(char *instr, char **outstr);
void complete_reset(void);
int command_complete(struct string_list *sl, char *instr);
int device_complete(struct string_list *sl, char *instr);
int empty_complete(struct string_list *sl, char *instr);
int eth_complete(struct string_list *sl, char *instr);
int cammand_var_complete(struct string_list *sl, char *instr);
int devfs_partition_complete(struct string_list *sl, char *instr);
#endif /* __COMPLETE_ */

View File

@ -5,10 +5,11 @@
struct string_list {
struct list_head list;
char str[0];
char *str;
};
int string_list_add(struct string_list *sl, char *str);
int string_list_add_asprintf(struct string_list *sl, const char *fmt, ...);
int string_list_add_sorted(struct string_list *sl, char *str);
int string_list_contains(struct string_list *sl, char *str);
void string_list_print_by_column(struct string_list *sl);
@ -22,8 +23,10 @@ static inline void string_list_free(struct string_list *sl)
{
struct string_list *entry, *safe;
list_for_each_entry_safe(entry, safe, &sl->list, list)
list_for_each_entry_safe(entry, safe, &sl->list, list) {
free(entry->str);
free(entry);
}
}
#endif /* __STRING_H */

View File

@ -1,6 +1,7 @@
#include <common.h>
#include <xfuncs.h>
#include <malloc.h>
#include <errno.h>
#include <stringlist.h>
static int string_list_compare(struct list_head *a, struct list_head *b)
@ -16,9 +17,31 @@ int string_list_add(struct string_list *sl, char *str)
{
struct string_list *new;
new = xmalloc(sizeof(struct string_list) + strlen(str) + 1);
new = xmalloc(sizeof(*new));
new->str = xstrdup(str);
strcpy(new->str, str);
list_add_tail(&new->list, &sl->list);
return 0;
}
int string_list_add_asprintf(struct string_list *sl, const char *fmt, ...)
{
struct string_list *new;
va_list args;
new = xmalloc(sizeof(*new));
va_start(args, fmt);
new->str = vasprintf(fmt, args);
va_end(args);
if (!new->str) {
free(new);
return -ENOMEM;
}
list_add_tail(&new->list, &sl->list);
@ -29,9 +52,8 @@ int string_list_add_sorted(struct string_list *sl, char *str)
{
struct string_list *new;
new = xmalloc(sizeof(struct string_list) + strlen(str) + 1);
strcpy(new->str, str);
new = xmalloc(sizeof(*new));
new->str = xstrdup(str);
list_add_sort(&new->list, &sl->list, string_list_compare);

View File

@ -10,6 +10,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <environment.h>
#include <clock.h>
#include <net.h>
@ -705,6 +706,7 @@ BAREBOX_CMD_START(dhcp)
.cmd = do_dhcp,
.usage = "invoke dhcp client to obtain ip/boot params",
BAREBOX_CMD_HELP(cmd_dhcp_help)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
BAREBOX_MAGICVAR(bootfile, "bootfile returned from DHCP request");

View File

@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
#include <driver.h>
#include <init.h>
#include <net.h>
@ -109,6 +110,26 @@ struct eth_device *eth_get_byname(char *ethname)
return NULL;
}
#ifdef CONFIG_AUTO_COMPLETE
int eth_complete(struct string_list *sl, char *instr)
{
struct eth_device *edev;
const char *devname;
int len;
len = strlen(instr);
list_for_each_entry(edev, &netdev_list, list) {
devname = dev_name(&edev->dev);
if (strncmp(instr, devname, len))
continue;
string_list_add_asprintf(sl, "%s ", devname);
}
return COMPLETE_CONTNINUE;
}
#endif
int eth_send(void *packet, int length)
{
int ret;