shell: separate code

tags/0.1.0
S.J.R. van Schaik 7 years ago
parent 422ef6ae51
commit eb41dd93db
  1. 3
      Makefile
  2. 4
      include/shell.h
  3. 81
      source/shell/cmd.c
  4. 210
      source/shell/flash.c

@ -17,7 +17,8 @@ CFLAGS += -Wall -Wundef -Wextra -Wshadow -Wimplicit-function-declaration
CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
obj-y += source/main.o
obj-y += source/shell.o
obj-y += source/shell/cmd.o
obj-y += source/shell/flash.o
obj-y += source/core/flash.o

@ -2,7 +2,9 @@
struct cmd {
const char *key;
void (* exec)(const char *s);
void (* exec)(const char *line);
};
void do_flash_cmd(const char *line);
void cmd_exec(struct cmd *cmds, const char *line);
void cmd_loop(const char *s);

@ -0,0 +1,81 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <shell.h>
struct cmd main_cmds[] = {
{ "flash", do_flash_cmd },
{ NULL, NULL },
};
static char *prompt(const char *prefix)
{
char *alloc, *line, *s;
size_t nbytes = 0, nalloc_bytes = 16;
char c;
printf(prefix);
if (!(line = malloc(nalloc_bytes)))
return NULL;
s = line;
while ((c = getchar()) && c != '\n') {
putchar(c);
if (nbytes + 1 >= nalloc_bytes) {
nalloc_bytes *= 2;
if (!(alloc = realloc(line, nalloc_bytes)))
goto err_free_line;
line = alloc;
}
*s++ = c;
nbytes++;
}
printf("\n");
*s = '\0';
return line;
err_free_line:
free(line);
return NULL;
}
void cmd_exec(struct cmd *cmds, const char *line)
{
struct cmd *cmd;
const char *args;
char *key;
size_t n;
n = strcspn(line, " \n");
key = strndup(line, n);
args = line + n;
args += strspn(args, " \n");
for (cmd = cmds; cmd->key; ++cmd) {
if (strcmp(cmd->key, key) == 0) {
cmd->exec(args);
return;
}
}
}
void cmd_loop(const char *show)
{
char *line;
while (1) {
line = prompt(show);
cmd_exec(main_cmds, line);
free(line);
}
}

@ -0,0 +1,210 @@
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <flash.h>
#include <macros.h>
#include <shell.h>
static void do_flash_probe(const char *s);
static void do_flash_read(const char *s);
static void do_flash_write(const char *s);
static void do_flash_erase(const char *s);
static struct cmd flash_cmds[] = {
{ "probe", do_flash_probe },
{ "read", do_flash_read },
{ "write", do_flash_write },
{ "erase", do_flash_erase },
{ NULL, NULL },
};
static struct flash_dev *flash = NULL;
/* TODO: implement a parser for hex arrays that is more user-friendly.
* Also implement dry runs for programmers. */
static void parse_hex(FILE *fp, char *buf, size_t len)
{
size_t i;
char s[3];
for (i = 0; i < len; ++i) {
memset(s, '\0', 3);
while ((s[0] = getc(fp)) && !isxdigit(s[0]))
putchar(s[0]);
putchar(s[0]);
while ((s[1] = getc(fp)) && !isxdigit(s[1]))
putchar(s[1]);
putchar(s[1]);
*buf++ = strtoul(s, NULL, 16);
}
}
static void print_hex_ascii(const char *buf, size_t len)
{
size_t n, i;
uint8_t c;
for (; len; buf += n, len -= n) {
n = min(len, 16);
for (i = 0; i < 16; ++i) {
c = (i < n) ? buf[i] : 0;
printf("%x", c);
}
printf(" ");
for (i = 0; i < 16; ++i) {
c = (i < n) ? buf[i] : 0;
printf("%c", isalnum(c) ? c : '.');
}
printf("\n");
}
}
static void do_flash_probe(const char *s)
{
(void)s;
flash = flash_probe();
}
static void do_flash_read(const char *s)
{
char buf[256], *end = NULL;
size_t addr, len, nbytes;
if (!flash) {
fprintf(stderr, "error: no flash device probed.\n");
return;
}
if (strncmp(s, "0x", 2) == 0)
s += 2;
addr = strtoull(s, &end, 16);
s = end;
if (errno == EINVAL || errno == ERANGE)
return;
s += strspn(s, " \n");
if (strncmp(s, "0x", 2) == 0)
s += 2;
len = strtoull(s, &end, 16);
s = end;
if (errno == EINVAL || errno == ERANGE)
return;
if (!len)
return;
while (len) {
nbytes = min(len, 256);
flash_read(flash, addr, buf, nbytes);
print_hex_ascii(buf, nbytes);
addr += nbytes;
len -= nbytes;
}
}
static void do_flash_write(const char *s)
{
char buf[256], *end = NULL;
size_t addr, len, nbytes;
if (!flash) {
fprintf(stderr, "error: no flash device probed.\n");
return;
}
if (strncmp(s, "0x", 2) == 0)
s += 2;
addr = strtoull(s, &end, 16);
s = end;
if (errno == EINVAL || errno == ERANGE)
return;
s += strspn(s, " \n");
if (strncmp(s, "0x", 2) == 0)
s += 2;
len = strtoull(s, &end, 16);
s = end;
if (errno == EINVAL || errno == ERANGE)
return;
if (!len)
return;
while (len) {
nbytes = (len > 256) ? 256 : len;
parse_hex(stdin, buf, nbytes);
printf("\n");
print_hex_ascii(buf, nbytes);
flash_write(flash, addr, buf, nbytes);
addr += nbytes;
len -= nbytes;
}
}
static void do_flash_erase(const char *s)
{
char *end = NULL;
size_t addr, len;
if (!flash) {
fprintf(stderr, "error: no flash device probed.\n");
return;
}
if (strncmp(s, "0x", 2) == 0)
s += 2;
addr = strtoull(s, &end, 16);
s = end;
if (errno == EINVAL || errno == ERANGE)
return;
s += strspn(s, " \n");
if (strncmp(s, "0x", 2) == 0)
s += 2;
len = strtoull(s, &end, 16);
s = end;
if (errno == EINVAL || errno == ERANGE)
return;
if (!len)
return;
flash_erase(flash, addr, len);
}
void do_flash_cmd(const char *line)
{
cmd_exec(flash_cmds, line);
}
Loading…
Cancel
Save