Skip to content

Commit

Permalink
XXX Add argp_parse() call to main() and build it
Browse files Browse the repository at this point in the history
  • Loading branch information
ndim committed Nov 24, 2024
1 parent 50edd05 commit 0ec3850
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 0 deletions.
6 changes: 6 additions & 0 deletions minimal-argp-parse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <argp.h>

int main(int argc, char *argv[]) {
error_t e = argp_parse(NULL, argc, argv, 0, NULL, NULL);
return (e != 0) ? 0 : 1;
}
6 changes: 6 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ avrdude_SOURCES = \
developer_opts.h \
developer_opts_private.h

if REQUIRE_ARGP_SOURCES
avrdude_CPPFLAGS += -I$(srcdir)/gnulib
avrdude_SOURCES += gnulib/argp.h
avrdude_SOURCES += gnulib/argp-parse.c
endif

dist_bin_SCRIPTS = elf2tag

man_MANS = avrdude.1
Expand Down
22 changes: 22 additions & 0 deletions src/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,28 @@ dnl Makefile.am:77: compiling `config_gram.c' with per-target flags requires `AM
AM_PROG_CC_C_O

# Checks for libraries.

# Check whether the argp API (argp_parse() etc.) is available out of
# the box or whether we need to compile and link against
# `gnulib/argp*.c`.
AC_MSG_CHECKING([whether compile and link works for argp_parse() etc])
AC_LINK_IFELSE([AC_LANG_SOURCE([[
#include <argp.h>
int main(int argc, char *argv[]) {
error_t e = argp_parse(NULL, argc, argv, 0, NULL, NULL);
return (e != 0) ? 0 : 1;
}
]])], [dnl
AC_MSG_RESULT([yes])
avrdude_require_argp_sources=no
], [dnl
AC_MSG_RESULT([no])
avrdude_require_argp_sources=yes
])
AM_CONDITIONAL([REQUIRE_ARGP_SOURCES],
[test "x$avrdude_require_argp_sources" = xyes])

# For MinGW.
AC_CHECK_LIB([ws2_32], [WSAStartup])

Expand Down
7 changes: 7 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
#include <dirent.h>
#endif

#include <argp.h>

#include "avrdude.h"
#include "libavrdude.h"
#include "config.h"
Expand Down Expand Up @@ -813,6 +815,11 @@ int main(int argc, char *argv[]) {
concatpath(usr_config, getenv("HOME"), USER_CONF_FILE, sizeof usr_config);
#endif

if (0 == 0) {
error_t err = argp_parse(NULL, argc, argv, 0, NULL, NULL);
printf("argp_parse() == %d\n", err);
}

// Process command line arguments
while((ch = getopt(argc, argv, "?Ab:B:c:C:DeE:Fi:l:nNp:OP:qrtT:U:vVx:")) != -1) {
switch(ch) {
Expand Down
108 changes: 108 additions & 0 deletions test-argp-parse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include <argp.h>
#include <assert.h>
#include <stdbool.h>

const char *argp_program_version = "test-argp-parse 1.0";

const char *argp_program_bug_address = "<[email protected]>";

/* Program documentation. */
static char doc[] =
"test-argp-parse -- Test the argp API with features useful for us.";

static const struct argp_option options[] = {
{"flag", 'f', NULL, 0, "Set the flag", 0},
{"include", 'I', "DIR", 0, "Look for include files in DIR", 0},
{NULL, 0, NULL, 0, NULL, 0}};

struct cli_arguments {
bool flag;
char *include_dir;
};

void print_cli_arguments(const struct cli_arguments *const cli) {
printf("CLI arguments @%p:\n", (void *)cli);
printf(" * include_dir: %s\n", cli->include_dir);
}

static error_t parse_opt(int key, char *arg, struct argp_state *state) {
assert(state != NULL);
struct cli_arguments *cli = state->input;
assert(cli != NULL);
switch (key) {

case 'f':
cli->flag = true;
break;

case 'I':
cli->include_dir = arg;
break;

default:
return ARGP_ERR_UNKNOWN;
}

return 0;
}

/* Our argument parser. The options, parser, and
args_doc fields are zero because we have neither options or
arguments; doc and argp_program_bug_address will be
used in the output for ‘--help’, and the ‘--version’
option will print out argp_program_version. */
static struct argp argp = {
options, /* argp_options */
parse_opt, /* arg_parser_t parser function */
NULL, /* argp_doc aka usage lines */
doc, /* doc */
NULL, /* argp_child children */
NULL, /* help_filter function */
NULL, /* argp_domain for translations */
};

int main(int argc, char *argv[]) {
printf("Original command line rguments:\n");
for (int i = 0; i < argc; i++) {
printf(" %d. %s\n", i, argv[i]);
}

struct cli_arguments cli = {false, NULL};

int first_unparsed = 0;
error_t ap_err = argp_parse(&argp, argc, argv, 0, &first_unparsed, &cli);

if (ap_err != 0) {
switch (ap_err) {
case EINVAL:
fprintf(stderr, "Error: Invalid command line found trying to parse the "
"command line.\n");
return 2;
case ENOMEM:
fprintf(stderr, "Error: Not enough memory to parse the command line.\n");
return 2;
default:
fprintf(stderr,
"Error: Unknown error %d trying to parse the command line.\n",
ap_err);
return 2;
}
}

printf("Reordered command line rguments after calling argp_parse():\n");
for (int i = 0; i < argc; i++) {
printf(" %d. %s\n", i, argv[i]);
}

print_cli_arguments(&cli);

printf("first_unparsed: %d\n", first_unparsed);
if (first_unparsed < argc) {
printf("Unparsed CLI arguments:\n");
for (int i = first_unparsed; i < argc; ++i) {
printf(" %d. %s\n", i, argv[i]);
}
}

return 0;
}

0 comments on commit 0ec3850

Please sign in to comment.