📄 args.c
字号:
/** This file is part of Firestorm NIDS* Copyright (c) 2002 Gianni Tedesco* This program is released under the terms of the GNU GPL version 2** This is an argument parsing library designed to work on const strings,* it is typesafe and presents a simple API. Supported types are strings,* integers (signed and unsigned) and boolean.*/#include <stdlib.h>#include <stdio.h>#include <string.h>#include <args.h>#define whitespace(x) ( ((x)==' ') || ((x)=='\t') )/* first char is blank because arg_q[0] means no quotes */static char arg_q[]=" \'\"";/* Dispatch functions */int arg_string(struct arg *, char *, void *);int arg_bytes(struct arg *, char *, void *);int arg_uint(struct arg *, char *, void *);int arg_int(struct arg *, char *, void *);int arg_bool(struct arg *, char *, void *);/* Dispatch table */typedef int(*proc_argdispatch)(struct arg *, char *, void *);proc_argdispatch arg_dfn[ARGTYPE_MAX]={ [ ARGTYPE_NOP ] arg_string, [ ARGTYPE_UINT ] arg_uint, [ ARGTYPE_PUINT ] arg_uint, [ ARGTYPE_INT ] arg_int, [ ARGTYPE_PINT ] arg_int, [ ARGTYPE_BYTES ] arg_bytes, [ ARGTYPE_PBYTES ] arg_bytes, [ ARGTYPE_STRING ] arg_string, [ ARGTYPE_BOOL ] arg_bool, [ ARGTYPE_PBOOL ] arg_bool,};/* Boolean data type */int arg_bool(struct arg *a, char *v, void *user){ unsigned int r; if ( !strcasecmp("true", v) || !strcasecmp("yes", v) || !strcasecmp("on", v) ) { r=1; }else if ( !strcasecmp("false", v) || !strcasecmp("no", v) || !strcasecmp("off", v) ) { r=0; }else return -1; if ( a->type==ARGTYPE_PBOOL ) { if ( a->val.vp_bool ) { *a->val.vp_bool=r; return 1; }else return -1; }else{ if ( !a->fn ) return -1; a->val.v_bool=r; return a->fn(a, user); }}/* Numeric datatype for representing bytes (eg: 1024k, 10M ) */int arg_bytes(struct arg *a, char *v, void *user){ unsigned int d; unsigned int r; int p; for(r=0,p=0; v[p]; p++) { if ( (d=(unsigned int)(v[p]-'0')) < 10 ) { r=r*10+d; }else if (v[p]=='k' || v[p]=='K' ) { if ( v[p+1]!=0 ) return -1; r*=1024; }else if (v[p]=='m' || v[p]=='M' ) { if ( v[p+1]!=0 ) return -1; r*=(1024*1024); }else{ return -1; } } /* We found an non-numerical character */ if ( v[p]!=0 ) return -1; if ( a->type==ARGTYPE_PBYTES ) { if ( a->val.vp_bytes ) { *a->val.vp_bytes=r; return 1; }else return -1; }else{ if ( !a->fn ) return -1; a->val.v_bytes=r; return a->fn(a, user); }}/* Unsigned integer data type */int arg_uint(struct arg *a, char *v, void *user){ unsigned int d; unsigned int r; int p; for(r=0,p=0; (d=(unsigned int)(v[p]-'0')) < 10; p++) { r=r*10+d; } /* We found an non-numerical character */ if ( v[p]!=0 ) return -1; if ( a->type==ARGTYPE_PUINT ) { if ( a->val.vp_uint ) { *a->val.vp_uint=r; return 1; }else return -1; }else{ if ( !a->fn ) return -1; a->val.v_uint=r; return a->fn(a, user); }}/* Signed integer data type */int arg_int(struct arg *a, char *v, void *user){ unsigned int d; int r=0; int p=0; if ( v[0]=='-' ) p=1; for(; (d=(unsigned int)(v[p]-'0')) < 10; p++) { r=r*10+d; } /* We found an non-numerical character */ if ( v[p]!=0 ) return -1; if ( v[0]=='-' ) r=-r; if ( a->type==ARGTYPE_PINT ) { if ( a->val.vp_int ) { *a->val.vp_int=r; return 1; }else return -1; }else{ if ( !a->fn ) return -1; a->val.v_int=r; return a->fn(a, user); }}/* String data type */int arg_string(struct arg *a, char *v, void *user){ /* By specifying string or literal you * are saying you want a string */ if (a->type!=ARGTYPE_NOP && v==NULL) return -1; if ( !a->fn ) return -1; a->val.v_str=v; return a->fn(a, user);}/* Copy and NULL terminate from a read-only vector * in to a pre-allocated read/write buffer. */size_t arg_strcpy(char *dst, size_t dlen, char *src, size_t slen){ char *dend; char *send; int esc=0; size_t len=0; if ( !dst || !dlen || dlen+1 == 0) return 0; if ( !src || !slen ) { *dst=0; return 0; } dend=dst+dlen-1; send=src+slen; while ( dst<dend && src<send ) { if ( !esc && *(src)=='\\' ) { esc=1; src++; }else{ *(dst++)=*(src++); esc=0; len++; } } *dst=0; return len;}/* Dispatch a key/value pair to the right place */int arg_found(struct arg *a, char *key, size_t klen, char *val, size_t vlen, void *user) { char kbuf[AKEY_SIZE]; char vbuf[AVAL_SIZE]; char *r; struct arg *tmp; char *sval; int ret=0; arg_strcpy(kbuf, sizeof(kbuf), key, klen); arg_strcpy(vbuf, sizeof(vbuf), val, vlen); if ( vbuf[0]==0 ) { sval=NULL; }else{ sval=vbuf; } for(tmp=a; ; tmp++) { /* if name is passed but isn't right, keep looking */ if ( tmp->name && strcmp(kbuf, tmp->name) ) continue; /* Check it is possible to call back */ if ( a->type>=ARGTYPE_MAX || !arg_dfn[a->type] ) { ret=-1; break; } if ( !tmp->name ) { /* Fill in what the arg was so * handler can do own matching */ tmp->name=kbuf; r=NULL; }else{ r=tmp->name; } ret=arg_dfn[tmp->type](tmp, sval, user); tmp->name=r; /* can only match once */ break; } return ret;}/* Determine what kind of quote character this is */static inline int arg_quote(char q){ int i=0; for(i=1; arg_q[i]; i++) { if ( arg_q[i]==q ) return i; } i=0; return i;}/* Actual function for outsiders to use */int args_parse(struct arg *a, char *str, void *user){ int ret=0; /* state machine tape position */ char *cur; /* Initial state */ int state=0; int end=0; int inq=0; int esc=0; /* Key and value vectors */ char *key=NULL; size_t klen=0; char *val=NULL; size_t vlen=0; if ( a==NULL ) return -1; if ( str==NULL ) return -1; for(cur=str; ; cur++) { if ( *cur==0 ) end=1; if ( state==0 ) { /* leading whitespace */ if ( !whitespace(*cur) ) { state=1; key=cur; klen=1; } }else if ( state==1 ) { /* Inside a key */ if ( *cur=='=' ) { val=cur+1; vlen=0; state=2; }else if ( whitespace(*cur) || *cur==0 ) { if ( (ret=arg_found(a, key, klen, val, vlen, user))<=0 ) return ret; state=0; }else klen++; }else if ( state==2 ) { /* Inside a value */ /* Handle escaped characters */ if ( esc > 2 ) esc=0; if ( !esc && *cur=='\\' ) { esc=1; }else if ( esc ){ esc++; } if ( !inq ) { if ( !vlen && (inq=arg_quote(*cur)) ) { /* The first char is a quote char */ val++; }else if ( whitespace(*cur) || *cur==0) { /* No quotes */ if ( !vlen ) val=NULL; if ( (ret=arg_found(a, key, klen, val, vlen, user))<=0 ) return ret; key=val=NULL; esc=state=inq=klen=vlen=0; }else vlen++; }else{ /* Check for an end quote */ if ( (!esc && *cur==arg_q[inq]) || *cur==0) { if ( !vlen ) val=NULL; if ( (ret=arg_found(a, key, klen, val, vlen, user))<=0 ) return ret; key=val=NULL; esc=state=inq=klen=vlen=0; }else vlen++; } } if ( end ) break; } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -