📄 getargs.c
字号:
/* @(#)getargs.c 2.28 00/05/20 Copyright 1985, 1988, 1995 J. Schilling */#ifndef lintstatic char sccsid[] = "@(#)getargs.c 2.28 00/05/20 Copyright 1985, 1988, 1995 J. Schilling";#endif#define NEW/* * Copyright (c) 1985, 1988, 1995 J. Schilling * * 1.3.88 Start implementation of release 2 *//* * Parse arguments on a command line. * Format string specifier (appearing directly after flag name): * '' BOOL * '*' string * '?' char * '#' number * '&' call function * '+' inctype +++ NEU +++ *//* * 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; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* LINTLIBRARY */#include <mconfig.h>#include <standard.h>#include <getargs.h>#include <ctype.h>#include <vadefs.h>#include <strdefs.h>#include <schily.h>#define NOARGS 0 /* No more args */#define NOTAFLAG 1 /* Not a flag type argument */#define BADFLAG (-1) /* Not a valid flag argument */#define BADFMT (-2) /* Error in format string */#define NOTAFILE (-3) /* Seems to be a flag type arg */ int _getargs __PR((int *, char *const **, const char *, BOOL, va_list));LOCAL int dofile __PR((int *, char *const **, const char **));LOCAL int doflag __PR((int *, char *const **, const char *, const char *, BOOL, va_list));LOCAL int dosflags __PR((const char *, const char *, BOOL, va_list));LOCAL int checkfmt __PR((const char *));LOCAL int checkeql __PR((const char *));LOCAL va_list va_dummy;LOCAL char fmtspecs[] = "#?*&+"; #define isfmtspec(c) (strchr(fmtspecs, c) != NULL)/*---------------------------------------------------------------------------|| get flags until a non flag type argument is reached|+---------------------------------------------------------------------------*//* VARARGS3 */#ifdef PROTOTYPESint getargs(int *pac, char *const **pav, const char *fmt, ...)#elseint getargs(pac, pav, fmt, va_alist) int *pac; char **pav[]; char *fmt; va_dcl#endif{ va_list args; int ret;#ifdef PROTOTYPES va_start(args, fmt);#else va_start(args);#endif ret = _getargs(pac, pav, fmt, TRUE, args); va_end(args); return (ret);}/*---------------------------------------------------------------------------|| get all flags on the command line, do not stop on files|+---------------------------------------------------------------------------*//* VARARGS3 */#ifdef PROTOTYPESint getallargs(int *pac, char *const **pav, const char *fmt, ...)#elseint getallargs(pac, pav, fmt, va_alist) int *pac; char **pav[]; char *fmt; va_dcl#endif{ va_list args; int ret;#ifdef PROTOTYPES va_start(args, fmt);#else va_start(args);#endif for (;; (*pac)--, (*pav)++) { if ((ret = _getargs(pac, pav, fmt, TRUE, args)) != NOTAFLAG) break; } va_end(args); return (ret);}/*---------------------------------------------------------------------------|| get next non flag type argument (i.e. a file)|+---------------------------------------------------------------------------*/int getfiles(pac, pav, fmt) int *pac; char *const *pav[]; const char *fmt;{ return (_getargs(pac, pav, fmt, FALSE, va_dummy));}/*---------------------------------------------------------------------------|| check args until the next non flag type argmument is reached| *pac is decremented, *pav is incremented so that the| non flag type argument is at *pav[0]|| return code:| NOARGS no more args| NOTAFLAG not a flag type argument| BADFLAG a non-matching flag type argument| BADFMT bad syntax in format string||+---------------------------------------------------------------------------*//*LOCAL*/ int _getargs(pac, pav, fmt, setargs, args) register int *pac; register char *const **pav; const char *fmt; BOOL setargs; va_list args;{ const char *argp; int ret; for(; *pac > 0; (*pac)--, (*pav)++) { argp = **pav; ret = dofile(pac, pav, &argp); if (ret != NOTAFILE) return (ret); ret = doflag(pac, pav, argp, fmt, setargs, args); if (ret != NOTAFLAG) return (ret); } return (NOARGS);}/*---------------------------------------------------------------------------|| check if *pargp is a file type argument|+---------------------------------------------------------------------------*/LOCAL int dofile(pac, pav, pargp) register int *pac; register char *const **pav; const char **pargp;{ register const char *argp = *pargp; if (argp[0] == '-') { /* * "-" is a special non flag type argument * that usually means take stdin instead of a named file */ if (argp[1] == '\0') return (NOTAFLAG); /* * "--" is a prefix to take the next argument * as non flag type argument * NOTE: Posix requires "--" to indicate the end of the * flags on the command line. But we are currently not * Posix. */ if (argp[1] == '-' && argp[2] == '\0') { if (--(*pac) > 0) { (*pav)++; return (NOTAFLAG); } else { return (NOARGS); } } } /* * now check if it may be flag type argument * flag type arguments begin with a '-', a '+' or contain a '=' * i.e. -flag +flag or flag= */ if (argp[0] != '-' && argp[0] != '+' && (!checkeql(argp))) return (NOTAFLAG); return (NOTAFILE);}/*---------------------------------------------------------------------------|| compare argp with the format string| if a match is found store the result a la scanf in one of the| arguments pointed to in the va_list|| If setargs is FALSE, only check arguments for getfiles()| in this case, va_list may be a dummy arg.|+---------------------------------------------------------------------------*/LOCAL int doflag(pac, pav, argp, fmt, setargs, oargs) int *pac; char *const **pav; register const char *argp; register const char *fmt; BOOL setargs; va_list oargs;{ long val; int singlecharflag = 0; BOOL isspec; BOOL hasdash = FALSE; BOOL doubledash = FALSE; BOOL haseql = checkeql(argp); const char *sargp; const char *sfmt = fmt; va_list args; char *const *spav = *pav; int spac = *pac; void *curarg = (void *)0; /* * flags beginning with '-' don't have to include the '-' in * the format string. * flags beginning with '+' have to include it in the format string. */ if (argp[0] == '-') { argp++; hasdash = TRUE; /* * Implement legacy support for --longopt * If we find a double dash, we do not look for combinations * of boolean single char flags. */ if (argp[0] == '-') { argp++; doubledash = TRUE; /* * Allow -- only for long options. */ if (argp[1] == '\0') { return (BADFLAG); } } } sargp = argp; /* * Initialize 'args' to the start of the argument list. * I don't know any portable way to copy an arbitrary * C object so I use a system-specific routine * (probably a macro) from stdarg.h. (Remember that * if va_list is an array, 'args' will be a pointer * and '&args' won't be what I would need for memcpy.) * It is a system requirement for SVr4 compatibility * to be able to do this assgignement. If your system * defines va_list to be an array but does not define * va_copy() you are lost. * This is needed to make sure, that 'oargs' will not * be clobbered. */ va_copy(args, oargs); if (setargs) curarg = va_arg(args, void *); /* * check if the first flag in format string is a singlechar flag */ if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0') singlecharflag++; /* * check the whole format string for a match */ for(;;) { for(;*fmt; fmt++,argp++) { if (*fmt == '\\') { /* * Allow "#?*&+" to appear inside a flag. * NOTE: they must be escaped by '\\' only * inside the the format string. */ fmt++; isspec = FALSE; } else { isspec = isfmtspec(*fmt); } /* * If isspec is TRUE, the arg beeing checked starts * like a valid flag. Argp now points to the rest. */ if (isspec) { /* * If *argp is '+' and we are on the * beginning of the arg that is currently * checked, this cannot be an inc type flag. */ if (*argp == '+' && argp == sargp) continue; /* * skip over to arg of flag */ if (*argp == '=') { argp++; } else if (*argp != '\0' && haseql) { /* * Flag and arg are not separated by a * space. * Check here for: * xxxxx=yyyyy match on '&' * Checked before: * abc=yyyyy match on 'abc&' * or 'abc*' * or 'abc#' * We come here if 'argp' starts with * the same sequence as a valid flag * and contains an equal sign. * We have tested before if the text * before 'argp' matches exactly. * At this point we have no exact match * and we only allow to match * the special pattern '&'. * We need this e.g. for 'make'. * We allow any flag type argument to * match the format string "&" to set * up a function that handles all odd * stuff that getargs will not grok. * In addition, to allow getargs to be
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -