📄 getopts.c
字号:
/* +++Date last modified: 05-Jul-1997 */
/************************************************************************/
/* */
/* 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. */
/* */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "sniptype.h"
#include "filnames.h"
#include "errors.h"
#include "dirport.h"
#include "snipmath.h"
#include "minmax.h"
#include "getopts.h"
#include "numcnvrt.h"
#define MAX_XARGS 512
int xargc = 0;
char *xargv[MAX_XARGS] = {NULL};
Boolean_T getopts_range_err = False_;
Boolean_T xargs_on = True_;
static FILE *rspfile = NULL;
static int count = 0, argidx = 0;
enum proc_stat { PSerror = -1, PSok, PSliteral};
static Boolean_T PASCAL bounds(struct Option_Tag *);
static enum proc_stat PASCAL swProc(char *swStr);
static void PASCAL 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; )
{
/*
** If necessary, open a response file
*/
if (scanning && !rspfile && '@' == argv[i][0])
{
rspfile = cant(&argv[i][1], "r");
--xargc;
continue;
}
/*
** Get the next argument
*/
if (rspfile)
{
if (NULL == fgets(newarg, 256, rspfile))
{
rspfile = NULL;
++i;
continue;
}
else
{
if ('\n' == LAST_CHAR(newarg))
LAST_CHAR(newarg) = NUL;
}
}
else
{
strcpy(newarg, argv[i++]);
}
/*
** Per Unix tradition, back-to-back switch characters signify
** the end of the switches
*/
if ((2 == strlen(newarg)) && strchr("-/", newarg[0]) &&
strchr("-/", newarg[1]))
{
scanning = False_;
if (!rspfile)
--xargc;
continue;
}
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
*/
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 PASCAL swProc(char *swStr)
{
struct Option_Tag *ptr;
Boolean_T searching;
unsigned short byte_var;
char *arg_ptr;
/*
** 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 Byte_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
sscanf(arg_ptr, "%hx", &byte_var);
*((char *)(ptr->buf)) = (unsigned char)(byte_var & 0xff);
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 *)(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 *)(ptr->buf)) =
(short)(dround(getopts_eval(arg_ptr)));
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 *)(ptr->buf));
bounds(ptr);
searching = False_;
break;
case Long_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
*((long *)(ptr->buf)) =
(long)(dround(getopts_eval(arg_ptr)));
bounds(ptr);
searching = False_;
break;
case DWord_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 *)(ptr->buf));
bounds(ptr);
searching = False_;
break;
case Float_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
}
else arg_ptr = &swStr[2];
*((double *)(ptr->buf)) = (double)getopts_eval(arg_ptr);
bounds(ptr);
searching = False_;
break;
case DFloat_Tag:
if (!swStr[2])
{
if (ptr->Default)
arg_ptr = ptr->Default;
else return PSerror;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -