aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGravatar Tim Segers <tsegers@pm.me>2022-12-23 18:44:58 +0100
committerGravatar Tim Segers <tsegers@pm.me>2022-12-23 18:44:58 +0100
commitc0f2ea4176b967ba902bb5e0e5c4ee3f28530beb (patch)
tree85ad3c174ab645f4e43a7ac91b6df9f98af7ebc3
parent14009b2ee28f763d343f1905a2da2092f8b61f0b (diff)
downloadopendeco-c0f2ea4176b967ba902bb5e0e5c4ee3f28530beb.tar.gz
Extract CLI handling into separate file
-rw-r--r--Makefile4
-rw-r--r--src/opendeco-cli.c112
-rw-r--r--src/opendeco-cli.h11
-rw-r--r--src/opendeco-conf.h24
-rw-r--r--src/opendeco.c129
5 files changed, 153 insertions, 127 deletions
diff --git a/Makefile b/Makefile
index 6702a26..24d7627 100644
--- a/Makefile
+++ b/Makefile
@@ -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;