cli: Extract flash argument parsing into cli_common
Move the parsing logic for `-c` and `-p` into the new function
cli_parse_flash_args(). This way it can be shared with other CLIs.
We start a new header file `cli.h` for common CLI functions.
Change-Id: If3f5eff0a2f56a1235038b19b3c1d6586536fd5d
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/72982
diff --git a/cli_classic.c b/cli_classic.c
index a9e8770..2621219 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -29,6 +29,7 @@
#include "fmap.h"
#include "programmer.h"
#include "libflashprog.h"
+#include "cli.h"
static void cli_classic_usage(const char *name)
{
@@ -270,8 +271,7 @@
char *fmapfile = NULL;
char *logfile = NULL;
char *tempstr = NULL;
- char *pname = NULL;
- char *pparam = NULL;
+ struct flash_args flash_args = { 0 };
struct layout_include_args *include_args = NULL;
/*
@@ -328,7 +328,12 @@
dont_verify_all = true;
break;
case 'c':
- chip_to_probe = strdup(optarg);
+ case 'p':
+ ret = cli_parse_flash_args(&flash_args, opt, optarg);
+ if (ret == 1)
+ cli_classic_abort_usage(NULL);
+ else if (ret)
+ exit(1);
break;
case 'V':
verbose_screen++;
@@ -413,26 +418,6 @@
"compiled in. Aborting.\n");
#endif
break;
- case 'p':
- if (pname != NULL) {
- cli_classic_abort_usage("Error: --programmer specified "
- "more than once. You can separate "
- "multiple\nparameters for a programmer "
- "with \",\". Please see the man page "
- "for details.\n");
- }
- const char *const colon = strchr(optarg, ':');
- if (colon) {
- pname = strndup(optarg, colon - optarg);
- pparam = strdup(colon + 1);
- } else {
- pname = strdup(optarg);
- }
- if (!pname || (colon && !pparam)) {
- fprintf(stderr, "Out of memory!\n");
- exit(1);
- }
- break;
case 'R':
/* print_version() is always called during startup. */
cli_classic_validate_singleop(&operation_specified);
@@ -510,12 +495,12 @@
goto out;
}
/* Does a chip with the requested name exist in the flashchips array? */
- if (chip_to_probe) {
+ if (flash_args.chip) {
for (chip = flashchips; chip && chip->name; chip++)
- if (!strcmp(chip->name, chip_to_probe))
+ if (!strcmp(chip->name, flash_args.chip))
break;
if (!chip || !chip->name) {
- msg_cerr("Error: Unknown chip '%s' specified.\n", chip_to_probe);
+ msg_cerr("Error: Unknown chip '%s' specified.\n", flash_args.chip);
msg_gerr("Run flashprog -L to view the hardware supported in this flashprog version.\n");
ret = 1;
goto out;
@@ -523,20 +508,20 @@
/* Keep chip around for later usage in case a forced read is requested. */
}
- if (pname == NULL) {
+ if (flash_args.prog_name == NULL) {
const char *const default_programmer = CONFIG_DEFAULT_PROGRAMMER_NAME;
if (default_programmer[0]) {
/* We need to strdup here because we free() unconditionally later. */
- pname = strdup(default_programmer);
- pparam = strdup(CONFIG_DEFAULT_PROGRAMMER_ARGS);
- if (!pname || !pparam) {
+ flash_args.prog_name = strdup(default_programmer);
+ flash_args.prog_args = strdup(CONFIG_DEFAULT_PROGRAMMER_ARGS);
+ if (!flash_args.prog_name || !flash_args.prog_args) {
fprintf(stderr, "Out of memory!\n");
ret = 1;
goto out;
}
msg_pinfo("Using default programmer \"%s\" with arguments \"%s\".\n",
- pname, pparam);
+ flash_args.prog_name, flash_args.prog_args);
} else {
msg_perr("Please select a programmer with the --programmer parameter.\n"
#if CONFIG_INTERNAL == 1
@@ -550,7 +535,7 @@
}
}
- if (flashprog_programmer_init(&prog, pname, pparam)) {
+ if (flashprog_programmer_init(&prog, flash_args.prog_name, flash_args.prog_args)) {
msg_perr("Error: Programmer initialization failed.\n");
ret = 1;
goto out;
@@ -559,6 +544,7 @@
msg_pdbg("The following protocols are supported: %s.\n", tempstr);
free(tempstr);
+ chip_to_probe = flash_args.chip;
struct registered_master *matched_master = NULL;
for (j = 0; j < registered_master_count; j++) {
startchip = 0;
@@ -583,18 +569,18 @@
goto out_shutdown;
} else if (!chipcount) {
msg_cinfo("No EEPROM/flash device found.\n");
- if (!force || !chip_to_probe) {
+ if (!force || !flash_args.chip) {
msg_cinfo("Note: flashprog can never write if the flash chip isn't found "
"automatically.\n");
}
- if (force && read_it && chip_to_probe) {
+ if (force && read_it && flash_args.chip) {
struct registered_master *mst;
int compatible_masters = 0;
msg_cinfo("Force read (-f -r -c) requested, pretending the chip is there:\n");
/* This loop just counts compatible controllers. */
for (j = 0; j < registered_master_count; j++) {
mst = ®istered_masters[j];
- /* chip is still set from the chip_to_probe earlier in this function. */
+ /* chip is still set from the search earlier in this function. */
if (mst->buses_supported & chip->bustype)
compatible_masters++;
}
@@ -614,7 +600,7 @@
}
if (startchip == -1) {
// FIXME: This should never happen! Ask for a bug report?
- msg_cinfo("Probing for flash chip '%s' failed.\n", chip_to_probe);
+ msg_cinfo("Probing for flash chip '%s' failed.\n", flash_args.chip);
ret = 1;
goto out_shutdown;
}
@@ -626,7 +612,7 @@
}
ret = 1;
goto out_shutdown;
- } else if (!chip_to_probe) {
+ } else if (!flash_args.chip) {
/* repeat for convenience when looking at foreign logs */
tempstr = flashbuses_to_text(flashes[0].chip->bustype);
msg_gdbg("Found %s flash chip \"%s\" (%d kB, %s).\n",
@@ -754,10 +740,10 @@
free(fmapfile);
free(referencefile);
free(layoutfile);
- free(pparam);
- free(pname);
+ free(flash_args.prog_args);
+ free(flash_args.prog_name);
+ free(flash_args.chip);
/* clean up global variables */
- free((char *)chip_to_probe); /* Silence! Freeing is not modifying contents. */
chip_to_probe = NULL;
free(logfile);
ret |= close_logfile();
diff --git a/cli_common.c b/cli_common.c
index cf3c7ae..c364efa 100644
--- a/cli_common.c
+++ b/cli_common.c
@@ -18,7 +18,47 @@
#include <stdlib.h>
#include <string.h>
+
#include "flash.h"
+#include "cli.h"
+
+int cli_parse_flash_args(struct flash_args *const args, const int opt, const char *const optarg)
+{
+ switch (opt) {
+ case OPTION_PROGRAMMER:
+ if (args->prog_name) {
+ fprintf(stderr,
+ "Error: --programmer specified more than once. You can separate multiple\n"
+ "arguments for a programmer with ','. Please see the man page for details.\n");
+ return 1;
+ }
+ const char *const colon = strchr(optarg, ':');
+ if (colon) {
+ args->prog_name = strndup(optarg, colon - optarg);
+ args->prog_args = strdup(colon + 1);
+ } else {
+ args->prog_name = strdup(optarg);
+ }
+ if (!args->prog_name || (colon && !args->prog_args)) {
+ fprintf(stderr, "Out of memory!\n");
+ return 2;
+ }
+ break;
+ case OPTION_CHIP:
+ if (args->chip) {
+ fprintf(stderr, "Error: --chip specified more than once.\n");
+ return 1;
+ }
+ args->chip = strdup(optarg);
+ if (!args->chip) {
+ fprintf(stderr, "Out of memory!\n");
+ return 2;
+ }
+ break;
+ }
+
+ return 0;
+}
void print_chip_support_status(const struct flashchip *chip)
{
diff --git a/include/cli.h b/include/cli.h
new file mode 100644
index 0000000..aef0b8d
--- /dev/null
+++ b/include/cli.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the flashprog project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef FLASHPROG_CLI_H
+#define FLASHPROG_CLI_H
+
+enum {
+ OPTION_CHIP = 'c',
+ OPTION_PROGRAMMER = 'p',
+};
+
+struct flash_args {
+ char *chip;
+ char *prog_name;
+ char *prog_args;
+};
+
+int cli_parse_flash_args(struct flash_args *, int opt, const char *optarg);
+
+#endif