GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/arg.c Lines: 101 133 75.9 %
Date: 2020-10-03 11:54:50 Branches: 32 54 59.3 %

Line Branch Exec Source
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
716
ANN static inline void config_end(const Vector config) {
14
716
  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
716
}
22
23
716
ANN static m_str plug_dir(void) {
24
716
  const m_str home = getenv("HOME");
25
716
  const size_t sz = strlen(home);
26
716
  const m_str pdir = "/.gwplug";
27
716
  m_str plug_dir = (m_str)xmalloc(sz + strlen(pdir) + 1);
28
716
  strcpy(plug_dir, home);
29
716
  strcpy(plug_dir + sz, pdir);
30
716
  return plug_dir;
31
}
32
33
716
ANN static void arg_init(Arg* arg) {
34
716
  vector_init(&arg->add);
35
716
  vector_init(&arg->lib);
36
716
  vector_init(&arg->mod);
37
716
  vector_init(&arg->config);
38
716
  vector_add(&arg->lib, (vtype)plug_dir());
39
716
}
40
41
716
ANN void arg_release(Arg* arg) {
42
716
  vector_release(&arg->add);
43
716
  xfree((m_str)vector_front(&arg->lib));
44
716
  vector_release(&arg->lib);
45
716
  vector_release(&arg->mod);
46
716
  config_end(&arg->config);
47
716
  vector_release(&arg->config);
48
716
}
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
716
ANN m_bool _arg_parse(const Gwion gwion, Arg* arg) {
76
716
  struct CArg *ca = &arg->arg;
77
2933
  for(ca->idx = 1; ca->idx < ca->argc; ++ca->idx) {
78
2220
    if(ca->argv[ca->idx][0] == '-') {
79
      m_str tmp;
80



883
      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
80
        case 'p':
89
80
          CHECK_OB((tmp = option_argument(ca)))
90
79
          vector_add(&arg->lib, (vtype)tmp);
91
79
          break;
92
78
        case 'm':
93
78
          CHECK_OB((tmp = option_argument(ca)))
94
78
          vector_add(&arg->mod, (vtype)tmp);
95
78
          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
714
        case 'd':
113
714
          CHECK_OB((tmp = option_argument(ca)))
114
714
          arg->si->arg = tmp;
115
714
          break;
116
2
        case 'g':
117
2
          CHECK_OB((tmp = option_argument(ca)))
118
2
          arg_set_pass(gwion, tmp);
119
2
          break;
120
        case '\0':
121
          arg->read_stdin = !arg->read_stdin;
122
          break;
123
2
        default:
124
2
          gw_err(_("invalid arguments"));
125
2
          return GW_ERROR;
126
      }
127
    } else
128
1337
      vector_add(&arg->add, (vtype)ca->argv[ca->idx]);
129
  }
130
713
  return GW_OK;
131
}
132
133
ANN static void split_line(const m_str line, const Vector v) {
134
  m_str d = strdup(line), c = d;
135
  while(d) {
136
    const m_str str = strsep(&d, " ");
137
    const size_t sz = strlen(str);
138
    const m_bool arg = (str[sz-1] == '\n');
139
    vector_add(v, (vtype)strndup(str, arg ? sz - 1 : sz));
140
  }
141
  xfree(d);
142
  xfree(c);
143
}
144
145
717
ANN static Vector get_config(const m_str name) {
146
717
  char *line = NULL;
147
717
  size_t len = 0;
148
  ssize_t nread;
149
717
  FILE *f = fopen(name, "r");
150
717
  CHECK_OO(f)
151
  const Vector v = (Vector)xmalloc(sizeof(struct Vector_));
152
  vector_init(v);
153
  vector_add(v, (vtype)name);
154
  while((nread = getline(&line, &len, f)) != -1) {
155
    if(line[0] != '#')
156
      split_line(line, v);
157
  }
158
  free(line);
159
  fclose(f);
160
  return v;
161
}
162
163
717
ANN static void config_parse(const Gwion gwion, Arg* arg, const m_str name) {
164
717
  const Vector v = get_config(name);
165
717
  if(v) {
166
    struct CArg ca = arg->arg;
167
    arg->arg.argc = vector_size(v);
168
    arg->arg.argv =  (m_str*)(v->ptr + OFFSET);
169
    _arg_parse(gwion, arg);
170
    arg->arg = ca;
171
    vector_add(&arg->config, (vtype)v);
172
  }
173
717
}
174
175
716
ANN static void config_default(const Gwion gwion , Arg* arg) {
176
716
  char* home = getenv("HOME");
177
716
  char c[strlen(home) + strlen(GWIONRC) + 2];
178
716
  sprintf(c, "%s/%s", home, GWIONRC);
179
716
  config_parse(gwion, arg, c);
180
716
}
181
182
716
ANN m_bool arg_parse(const Gwion gwion, Arg* a) {
183
716
  arg_init(a);
184
#ifdef __FUZZING
185
  return;
186
#endif
187
716
  config_default(gwion, a);
188
716
  return _arg_parse(gwion, a);
189
}