Skip to content

Commit

Permalink
bios: add auto completion for commands
Browse files Browse the repository at this point in the history
  • Loading branch information
fjullien committed Apr 26, 2020
1 parent a5a9adf commit 6d7345b
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 1 deletion.
2 changes: 1 addition & 1 deletion litex/soc/software/bios/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ boot-helper-$(CPU).o \
boot.o \
readline.o \
helpers.o \
complete.o \
cmd_mem_access.o \
cmd_spi_flash.o \
cmd_bios.o \
Expand All @@ -42,7 +43,6 @@ endif

bios.elf: $(BIOS_DIRECTORY)/linker.ld $(OBJECTS)


%.elf: ../libbase/crt0-$(CPU)-ctr.o ../libnet/libnet.a ../libbase/libbase-nofloat.a ../libcompiler_rt/libcompiler_rt.a
$(LD) $(LDFLAGS) -T $(BIOS_DIRECTORY)/linker.ld -N -o $@ \
../libbase/crt0-$(CPU)-ctr.o \
Expand Down
2 changes: 2 additions & 0 deletions litex/soc/software/bios/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#define __COMMAND_H__

#define MAX_PARAM 8
#define CMD_MAX_SIZE 32 /* Used in string list, complete.c */
#define MAX_CMDS 40 /* Used in string list, complete.c */

struct command_struct {
void (*func)(int nb_params, char **params);
Expand Down
174 changes: 174 additions & 0 deletions litex/soc/software/bios/complete.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// This file is Copyright (c) 2020 Franck Jullien <franck.jullien@gmail.com>
//
// Largely inspired/copied from U-boot and Barebox projects wich are:
// Sascha Hauer, Pengutronix, <s.hauer@pengutronix.de>

// License: BSD

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "readline.h"
#include "helpers.h"
#include "command.h"
#include "complete.h"

static int tab_pressed = 0;

char sl[MAX_CMDS][CMD_MAX_SIZE];
int sl_idx = 0;

char out[CMD_MAX_SIZE];

static void string_list_init(void)
{
int i;
for (i = 0; i < MAX_CMDS; i++)
sl[i][0] = 0;
}

static int string_list_add(const char *string)
{
int i;
for (i = 0; i < MAX_CMDS; i++) {
if (sl[i][0] == 0) {
strncpy(&sl[i][0], string, CMD_MAX_SIZE);
return 0;
}
}
return -1;
}

static int string_list_empty(void)
{
int i;
for (i = 0; i < MAX_CMDS; i++)
if (sl[i][0] != 0)
return 0;
return 1;
}

static int string_list_count(void)
{
int i, count = 0;
for (i = 0; i < MAX_CMDS; i++)
if (sl[i][0] != 0)
count++;
return count;
}

static char *list_first_entry(void)
{
int i;
for (i = 0; i < MAX_CMDS; i++)
if (sl[i][0] != 0)
return &sl[i][0];
return NULL;
}

static void string_list_print_by_column(void)
{
int len = 0, num, i, j;

for (i = 0; i < MAX_CMDS; i++) {
if (sl[i][0] != 0) {
int l = strlen(&sl[i][0]) + 4;
if (l > len)
len = l;
}
}

if (!len)
return;

num = 80 / (len + 1);

for (j = 0; j < MAX_CMDS; j++) {
if (sl[j][0] != 0) {
if (!(++i % num))
printf("%s\n", &sl[j][0]);
else
printf("%-*s", len, &sl[j][0]);
}
}
if (i % num)
printf("\n");
}

static void command_complete(char *instr)
{
struct command_struct * const *cmd;

for (cmd = __bios_cmd_start; cmd != __bios_cmd_end; cmd++)
if (!strncmp(instr, (*cmd)->name, strlen(instr)))
string_list_add((*cmd)->name);
}

int complete(char *instr, char **outstr)
{
int pos;
char ch;
int changed;
int outpos = 0;
int reprint = 0;
char *first_entry;
char *entry;
int i;

string_list_init();
command_complete(instr);

pos = strlen(instr);

*outstr = "";
if (string_list_empty())
reprint = 0;
else
{
out[0] = 0;

first_entry = list_first_entry();

while (1) {
entry = first_entry;
ch = entry[pos];
if (!ch)
break;

changed = 0;
for (i = 0; i < MAX_CMDS; i++) {
if (sl[i][0] != 0) {
if (!sl[i][pos])
break;
if (ch != sl[i][pos]) {
changed = 1;
break;
}
}
}

if (changed)
break;
out[outpos++] = ch;
pos++;
}

if ((string_list_count() != 1) && !outpos && tab_pressed) {
printf("\n");
string_list_print_by_column();
reprint = 1;
tab_pressed = 0;
}

out[outpos++] = 0;
*outstr = out;

if (*out == 0)
tab_pressed = 1;
else
tab_pressed = 0;
}

return reprint;
}
6 changes: 6 additions & 0 deletions litex/soc/software/bios/complete.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef __COMPLETE_H__
#define __COMPLETE_H__

int complete(char *instr, char **outstr);

#endif
25 changes: 25 additions & 0 deletions litex/soc/software/bios/readline.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <uart.h>

#include "readline.h"
#include "complete.h"

static int hist_max = 0;
static int hist_add_idx = 0;
Expand Down Expand Up @@ -188,6 +189,10 @@ int readline(char *buf, int len)
int insert = 1;
char ichar;

char tmp;
int reprint, i;
char *completestr;

while (1) {

ichar = read_key();
Expand All @@ -197,6 +202,26 @@ int readline(char *buf, int len)

switch (ichar) {
case '\t':
buf[eol_num] = 0;
tmp = buf[num];

buf[num] = 0;
reprint = complete(buf, &completestr);
buf[num] = tmp;

if (reprint) {
printf("%s%s", PROMPT, buf);

if (tmp)
for (i = 0; i < eol_num - num; i++)
getcmd_putch(CTL_BACKSPACE);
}

i = 0;
while (completestr[i])
cread_add_char(completestr[i++], insert, &num,
&eol_num, buf, len);

break;

case KEY_HOME:
Expand Down

0 comments on commit 6d7345b

Please sign in to comment.