1 |
|
|
#include "gwion_util.h" |
2 |
|
|
#include "gwion_ast.h" |
3 |
|
|
#include "gwion_env.h" |
4 |
|
|
#include "soundinfo.h" |
5 |
|
|
#include "vm.h" |
6 |
|
|
#include "gwion.h" |
7 |
|
|
#include "arg.h" |
8 |
|
|
#include "pass.h" |
9 |
|
|
|
10 |
|
|
#define GWIONRC ".gwionrc" |
11 |
|
|
|
12 |
|
|
/* use before MemPool allocation */ |
13 |
|
714 |
ANN static inline void config_end(const Vector config) { |
14 |
✗✓ |
714 |
for(m_uint i = 0; i < vector_size(config); ++i) { |
15 |
|
|
const Vector v = (Vector)vector_at(config, i); |
16 |
|
|
for(m_uint i = 1; i < vector_size(v); ++i) |
17 |
|
|
xfree((m_str)vector_at(v, i)); |
18 |
|
|
vector_release(v); |
19 |
|
|
xfree(v); |
20 |
|
|
} |
21 |
|
714 |
} |
22 |
|
|
|
23 |
|
714 |
ANN static m_str plug_dir(void) { |
24 |
|
714 |
const m_str home = getenv("HOME"); |
25 |
|
714 |
const size_t sz = strlen(home); |
26 |
|
714 |
const m_str pdir = "/.gwplug"; |
27 |
|
714 |
m_str plug_dir = (m_str)xmalloc(sz + strlen(pdir) + 1); |
28 |
|
714 |
strcpy(plug_dir, home); |
29 |
|
714 |
strcpy(plug_dir + sz, pdir); |
30 |
|
714 |
return plug_dir; |
31 |
|
|
} |
32 |
|
|
|
33 |
|
714 |
ANN static void arg_init(Arg* arg) { |
34 |
|
714 |
vector_init(&arg->add); |
35 |
|
714 |
vector_init(&arg->lib); |
36 |
|
714 |
vector_init(&arg->mod); |
37 |
|
714 |
vector_init(&arg->config); |
38 |
|
714 |
vector_add(&arg->lib, (vtype)plug_dir()); |
39 |
|
714 |
} |
40 |
|
|
|
41 |
|
714 |
ANN void arg_release(Arg* arg) { |
42 |
|
714 |
vector_release(&arg->add); |
43 |
|
714 |
xfree((m_str)vector_front(&arg->lib)); |
44 |
|
714 |
vector_release(&arg->lib); |
45 |
|
714 |
vector_release(&arg->mod); |
46 |
|
714 |
config_end(&arg->config); |
47 |
|
714 |
vector_release(&arg->config); |
48 |
|
714 |
} |
49 |
|
|
|
50 |
|
|
static const char usage[] = |
51 |
|
|
"usage: Gwion <options>\n" |
52 |
|
|
" -h : this help\n" |
53 |
|
|
" -c <file> : load config\n" |
54 |
|
|
" -p <path> : add a plugin directory\n" |
55 |
|
|
" -s <number> : set samplerate\n" |
56 |
|
|
" -i <number> : set input channel number\n" |
57 |
|
|
" -o <number> : set output channel number\n" |
58 |
|
|
" -d <number> : set driver (and arguments)\n" |
59 |
|
|
" -l <number> : set loop mode\n" |
60 |
|
|
" -m <mod:args> : load module (and arguments)\n" |
61 |
|
|
" -g <mod:args> : set Gwion compiler passes order\n"; |
62 |
|
|
|
63 |
|
|
ANN static void config_parse(const Gwion, Arg*, const m_str); |
64 |
|
|
|
65 |
|
|
#define ARG2INT(a) strtol(a, NULL, 10) |
66 |
|
|
|
67 |
|
2 |
ANN2(1) static inline void arg_set_pass(const Gwion gwion, const m_str str) { |
68 |
|
2 |
const Vector v = split_args(gwion->mp, str); |
69 |
|
2 |
pass_set(gwion, v); |
70 |
✓✓ |
4 |
for(m_uint i = 0; i < vector_size(v); ++i) |
71 |
|
2 |
free_mstr(gwion->mp, (m_str)vector_at(v, i)); |
72 |
|
2 |
free_vector(gwion->mp, v); |
73 |
|
2 |
} |
74 |
|
|
|
75 |
|
714 |
ANN m_bool _arg_parse(const Gwion gwion, Arg* arg) { |
76 |
|
714 |
struct CArg *ca = &arg->arg; |
77 |
✓✓ |
2924 |
for(ca->idx = 1; ca->idx < ca->argc; ++ca->idx) { |
78 |
✓✓ |
2213 |
if(ca->argv[ca->idx][0] == '-') { |
79 |
|
|
m_str tmp; |
80 |
✓✓✓✓ ✓✓✓✓ ✓✓✓ |
879 |
switch(ca->argv[ca->idx][1]) { |
81 |
|
1 |
case 'h': |
82 |
|
1 |
gw_err(usage); |
83 |
|
1 |
break; |
84 |
|
1 |
case 'c': |
85 |
✗✓ |
1 |
CHECK_OB((tmp = option_argument(ca))) |
86 |
|
1 |
config_parse(gwion, arg, tmp); |
87 |
|
1 |
break; |
88 |
|
79 |
case 'p': |
89 |
✓✓ |
79 |
CHECK_OB((tmp = option_argument(ca))) |
90 |
|
78 |
vector_add(&arg->lib, (vtype)tmp); |
91 |
|
78 |
break; |
92 |
|
77 |
case 'm': |
93 |
✗✓ |
77 |
CHECK_OB((tmp = option_argument(ca))) |
94 |
|
77 |
vector_add(&arg->mod, (vtype)tmp); |
95 |
|
77 |
break; |
96 |
|
2 |
case 'l': |
97 |
✗✓ |
2 |
CHECK_OB((tmp = option_argument(ca))) |
98 |
✓✓ |
2 |
arg->loop = (m_bool)ARG2INT(tmp) > 0 ? 1 : -1; |
99 |
|
2 |
break; |
100 |
|
1 |
case 'i': |
101 |
✗✓ |
1 |
CHECK_OB((tmp = option_argument(ca))) |
102 |
|
1 |
arg->si->in = (uint8_t)ARG2INT(tmp); |
103 |
|
1 |
break; |
104 |
|
1 |
case 'o': |
105 |
✗✓ |
1 |
CHECK_OB((tmp = option_argument(ca))) |
106 |
|
1 |
arg->si->out = (uint8_t)ARG2INT(tmp); |
107 |
|
1 |
break; |
108 |
|
1 |
case 's': |
109 |
✗✓ |
1 |
CHECK_OB((tmp = option_argument(ca))) |
110 |
|
1 |
arg->si->sr = (uint32_t)ARG2INT(tmp); |
111 |
|
1 |
break; |
112 |
|
712 |
case 'd': |
113 |
✗✓ |
712 |
CHECK_OB((tmp = option_argument(ca))) |
114 |
|
712 |
arg->si->arg = tmp; |
115 |
|
712 |
break; |
116 |
|
2 |
case 'g': |
117 |
✗✓ |
2 |
CHECK_OB((tmp = option_argument(ca))) |
118 |
|
2 |
arg_set_pass(gwion, tmp); |
119 |
|
2 |
break; |
120 |
|
2 |
default: |
121 |
|
2 |
gw_err(_("invalid arguments")); |
122 |
|
2 |
return GW_ERROR; |
123 |
|
|
} |
124 |
|
|
} else |
125 |
|
1334 |
vector_add(&arg->add, (vtype)ca->argv[ca->idx]); |
126 |
|
|
} |
127 |
|
711 |
return GW_OK; |
128 |
|
|
} |
129 |
|
|
|
130 |
|
|
ANN static void split_line(const m_str line, const Vector v) { |
131 |
|
|
m_str d = strdup(line), c = d; |
132 |
|
|
while(d) { |
133 |
|
|
const m_str str = strsep(&d, " "); |
134 |
|
|
const size_t sz = strlen(str); |
135 |
|
|
const m_bool arg = (str[sz-1] == '\n'); |
136 |
|
|
vector_add(v, (vtype)strndup(str, arg ? sz - 1 : sz)); |
137 |
|
|
} |
138 |
|
|
xfree(d); |
139 |
|
|
xfree(c); |
140 |
|
|
} |
141 |
|
|
|
142 |
|
715 |
ANN static Vector get_config(const m_str name) { |
143 |
|
715 |
char *line = NULL; |
144 |
|
715 |
size_t len = 0; |
145 |
|
|
ssize_t nread; |
146 |
|
715 |
FILE *f = fopen(name, "r"); |
147 |
✓✗ |
715 |
CHECK_OO(f) |
148 |
|
|
const Vector v = (Vector)xmalloc(sizeof(struct Vector_)); |
149 |
|
|
vector_init(v); |
150 |
|
|
vector_add(v, (vtype)name); |
151 |
|
|
while((nread = getline(&line, &len, f)) != -1) { |
152 |
|
|
if(line[0] != '#') |
153 |
|
|
split_line(line, v); |
154 |
|
|
} |
155 |
|
|
free(line); |
156 |
|
|
fclose(f); |
157 |
|
|
return v; |
158 |
|
|
} |
159 |
|
|
|
160 |
|
715 |
ANN static void config_parse(const Gwion gwion, Arg* arg, const m_str name) { |
161 |
|
715 |
const Vector v = get_config(name); |
162 |
✗✓ |
715 |
if(v) { |
163 |
|
|
struct CArg ca = arg->arg; |
164 |
|
|
arg->arg.argc = vector_size(v); |
165 |
|
|
arg->arg.argv = (m_str*)(v->ptr + OFFSET); |
166 |
|
|
_arg_parse(gwion, arg); |
167 |
|
|
arg->arg = ca; |
168 |
|
|
vector_add(&arg->config, (vtype)v); |
169 |
|
|
} |
170 |
|
715 |
} |
171 |
|
|
|
172 |
|
714 |
ANN static void config_default(const Gwion gwion , Arg* arg) { |
173 |
|
714 |
char* home = getenv("HOME"); |
174 |
|
714 |
char c[strlen(home) + strlen(GWIONRC) + 2]; |
175 |
|
714 |
sprintf(c, "%s/%s", home, GWIONRC); |
176 |
|
714 |
config_parse(gwion, arg, c); |
177 |
|
714 |
} |
178 |
|
|
|
179 |
|
714 |
ANN m_bool arg_parse(const Gwion gwion, Arg* a) { |
180 |
|
714 |
arg_init(a); |
181 |
|
|
#ifdef __FUZZING |
182 |
|
|
return; |
183 |
|
|
#endif |
184 |
|
714 |
config_default(gwion, a); |
185 |
|
714 |
return _arg_parse(gwion, a); |
186 |
|
|
} |