diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/simple-opt.h | 126 | 
1 files changed, 98 insertions, 28 deletions
| diff --git a/src/simple-opt.h b/src/simple-opt.h index 2a3564d..7bbb8b8 100644 --- a/src/simple-opt.h +++ b/src/simple-opt.h @@ -6,6 +6,7 @@  #include <string.h>  #include <stdio.h>  #include <ctype.h> +#include <errno.h>  /* the maximum number of options that can be passed on the cli */  #ifndef SIMPLE_OPT_MAX_ARGC @@ -33,7 +34,10 @@ enum simple_opt_type {  	SIMPLE_OPT_BOOL,  	SIMPLE_OPT_INT,  	SIMPLE_OPT_UNSIGNED, +	SIMPLE_OPT_DOUBLE, +	SIMPLE_OPT_CHAR,  	SIMPLE_OPT_STRING, +	SIMPLE_OPT_STRING_SET,  	SIMPLE_OPT_END,  }; @@ -43,21 +47,28 @@ struct simple_opt {  	const char *long_name;  	bool arg_is_required; -	/* optional, used for usage printing */ +	/* optional, a description of the option used for usage printing */  	const char *description;  	/* optional, a custom string describing the arg, used for usage printing */  	const char *custom_arg_string; +	/* for type SIMPLE_OPT_STRING_SET, a NULL-terminated array of string +	 * possibilities against which an option's argument is matched */ +	const char **string_set; +  	/* values assigned upon successful option parse */  	bool was_seen;  	bool arg_is_stored;  	union {  		bool val_bool; -		int val_int; -		unsigned val_unsigned; +		long val_int; +		unsigned long val_unsigned; +		double val_double; +		char val_char;  		char val_string[SIMPLE_OPT_OPT_ARG_MAX_WIDTH]; +		int val_string_set_idx;  	};  }; @@ -95,7 +106,7 @@ static void simple_opt_print_usage(FILE *f, unsigned width, char *usage_name,  static bool sub_simple_opt_parse(struct simple_opt *o, char *s)  {  	int i, j; -	char *str; +	char *str, *cp;  	bool match;  	switch (o->type) { @@ -148,35 +159,40 @@ strmatch_out:  	case SIMPLE_OPT_INT: +		errno = 0; +		o->val_int = strtol(s, &cp, 0); -		if (s[0] == '-' || s[0] == '+') { -			if (strlen(s) < 2) -				return false; -			j = 1; -		} else { -			j = 0; -		} +		if (cp == s || *cp != '\0' || errno) +			return false; -		for (i = j; s[i] != '\0'; i++) { -			if ( !isdigit(s[i]) ) -				return false; -		} +		return true; -		if (s[0] == '-') -			o->val_int = -atoi(s+j); -		else -			o->val_int = atoi(s+j); +	case SIMPLE_OPT_UNSIGNED: +		if (s[0] == '-' || s[0] == '+') +			return false; + +		errno = 0; +		o->val_unsigned = strtoul(s, &cp, 0); + +		if (cp == s || *cp != '\0' || errno) +			return false;  		return true; -	case SIMPLE_OPT_UNSIGNED: +	case SIMPLE_OPT_DOUBLE: +		errno = 0; +		o->val_double = strtod(s, &cp); -		for (i = 0; s[i] != '\0'; i++) { -			if ( !isdigit(s[i]) ) -				return false; -		} +		if (cp == s || *cp != '\0' || errno) +			return false; -		o->val_int = atoi(s); +		return true; + +	case SIMPLE_OPT_CHAR: +		if (strlen(s) != 1) +			return false; + +		o->val_char = s[0];  		return true;  	case SIMPLE_OPT_STRING: @@ -186,6 +202,16 @@ strmatch_out:  		strcpy(o->val_string, s);  		return true; +	case SIMPLE_OPT_STRING_SET: +		for (i = 0; o->string_set[i] != NULL; i++) { +			if (!strcmp(s, o->string_set[i])) { +				o->val_string_set_idx = i; +				return true; +			} +		} + +		return false; +  	default:  		return false;  	} @@ -398,8 +424,15 @@ static int sub_simple_opt_wrap_print(FILE *f, unsigned width, int col,  		add_newline = true;  	} -	if (add_newline) +	if (add_newline) {  		fprintf(f, "\n"); +		col = 0; + +		if (width > 20) { +			fprintf(f, "  "); +			col += 2; +		} +	}  	/* print out the message, trying to wrap at words */  	word_start = 0; @@ -426,12 +459,20 @@ static int sub_simple_opt_wrap_print(FILE *f, unsigned width, int col,  		if (width != 0 && col + (word_end - word_start) + (first_word ? 0 : 1)  				> width && first_word == false) {  			fprintf(f, "\n"); -			/* buffer up to line_start with spaces */  			col = 0; + +			/* buffer up to line_start with spaces */  			while (col < line_start) {  				fprintf(f, " ");  				col++;  			} + +			/* newline indentation, for readability */ +			if (width > 20) { +				fprintf(f, "  "); +				col += 2; +			} +  			first_word = true;  		}  @@ -522,9 +563,18 @@ static void simple_opt_print_usage(FILE *f, unsigned width, char *usage_name,  				case SIMPLE_OPT_UNSIGNED:  					j += 8;  					break; +				case SIMPLE_OPT_DOUBLE: +					j += 6; +					break; +				case SIMPLE_OPT_CHAR: +					j += 4; +					break;  				case SIMPLE_OPT_STRING:  					j += 6;  					break; +				case SIMPLE_OPT_STRING_SET: +					j += 10; +					break;  				default:  					break;  				} @@ -542,6 +592,11 @@ static void simple_opt_print_usage(FILE *f, unsigned width, char *usage_name,  		return;  	} +	/* if the desc_line_start is so far over it threatens readability, move it +	 * back a bit and just let the offending longer args be offset */ +	if (desc_line_start > (width / 2 < 30 ? width / 2 : 30)) +		desc_line_start = (width / 2 < 30 ? width / 2 : 30); +  	/*   	 * printing  @@ -631,10 +686,22 @@ static void simple_opt_print_usage(FILE *f, unsigned width, char *usage_name,  					sprintf(print_buffer + print_buffer_offset, "UNSIGNED");  					print_buffer_offset += 8;  					break; +				case SIMPLE_OPT_DOUBLE: +					sprintf(print_buffer + print_buffer_offset, "DOUBLE"); +					print_buffer_offset += 6; +					break; +				case SIMPLE_OPT_CHAR: +					sprintf(print_buffer + print_buffer_offset, "CHAR"); +					print_buffer_offset += 4; +					break;  				case SIMPLE_OPT_STRING:  					sprintf(print_buffer + print_buffer_offset, "STRING");  					print_buffer_offset += 6;  					break; +				case SIMPLE_OPT_STRING_SET: +					sprintf(print_buffer + print_buffer_offset, "STRING-SET"); +					print_buffer_offset += 10; +					break;  				default:  					break;  				} @@ -649,9 +716,12 @@ static void simple_opt_print_usage(FILE *f, unsigned width, char *usage_name,  		col = sub_simple_opt_wrap_print(f, width, col, 5, print_buffer);  		/* print option description */ -		if (options[i].description != NULL) +		if (options[i].description != NULL) { +			fprintf(f, "  "); +			col += 2;  			sub_simple_opt_wrap_print(f, width, col, desc_line_start,  					options[i].description); +		}  		/* end of this option */  		fprintf(f, "\n"); | 
