📄 argv.c
字号:
/* argv.c
* Copyright (C) 1998-2005 David Cole
*
* Implement getopt() like argv/argc parsing
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "argv.h"
/* Split a string into argc/argv
*
* Args:
* str - the argument string. Will be modified in place
* argv - array that will be filled with pointers to individual arguments
* argvSize - number of elements in argv
*
* Returns number of arguments found (argc)
*
* Example of sh-like argument parsing:
*
* in: \a\ \c
* out: a c
* in: "\a\ \c"
* out: \a\ \c
* in: '\a\ \c'
* out: \a\ \c
* in: \r\ Hallo" "\rLajos'\'"\""
* out: r Hallo \rLajos\"
*/
int getoptInit (char* str, char** argv, int argvSize)
{
int argc, state, strsep;
char *to;
for (argc= 0, to= str, state= 0; argc <= argvSize && *str; ++str) {
if (state==0) {
if (isspace(*str)); /* do nothing */
else if (*str=='"' || *str=='\'') {
argv[argc]= to; strsep= *str; state= 3;
} else if (*str=='\\') state= 2;
else {
argv[argc]= to; *to++ = *str; state= 1;
}
} else if (state==1) {
if (isspace(*str)) {
++argc; *to++ = '\0'; state= 0;
} else if (*str=='"' || *str=='\'') { strsep= *str; state= 3; }
else if (*str=='\\') state= 2;
else { *to++ = *str; }
} else if (state==2) {
*to++ = *str;
state = 1;
} else if (state==3) {
if (*str==strsep) state= 1;
else if (strsep=='"' && *str=='\\') state= 4;
else { *to++ = *str; }
} else if (state==4) {
if (*str!='"' && *str!='\\') *to++ = '\\';
*to++ = *str;
state = 3;
}
}
if (state!=0) { ++argc; *to= '\0'; };
return argc;
}
/* This variable is part of the getopt() functionality
*/
OptRet opt;
/* Iterates over argc/argv, returning arguments in the order that they
* appear in argv. The first time that the function is called, it
* stores the passed argc/argv, these are then used for each
* subsequent call.
*
* Args:
* argcInit - number of arguments in argv
* argvInit - array of string arguments
* opts - describes argument structure;
* <c> - <c> is a switch (no associated data)
* <c>: - <c> is an argument with associated data
*
* Returns the next valid argument found in argv. If argument found
* does not appear in opts, '?' is returned. At end of argv or
* non-argument encountered, EOF is returned.
*/
int getopt (int argcInit, char* argvInit[], const char* opts)
{
static int argc; /* iterate over argc */
static char** argv; /* iterate over argv */
int c; /* the next command line argument */
const char *str, *optbeg, *optend; /* scan the option string */
const char *arg; /* scan the argument string */
int arglen, optlen, found, optno;
if (argv == NULL) {
/* Initialise getopt if this is the first time we have been
* called.
*/
argc = argcInit;
argv = argvInit;
opt.optind = -1;
}
/* Skip to the next argument, return EOF if there are no more.
*/
opt.optind++;
if (opt.optind == argc) {
argv = NULL;
return EOF;
}
/* Terminate argument processing if the next argument does not
* start with either a '-' or a '/'.
*/
if (*argv[opt.optind] != '/' && *argv[opt.optind] != '-') {
argv = NULL;
return EOF;
}
/* Get the argument, if it is '\0', then we have an error.
*/
arg = argv[opt.optind]+1;
c = toupper (arg[0]);
arglen = strlen (arg);
if (c == 0) {
return '?';
}
/* Find the argument in the option string, if not found, we have
* an error.
*/
for (found= 0, str= opts, optno= 1; ! found && *str != '\0'; ) {
if (*str=='(') {
optbeg = str+1;
optend = strchr (optbeg, ')');
if (optend) {
str = optend + 1;
} else { /* This should not be happen */
optend = str + strlen (str);
str = optend;
}
optlen = (int)(optend - optbeg);
found= arglen>=optlen &&
(arg[optlen]=='\x0' || arg[optlen]=='=') &&
strnicmp (optbeg, arg, optlen)==0;
} else {
found= toupper(*str)==c;
if (found) {
optbeg = str;
optend = str+1;
optlen = (int)(optend-optbeg);
}
++str;
}
if (! found) {
++optno;
if (*str==':') ++str;
}
}
if (! found) {
return '?';
}
if (*str == ':') { /* option with value */
if (optlen>1 && arg[optlen]=='=') { /* /LongOpt=Vale */
opt.optarg = (char *)(arg + optlen + 1);
} else if (optlen==1 && arg[1]!='\0') { /* /XValue */
opt.optarg = (char *)(arg + optlen);
} else { /* /Option Value */
if (opt.optind+1 < argc )
opt.optarg = argv[++opt.optind];
else {
/* error if the arguments are ended */
return '?';
}
}
}
/* Tell caller which argument we found
*/
if (optlen==1) return c;
else return GETOPT_LONGOPT + optno;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -