vampirefrog 1 year ago
parent
commit
2833de2047
3 changed files with 147 additions and 1 deletions
  1. 119
    0
      cmdline.c
  2. 28
    0
      cmdline.h
  3. 0
    1
      main.c

+ 119
- 0
cmdline.c View File

@@ -0,0 +1,119 @@
1
+#include <stdlib.h>
2
+#include <string.h>
3
+
4
+#include <stdio.h>
5
+
6
+#include "cmdline.h"
7
+
8
+void cmdline_print_help(char *argv0, struct cmdline_option *opts, char *args_text) {
9
+	printf("Usage: %s [options] %s\n", argv0, args_text);
10
+	for(struct cmdline_option *opt = opts; opt->option_type != TYPE_END; opt++) {
11
+		printf("\t");
12
+		int l = 0;
13
+		if(opt->opt_char) {
14
+			printf("-%c", opt->opt_char);
15
+			l += 2;
16
+		}
17
+		if(opt->opt_char && opt->opt_long) {
18
+			printf(", ");
19
+			l += 2;
20
+		}
21
+		if(opt->opt_long) {
22
+			printf("--%s", opt->opt_long);
23
+			l += 2 + strlen(opt->opt_long);
24
+		}
25
+		if(opt->option_type == TYPE_REQUIRED) {
26
+			char *arg_name = opt->arg_name ? opt->arg_name : "X";
27
+			printf(" <%s>", arg_name);
28
+			l += 3 + strlen(arg_name);
29
+		}
30
+		else if(opt->option_type == TYPE_OPTIONAL) {
31
+			char *arg_name = opt->arg_name ? opt->arg_name : "X";
32
+			printf(" [%s]", arg_name);
33
+			l += 3 + strlen(arg_name);
34
+		}
35
+#define ALIGN 20
36
+		if(l < ALIGN)
37
+			for(int i = ALIGN; i > l; i--)
38
+				printf(" ");
39
+		if(opt->opt_help) printf("    %s\n", opt->opt_help);
40
+	}
41
+}
42
+
43
+static void cmdline_set_option_argument(struct cmdline_option *opt, char *str) {
44
+	switch(opt->option_argument_type) {
45
+		case TYPE_INT:
46
+			if(opt->target)
47
+				*((int *)opt->target) = strtol(str, 0, 0);
48
+			break;
49
+		case TYPE_FLOAT:
50
+			if(opt->target)
51
+				*((float *)opt->target) = strtof(str, 0);
52
+			break;
53
+		case TYPE_STRING:
54
+			if(opt->target)
55
+				*((char **)opt->target) = str;
56
+			break;
57
+		default:
58
+			break;
59
+	}
60
+}
61
+
62
+int cmdline_parse_args(int argc, char **argv, struct cmdline_option *opts, int num_required, int max_args, char *args_text) {
63
+	struct cmdline_option *expecting_opt = 0;
64
+	int first_nonopt = 1;
65
+	int stop_parsing = 0;
66
+	for(int i = 1; i < argc; i++) {
67
+		if(argv[i][0] == '-' && argv[i][1] != 0 && !stop_parsing) {
68
+			if(argv[i][1] == '-' && argv[i][2] == 0) {
69
+				stop_parsing = 1;
70
+			} else if((argv[i][1] == 'h' && argv[i][2] == 0) || !strcmp(argv[i], "--help")) {
71
+				cmdline_print_help(argv[0], opts, args_text);
72
+				return -1;
73
+			} else {
74
+				if(expecting_opt && expecting_opt->option_type == TYPE_REQUIRED)
75
+					fprintf(stderr, "Required argument not found: %s\n", argv[first_nonopt-1]);
76
+
77
+				expecting_opt = 0;
78
+				int found = 0;
79
+				for(struct cmdline_option *opt = opts; opt->option_type != TYPE_END; opt++) {
80
+					if(opt->opt_char > 0 && argv[i][1] == opt->opt_char) {
81
+						if(opt->option_type == TYPE_SWITCH) {
82
+							if(opt->target) *((int *)opt->target) = 1;
83
+						} else if(argv[i][2] != 0) {
84
+							cmdline_set_option_argument(opt, &argv[i][2]);
85
+						} else {
86
+							expecting_opt = opt;
87
+						}
88
+						found = 1;
89
+					} else if(opt->opt_long && argv[i][1] == '-' && !strcmp(&argv[i][2], opt->opt_long)) {
90
+						if(opt->option_type == TYPE_SWITCH) {
91
+							if(opt->target) *((int *)opt->target) = 1;
92
+						} else {
93
+							expecting_opt = opt;
94
+						}
95
+						found = 1;
96
+					}
97
+				}
98
+				if(!found) {
99
+					fprintf(stderr, "Unknown option: %s\n", argv[i]);
100
+				}
101
+			}
102
+		} else if(expecting_opt) {
103
+			cmdline_set_option_argument(expecting_opt, argv[i]);
104
+			expecting_opt = 0;
105
+		} else continue; // non-opt opt, just skip over it and don't execute code below
106
+
107
+		char *curarg = argv[i];
108
+		for(int j = i-1; j >= first_nonopt; j--) {
109
+			argv[j+1] = argv[j];
110
+		}
111
+		argv[first_nonopt] = curarg;
112
+		first_nonopt++;
113
+	}
114
+	if(argc - first_nonopt < num_required) {
115
+		cmdline_print_help(argv[0], opts, args_text);
116
+		return -1;
117
+	}
118
+	return first_nonopt;
119
+}

+ 28
- 0
cmdline.h View File

@@ -0,0 +1,28 @@
1
+#ifndef CMDLINE_H_
2
+#define CMDLINE_H_
3
+
4
+struct cmdline_option {
5
+	int opt_char;
6
+	char *opt_long;
7
+	char *opt_help;
8
+	char *arg_name;
9
+	enum {
10
+		TYPE_END = 0,
11
+		TYPE_SWITCH,
12
+		TYPE_REQUIRED,
13
+		TYPE_OPTIONAL
14
+	} option_type;
15
+	enum {
16
+		TYPE_NONE,
17
+		TYPE_INT,
18
+		TYPE_FLOAT,
19
+		TYPE_STRING
20
+	} option_argument_type;
21
+	void *target;
22
+};
23
+
24
+#define CMDLINE_ARG_TERMINATOR { 0, 0, 0, 0, TYPE_END, 0, 0 }
25
+
26
+int cmdline_parse_args(int argc, char **argv, struct cmdline_option opts[], int num_required_args, int max_args, char *args_text);
27
+
28
+#endif /* CMDLINE_H_ */

+ 0
- 1
main.c View File

@@ -10,7 +10,6 @@
10 10
 
11 11
 #include "v68.h"
12 12
 #include "v68io.h"
13
-#include "cmdline.h"
14 13
 #include "tools.h"
15 14
 
16 15
 #define BUF_SIZE 4096

Loading…
Cancel
Save