]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
Enable expression evaluation for numeric command line args
authorLeo C <erbl259-lmu@yahoo.de>
Tue, 21 Jun 2016 11:18:19 +0000 (13:18 +0200)
committerLeo C <erbl259-lmu@yahoo.de>
Tue, 21 Jun 2016 15:14:07 +0000 (17:14 +0200)
avr/Tupfile
avr/cmd_mem.c
avr/command.c
avr/command_tbl.c
avr/eval_arg.c [new file with mode: 0644]
include/command.h
include/eval_arg.h [new file with mode: 0644]

index 0eb910acd450541a899efa2d931ce0a55cfae95c..d41de254de17d8d473aac5151047f96bc5a13d98 100644 (file)
@@ -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
index 4fe941556205d05121fd0a6ba4e1b01abe0c58a2..2ddeab79a52a6a9a1ec00f10b4f04db314c1b693 100644 (file)
@@ -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);
index 5499b9d08716d79a06268936bdddf927a00e7a19..cd2ee39c81be86cc8035e4a738c4697db7174ec8 100644 (file)
  *  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);
index 8c3fb7656bb64b4127da966523aeeb7bc7b6d8e0..ed14db9e259ff18d48ef7460118a29781a2711f0 100644 (file)
@@ -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 (file)
index 0000000..020dd98
--- /dev/null
@@ -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;
+}
index db469e314f7ed8af865a571c2ece8970b3d2ecce..9ca460df4284a076a5179a46fef63bde45258572 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "common.h"
 #include "config.h"
+#include <setjmp.h>
 
 #ifndef NULL
 #define NULL   0
@@ -160,5 +161,7 @@ typedef command_ret_t (*do_cmd_t)(cmd_tbl_t *, int, int, char * const []);
 
 extern  cmd_tbl_t cmd_tbl[];
 
+extern jmp_buf cmd_jbuf;
+
 
 #endif /* __COMMAND_H */
diff --git a/include/eval_arg.h b/include/eval_arg.h
new file mode 100644 (file)
index 0000000..a86b0d5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * (C) Copyright 2016 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef EVAL_ARG_H
+#define EVAL_ARG_H
+
+/**
+ * eval_arg() - evaluate a command argument expression
+ *
+ * @arg: pointer to argument (usually argv[i])
+ * @end_ptr: pointer to position, where evaluation stopped. Points to '\0' if no error.
+ * @return evaluated argument
+ */
+long eval_arg(char *arg, char **end_ptr);
+
+#endif /* EVAL_ARG_H */