From: Jeff Garzik Date: Sat, 21 May 2005 04:08:36 GMT Subject: Re: [RFC] git-fsck-cache argument processing Message-ID: <428EB444.7010200@pobox.com> In-Reply-To: <4870.10.10.10.24.1116646732.squirrel@linux1> Sean wrote: > Here is a first crack at using argp as suggested by Jeff Garzik to > implement argument processing as requested by Junio and Linus. Each of > the long arguments have been given a single character equivalent as well. > > This patch only converts fsck-cache to use argp in case anyone has > objections to the basic format or style. The patch includes a version > number inside of fsck-cache.c; this should really be in a separate include > file so you can run any command with --version and get the same answer. Pretty good. You'll probably want some additional changes: 1) eliminate + case ARGP_KEY_ARG: state->next = state->argc; break; This will cause option processing to stop at the first unknown argument. 2) Pass-by-reference a variable to argp_parse(), which will store the index of the argument where processing stopped. This is the first hash/file/etc. non-option argument. (example code from posixutils) int parse_cmdline(struct cmdline_walker *cw) { error_t rc_argp; int idx = 0; rc_argp = argp_parse(cw->argp, cw->argc, cw->argv, 0, &idx, NULL); if (rc_argp) { fprintf(stderr, "argp_parse: %s\n", strerror(rc_argp)); return -rc_argp; } return idx; } 'idx' in this case is the first non-option argument, which can be passed directly to argv[]. From there, you perform standard iteration over the arguments provided on the command line, starting at argv[idx]. If you have a fixed number of arguments following the options, then your parse_opt function can easily parse those args as well: static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { case '1': outmask |= OPT_FILE1; break; case '2': outmask |= OPT_FILE2; break; case '3': outmask |= OPT_DUP; break; case ARGP_KEY_ARG: switch(state->arg_num) { case 0: file1 = arg; break; /* 1st non-opt arg */ case 1: file2 = arg; break; /* 2nd non-opt arg */ default: argp_usage (state); break; /* too many args */ } break; case ARGP_KEY_END: if (state->arg_num < 2) /* not enough args */ argp_usage (state); break; default: return ARGP_ERR_UNKNOWN; } return 0; }