util: Further consolidate the Args interface in the m5 utility.
authorGabe Black <gabeblack@google.com>
Sun, 5 Apr 2020 07:32:25 +0000 (00:32 -0700)
committerGabe Black <gabeblack@google.com>
Fri, 24 Jul 2020 00:05:00 +0000 (00:05 +0000)
Create static methods to convert any string to an integer or to pack it
into an array of integers. Create non-static methdos named pop() to
pop() the first element and simultaneously convert it. If the conversion
fails, the argument is not popped.

Change-Id: I55d98b3971e7abb7b6206d06ec7fcf046e828d29
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27553
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
util/m5/src/args.cc
util/m5/src/args.hh
util/m5/src/call_type/addr.cc
util/m5/src/commands.cc

index b6bd1c8f75efb6824fe4c0a09e43913db5673f67..1caad43941723bba47220cb4921bb4aaff659b6e 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <cinttypes>
-#include <cstdlib>
 #include <cstring>
 
 #include "args.hh"
 
 bool
-parse_int_args(Args &args, uint64_t ints[], int len)
-{
-// On 32 bit platforms we need to use strtoull to do the conversion
-#ifdef __LP64__
-#define strto64 strtoul
-#else
-#define strto64 strtoull
-#endif
-    for (int i = 0; i < len; ++i)
-        ints[i] = strto64(args.pop("0").c_str(), NULL, 0);
-
-#undef strto64
-    return true;
-}
-
-bool
-pack_arg_into_regs(Args &args, uint64_t regs[], int num_regs)
+Args::pack(const std::string &str, uint64_t regs[], int num_regs)
 {
     const size_t RegSize = sizeof(regs[0]);
     const size_t MaxLen = num_regs * RegSize;
-    const std::string &sarg = args.pop();
-    const char *arg = sarg.c_str();
+    const char *arg = str.c_str();
 
     memset(regs, 0, MaxLen);
 
-    size_t len = sarg.size();
+    size_t len = str.size();
 
     if (len > MaxLen)
         return false;
index 1afd2f28a5d65ef93989eee409aa2ee874fc3e25..b541533c5b9854485bb4b4aeffe0d3b7c3b9d9de 100644 (file)
@@ -41,9 +41,9 @@
 #ifndef __ARGS_HH__
 #define __ARGS_HH__
 
-#include <cstddef>
 #include <cstdint>
 #include <initializer_list>
+#include <stdexcept>
 #include <string>
 #include <vector>
 
@@ -61,19 +61,115 @@ class Args
     }
     Args(std::initializer_list<std::string> strings) : args(strings) {}
 
+    /*
+     * Attempt to convert str into an integer.
+     *
+     * Return whether that succeeded.
+     */
+    static bool
+    stoi(const std::string &str, uint64_t &val)
+    {
+        try {
+            val = std::stoi(str, nullptr, 0);
+            return true;
+        } catch (const std::invalid_argument &e) {
+            return false;
+        } catch (const std::out_of_range &e) {
+            return false;
+        }
+    }
+
+    /*
+     * Attempt to convert str into an integer.
+     *
+     * Return whether that suceeded. If not, val will be set to def.
+     */
+    static bool
+    stoi(const std::string &str, uint64_t &val, uint64_t def)
+    {
+        val = def;
+        return stoi(str, val);
+    }
+
+    /*
+     * Attempt to pack str as a sequence of bytes in to regs in little endian
+     * byte order.
+     *
+     * Return whether that succeeded.
+     */
+    static bool pack(const std::string &str, uint64_t regs[], int num_regs);
+
+    /*
+     * If there are any arguments in the list, remove and return the first
+     * one. If not, return def instead.
+     */
     const std::string &
-    pop(const std::string &def = "") {
+    pop(const std::string &def = "")
+    {
         if (!size())
             return def;
         return args[offset++];
     }
 
+    /*
+     * If there are any arguments in the list, attempt to convert the first
+     * one to an integer. If successful, remove it and store its value in val.
+     *
+     * Return whether that succeeded.
+     */
+    bool
+    pop(uint64_t &val)
+    {
+        if (!size() || !stoi(args[offset], val)) {
+            return false;
+        } else {
+            offset++;
+            return true;
+        }
+    }
+
+    /*
+     * If there are any arguments in the list, attempt to convert the first
+     * one to an integer. If successful, remove it and store its value in val.
+     * If there are no arguments or the conversion failed, set val to def.
+     *
+     * Return true if there were no arguments, or there were and the conversion
+     * succeeded.
+     */
+    bool
+    pop(uint64_t &val, uint64_t def)
+    {
+        val = def;
+        if (!size())
+            return true;
+        if (stoi(args[offset], val)) {
+            offset++;
+            return true;
+        }
+        return false;
+    }
+
+    /*
+     * If there are any arguments in the list, attempt to pack the first one
+     * as a sequence of bytes into the integers in regs in little endian byte
+     * order.
+     *
+     * Return whether that succeeded.
+     */
+    bool
+    pop(uint64_t regs[], int num_regs)
+    {
+        if (!size() || !pack(args[offset], regs, num_regs)) {
+            return false;
+        } else {
+            offset++;
+            return true;
+        }
+    }
+
     size_t size() { return args.size() - offset; }
 
     const std::string &operator [] (size_t idx) { return args[offset + idx]; }
 };
 
-bool parse_int_args(Args &args, uint64_t ints[], int len);
-bool pack_arg_into_regs(Args &args, uint64_t regs[], int num_regs);
-
 #endif // __ARGS_HH__
index 752d831253dd020be247d432705717837d0c1912..f8e39c9f5c398cec655781597212954095f20f87 100644 (file)
@@ -97,8 +97,7 @@ class AddrCallType : public CallType
             if (arg[0] != '=')
                 usage();
             // Attempt to extract an address after the '='.
-            Args temp_args({ arg.substr(1) });
-            if (!parse_int_args(temp_args, &addr_override, 1))
+            if (!args.stoi(arg.substr(1), addr_override))
                 usage();
             // If we found an address, use it to override m5op_addr.
             m5op_addr = addr_override;
@@ -106,7 +105,7 @@ class AddrCallType : public CallType
         }
         // If an address override wasn't part of the first argument, check if
         // it's the second argument. If not, then there's no override.
-        if (args.size() && parse_int_args(args, &addr_override, 1)) {
+        if (args.pop(addr_override)) {
             m5op_addr = addr_override;
             return true;
         }
index d721899d2e18ed70d2c710c4f9672f8b2a571e0f..b59633b23c61f37cd0e569eb35684ab0358ef6b0 100644 (file)
@@ -108,49 +108,63 @@ do_exit(const DispatchTable &dt, Args &args)
     if (args.size() > 1)
         usage();
 
-    uint64_t ints[1];
-    if (!parse_int_args(args, ints, 1))
+    uint64_t ns_delay;
+    if (!args.pop(ns_delay, 0))
         usage();
-    (*dt.m5_exit)(ints[0]);
+
+    (*dt.m5_exit)(ns_delay);
 }
 
 static void
 do_fail(const DispatchTable &dt, Args &args)
 {
-    if (args.size() < 1 || args.size() > 2)
+    if (args.size() > 2)
         usage();
 
-    uint64_t ints[2] = { 0, 0 };
-    if (!parse_int_args(args, ints, args.size()))
+    uint64_t ns_delay, code;
+    if (!args.pop(code) || !args.pop(ns_delay, 0))
         usage();
-    (*dt.m5_fail)(ints[1], ints[0]);
+
+    (*dt.m5_fail)(ns_delay, code);
 }
 
 static void
 do_reset_stats(const DispatchTable &dt, Args &args)
 {
-    uint64_t ints[2];
-    if (!parse_int_args(args, ints, 2))
+    if (args.size() > 2)
+        usage();
+
+    uint64_t ns_delay, ns_period;
+    if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
         usage();
-    (*dt.m5_reset_stats)(ints[0], ints[1]);
+
+    (*dt.m5_reset_stats)(ns_delay, ns_period);
 }
 
 static void
 do_dump_stats(const DispatchTable &dt, Args &args)
 {
-    uint64_t ints[2];
-    if (!parse_int_args(args, ints, 2))
+    if (args.size() > 2)
+        usage();
+
+    uint64_t ns_delay, ns_period;
+    if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
         usage();
-    (*dt.m5_dump_stats)(ints[0], ints[1]);
+
+    (*dt.m5_dump_stats)(ns_delay, ns_period);
 }
 
 static void
 do_dump_reset_stats(const DispatchTable &dt, Args &args)
 {
-    uint64_t ints[2];
-    if (!parse_int_args(args, ints, 2))
+    if (args.size() > 2)
         usage();
-    (*dt.m5_dump_reset_stats)(ints[0], ints[1]);
+
+    uint64_t ns_delay, ns_period;
+    if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
+        usage();
+
+    (*dt.m5_dump_reset_stats)(ns_delay, ns_period);
 }
 
 static void
@@ -165,7 +179,7 @@ do_read_file(const DispatchTable &dt, Args &args)
 static void
 do_write_file(const DispatchTable &dt, Args &args)
 {
-    if (args.size() != 1 && args.size() != 2)
+    if (args.size() < 1 || args.size() > 2)
         usage();
 
     const std::string &filename = args.pop();
@@ -177,10 +191,14 @@ do_write_file(const DispatchTable &dt, Args &args)
 static void
 do_checkpoint(const DispatchTable &dt, Args &args)
 {
-    uint64_t ints[2];
-    if (!parse_int_args(args, ints, 2))
+    if (args.size() > 2)
+        usage();
+
+    uint64_t ns_delay, ns_period;
+    if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
         usage();
-    (*dt.m5_checkpoint)(ints[0], ints[1]);
+
+    (*dt.m5_checkpoint)(ns_delay, ns_period);
 }
 
 static void
@@ -189,8 +207,11 @@ do_addsymbol(const DispatchTable &dt, Args &args)
     if (args.size() != 2)
         usage();
 
-    uint64_t addr = strtoul(args.pop().c_str(), NULL, 0);
+    uint64_t addr;
+    if (!args.pop(addr))
+        usage();
     const std::string &symbol = args.pop();
+
     (*dt.m5_add_symbol)(addr, symbol.c_str());
 }
 
@@ -207,11 +228,11 @@ do_loadsymbol(const DispatchTable &dt, Args &args)
 static void
 do_initparam(const DispatchTable &dt, Args &args)
 {
-    if (args.size() > 1)
+    if (args.size() != 1)
         usage();
 
     uint64_t key_str[2];
-    if (!pack_arg_into_regs(args, key_str, 2))
+    if (!args.pop(key_str, 2))
         usage();
     uint64_t val = (*dt.m5_init_param)(key_str[0], key_str[1]);
     std::cout << val;