getopts.c
来自「国外网站上的一些精典的C程序」· C语言 代码 · 共 945 行 · 第 1/3 页
C
945 行
/************************************************************************/
/* */
/* GETOPTS.C - Universal command line options parser */
/* */
/* Original Copyright 1990-96 by Robert B. Stout as part of */
/* the MicroFirm Function Library (MFL) */
/* */
/* The user is granted a free limited license to use this source file */
/* to create royalty-free programs, subject to the terms of the */
/* license restrictions specified in the LICENSE.MFL file. */
/* */
/************************************************************************/
/*
** Modified 02-Aug-2001 for Win/Solaris by rbs
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "snipmath.h"
#include "sniptype.h"
#include "snip_str.h"
#include "filnames.h"
#include "errors.h"
#include "minmax.h"
#include "getopts.h"
#include "numcnvrt.h"
#include "dirport.h"
int xargc = 0;
char *xargv[MAX_XARGS] = {NULL};
Boolean_T getopts_range_err = False_;
#if defined(__unix__)
Boolean_T xargs_on = False_;
#else
Boolean_T xargs_on = True_;
#endif
static FILE *rspfile = NULL;
static int count = 0, argidx = 0;
static Boolean_T string_pending = False_;
static Boolean_T additive_pending = False_;
static char *pending_buf = NULL;
enum proc_stat { PSerror = -1, PSok, PSliteral};
static Boolean_T bounds(struct Option_Tag *);
static enum proc_stat swProc(char *swStr);
static enum proc_stat VoProc(char *swStr);
static void argProc(char *argStr);
/*
** getopts()
**
** Parameters: 1 - argc from main()
** 2 - argv from main()
** 3 - your program's options[] array
**
** Returns: Number of options specified or Error_
**
** Notes: 1. Your program should declare the global options[] array which
** specifies all options recognized by getopts().
**
** 2. Out of range data are coerced into range and getopts_range_err
** is set True_.
*/
int getopts(int argc, char *argv[])
{
int i;
Boolean_T scanning = True_;
struct Option_Tag *ptr;
char rspfname[FILENAME_MAX];
char newarg[256];
enum proc_stat ps;
xargc = argc;
xargv[argidx++] = argv[0];
for (i = 1, count = 0; i < argc; )
{
/*
** Get the next argument - first see if we're looking for a string
*/
if (string_pending)
{
if (additive_pending)
strcat(pending_buf, argv[i]);
else strcpy(pending_buf, argv[i]);
string_pending = additive_pending = False_;
pending_buf = NULL;
--xargc;
++i;
continue;
}
/*
** Next try a response file
*/
if (rspfile && !feof(rspfile))
{
if (NULL == fgets(newarg, 256, rspfile))
{
fclose(rspfile);
rspfile = NULL;
++i;
continue;
}
else strdelch(newarg, "\r\n");
}
/*
** Next, see if we're supposed to open a response file
*/
else if (scanning && !rspfile && '@' == argv[i][0])
{
/*
** If necessary, open a response file
*/
rspfile = cant(&argv[i][1], "r");
--xargc;
continue;
}
/*
** None of the above, copy the argument verbatim
*/
else
{
strcpy(newarg, argv[i++]);
}
/*
** Per Unix tradition, back-to-back switch characters signify
** the end of the switches
*/
if ('-' == newarg[0] && '-' == newarg[1])
{
printf("Found %s\n", newarg);
if (2 == strlen(newarg))
{
scanning = False_;
if (!rspfile)
--xargc;
continue;
}
else /* Process a verbose option */
{
VoProc(&newarg[2]);
continue;
}
}
/*
** If we got here, we're still processing switches
*/
if (scanning && (strchr("-", newarg[0])))
{
ps = swProc(newarg);
if (PSerror == ps)
return Error_;
if (PSok == ps)
continue;
}
/*
** If we got here, newarg must be an argument or filename
*/
else argProc(newarg);
}
return count;
}
/*
** Static function to process switch statements
**
** Parameters: 1 - argv[i] containing the switch
**
** Returns: PSok if switch successful
** PSerror if invalid
** PSliteral if literal (non-switch) argument
*/
static enum proc_stat swProc(char *swStr)
{
struct Option_Tag *ptr;
Boolean_T searching;
char *arg_ptr;
unsigned char byte_var;
int int_var;
short short_var;
unsigned short word_var;
long long_var;
unsigned long dword_var, bitfield_var;
double double_var;
/*
** Found a switch - If the 2nd character is also a switch
** character. If so, then it's a literal and is skipped
*/
if (strchr("-@", swStr[1]))
return PSliteral;
for (ptr = options, searching = True_; searching; ++ptr)
{
if (!ptr->case_sense)
{
ptr->letter = toupper(ptr->letter);
swStr[1] = toupper(swStr[1]);
}
if ((int)swStr[1] == ptr->letter) switch (ptr->type)
{
case Boolean_Tag:
if ('-' == swStr[2])
*((Boolean_T *)(ptr->buf)) = False_;
else *((Boolean_T *)(ptr->buf)) = True_;
searching = False_;
break;
case Bitfield_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
sscanf(arg_ptr, "%lx", (unsigned long *)(bitfield_var));
*((unsigned long *)(ptr->buf)) |= (unsigned long)bitfield_var;
bounds(ptr);
searching = False_;
break;
case Byte_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
sscanf(arg_ptr, "%lx", &long_var);
byte_var = (unsigned char)(long_var & 0xffL);
if (ptr->additive)
*((char *)(ptr->buf)) += byte_var;
else *((char *)(ptr->buf)) = byte_var;
bounds(ptr);
searching = False_;
break;
case Int_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
int_var = (int)(dround(getopts_eval(arg_ptr)));
if (ptr->additive)
*((int *)(ptr->buf)) += (int)(dround(getopts_eval(arg_ptr)));
else *((int *)(ptr->buf)) = (int)(dround(getopts_eval(arg_ptr)));
bounds(ptr);
searching = False_;
break;
case Short_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
short_var = (short)dround(getopts_eval(arg_ptr));
if (ptr->additive)
*((short *)(ptr->buf)) += short_var;
else *((short *)(ptr->buf)) = short_var;
bounds(ptr);
searching = False_;
break;
case Word_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
sscanf(arg_ptr, "%hx", (unsigned short *)(&word_var));
if (ptr->additive)
*((unsigned short *)(ptr->buf)) += word_var;
else *((unsigned short *)(ptr->buf)) = word_var;
bounds(ptr);
searching = False_;
break;
case Long_Tag:
if (!swStr[2])
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?