Message ID | 20180620053409.14538-7-alistair@popple.id.au |
---|---|
State | Accepted |
Headers | show |
Series | Rework option parsing | expand |
On 20/06/18 15:34, Alistair Popple wrote: > Parsers need to take a string argument and convert it into a specific type, > returning the value as a pointer to memory allocated by the parser (or NULL in > the case of an error). This just defines a couple of common parsers useful for > various commands. > > It also defines a couple of convenience macros for easier usage of these > parsers. > > Signed-off-by: Alistair Popple <alistair@popple.id.au> > --- > src/parsers.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > src/parsers.h | 21 +++++++++++++++ > 2 files changed, 106 insertions(+) > create mode 100644 src/parsers.c > create mode 100644 src/parsers.h > > diff --git a/src/parsers.c b/src/parsers.c > new file mode 100644 > index 0000000..0399933 > --- /dev/null > +++ b/src/parsers.c > @@ -0,0 +1,85 @@ > +#include <stdlib.h> > +#include <stdint.h> > +#include <stdbool.h> > +#include <errno.h> > + > +uint64_t *parse_number64(const char *argv) > +{ > + uint64_t *n = malloc(sizeof(*n)); > + char *endptr; > + > + if (!argv) > + return NULL; > + > + errno = 0; > + *n = strtoull(argv, &endptr, 0); > + if (errno || *endptr != '\0') > + return NULL; > + > + return n; > +} > + > +uint32_t *parse_number32(const char *argv) > +{ > + unsigned long long tmp; > + uint32_t *n = malloc(sizeof(*n)); > + char *endptr; > + > + if (!argv) > + return NULL; > + > + errno = 0; > + tmp = strtoul(argv, &endptr, 0); > + if (errno || *endptr != '\0' || tmp > (uint32_t) -1UL) What about using UINT32_MAX instead of '(uint32_t) -1UL'? > + return NULL; > + > + *n = tmp; > + return n; > +} > + > +/* Parse a GPR number, returning an error if it's greater than 32 */ > +int *parse_gpr(const char *argv) > +{ > + int *gpr = malloc(sizeof(*gpr)); > + char *endptr; > + > + if (!argv) > + return NULL; > + > + errno = 0; > + *gpr = strtoul(argv, &endptr, 0); > + if (errno || *endptr != '\0' || *gpr > 32) > + return NULL; > + > + return gpr; > +} > + > +/* Parse an SPR. Currently only supports SPR by numbers but could be extended to > + * support names (eg. lr) */ > +int *parse_spr(const char *argv) > +{ > + int *spr = malloc(sizeof(*spr)); > + char *endptr; > + > + if (!argv) > + return NULL; > + > + errno = 0; > + *spr = strtoul(argv, &endptr, 0); > + if (errno || *endptr != '\0' || *spr > 0x3ff) > + return NULL; > + > + return spr; > +} > + > + > +/* A special parser that always returns true. Allows for boolean flags which > + * don't take arguments. Sets the associated field to true if specified, > + * otherwise sets it to the default value (usually false). */ > +bool *parse_flag_noarg(const char *argv) > +{ > + bool *result = malloc(sizeof(*result)); > + > + *result = true; > + return result; > +} > diff --git a/src/parsers.h b/src/parsers.h > new file mode 100644 > index 0000000..b5f23cf > --- /dev/null > +++ b/src/parsers.h > @@ -0,0 +1,21 @@ > +#ifndef __PARSERS_H > +#define __PARSERS_H > + > +#include <stdint.h> > +#include <stdbool.h> > + > +#define ADDRESS (parse_number64, NULL) > +#define ADDRESS32 (parse_number32, NULL) > +#define DATA (parse_number64, NULL) > +#define DATA32 (parse_number32, NULL) > +#define DEFAULT_DATA(default) (parse_number64, default) > +#define GPR (parse_gpr, NULL) > +#define SPR (parse_spr, NULL) > + > +uint64_t *parse_number64(const char *argv); > +uint32_t *parse_number32(const char *argv); > +int *parse_gpr(const char *argv); > +int *parse_spr(const char *argv); > +bool *parse_flag_noarg(const char *argv); > + > +#endif
> > + errno = 0; > > + tmp = strtoul(argv, &endptr, 0); > > + if (errno || *endptr != '\0' || tmp > (uint32_t) -1UL) > > What about using UINT32_MAX instead of '(uint32_t) -1UL'? Good idea! Thanks. - Alistair
diff --git a/src/parsers.c b/src/parsers.c new file mode 100644 index 0000000..0399933 --- /dev/null +++ b/src/parsers.c @@ -0,0 +1,85 @@ +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <errno.h> + +uint64_t *parse_number64(const char *argv) +{ + uint64_t *n = malloc(sizeof(*n)); + char *endptr; + + if (!argv) + return NULL; + + errno = 0; + *n = strtoull(argv, &endptr, 0); + if (errno || *endptr != '\0') + return NULL; + + return n; +} + +uint32_t *parse_number32(const char *argv) +{ + unsigned long long tmp; + uint32_t *n = malloc(sizeof(*n)); + char *endptr; + + if (!argv) + return NULL; + + errno = 0; + tmp = strtoul(argv, &endptr, 0); + if (errno || *endptr != '\0' || tmp > (uint32_t) -1UL) + return NULL; + + *n = tmp; + return n; +} + +/* Parse a GPR number, returning an error if it's greater than 32 */ +int *parse_gpr(const char *argv) +{ + int *gpr = malloc(sizeof(*gpr)); + char *endptr; + + if (!argv) + return NULL; + + errno = 0; + *gpr = strtoul(argv, &endptr, 0); + if (errno || *endptr != '\0' || *gpr > 32) + return NULL; + + return gpr; +} + +/* Parse an SPR. Currently only supports SPR by numbers but could be extended to + * support names (eg. lr) */ +int *parse_spr(const char *argv) +{ + int *spr = malloc(sizeof(*spr)); + char *endptr; + + if (!argv) + return NULL; + + errno = 0; + *spr = strtoul(argv, &endptr, 0); + if (errno || *endptr != '\0' || *spr > 0x3ff) + return NULL; + + return spr; +} + + +/* A special parser that always returns true. Allows for boolean flags which + * don't take arguments. Sets the associated field to true if specified, + * otherwise sets it to the default value (usually false). */ +bool *parse_flag_noarg(const char *argv) +{ + bool *result = malloc(sizeof(*result)); + + *result = true; + return result; +} diff --git a/src/parsers.h b/src/parsers.h new file mode 100644 index 0000000..b5f23cf --- /dev/null +++ b/src/parsers.h @@ -0,0 +1,21 @@ +#ifndef __PARSERS_H +#define __PARSERS_H + +#include <stdint.h> +#include <stdbool.h> + +#define ADDRESS (parse_number64, NULL) +#define ADDRESS32 (parse_number32, NULL) +#define DATA (parse_number64, NULL) +#define DATA32 (parse_number32, NULL) +#define DEFAULT_DATA(default) (parse_number64, default) +#define GPR (parse_gpr, NULL) +#define SPR (parse_spr, NULL) + +uint64_t *parse_number64(const char *argv); +uint32_t *parse_number32(const char *argv); +int *parse_gpr(const char *argv); +int *parse_spr(const char *argv); +bool *parse_flag_noarg(const char *argv); + +#endif
Parsers need to take a string argument and convert it into a specific type, returning the value as a pointer to memory allocated by the parser (or NULL in the case of an error). This just defines a couple of common parsers useful for various commands. It also defines a couple of convenience macros for easier usage of these parsers. Signed-off-by: Alistair Popple <alistair@popple.id.au> --- src/parsers.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/parsers.h | 21 +++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/parsers.c create mode 100644 src/parsers.h