summaryrefslogtreecommitdiff
path: root/src/til_args.c
blob: b51f81b453595388584672dd2a6844519a19e532 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "til_args.h"

/*
 * ./rototiller --video=drm,dev=/dev/dri/card3,connector=VGA-1,mode=640x480@60
 * ./rototiller --video=sdl,size=640x480
 * ./rototiller --module=roto,foo=bar,module=settings
 * ./rototiller --defaults		// use default settings where unspecified
 * ./rototiller --go			// don't show args and wait for user input before proceeding
 * ./rototiller --seed=0xdeadbeef	// explicitly set global random seed instead of generating one
 * ./rototiller --print-pipes		// print values for the pipes every frame
 * ./rototiller --print-module-contexts // print information about registered module contexts every frame
 *
 * unrecognized arguments trigger an -EINVAL error, unless res_{argc,argv} are non-NULL
 * where a new argv will be allocated and populated with the otherwise invalid arguments
 * in the same order they were encountered in the input argv.  This is to support integration
 * with argv-handling application libraries like glib(g_application_run()).
 */
static int args_parse(int argc, const char *argv[], til_args_t *res_args, int *res_argc, const char **res_argv[])
{
	assert(argv);
	assert(res_args);
	assert(!res_argc || res_argv);

	if (res_argv) {
		*res_argv = calloc(argc + 1, sizeof(*res_argv));

		if (!*res_argv)
			return -ENOMEM;

		*res_argc = 0;
	}

	if (!argc)
		return 0;

	if (res_argv)
		(*res_argv)[(*res_argc)++] = argv[0];

	/* this is intentionally being kept very simple, no new dependencies like getopt. */

	for (int i = 1; i < argc; i++) {
		if (!strncasecmp("--video=", argv[i], 8)) {
			res_args->video = &argv[i][8];
		} else if (!strncasecmp("--module=", argv[i], 9)) {
			res_args->module = &argv[i][9];
		} else if (!strncasecmp("--seed=", argv[i], 7)) {
			res_args->seed = &argv[i][7];
		} else if (!strcasecmp("--defaults", argv[i])) {
			res_args->use_defaults = 1;
		} else if (!strcasecmp("--help", argv[i])) {
			res_args->help = 1;
		} else if (!strcasecmp("--go", argv[i])) {
			res_args->gogogo = 1;
		} else if (!strcasecmp("--print-module-contexts", argv[i])) {
			res_args->print_module_contexts = 1;
		} else if (!strcasecmp("--print-pipes", argv[i])) {
			res_args->print_pipes = 1;
		} else if (!strncasecmp("--title=", argv[i], 8)) {
			res_args->title = &argv[i][8];
		} else {
			if (!res_argv)
				return -EINVAL;

			(*res_argv)[(*res_argc)++] = argv[i];
		}
	}

	return 0;
}


int til_args_pruned_parse(int argc, const char *argv[], til_args_t *res_args, int *res_argc, const char **res_argv[])
{
	assert(res_argc && res_argv);

	return args_parse(argc, argv, res_args, res_argc, res_argv);
}


int til_args_parse(int argc, const char *argv[], til_args_t *res_args)
{
	return args_parse(argc, argv, res_args, NULL, NULL);

}


int til_args_help(FILE *out)
{
	return fprintf(out,
		"  --defaults              use defaults for unspecified settings\n"
		"  --go                    start rendering immediately upon fulfilling all required settings\n"
		"  --help                  this help\n"
		"  --module=               module settings\n"
		"  --print-module-contexts print active contexts on-stream to stdout\n"
		"  --print-pipes           print active pipes on-stream to stdout\n"
		"  --seed=                 seed to use for all PRNG in hexadecimal (e.g. 0xdeadbeef)\n"
		"  --title=                title to use where applicable (e.g. window title)\n"
		"  --video=                video settings\n"
		);
}
© All Rights Reserved