📄 goptions.c
字号:
/****************** Start of $RCSfile: goptions.c,v $ ****************** $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/goptions.c,v $* $Id: goptions.c,v 1.3 2004/07/08 20:34:44 alb Exp alb $* $Date: 2004/07/08 20:34:44 $* $Author: alb $********* description *********************************************************************************************************************/#include <conf.h>#include <version.h> static char * fileversion = "$RCSfile: goptions.c,v $ $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/goptions.c,v $ $Id: goptions.c,v 1.3 2004/07/08 20:34:44 alb Exp alb $ " PACKAGE " " VERSION_STRING;#include <string.h>#include <stdarg.h>#include <x_types.h>#include <x_errno.h>#include <genutils.h>#include <fileutil.h>#include <ctype.h>#define GETOUT { goto getout; }#define CLEANUP { goto cleanup; }struct optdesc { Int32 minargs; Int32 maxargs; UChar *optname; Int32 *argnumptr; void **arglist; UChar *plusoptptr; X_Type argtype; Flag plusopt; Flag countflag;};#define newarg \ { args = ZRENEWP(args, struct optdesc, num_args + 1); \ if(!args) \ GETOUT; \ SETZERO(args[num_args]); \ args[num_args].optname = NULL; \ actarg = num_args; \ num_args++; \ }#define act optstring[i]#define errexit(num) { errno = r = num ; GETOUT ; }#define nextc { i++; while(isspace(optstring[i]) && optstring[i]) i++; \ if(!optstring[i]) errexit(BAD_STRING_FORMAT); }#define NOT_USED -1#define OPTION_FLAGS -2#define TypeUNUSED_ARG TypeReal32PTRstatic Int32 all_flag_args(UChar *, struct optdesc *, Int32);Int32goptions( Int32 argc, UChar **argv, UChar *optionstring, ...){ va_list add_args; struct optdesc *args = NULL; Int32 num_args = 0, actarg, used_args, idx; Int32 nonames, i, j, argoffset = 0, ii; Int32 unused_args_idx = -1; UChar *cptr; Int32 *argtable = NULL, r = NO_ERROR; UChar **argstrings = NULL, *optstring = NULL; UChar no_msgs = 0; int n; long int ibuf; if(argc < 0){ argc = -argc; no_msgs = 1; } /* get memory for some stuff and initialize it */ argstrings = NEWP(UChar *, argc + argc); /* 2*argc is safety space */ argtable = NEWP(Int32, argc); optstring = strdup(optionstring); /* work on duplicate, cause it */ if(!argstrings || !argtable || !optstring) /* is to be modified */ errexit(errno); for(i = 0; i < argc; i++){ argtable[i] = NOT_USED; } /* build a record of possible options from the option-string */ i = 0; /* i points to the current character in the option-string */ forever{ while(act == ';') /* skip separator(s) */ i++; if(!act) /* act is defined as the current character */ break; newarg; /* increment i, skip whitespace and check for EOS */ if(act == '+'){ /* option starts with a '+' */ args[actarg].plusopt = 1; nextc; } switch(act){ /* select format character -> type */ case 'f': args[actarg].argtype = TypeReal32; break; case 'd': args[actarg].argtype = TypeReal64; break; case 'i': args[actarg].argtype = TypeInt32; break; case 'u': args[actarg].argtype = TypeUns32; break; case 'b': args[actarg].argtype = TypeUChar; break; case 'c': args[actarg].argtype = TypeInt32; args[actarg].countflag = YES; break; case 's': args[actarg].argtype = TypeUCharPTR; break; case '*': args[actarg].argtype = TypeUNUSED_ARG; break; default: errexit(BAD_STRING_FORMAT); } if(args[actarg].argtype != TypeUNUSED_ARG) nextc; if(args[actarg].argtype == TypeUNUSED_ARG){ args[actarg].minargs = 2; args[actarg].maxargs = 2; unused_args_idx = actarg; } else if(act == ':'){ /* separator ? -> no range of */ args[actarg].minargs = 1; /* option arguments defined */ args[actarg].maxargs = 1; /* -> 1 argument for option */ } else{ if(args[actarg].argtype == TypeUChar) errexit(BAD_STRING_FORMAT); if(act == '-'){ /* opening range */ args[actarg].minargs = 0; /* get maximum # of args */ nextc; if(1 > sscanf(optstring + i, "%ld%n", &ibuf, &n)) errexit(BAD_STRING_FORMAT); args[actarg].maxargs = ibuf; if(args[actarg].maxargs < 0) /* illegal value: maximum < 0 */ errexit(ILLEGAL_VALUE); i += n - 1; nextc; } else{ /* get first number */ if(1 > sscanf(optstring + i, "%ld%n", &ibuf, &n)) errexit(BAD_STRING_FORMAT); args[actarg].minargs = ibuf; i += n - 1; nextc; if(act == '-'){ /* range given: get second number */ nextc; if(1 > sscanf(optstring + i, "%ld%n", &ibuf, &n)) errexit(BAD_STRING_FORMAT); args[actarg].maxargs = ibuf; i += n - 1; nextc; if(act != ':') /* syntax check, ':' must follow */ errexit(BAD_STRING_FORMAT); /* exchange, if min > max */ if(args[actarg].maxargs < args[actarg].minargs) memswap(&args[actarg].maxargs, &args[actarg].minargs, sizeof(Int32)); if(args[actarg].minargs < 0 || args[actarg].maxargs < 0) errexit(ILLEGAL_VALUE); /* illegal values: min || max < 0 */ } else /* no range: exact number of arguments given */ args[actarg].maxargs = args[actarg].minargs; } if(act != ':') /* syntax check, ':' must follow */ errexit(BAD_STRING_FORMAT); } i++; /* skip whitespace */ while(optstring[i] && isspace(optstring[i])) i++; cptr = strchr(optstring + i, ';'); /* find end of option name */ if(cptr) *cptr = '\0'; if(args[actarg].argtype != TypeUNUSED_ARG) args[actarg].optname = strdup(optstring + i); /* get option name */ else args[actarg].optname = strdup(" "); /* check for multiple appearance of option names */ for(j = 0; j < num_args - 1; j++){ if(!strcmp(args[j].optname, args[actarg].optname)){ if(!args[j].optname[0] && ((args[j].argtype == TypeUChar && args[actarg].argtype != TypeUChar) || (args[j].argtype != TypeUChar && args[actarg].argtype == TypeUChar))) continue; /* This is the exception: The empty name may */ /* appear two times: as a boolean option and */ /* one other */ errexit(MULTIPLE_USE_ILLEGAL); } } if(cptr){ i = cptr - optstring; /* restore end of option name, */ *cptr = ';'; /* if not at the end of the optionstring */ } else i = strlen(optstring); /* now we're done with the optionstring */ } for(i = 0; i < num_args; i++){ /* get memory for the pointers */ j = args[i].maxargs; /* to the arguments */ if(j < 1) /* for safety we always use >= 1 */ j = 1; args[i].arglist = NEWP(void *, j); /* they can be of several types */ if(!args[i].arglist) errexit(errno); } va_start(add_args, optionstring); /* collect the argument pointers */ for(i = 0; i < num_args; i++){ /* first, if we have a '+'-option */ if(args[i].plusopt && args[i].argtype != TypeUChar) args[i].plusoptptr = va_arg(add_args, UChar *); if(args[i].minargs != args[i].maxargs){ /* for the # of arguments */ args[i].argnumptr = va_arg(add_args, Int32 *); } for(j = 0; j < args[i].maxargs; j++) /* now for the arguments */ args[i].arglist[j] = va_arg(add_args, void *); } va_end(add_args); /* users arg-pointers are processed */ for(i = 1; i < argc; i++){ /* step through the command line and */ switch(argv[i][0]){ /* connect the argv with the options' record */ case '-': /* an option always starts with - or + */ case '+': /* 1st: the options with names longer than 1 char */ for(j = 0; j < num_args; j++){ if(((args[j].argtype != TypeUChar && !args[j].countflag) || strlen(args[j].optname) > 1) && strlen(argv[i]) > 1/*2*/){ if(!strncmp(argv[i] + 1, args[j].optname, strlen(argv[i] + 1))){ if(strlen(argv[i]) == 2){ for(ii = 0; ii < num_args; ii++){ if(strlen(args[ii].optname) == 1 && ii != j && args[ii].optname[0] == argv[i][1]) break; } if(ii < num_args){ if(! no_msgs) fprintf(stderr, T_("Warning: one-letter flag %s ambigous, ignored.\n"), argv[i] + 1); break; /* the name has already been used */ } } if(argtable[i] >= 0){ if(! no_msgs) fprintf(stderr, T_("Warning: Ambigous argument: %s. Second occurrence ignored.\n"), argv[i] + 1); break; /* the name has already been used */ } argtable[i] = j; /* mark the index to the record */ if(args[j].argnumptr) *args[j].argnumptr = 0; /* reset the # */ break; } } } if(j >= num_args){ /* 2nd: the non-bool options, 1 char leng */ for(j = 0; j < num_args; j++){ if(args[j].argtype != TypeUChar && !args[j].countflag && strlen(args[j].optname) == 1){ if(argv[i][1] == args[j].optname[0]){ if(argtable[i] >= 0){ if(! no_msgs) fprintf(stderr, T_("Warning: Ambigous argument: %s. Second occurrence ignored.\n"), argv[i] + 1); break; /* the name has already been used */ } argtable[i] = j; /* mark the index to the record */ if(args[j].argnumptr) *args[j].argnumptr = 0; /* reset the # */ break; } } } } /* 3rd: the options - and + without any letters */ if(j >= num_args && argv[i][1] == '\0'){ for(j = 0; j < num_args; j++){ if(! args[j].optname[0] && args[j].argtype == TypeUChar){ argtable[i] = j;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -