uboot/common/cmd_itest.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003
   3 * Tait Electronics Limited, Christchurch, New Zealand
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24/*
  25 * This file provides a shell like 'test' function to return
  26 * true/false from an integer or string compare of two memory
  27 * locations or a location and a scalar/literal.
  28 * A few parts were lifted from bash 'test' command
  29 */
  30
  31#include <common.h>
  32#include <config.h>
  33#include <command.h>
  34
  35#define EQ      0
  36#define NE      1
  37#define LT      2
  38#define GT      3
  39#define LE      4
  40#define GE      5
  41
  42struct op_tbl_s {
  43        char    *op;            /* operator string */
  44        int     opcode;         /* internal representation of opcode */
  45};
  46
  47typedef struct op_tbl_s op_tbl_t;
  48
  49op_tbl_t op_table [] = {
  50        { "-lt", LT },
  51        { "<"  , LT },
  52        { "-gt", GT },
  53        { ">"  , GT },
  54        { "-eq", EQ },
  55        { "==" , EQ },
  56        { "-ne", NE },
  57        { "!=" , NE },
  58        { "<>" , NE },
  59        { "-ge", GE },
  60        { ">=" , GE },
  61        { "-le", LE },
  62        { "<=" , LE },
  63};
  64
  65#define op_tbl_size (sizeof(op_table)/sizeof(op_table[0]))
  66
  67static long evalexp(char *s, int w)
  68{
  69        long l, *p;
  70
  71        /* if the parameter starts with a * then assume is a pointer to the value we want */
  72        if (s[0] == '*') {
  73                p = (long *)simple_strtoul(&s[1], NULL, 16);
  74                l = *p;
  75        } else {
  76                l = simple_strtoul(s, NULL, 16);
  77        }
  78
  79        return (l & ((1 << (w * 8)) - 1));
  80}
  81
  82static char * evalstr(char *s)
  83{
  84        /* if the parameter starts with a * then assume a string pointer else its a literal */
  85        if (s[0] == '*') {
  86                return (char *)simple_strtoul(&s[1], NULL, 16);
  87        } else {
  88                return s;
  89        }
  90}
  91
  92static int stringcomp(char *s, char *t, int op)
  93{
  94        int n, p;
  95        char *l, *r;
  96
  97        l = evalstr(s);
  98        r = evalstr(t);
  99
 100        /* we'll do a compare based on the length of the shortest string */
 101        n = min(strlen(l), strlen(r));
 102
 103        p = strncmp(l, r, n);
 104        switch (op) {
 105        case EQ: return (p == 0);
 106        case NE: return (p != 0);
 107        case LT: return (p < 0);
 108        case GT: return (p > 0);
 109        case LE: return (p <= 0);
 110        case GE: return (p >= 0);
 111        }
 112        return (0);
 113}
 114
 115static int arithcomp (char *s, char *t, int op, int w)
 116{
 117        long l, r;
 118
 119        l = evalexp (s, w);
 120        r = evalexp (t, w);
 121
 122        switch (op) {
 123        case EQ: return (l == r);
 124        case NE: return (l != r);
 125        case LT: return (l < r);
 126        case GT: return (l > r);
 127        case LE: return (l <= r);
 128        case GE: return (l >= r);
 129        }
 130        return (0);
 131}
 132
 133int binary_test (char *op, char *arg1, char *arg2, int w)
 134{
 135        int len, i;
 136        op_tbl_t *optp;
 137
 138        len = strlen(op);
 139
 140        for (optp = (op_tbl_t *)&op_table, i = 0;
 141             i < op_tbl_size;
 142             optp++, i++) {
 143
 144                if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) {
 145                        if (w == 0) {
 146                                return (stringcomp(arg1, arg2, optp->opcode));
 147                        } else {
 148                                return (arithcomp (arg1, arg2, optp->opcode, w));
 149                        }
 150                }
 151        }
 152
 153        printf("Unknown operator '%s'\n", op);
 154        return 0;       /* op code not found */
 155}
 156
 157/* command line interface to the shell test */
 158int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
 159{
 160        int     value, w;
 161
 162        /* Validate arguments */
 163        if ((argc != 4)){
 164                cmd_usage(cmdtp);
 165                return 1;
 166        }
 167
 168        /* Check for a data width specification.
 169         * Defaults to long (4) if no specification.
 170         * Uses -2 as 'width' for .s (string) so as not to upset existing code
 171         */
 172        switch (w = cmd_get_data_size(argv[0], 4)) {
 173        case 1:
 174        case 2:
 175        case 4:
 176                value = binary_test (argv[2], argv[1], argv[3], w);
 177                break;
 178        case -2:
 179                value = binary_test (argv[2], argv[1], argv[3], 0);
 180                break;
 181        case -1:
 182        default:
 183                puts("Invalid data width specifier\n");
 184                value = 0;
 185                break;
 186        }
 187
 188        return !value;
 189}
 190
 191U_BOOT_CMD(
 192        itest, 4, 0, do_itest,
 193        "return true/false on integer compare",
 194        "[.b, .w, .l, .s] [*]value1 <op> [*]value2\n"
 195);
 196