summaryrefslogtreecommitdiff
path: root/avr
diff options
context:
space:
mode:
authorLeo C2016-06-21 13:18:19 +0200
committerLeo C2016-06-21 17:14:07 +0200
commitfcd2239eb2849432269ba4456718b657fdff3972 (patch)
tree12b010a2fc7f5be9b42eb856af072dcad1cad49b /avr
parentccb6ffb997835073a650faeac61b2fcdf2f74503 (diff)
downloadz180-stamp-fcd2239eb2849432269ba4456718b657fdff3972.zip
Enable expression evaluation for numeric command line args
Diffstat (limited to 'avr')
-rw-r--r--avr/Tupfile3
-rw-r--r--avr/cmd_mem.c66
-rw-r--r--avr/command.c9
-rw-r--r--avr/command_tbl.c9
-rw-r--r--avr/eval_arg.c161
5 files changed, 216 insertions, 32 deletions
diff --git a/avr/Tupfile b/avr/Tupfile
index 0eb910a..d41de25 100644
--- a/avr/Tupfile
+++ b/avr/Tupfile
@@ -9,7 +9,8 @@ SRC += cli.c cli_readline.c command.c command_tbl.c
SRC += cmd_help.c cmd_run.c cmd_boot.c cmd_misc.c
SRC += cmd_date.c cmd_mem.c cmd_gpio.c cmd_attach.c
SRC += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c
-SRC += env.c xmalloc.c con-utils.c print-utils.c getopt-min.c
+SRC += env.c xmalloc.c con-utils.c print-utils.c
+SRC += getopt-min.c eval_arg.c
SRC += timer.c serial.c i2c.c bcd.c pcf8583.c mmc.c
SRC += background.c z180-serv.c z80-if.c gpio.c
SRC += $(FATFS) $(TOP)/fatfs/src/option/unicode.c
diff --git a/avr/cmd_mem.c b/avr/cmd_mem.c
index 4fe9415..2ddeab7 100644
--- a/avr/cmd_mem.c
+++ b/avr/cmd_mem.c
@@ -14,7 +14,6 @@
*/
#include "common.h"
-#include <stdlib.h>
#include <ctype.h>
#include <avr/interrupt.h>
@@ -23,6 +22,7 @@
#include "print-utils.h"
#include "con-utils.h"
#include "getopt-min.h"
+#include "eval_arg.h"
#include "timer.h"
#include "z80-if.h"
#include "debug.h"
@@ -85,12 +85,12 @@ command_ret_t do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
if ((flag & CMD_FLAG_REPEAT) == 0) {
/* Address is specified since argc > 1 */
- addr = strtoul(argv[1], NULL, 16);
+ addr = eval_arg(argv[1], NULL);
addr += base_address;
/* If another parameter, it is the length to display. */
if (argc > 2)
- length = strtoul(argv[2], NULL, 16);
+ length = eval_arg(argv[2], NULL);
}
/* Print the lines. */
@@ -136,7 +136,7 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
/* Address is specified since argc > 1
*/
- addr = strtoul(argv[1], NULL, 16);
+ addr = eval_arg(argv[1], NULL);
addr += base_address;
}
@@ -163,7 +163,7 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
} else {
char *endp;
- data = strtoul(console_buffer, &endp, 16);
+ data = eval_arg(console_buffer, &endp);
nbytes = endp - console_buffer;
if (nbytes) {
if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
@@ -227,13 +227,13 @@ command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
return CMD_RET_USAGE;
/* Address and value are specified since (adjusted) argc >= 2 */
- addr = strtoul(argv[optind++], NULL, 16);
+ addr = eval_arg(argv[optind++], NULL);
addr += base_address;
- writeval = strtoul(argv[optind++], NULL, 16);
+ writeval = eval_arg(argv[optind++], NULL);
/* Count ? */
if (argc == 3)
- count = strtoul(argv[optind], NULL, 16);
+ count = eval_arg(argv[optind], NULL);
if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
my_puts_P(PSTR("Bus timeout\n"));
@@ -262,18 +262,30 @@ command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const ar
(void) cmdtp;
(void) flag;
- if (argc < 4)
+ optind = 0;
+ if (argv[0][1] != 'd') {
+ int opt;
+ while ((opt = getopt(argc, argv, PSTR("bwl"))) != -1)
+ if (opt == '?')
+ return CMD_RET_USAGE;
+ --optind;
+ }
+
+ printf_P(PSTR("# argc: %d, optind: %d, argv[optind+3]: '%s'\n"),
+ argc, optind, argv[optind+3]);
+
+ if (argc-optind != 4)
return CMD_RET_USAGE;
- count = strtoul(argv[3], NULL, 10);
+ count = eval_arg(argv[optind + 3], NULL);
clear_ctrlc(); /* forget any previous Control C */
for (;;) {
if (argv[0][1] == 'd')
- do_mem_md (NULL, 0, 3, argv);
+ do_mem_md (NULL, 0, argc-1, argv); /* memory display */
else
- do_mem_mw (NULL, 0, 3, argv);
+ do_mem_mw (NULL, 0, argc-1, argv); /* memory write */
/* delay for <count> ms... */
@@ -304,11 +316,11 @@ command_ret_t do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
return CMD_RET_USAGE;
- addr1 = strtoul(argv[1], NULL, 16);
+ addr1 = eval_arg(argv[1], NULL);
addr1 += base_address;
- addr2 = strtoul(argv[2], NULL, 16);
+ addr2 = eval_arg(argv[2], NULL);
addr2 += base_address;
- count = strtoul(argv[3], NULL, 16);
+ count = eval_arg(argv[3], NULL);
for (ngood = 0; ngood < count; ++ngood) {
if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
@@ -351,11 +363,11 @@ command_ret_t do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
if (argc != 4)
return CMD_RET_USAGE;
- src = strtoul(argv[1], NULL, 16);
+ src = eval_arg(argv[1], NULL);
src += base_address;
- dest = strtoul(argv[2], NULL, 16);
+ dest = eval_arg(argv[2], NULL);
dest += base_address;
- count = strtoul(argv[3], NULL, 16);
+ count = eval_arg(argv[3], NULL);
if (count == 0) {
my_puts_P(PSTR("Zero length?\n"));
@@ -398,7 +410,7 @@ command_ret_t do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
if (argc > 1) {
/* Set new base address. */
- base_address = strtoul(argv[1], NULL, 16);
+ base_address = eval_arg(argv[1], NULL);
}
/* Print the current base address. */
printf_P(PSTR("Base Address: 0x%05lx\n"), base_address);
@@ -417,10 +429,10 @@ command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
/* Address is always specified. */
- addr = strtoul(argv[1], NULL, 16);
+ addr = eval_arg(argv[1], NULL);
/* Length is the number of bytes. */
- length = strtoul(argv[2], NULL, 16);
+ length = eval_arg(argv[2], NULL);
/* We want to optimize the loops to run as fast as possible.
@@ -463,12 +475,12 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
return CMD_RET_USAGE;
/* Address is always specified. */
- addr = strtoul(argv[1], NULL, 16);
+ addr = eval_arg(argv[1], NULL);
/* Length is the number of bytes. */
- length = strtoul(argv[2], NULL, 16);
+ length = eval_arg(argv[2], NULL);
- data = strtoul(argv[3], NULL, 16);
+ data = eval_arg(argv[3], NULL);
/*
* We want to optimize the loops to run as fast as possible.
@@ -739,15 +751,15 @@ command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
(void) flag;
if (argc > 1)
- start = strtoul(argv[1], NULL, 16);
+ start = eval_arg(argv[1], NULL);
if (argc > 2)
- end = strtoul(argv[2], NULL, 16);
+ end = eval_arg(argv[2], NULL);
else
end = CONFIG_SYS_RAMSIZE_MAX - 1;
if (argc > 3)
- iteration_limit = (unsigned int) strtoul(argv[3], NULL, 16);
+ iteration_limit = (unsigned int) eval_arg(argv[3], NULL);
printf_P(PSTR("Testing %05lx ... %05lx:\n"), start, end);
// debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end);
diff --git a/avr/command.c b/avr/command.c
index 5499b9d..cd2ee39 100644
--- a/avr/command.c
+++ b/avr/command.c
@@ -11,17 +11,21 @@
* Command Processor Table
*/
+#include "command.h"
#include "common.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <setjmp.h>
#include "config.h"
#include "print-utils.h"
#include "con-utils.h"
#include "env.h"
#include "debug.h"
-#include "command.h"
+
+
+jmp_buf cmd_jbuf;
static void print_usage_line(const FLASH char *name, int width,
@@ -521,6 +525,9 @@ command_ret_t cmd_process(int flag, int argc, char * const argv[],
}
#endif
+ if (setjmp(cmd_jbuf) != 0)
+ return CMD_RET_FAILURE;
+
/* If OK so far, then do the command */
if (!rc) {
rc = cmd_call(cmdtp, flag, argc, argv);
diff --git a/avr/command_tbl.c b/avr/command_tbl.c
index 8c3fb76..ed14db9 100644
--- a/avr/command_tbl.c
+++ b/avr/command_tbl.c
@@ -284,7 +284,7 @@ CMD_TBL_ITEM(
"[-bwl] address value [count]\n"
" -b write value as byte (8 bit, default)\n"
" -w write value as word (16 bit)\n"
- " -l write value as long (32 bit)\n"
+ " -l write value as long (32 bit)"
),
CMD_TBL_ITEM(
cp, 4, 1, do_mem_cp,
@@ -330,9 +330,12 @@ CMD_TBL_ITEM(
"address count delay(ms)"
),
CMD_TBL_ITEM(
- mwc, 4, 1, do_mem_mdc,
+ mwc, CONFIG_SYS_MAXARGS, 1, do_mem_mdc,
"memory write cyclic",
- "address value delay(ms)"
+ "[-bwl] address value delay(ms)\n"
+ " -b write value as byte (8 bit, default)\n"
+ " -w write value as word (16 bit)\n"
+ " -l write value as long (32 bit)"
),
#endif /* CONFIG_MX_CYCLIC */
diff --git a/avr/eval_arg.c b/avr/eval_arg.c
new file mode 100644
index 0000000..020dd98
--- /dev/null
+++ b/avr/eval_arg.c
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2016 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include "eval_arg.h"
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include "print-utils.h"
+#include "command.h" /* jump_buf */
+
+static jmp_buf eval_jbuf;
+static char ch;
+static char *start_p;
+static char *bp;
+
+
+static long expr(void);
+
+static void print_error_pos(void)
+{
+ printf_P(PSTR("Arg: '%s'\n"
+ " "), start_p);
+ print_blanks(bp - start_p);
+ my_puts_P(PSTR("^syntax error!\n"));
+}
+
+static void error (void)
+{
+ --bp;
+ longjmp (eval_jbuf, 1);
+}
+
+static void next(void)
+{
+ do
+ ch = *bp++;
+ while (ch == ' ' || ch == '\n');
+}
+
+static long number (void)
+{
+ int base = 16;
+ char *end_p;
+ long n;
+
+ if (ch == '$') { /* FIXME: should be '#' */
+ next();
+ base = 10;
+ }
+ if (!isdigit(ch) && !(base == 16 && isxdigit(ch)))
+ error ();
+
+ n = strtoul(bp - 1, &end_p, base);
+
+ if (end_p == bp - 1)
+ error();
+ bp = end_p;
+ next();
+
+ return n;
+}
+
+static long factor (void)
+{
+ long f;
+
+ if (ch == '(')
+ {
+ next();
+ f = expr();
+ if (ch == ')')
+ next();
+ else
+ error ();
+ }
+ else
+ f = number ();
+
+ return f;
+}
+
+static long term (void)
+{
+ long t = factor();
+
+ for (;;)
+ switch (ch) {
+ case '*':
+ next();
+ t *= factor();
+ break;
+ case '/':
+ next();
+ t /= factor();
+ break;
+ case '%':
+ next();
+ t %= factor();
+ break;
+ default:
+ return t;
+ }
+}
+
+
+static long expr(void)
+{
+ long e;
+
+ if (ch == '+') {
+ next();
+ e = term ();
+ } else if (ch == '-') {
+ next();
+ e = - term ();
+ } else
+ e = term ();
+
+ while (ch == '+' || ch == '-') {
+ char op = ch;
+ next();
+ if (op == '-')
+ e -= term ();
+ else
+ e += term ();
+ }
+ return e;
+}
+
+long eval_arg(char *arg, char **end_ptr)
+{
+ long val;
+
+ start_p = arg;
+ bp = arg;
+ next();
+ if (setjmp (eval_jbuf) != 0) {
+ if (!end_ptr) {
+ print_error_pos();
+ longjmp(cmd_jbuf, 1);
+ }
+ val = -1;
+ } else {
+ val = expr ();
+ --bp;
+ }
+
+ if (!end_ptr) {
+ if (*bp != '\0') {
+ print_error_pos();
+ longjmp(cmd_jbuf, 1);
+ }
+ } else
+ *end_ptr = bp;
+
+ return val;
+}