aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkatherine <shmibs@shmibbles.me>2018-03-25 14:02:56 -0700
committerkatherine <shmibs@shmibbles.me>2018-03-25 14:02:56 -0700
commit274369e625cd972aa95aa900eb861a6dc5a24712 (patch)
tree3d6029e73b2e0929344dfd81a434ac72c6445173
parentb72f0a2f2657356286f0eda7408b5816561bccb7 (diff)
downloadsimple-opt-274369e625cd972aa95aa900eb861a6dc5a24712.tar.gz
use word-wrapping for error printing
-rw-r--r--README.md4
-rw-r--r--doc/example.c2
-rw-r--r--doc/interface.md5
-rw-r--r--simple-opt.h129
4 files changed, 97 insertions, 43 deletions
diff --git a/README.md b/README.md
index 8fc29f9..4dc9861 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,7 @@ int main(int argc, char **argv)
/* catch any errors and print a default error message. you can do this bit
* yourself, if you'd like more control of the output */
if (result.result_type != SIMPLE_OPT_RESULT_SUCCESS) {
- simple_opt_print_error(stderr, argv[0], result);
+ simple_opt_print_error(stderr, 80, argv[0], result);
return 1;
}
@@ -160,7 +160,7 @@ $ ./a.out --int
```
$ ./a.out --bool fake
./a.out: bad argument `fake` passed to option `--bool`
-expected boolean, (yes|true|on) or (no|false|off)
+ expected a boolean: (yes|true|on) or (no|false|off)
```
if one of the options passed is the help flag (`-h` or `--help`), this example
diff --git a/doc/example.c b/doc/example.c
index 2c21341..324473e 100644
--- a/doc/example.c
+++ b/doc/example.c
@@ -38,7 +38,7 @@ int main(int argc, char **argv)
/* catch any errors and print a default error message. you can do this bit
* yourself, if you'd like more control of the output */
if (result.result_type != SIMPLE_OPT_RESULT_SUCCESS) {
- simple_opt_print_error(stderr, argv[0], result);
+ simple_opt_print_error(stderr, 80, argv[0], result);
return 1;
}
diff --git a/doc/interface.md b/doc/interface.md
index e757e80..f8d5886 100644
--- a/doc/interface.md
+++ b/doc/interface.md
@@ -281,12 +281,15 @@ an alternative method for usage printing.
message, if there is one to be printed:
```
-static void simple_opt_print_error(FILE *f, char *command_name,
+static void simple_opt_print_error(FILE *f, unsigned width, char *command_name,
struct simple_opt_result result);
```
`f` is a file pointer to which the message should be printed.
+`width` is the width to which the output should be word-wrapped. if 0, no
+wrapping will be performed. see `width` in `simple_opt_print_usage` above.
+
`command_name` is the name of the command as it will be printed in the usage
statement. easiest is just to pass `argv[0]` here. if NULL is passed, "err:"
will be printed instead.
diff --git a/simple-opt.h b/simple-opt.h
index 0260467..56ff1f3 100644
--- a/simple-opt.h
+++ b/simple-opt.h
@@ -26,8 +26,8 @@
/* an internal print buffer width for usage printing. you shouldn't have to
* worry about this if you're sane */
-#ifndef SIMPLE_OPT_USAGE_PRINT_BUFFER_WIDTH
-#define SIMPLE_OPT_USAGE_PRINT_BUFFER_WIDTH 256
+#ifndef SIMPLE_OPT_PRINT_BUFFER_WIDTH
+#define SIMPLE_OPT_PRINT_BUFFER_WIDTH 4096
#endif
enum simple_opt_type {
@@ -100,7 +100,7 @@ static void simple_opt_print_usage(FILE *f, unsigned width,
char *command_name, char *command_options, char *command_summary,
struct simple_opt *options);
-static void simple_opt_print_error(FILE *f, char *command_name,
+static void simple_opt_print_error(FILE *f, unsigned width, char *command_name,
struct simple_opt_result result);
@@ -529,15 +529,15 @@ static void simple_opt_print_usage(FILE *f, unsigned width,
char *command_name, char *command_options, char *command_summary,
struct simple_opt *options)
{
- char print_buffer[SIMPLE_OPT_USAGE_PRINT_BUFFER_WIDTH];
+ char print_buffer[SIMPLE_OPT_PRINT_BUFFER_WIDTH];
unsigned i, j, col, print_buffer_offset, desc_line_start;
/* calculate the required line_start for printing descriptions (leaving
* space for the widest existing long-option) */
/* check for space for column 1 (short_name) */
- if (5 >= SIMPLE_OPT_USAGE_PRINT_BUFFER_WIDTH) {
- fprintf(f, "simple-opt internal err: usage print buffer too small\n");
+ if (5 >= SIMPLE_OPT_PRINT_BUFFER_WIDTH) {
+ fprintf(f, "simple-opt internal err: print buffer too small\n");
return;
}
@@ -596,7 +596,7 @@ static void simple_opt_print_usage(FILE *f, unsigned width,
}
/* check for space for long_name printing */
- if (desc_line_start - 5 - 2 >= SIMPLE_OPT_USAGE_PRINT_BUFFER_WIDTH) {
+ if (desc_line_start - 5 - 2 >= SIMPLE_OPT_PRINT_BUFFER_WIDTH) {
fprintf(f, "simple-opt internal err: usage print buffer too small\n");
return;
}
@@ -741,92 +741,143 @@ static void simple_opt_print_usage(FILE *f, unsigned width,
}
}
-static void simple_opt_print_error(FILE *f, char *command_name,
+static void simple_opt_print_error(FILE *f, unsigned width, char *command_name,
struct simple_opt_result result)
{
- char *s;
- unsigned i;
+ char print_buffer[SIMPLE_OPT_PRINT_BUFFER_WIDTH];
+ unsigned i, line_start, col;
+ int rval;
+
+ /* just easier to write */
+ size_t size = SIMPLE_OPT_PRINT_BUFFER_WIDTH;
if (result.result_type == SIMPLE_OPT_RESULT_SUCCESS)
return;
if (command_name != NULL)
- fprintf(f, "%s: ", command_name);
+ rval = snprintf(print_buffer, size, "%s:", command_name);
else
- fprintf(f, "err: ");
+ rval = snprintf(print_buffer, size, "err:");
+
+ if (rval < 0 || (unsigned)rval >= size) {
+ fprintf(f, "simple-opt internal err: print buffer too small\n");
+ return;
+ }
+
+ col = sub_simple_opt_wrap_print(f, width, 0, 0, print_buffer);
+
+ line_start = strlen(print_buffer) + 1;
switch (result.result_type) {
case SIMPLE_OPT_RESULT_UNRECOGNISED_OPTION:
- fprintf(f, "unrecognised option `%s`\n",
+ rval = snprintf(print_buffer, size, "unrecognised option `%s`",
result.option_string);
break;
case SIMPLE_OPT_RESULT_BAD_ARG:
- fprintf(f, "bad argument `%s` passed to option `%s`\n",
+ rval = snprintf(print_buffer, size,
+ "bad argument `%s` passed to option `%s`",
result.argument_string, result.option_string);
+
+ if (rval < 0 || (unsigned)rval >= size) {
+ fprintf(f, "simple-opt internal err: print buffer too small\n");
+ return;
+ }
+
+ sub_simple_opt_wrap_print(f, width, col, line_start,
+ print_buffer);
+ fprintf(f, "\n");
+ col = 0;
+
switch (result.option_type) {
case SIMPLE_OPT_BOOL:
- fprintf(f,
- "expected boolean, (yes|true|on) or (no|false|off)\n");
+ rval = snprintf(print_buffer, size,
+ "expected a boolean: (yes|true|on) or (no|false|off)");
break;
case SIMPLE_OPT_INT:
- fprintf(f, "expected integer value\n");
+ rval = snprintf(print_buffer, size,"expected integer value");
break;
case SIMPLE_OPT_UNSIGNED:
- fprintf(f, "expected unsigned integer value\n");
+ rval = snprintf(print_buffer, size,
+ "expected unsigned integer value");
break;
case SIMPLE_OPT_DOUBLE:
- fprintf(f, "expected floating-point value\n");
+ rval = snprintf(print_buffer, size,
+ "expected floating-point value");
break;
case SIMPLE_OPT_CHAR:
- fprintf(f, "expected single character\n");
+ rval = snprintf(print_buffer, size,
+ "expected single character");
break;
case SIMPLE_OPT_STRING:
- fprintf(f, "expected a string\n");
+ rval = snprintf(print_buffer, size,
+ "expected a string");
break;
case SIMPLE_OPT_STRING_SET:
for (i = 0; result.option->string_set[i] != NULL; i++);
- if (i == 1)
- fprintf(f, "expected \"%s\"\n", result.option->string_set[0]);
- else if (i == 2)
- fprintf(f, "expected \"%s\" or \"%s\"\n",
- result.option->string_set[0], result.option->string_set[1]);
- else if (i == 3)
- fprintf(f, "expected \"%s\", \"%s\" or \"%s\"\n",
- result.option->string_set[0], result.option->string_set[1],
+ if (i == 1) {
+ rval = snprintf(print_buffer, size, "expected \"%s\"",
+ result.option->string_set[0]);
+ } else if (i == 2) {
+ rval = snprintf(print_buffer, size,
+ "expected \"%s\" or \"%s\"",
+ result.option->string_set[0],
+ result.option->string_set[1]);
+ } else if (i == 3) {
+ rval = snprintf(print_buffer, size,
+ "expected \"%s\", \"%s\" or \"%s\"",
+ result.option->string_set[0],
+ result.option->string_set[1],
result.option->string_set[2]);
- else if (i == 4)
- fprintf(f, "expected \"%s\", \"%s\", \"%s\", or \"%s\"\n",
- result.option->string_set[0], result.option->string_set[1],
- result.option->string_set[2], result.option->string_set[3]);
- else
- fprintf(f, "expected a string\n");
+ } else if (i == 4) {
+ rval = snprintf(print_buffer, size,
+ "expected \"%s\", \"%s\", \"%s\", or \"%s\"",
+ result.option->string_set[0],
+ result.option->string_set[1],
+ result.option->string_set[2],
+ result.option->string_set[3]);
+ } else {
+ rval = snprintf(print_buffer, size,
+ "expected one of %u possibile strings", i);
+ }
default:
break;
}
break;
case SIMPLE_OPT_RESULT_MISSING_ARG:
- fprintf(f, "argument expected for option `%s`\n",
+ rval = snprintf(print_buffer, size,
+ "argument expected for option `%s`",
result.option_string);
break;
case SIMPLE_OPT_RESULT_OPT_ARG_TOO_LONG:
- fprintf(f, "argument passed to option `%s` is too long\n",
+ rval = snprintf(print_buffer, size,
+ "argument passed to option `%s` is too long",
result.option_string);
break;
case SIMPLE_OPT_RESULT_TOO_MANY_ARGS:
- fprintf(f, "too many cli arguments received\n");
+ rval = snprintf(print_buffer, size,
+ "too many cli arguments received");
break;
case SIMPLE_OPT_RESULT_MALFORMED_OPTION_STRUCT:
- fprintf(f, "malformed option struct (internal err)\n");
+ rval = snprintf(print_buffer, size,
+ "malformed option struct (internal err)");
break;
default:
break;
}
+
+ if (rval < 0 || (unsigned)rval >= size) {
+ fprintf(f, "simple-opt internal err: print buffer too small");
+ return;
+ }
+
+ sub_simple_opt_wrap_print(f, width, col, line_start, print_buffer);
+ fprintf(f, "\n");
}
#endif