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

📄 getopt_long.c

📁 sntop是一个基于curses的控制台工具
💻 C
字号:
/* Getopt for GNU.   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993   	Free Software Foundation, Inc.   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, 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.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        Modified 07.31.2000 by Robert M. Love:   	- cleaned up (ever hear of ANSI C?)   	- removed everything but getopt_long   	- removed need for alloca   	- removed need for tons of other crap   	- cleaned up*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <string.h>#include <stdlib.h>#include "getopt_long.h"#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || !defined (HAVE_GETOPT_LONG)char *optarg = 0;int optind = 0;static char *nextchar;int opterr = 1;int optopt = '?';static enum{  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER} ordering;static int first_nonopt;static int last_nonopt;/* Exchange two adjacent subsequences of ARGV.   One subsequence is elements [first_nonopt,last_nonopt)   which contains all the non-options that have been skipped so far.   The other is elements [last_nonopt,optind), which contains all   the options processed since those non-options were skipped.   `first_nonopt' and `last_nonopt' are relocated so that they describe   the new indices of the non-options in ARGV after they are moved.  */static void exchange (char **argv){  int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);  char **temp = (char **) malloc (nonopts_size);  /* Interchange the two blocks of data in ARGV.  */  memcpy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size);  memcpy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt],	    (optind - last_nonopt) * sizeof (char *));  memcpy ((char *) temp,	    (char *) &argv[first_nonopt + optind - last_nonopt],	    nonopts_size);	      free(temp);  /* Update records for the slots the non-options now occupy.  */  first_nonopt += (optind - last_nonopt);  last_nonopt = optind;}int getopt_long (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind){  int option_index;  optarg = 0;  /* Initialize the internal data when the first call is made.     Start processing options with ARGV-element 1 (since ARGV-element 0     is the program name); the sequence of previously skipped     non-option ARGV-elements is empty.  */  if (optind == 0)    {      first_nonopt = last_nonopt = optind = 1;      nextchar = NULL;      /* Determine how to handle the ordering of options and nonoptions.  */      if (optstring[0] == '-')	{	  ordering = RETURN_IN_ORDER;	  ++optstring;	}      else if (optstring[0] == '+')	{	  ordering = REQUIRE_ORDER;	  ++optstring;	}      else	ordering = PERMUTE;    }  if (nextchar == NULL || *nextchar == '\0')    {      if (ordering == PERMUTE)	{	  /* If we have just processed some options following some non-options,	     exchange them so that the options come first.  */	  if (first_nonopt != last_nonopt && last_nonopt != optind)	    exchange ((char **) argv);	  else if (last_nonopt != optind)	    first_nonopt = optind;	  /* Now skip any additional non-options	     and extend the range of non-options previously skipped.  */	  while (optind < argc		 && (argv[optind][0] != '-' || argv[optind][1] == '\0')		 )	    optind++;	  last_nonopt = optind;	}      /* Special ARGV-element `--' means premature end of options.	 Skip it like a null option,	 then exchange with previous non-options as if it were an option,	 then skip everything else like a non-option.  */      if (optind != argc && !strcmp (argv[optind], "--"))	{	  optind++;	  if (first_nonopt != last_nonopt && last_nonopt != optind)	    exchange ((char **) argv);	  else if (first_nonopt == last_nonopt)	    first_nonopt = optind;	  last_nonopt = argc;	  optind = argc;	}      /* If we have done all the ARGV-elements, stop the scan	 and back over any non-options that we skipped and permuted.  */      if (optind == argc)	{	  /* Set the next-arg-index to point at the non-options	     that we previously skipped, so the caller will digest them.  */	  if (first_nonopt != last_nonopt)	    optind = first_nonopt;	  return EOF;	}      /* If we have come to a non-option and did not permute it,	 either stop the scan or describe it to the caller and pass it by.  */      if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))	{	  if (ordering == REQUIRE_ORDER)	    return EOF;	  optarg = argv[optind++];	  return 1;	}      /* We have found another option-ARGV-element.	 Start decoding its characters.  */      nextchar = (argv[optind] + 1		  + (longopts != NULL && argv[optind][1] == '-'));    }  if (longopts != NULL && ((argv[optind][0] == '-' && (argv[optind][1] == '-'))))    {      const struct option *p;      char *s = nextchar;      int exact = 0;      int ambig = 0;      const struct option *pfound = NULL;      int indfound = 0;      while (*s && *s != '=')	s++;      /* Test all options for either exact match or abbreviated matches.  */      for (p = longopts, option_index = 0; p->name;	   p++, option_index++)	if (!strncmp (p->name, nextchar, s - nextchar))	  {	    if (s - nextchar == strlen (p->name))	      {		/* Exact match found.  */		pfound = p;		indfound = option_index;		exact = 1;		break;	      }	    else if (pfound == NULL)	      {		/* First nonexact match found.  */		pfound = p;		indfound = option_index;	      }	    else	      /* Second nonexact match found.  */	      ambig = 1;	  }      if (ambig && !exact)	{	  if (opterr)	    fprintf (stderr, "%s: option `%s' is ambiguous\n",		     argv[0], argv[optind]);	  nextchar += strlen (nextchar);	  optind++;	  return '?';	}      if (pfound != NULL)	{	  option_index = indfound;	  optind++;	  if (*s)	    {	      /* Don't test has_arg with >, because some C compilers don't		 allow it to be used on enums.  */	      if (pfound->has_arg)		optarg = s + 1;	      else		{		  if (opterr)		    {		      if (argv[optind - 1][1] == '-')			/* --option */			fprintf (stderr,				 "%s: option `--%s' doesn't allow an argument\n",				 argv[0], pfound->name);		      else			/* +option or -option */			fprintf (stderr,			     "%s: option `%c%s' doesn't allow an argument\n",			     argv[0], argv[optind - 1][0], pfound->name);		    }		  nextchar += strlen (nextchar);		  return '?';		}	    }	  else if (pfound->has_arg == 1)	    {	      if (optind < argc)		optarg = argv[optind++];	      else		{		  if (opterr)		    fprintf (stderr, "%s: option `%s' requires an argument\n",			     argv[0], argv[optind - 1]);		  nextchar += strlen (nextchar);		  return optstring[0] == ':' ? ':' : '?';		}	    }	  nextchar += strlen (nextchar);	  if (longind != NULL)	    *longind = option_index;	  if (pfound->flag)	    {	      *(pfound->flag) = pfound->val;	      return 0;	    }	  return pfound->val;	}      /* Can't find it as a long option.  If 	 the option starts with '--' or is not a valid short	 option, then it's an error.	 Otherwise interpret it as a short option.  */      if (argv[optind][1] == '-' || strchr (optstring, *nextchar) == NULL)	{	  if (opterr)	    {	      if (argv[optind][1] == '-')		/* --option */		fprintf (stderr, "%s: unrecognized option `--%s'\n",			 argv[0], nextchar);	      else		/* +option or -option */		fprintf (stderr, "%s: unrecognized option `%c%s'\n",			 argv[0], argv[optind][0], nextchar);	    }	  nextchar = (char *) "";	  optind++;	  return '?';	}    }  /* Look at and handle the next option-character.  */  {    char c = *nextchar++;    char *temp = strchr (optstring, c);    /* Increment `optind' when we start to process its last character.  */    if (*nextchar == '\0')      ++optind;    if (temp == NULL || c == ':')      {	if (opterr)	  {	    /* 1003.2 specifies the format of this message.  */	    fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);	  }	optopt = c;	return '?';      }    if (temp[1] == ':')      {	if (temp[2] == ':')	  {	    /* This is an option that accepts an argument optionally.  */	    if (*nextchar != '\0')	      {		optarg = nextchar;		optind++;	      }	    else	      optarg = 0;	    nextchar = NULL;	  }	else	  {	    /* This is an option that requires an argument.  */	    if (*nextchar != '\0')	      {		optarg = nextchar;		/* If we end this ARGV-element by taking the rest as an arg,		   we must advance to the next element now.  */		optind++;	      }	    else if (optind == argc)	      {		if (opterr)		  {		    /* 1003.2 specifies the format of this message.  */		    fprintf (stderr, "%s: option requires an argument -- %c\n",			     argv[0], c);		  }		optopt = c;		if (optstring[0] == ':')		  c = ':';		else		  c = '?';	      }	    else	      /* We already incremented `optind' once;		 increment it again when taking next ARGV-elt as argument.  */	      optarg = argv[optind++];	    nextchar = NULL;	  }      }    return c;  }}#endif	/* _LIBC or not __GNU_LIBRARY__.  */

⌨️ 快捷键说明

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