diff options
author | Tim Segers <tsegers@pm.me> | 2022-12-23 18:44:58 +0100 |
---|---|---|
committer | Tim Segers <tsegers@pm.me> | 2022-12-23 18:44:58 +0100 |
commit | c0f2ea4176b967ba902bb5e0e5c4ee3f28530beb (patch) | |
tree | 85ad3c174ab645f4e43a7ac91b6df9f98af7ebc3 | |
parent | 14009b2ee28f763d343f1905a2da2092f8b61f0b (diff) | |
download | opendeco-c0f2ea4176b967ba902bb5e0e5c4ee3f28530beb.tar.gz |
Extract CLI handling into separate file
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/opendeco-cli.c | 112 | ||||
-rw-r--r-- | src/opendeco-cli.h | 11 | ||||
-rw-r--r-- | src/opendeco-conf.h | 24 | ||||
-rw-r--r-- | src/opendeco.c | 129 |
5 files changed, 153 insertions, 127 deletions
@@ -5,8 +5,8 @@ CFLAGS = --std=c99 -pedantic -Wall -Werror -Os -DVERSION=${VERSION} all: opendeco opendeco_test libopendeco.a -opendeco: src/opendeco.c src/deco.c src/deco.h src/schedule.c src/schedule.h src/output.c src/output.h - $(CC) $(CFLAGS) src/opendeco.c src/deco.c src/schedule.c src/output.c -lm -o opendeco +opendeco: src/opendeco.c src/deco.c src/deco.h src/schedule.c src/schedule.h src/output.c src/output.h src/opendeco-cli.h src/opendeco-cli.c src/opendeco-conf.h + $(CC) $(CFLAGS) src/opendeco.c src/deco.c src/schedule.c src/output.c src/opendeco-cli.c -lm -o opendeco opendeco_test: test/opendeco_test.c test/deco_test.c src/deco.c $(CC) $(CFLAGS) test/minunit.c test/opendeco_test.c test/deco_test.c src/deco.c -lm -o opendeco_test diff --git a/src/opendeco-cli.c b/src/opendeco-cli.c new file mode 100644 index 0000000..4e21405 --- /dev/null +++ b/src/opendeco-cli.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: MIT-0 */ + +#include <argp.h> +#include <stdlib.h> + +#include "opendeco-cli.h" + +static char args_doc[] = ""; +static char doc[] = "Implementation of Buhlmann ZH-L16 with Gradient Factors:" + "\vExamples:\n\n" + " ./opendeco -d 18 -t 60 -g Air\n" + " ./opendeco -d 30 -t 60 -g EAN32\n" + " ./opendeco -d 40 -t 120 -g 21/35 -L 20 -H 80 --decogasses Oxygen,EAN50\n"; +const char *argp_program_bug_address = "<~tsegers/opendeco@lists.sr.ht> or https://todo.sr.ht/~tsegers/opendeco"; +const char *argp_program_version = "opendeco " VERSION; + +static struct argp_option options[] = { + {0, 0, 0, 0, "Dive options:", 0 }, + {"depth", 'd', "NUMBER", 0, "Set the depth of the dive in meters", 0 }, + {"time", 't', "NUMBER", 0, "Set the time of the dive in minutes", 1 }, + {"gas", 'g', "STRING", 0, "Set the bottom gas used during the dive, defaults to Air", 2 }, + {"pressure", 'p', "NUMBER", 0, "Set the surface air pressure, defaults to 1.01325bar or 1atm", 3 }, + {"rmv", 'r', "NUMBER", 0, "Set the RMV during the dive portion of the dive, defaults to 20", 4 }, + + {0, 0, 0, 0, "Deco options:", 0 }, + {"gflow", 'L', "NUMBER", 0, "Set the gradient factor at the first stop, defaults to 30", 5 }, + {"gfhigh", 'H', "NUMBER", 0, "Set the gradient factor at the surface, defaults to 75", 6 }, + {"decogasses", 'G', "LIST", 0, "Set the gasses available for deco", 7 }, + {0, 'S', 0, OPTION_ARG_OPTIONAL, "Only switch gas at deco stops", 8 }, + {0, '6', 0, OPTION_ARG_OPTIONAL, "Perform last deco stop at 6m", 9 }, + {"decormv", 'R', "NUMBER", 0, "Set the RMV during the deco portion of the dive, defaults to 15", 10}, + {"showtravel", 'T', 0, 0, "Show travel segments in deco plan", 11}, + + {0, 0, 0, 0, "Informational options:", 0 }, + {0, 0, 0, 0, 0, 0 } +}; + +static error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + struct arguments *arguments = state->input; + + switch (key) { + case 'd': + arguments->depth = arg ? atof(arg) : -1; + break; + case 't': + arguments->time = arg ? atof(arg) : -1; + break; + case 'g': + arguments->gas = arg; + break; + case 'p': + arguments->SURFACE_PRESSURE = arg ? atof(arg) : -1; + break; + case 'r': + arguments->RMV_DIVE = arg ? atof(arg) : -1; + break; + case 'L': + arguments->gflow = arg ? atoi(arg) : 100; + break; + case 'H': + arguments->gfhigh = arg ? atoi(arg) : 100; + break; + case 'G': + arguments->decogasses = arg; + break; + case 'S': + arguments->SWITCH_INTERMEDIATE = 0; + break; + case '6': + arguments->LAST_STOP_AT_SIX = 1; + break; + case 'R': + arguments->RMV_DECO = arg ? atof(arg) : -1; + break; + case 'T': + arguments->SHOW_TRAVEL = 1; + break; + case ARGP_KEY_END: + if (arguments->depth < 0 || arguments->time < 0) { + argp_state_help(state, stderr, ARGP_HELP_USAGE); + argp_failure(state, 1, 0, "Options -d and -t are required. See --help for more information"); + exit(ARGP_ERR_UNKNOWN); + } + if (arguments->SURFACE_PRESSURE <= 0) { + argp_failure(state, 1, 0, "Surface air pressure must be positive"); + exit(ARGP_ERR_UNKNOWN); + } + if (arguments->gflow > arguments->gfhigh) { + argp_failure(state, 1, 0, "GF Low must not be greater than GF High"); + exit(ARGP_ERR_UNKNOWN); + } + if (arguments->RMV_DIVE <= 0) { + argp_failure(state, 1, 0, "Dive RMV must be greater than 0"); + exit(ARGP_ERR_UNKNOWN); + } + if (arguments->RMV_DECO <= 0) { + argp_failure(state, 1, 0, "Deco RMV must be greater than 0"); + exit(ARGP_ERR_UNKNOWN); + } + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +void opendeco_argp_parse(int argc, char *argv[], struct arguments *arguments) +{ + static struct argp argp = {options, parse_opt, args_doc, doc, 0, 0, 0}; + argp_parse(&argp, argc, argv, 0, 0, arguments); +} diff --git a/src/opendeco-cli.h b/src/opendeco-cli.h new file mode 100644 index 0000000..70aa3ce --- /dev/null +++ b/src/opendeco-cli.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT-0 */ + +#ifndef OPENDECOCLI_H +#define OPENDECOCLI_H + +#include "opendeco-conf.h" + +/* functions */ +void opendeco_argp_parse(int argc, char *argv[], struct arguments *arguments); + +#endif /* end of include guard: OPENDECOCLI_H */ diff --git a/src/opendeco-conf.h b/src/opendeco-conf.h new file mode 100644 index 0000000..cb5b863 --- /dev/null +++ b/src/opendeco-conf.h @@ -0,0 +1,24 @@ +#ifndef OPENDECOCONF_H +#define OPENDECOCONF_H + +#ifndef VERSION +#define VERSION "unknown version" +#endif + +/* types */ +struct arguments { + double depth; + double time; + char *gas; + int gflow; + int gfhigh; + char *decogasses; + double SURFACE_PRESSURE; + int SWITCH_INTERMEDIATE; + int LAST_STOP_AT_SIX; + double RMV_DIVE; + double RMV_DECO; + int SHOW_TRAVEL; +}; + +#endif /* end of include guard: OPENDECOCONF_H */ diff --git a/src/opendeco.c b/src/opendeco.c index 0177b08..862923e 100644 --- a/src/opendeco.c +++ b/src/opendeco.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: MIT-0 */ -#include <argp.h> #include <locale.h> #include <math.h> #include <stdlib.h> @@ -8,8 +7,10 @@ #include <wchar.h> #include "deco.h" -#include "schedule.h" +#include "opendeco-cli.h" +#include "opendeco-conf.h" #include "output.h" +#include "schedule.h" #define MOD_OXY (abs_depth(msw_to_bar(6))) @@ -17,131 +18,11 @@ #define RMV_DECO_DEFAULT 15 #define SHOW_TRAVEL_DEFAULT 0 -#ifndef VERSION -#define VERSION "unknown version" -#endif - double RMV_DIVE = RMV_DIVE_DEFAULT; double RMV_DECO = RMV_DECO_DEFAULT; int SHOW_TRAVEL = SHOW_TRAVEL_DEFAULT; -/* argp settings */ -static char args_doc[] = ""; -static char doc[] = "Implementation of Buhlmann ZH-L16 with Gradient Factors:" - "\vExamples:\n\n" - " ./opendeco -d 18 -t 60 -g Air\n" - " ./opendeco -d 30 -t 60 -g EAN32\n" - " ./opendeco -d 40 -t 120 -g 21/35 -L 20 -H 80 --decogasses Oxygen,EAN50\n"; -const char *argp_program_bug_address = "<~tsegers/opendeco@lists.sr.ht> or https://todo.sr.ht/~tsegers/opendeco"; -const char *argp_program_version = "opendeco " VERSION; - -static struct argp_option options[] = { - {0, 0, 0, 0, "Dive options:", 0 }, - {"depth", 'd', "NUMBER", 0, "Set the depth of the dive in meters", 0 }, - {"time", 't', "NUMBER", 0, "Set the time of the dive in minutes", 1 }, - {"gas", 'g', "STRING", 0, "Set the bottom gas used during the dive, defaults to Air", 2 }, - {"pressure", 'p', "NUMBER", 0, "Set the surface air pressure, defaults to 1.01325bar or 1atm", 3 }, - {"rmv", 'r', "NUMBER", 0, "Set the RMV during the dive portion of the dive, defaults to 20", 4 }, - - {0, 0, 0, 0, "Deco options:", 0 }, - {"gflow", 'L', "NUMBER", 0, "Set the gradient factor at the first stop, defaults to 30", 5 }, - {"gfhigh", 'H', "NUMBER", 0, "Set the gradient factor at the surface, defaults to 75", 6 }, - {"decogasses", 'G', "LIST", 0, "Set the gasses available for deco", 7 }, - {0, 'S', 0, OPTION_ARG_OPTIONAL, "Only switch gas at deco stops", 8 }, - {0, '6', 0, OPTION_ARG_OPTIONAL, "Perform last deco stop at 6m", 9 }, - {"decormv", 'R', "NUMBER", 0, "Set the RMV during the deco portion of the dive, defaults to 15", 10}, - {"showtravel", 'T', 0, 0, "Show travel segments in deco plan", 11}, - - {0, 0, 0, 0, "Informational options:", 0 }, - {0, 0, 0, 0, 0, 0 } -}; - -struct arguments { - double depth; - double time; - char *gas; - int gflow; - int gfhigh; - char *decogasses; - double SURFACE_PRESSURE; - int SWITCH_INTERMEDIATE; - int LAST_STOP_AT_SIX; - double RMV_DIVE; - double RMV_DECO; - int SHOW_TRAVEL; -}; - -static error_t parse_opt(int key, char *arg, struct argp_state *state) -{ - struct arguments *arguments = state->input; - - switch (key) { - case 'd': - arguments->depth = arg ? atof(arg) : -1; - break; - case 't': - arguments->time = arg ? atof(arg) : -1; - break; - case 'g': - arguments->gas = arg; - break; - case 'p': - arguments->SURFACE_PRESSURE = arg ? atof(arg) : -1; - break; - case 'r': - arguments->RMV_DIVE = arg ? atof(arg) : -1; - break; - case 'L': - arguments->gflow = arg ? atoi(arg) : 100; - break; - case 'H': - arguments->gfhigh = arg ? atoi(arg) : 100; - break; - case 'G': - arguments->decogasses = arg; - break; - case 'S': - arguments->SWITCH_INTERMEDIATE = 0; - break; - case '6': - arguments->LAST_STOP_AT_SIX = 1; - break; - case 'R': - arguments->RMV_DECO = arg ? atof(arg) : -1; - break; - case 'T': - arguments->SHOW_TRAVEL = 1; - break; - case ARGP_KEY_END: - if (arguments->depth < 0 || arguments->time < 0) { - argp_state_help(state, stderr, ARGP_HELP_USAGE); - argp_failure(state, 1, 0, "Options -d and -t are required. See --help for more information"); - exit(ARGP_ERR_UNKNOWN); - } - if (arguments->SURFACE_PRESSURE <= 0) { - argp_failure(state, 1, 0, "Surface air pressure must be positive"); - exit(ARGP_ERR_UNKNOWN); - } - if (arguments->gflow > arguments->gfhigh) { - argp_failure(state, 1, 0, "GF Low must not be greater than GF High"); - exit(ARGP_ERR_UNKNOWN); - } - if (arguments->RMV_DIVE <= 0) { - argp_failure(state, 1, 0, "Dive RMV must be greater than 0"); - exit(ARGP_ERR_UNKNOWN); - } - if (arguments->RMV_DECO <= 0) { - argp_failure(state, 1, 0, "Deco RMV must be greater than 0"); - exit(ARGP_ERR_UNKNOWN); - } - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - static struct gas_usage { const gas_t *gas; double usage; @@ -257,8 +138,6 @@ int main(int argc, char *argv[]) setlocale(LC_ALL, "en_US.utf8"); /* argp */ - static struct argp argp = {options, parse_opt, args_doc, doc, 0, 0, 0}; - struct arguments arguments = { .depth = -1, .time = -1, @@ -274,7 +153,7 @@ int main(int argc, char *argv[]) .SHOW_TRAVEL = SHOW_TRAVEL_DEFAULT, }; - argp_parse(&argp, argc, argv, 0, 0, &arguments); + opendeco_argp_parse(argc, argv, &arguments); /* apply global options */ SURFACE_PRESSURE = arguments.SURFACE_PRESSURE; |