⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 argp-parse.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* Lengths of the various bits of storage used by PARSER.  */  glen = (szs.num_groups + 1) * sizeof (struct group);  clen = szs.num_child_inputs * sizeof (void *);  llen = (szs.long_len + 1) * sizeof (struct option);  slen = szs.short_len + 1;  /* Sums of previous lengths, properly aligned.  There's no need to     align gsum, since struct group is aligned at least as strictly as     void * (since it contains a void * member).  And there's no need     to align lsum, since struct option is aligned at least as     strictly as char.  */  gsum = glen;  csum = alignto (gsum + clen, alignof (struct option));  lsum = csum + llen;  ssum = lsum + slen;  parser->storage = malloc (ssum);  if (! parser->storage)    return ENOMEM;  storage = parser->storage;  parser->groups = parser->storage;  parser->child_inputs = (void **) (storage + gsum);  parser->long_opts = (struct option *) (storage + csum);  parser->short_opts = storage + lsum;  parser->opt_data = opt_data;  memset (parser->child_inputs, 0, clen);  parser_convert (parser, argp, flags);  memset (&parser->state, 0, sizeof (struct argp_state));  parser->state.root_argp = parser->argp;  parser->state.argc = argc;  parser->state.argv = argv;  parser->state.flags = flags;  parser->state.err_stream = stderr;  parser->state.out_stream = stdout;  parser->state.next = 0;	/* Tell getopt to initialize.  */  parser->state.pstate = parser;  parser->try_getopt = 1;  /* Call each parser for the first time, giving it a chance to propagate     values to child parsers.  */  if (parser->groups < parser->egroup)    parser->groups->input = input;  for (group = parser->groups;       group < parser->egroup && (!err || err == EBADKEY);       group++)    {      if (group->parent)	/* If a child parser, get the initial input value from the parent. */	group->input = group->parent->child_inputs[group->parent_index];      if (!group->parser	  && group->argp->children && group->argp->children->argp)	/* For the special case where no parsing function is supplied for an	   argp, propagate its input to its first child, if any (this just	   makes very simple wrapper argps more convenient).  */	group->child_inputs[0] = group->input;      err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);    }  if (err == EBADKEY)    err = 0;			/* Some parser didn't understand.  */  if (err)    return err;  if (parser->state.flags & ARGP_NO_ERRS)    {      parser->opt_data.opterr = 0;      if (parser->state.flags & ARGP_PARSE_ARGV0)	/* getopt always skips ARGV[0], so we have to fake it out.  As long	   as OPTERR is 0, then it shouldn't actually try to access it.  */	parser->state.argv--, parser->state.argc++;    }  else    parser->opt_data.opterr = 1;	/* Print error messages.  */  if (parser->state.argv == argv && argv[0])    /* There's an argv[0]; use it for messages.  */    parser->state.name = __argp_base_name (argv[0]);  else    parser->state.name = __argp_short_program_name ();  return 0;}/* Free any storage consumed by PARSER (but not PARSER itself).  */static error_tparser_finalize (struct parser *parser,		 error_t err, int arg_ebadkey, int *end_index){  struct group *group;  if (err == EBADKEY && arg_ebadkey)    /* Suppress errors generated by unparsed arguments.  */    err = 0;  if (! err)    {      if (parser->state.next == parser->state.argc)	/* We successfully parsed all arguments!  Call all the parsers again,	   just a few more times... */	{	  for (group = parser->groups;	       group < parser->egroup && (!err || err==EBADKEY);	       group++)	    if (group->args_processed == 0)	      err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0);	  for (group = parser->egroup - 1;	       group >= parser->groups && (!err || err==EBADKEY);	       group--)	    err = group_parse (group, &parser->state, ARGP_KEY_END, 0);	  if (err == EBADKEY)	    err = 0;		/* Some parser didn't understand.  */	  /* Tell the user that all arguments are parsed.  */	  if (end_index)	    *end_index = parser->state.next;	}      else if (end_index)	/* Return any remaining arguments to the user.  */	*end_index = parser->state.next;      else	/* No way to return the remaining arguments, they must be bogus. */	{	  if (!(parser->state.flags & ARGP_NO_ERRS)	      && parser->state.err_stream)	    fprintf (parser->state.err_stream,		     dgettext (parser->argp->argp_domain,			       "%s: Too many arguments\n"),		     parser->state.name);	  err = EBADKEY;	}    }  /* Okay, we're all done, with either an error or success; call the parsers     to indicate which one.  */  if (err)    {      /* Maybe print an error message.  */      if (err == EBADKEY)	/* An appropriate message describing what the error was should have	   been printed earlier.  */	__argp_state_help (&parser->state, parser->state.err_stream,			   ARGP_HELP_STD_ERR);      /* Since we didn't exit, give each parser an error indication.  */      for (group = parser->groups; group < parser->egroup; group++)	group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);    }  else    /* Notify parsers of success, and propagate back values from parsers.  */    {      /* We pass over the groups in reverse order so that child groups are	 given a chance to do there processing before passing back a value to	 the parent.  */      for (group = parser->egroup - 1	   ; group >= parser->groups && (!err || err == EBADKEY)	   ; group--)	err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0);      if (err == EBADKEY)	err = 0;		/* Some parser didn't understand.  */    }  /* Call parsers once more, to do any final cleanup.  Errors are ignored.  */  for (group = parser->egroup - 1; group >= parser->groups; group--)    group_parse (group, &parser->state, ARGP_KEY_FINI, 0);  if (err == EBADKEY)    err = EINVAL;  free (parser->storage);  return err;}/* Call the user parsers to parse the non-option argument VAL, at the current   position, returning any error.  The state NEXT pointer is assumed to have   been adjusted (by getopt) to point after this argument; this function will   adjust it correctly to reflect however many args actually end up being   consumed.  */static error_tparser_parse_arg (struct parser *parser, char *val){  /* Save the starting value of NEXT, first adjusting it so that the arg     we're parsing is again the front of the arg vector.  */  int index = --parser->state.next;  error_t err = EBADKEY;  struct group *group;  int key = 0;			/* Which of ARGP_KEY_ARG[S] we used.  */  /* Try to parse the argument in each parser.  */  for (group = parser->groups       ; group < parser->egroup && err == EBADKEY       ; group++)    {      parser->state.next++;	/* For ARGP_KEY_ARG, consume the arg.  */      key = ARGP_KEY_ARG;      err = group_parse (group, &parser->state, key, val);      if (err == EBADKEY)	/* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */	{	  parser->state.next--;	/* For ARGP_KEY_ARGS, put back the arg.  */	  key = ARGP_KEY_ARGS;	  err = group_parse (group, &parser->state, key, 0);	}    }  if (! err)    {      if (key == ARGP_KEY_ARGS)	/* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't	   changed by the user, *all* arguments should be considered	   consumed.  */	parser->state.next = parser->state.argc;      if (parser->state.next > index)	/* Remember that we successfully processed a non-option	   argument -- but only if the user hasn't gotten tricky and set	   the clock back.  */	(--group)->args_processed += (parser->state.next - index);      else	/* The user wants to reparse some args, give getopt another try.  */	parser->try_getopt = 1;    }  return err;}/* Call the user parsers to parse the option OPT, with argument VAL, at the   current position, returning any error.  */static error_tparser_parse_opt (struct parser *parser, int opt, char *val){  /* The group key encoded in the high bits; 0 for short opts or     group_number + 1 for long opts.  */  int group_key = opt >> USER_BITS;  error_t err = EBADKEY;  if (group_key == 0)    /* A short option.  By comparing OPT's position in SHORT_OPTS to the       various starting positions in each group's SHORT_END field, we can       determine which group OPT came from.  */    {      struct group *group;      char *short_index = strchr (parser->short_opts, opt);      if (short_index)	for (group = parser->groups; group < parser->egroup; group++)	  if (group->short_end > short_index)	    {	      err = group_parse (group, &parser->state, opt,				 parser->opt_data.optarg);	      break;	    }    }  else    /* A long option.  We use shifts instead of masking for extracting       the user value in order to preserve the sign.  */    err =      group_parse (&parser->groups[group_key - 1], &parser->state,		   (opt << GROUP_BITS) >> GROUP_BITS,		   parser->opt_data.optarg);  if (err == EBADKEY)    /* At least currently, an option not recognized is an error in the       parser, because we pre-compute which parser is supposed to deal       with each option.  */    {      static const char bad_key_err[] =	N_("(PROGRAM ERROR) Option should have been recognized!?");      if (group_key == 0)	__argp_error (&parser->state, "-%c: %s", opt,		      dgettext (parser->argp->argp_domain, bad_key_err));      else	{	  struct option *long_opt = parser->long_opts;	  while (long_opt->val != opt && long_opt->name)	    long_opt++;	  __argp_error (&parser->state, "--%s: %s",			long_opt->name ? long_opt->name : "???",			dgettext (parser->argp->argp_domain, bad_key_err));	}    }  return err;}/* Parse the next argument in PARSER (as indicated by PARSER->state.next).   Any error from the parsers is returned, and *ARGP_EBADKEY indicates   whether a value of EBADKEY is due to an unrecognized argument (which is   generally not fatal).  */static error_tparser_parse_next (struct parser *parser, int *arg_ebadkey){  int opt;  error_t err = 0;  if (parser->state.quoted && parser->state.next < parser->state.quoted)    /* The next argument pointer has been moved to before the quoted       region, so pretend we never saw the quoting `--', and give getopt       another chance.  If the user hasn't removed it, getopt will just       process it again.  */    parser->state.quoted = 0;  if (parser->try_getopt && !parser->state.quoted)    /* Give getopt a chance to parse this.  */    {      /* Put it back in OPTIND for getopt.  */      parser->opt_data.optind = parser->state.next;      /* Distinguish KEY_ERR from a real option.  */      parser->opt_data.optopt = KEY_END;      if (parser->state.flags & ARGP_LONG_ONLY)	opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,				   parser->short_opts, parser->long_opts, 0,				   &parser->opt_data);      else	opt = _getopt_long_r (parser->state.argc, parser->state.argv,			      parser->short_opts, parser->long_opts, 0,			      &parser->opt_data);      /* And see what getopt did.  */      parser->state.next = parser->opt_data.optind;      if (opt == KEY_END)	/* Getopt says there are no more options, so stop using	   getopt; we'll continue if necessary on our own.  */	{	  parser->try_getopt = 0;	  if (parser->state.next > 1	      && strcmp (parser->state.argv[parser->state.next - 1], QUOTE)	           == 0)	    /* Not only is this the end of the options, but it's a	       `quoted' region, which may have args that *look* like	       options, so we definitely shouldn't try to use getopt past	       here, whatever happens.  */	    parser->state.quoted = parser->state.next;	}      else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)	/* KEY_ERR can have the same value as a valid user short	   option, but in the case of a real error, getopt sets OPTOPT	   to the offending character, which can never be KEY_END.  */	{	  *arg_ebadkey = 0;	  return EBADKEY;	}    }  else    opt = KEY_END;  if (opt == KEY_END)    {      /* We're past what getopt considers the options.  */      if (parser->state.next >= parser->state.argc	  || (parser->state.flags & ARGP_NO_ARGS))	/* Indicate that we're done.  */	{	  *arg_ebadkey = 1;	  return EBADKEY;	}      else	/* A non-option arg; simulate what getopt might have done.  */	{	  opt = KEY_ARG;	  parser->opt_data.optarg = parser->state.argv[parser->state.next++];	}    }  if (opt == KEY_ARG)    /* A non-option argument; try each parser in turn.  */    err = parser_parse_arg (parser, parser->opt_data.optarg);  else    err = parser_parse_opt (parser, opt, parser->opt_data.optarg);  if (err == EBADKEY)    *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);  return err;}/* Parse the options strings in ARGC & ARGV according to the argp in ARGP.   FLAGS is one of the ARGP_ flags above.  If END_INDEX is non-NULL, the   index in ARGV of the first unparsed option is returned in it.  If an   unknown option is present, EINVAL is returned; if some parser routine   returned a non-zero value, it is returned; otherwise 0 is returned.  */error_t__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,	      int *end_index, void *input){  error_t err;  struct parser parser;  /* If true, then err == EBADKEY is a result of a non-option argument failing     to be parsed (which in some cases isn't actually an error).  */  int arg_ebadkey = 0;#ifndef _LIBC  if (!(flags & ARGP_PARSE_ARGV0))    {#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME      if (!program_invocation_name)	program_invocation_name = argv[0];#endif#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME      if (!program_invocation_short_name)	program_invocation_short_name = __argp_base_name (argv[0]);#endif    }#endif	  if (! (flags & ARGP_NO_HELP))    /* Add our own options.  */    {      struct argp_child *child = alloca (4 * sizeof (struct argp_child));      struct argp *top_argp = alloca (sizeof (struct argp));      /* TOP_ARGP has no options, it just serves to group the user & default	 argps.  */      memset (top_argp, 0, sizeof (*top_argp));      top_argp->children = child;      memset (child, 0, 4 * sizeof (struct argp_child));      if (argp)	(child++)->argp = argp;      (child++)->argp = &argp_default_argp;      if (argp_program_version || argp_program_version_hook)	(child++)->argp = &argp_version_argp;      child->argp = 0;      argp = top_argp;    }  /* Construct a parser for these arguments.  */  err = parser_init (&parser, argp, argc, argv, flags, input);  if (! err)    /* Parse! */    {      while (! err)	err = parser_parse_next (&parser, &arg_ebadkey);      err = parser_finalize (&parser, err, arg_ebadkey, end_index);    }  return err;}#ifdef weak_aliasweak_alias (__argp_parse, argp_parse)#endif/* Return the input field for ARGP in the parser corresponding to STATE; used   by the help routines.  */void *__argp_input (const struct argp *argp, const struct argp_state *state){  if (state)    {      struct group *group;      struct parser *parser = state->pstate;      for (group = parser->groups; group < parser->egroup; group++)	if (group->argp == argp)	  return group->input;    }  return 0;}#ifdef weak_aliasweak_alias (__argp_input, _argp_input)#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -