GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/arg.c Lines: 101 130 77.7 %
Date: 2020-07-24 14:14:26 Branches: 32 53 60.4 %

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


898
      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
731
        case 'd':
113
731
          CHECK_OB((tmp = option_argument(ca)))
114
731
          arg->si->arg = tmp;
115
731
          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
1372
      vector_add(&arg->add, (vtype)ca->argv[ca->idx]);
126
  }
127
730
  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
734
ANN static Vector get_config(const m_str name) {
143
734
  char *line = NULL;
144
734
  size_t len = 0;
145
  ssize_t nread;
146
734
  FILE *f = fopen(name, "r");
147
734
  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
734
ANN static void config_parse(const Gwion gwion, Arg* arg, const m_str name) {
161
734
  const Vector v = get_config(name);
162
734
  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
734
}
171
172
733
ANN static void config_default(const Gwion gwion , Arg* arg) {
173
733
  char* home = getenv("HOME");
174
733
  char c[strlen(home) + strlen(GWIONRC) + 2];
175
733
  sprintf(c, "%s/%s", home, GWIONRC);
176
733
  config_parse(gwion, arg, c);
177
733
}
178
179
733
ANN m_bool arg_parse(const Gwion gwion, Arg* a) {
180
733
  arg_init(a);
181
#ifdef __FUZZING
182
  return;
183
#endif
184
733
  config_default(gwion, a);
185
733
  return _arg_parse(gwion, a);
186
}