cpp

Coverage Report

Created: 2022-07-20 01:16

/home/uke/oil/cpp/leaky_frontend_flag_spec.cc
Line
Count
Source (jump to first uncovered line)
1
// frontend_flag_spec.cc
2
3
#include "leaky_frontend_flag_spec.h"
4
5
#include "_build/cpp/arg_types.h"
6
7
#ifndef CPP_UNIT_TEST
8
#include "_build/cpp/osh_eval.h"  // args::Reader, etc.
9
#endif
10
11
namespace flag_spec {
12
13
using arg_types::kFlagSpecs;
14
using arg_types::kFlagSpecsAndMore;
15
using runtime_asdl::flag_type_e;
16
using runtime_asdl::value__Bool;
17
using runtime_asdl::value__Undef;
18
using runtime_asdl::value_t;
19
20
3
void _CreateStrList(const char** in, List<Str*>* out) {
21
3
  int i = 0;
22
15
  while (true) {
23
15
    const char* s = in[i];
24
15
    if (!s) {
25
3
      break;
26
3
    }
27
    // log("a0 %s", s);
28
12
    out->append(new Str(s));
29
12
    ++i;
30
12
  }
31
3
}
32
33
void _CreateDefaults(DefaultPair_c* in,
34
2
                     Dict<Str*, runtime_asdl::value_t*>* out) {
35
2
  int i = 0;
36
14
  while (true) {
37
14
    DefaultPair_c* pair = &(in[i]);
38
14
    if (!pair->name) {
39
2
      break;
40
2
    }
41
12
    value_t* val;
42
12
    switch (pair->typ) {
43
9
    case flag_type_e::Bool:
44
9
      val = new value__Bool(pair->val.b);
45
9
      break;
46
0
    case flag_type_e::Int:
47
0
      val = new value__Int(pair->val.i);
48
0
      break;
49
0
    case flag_type_e::Float:
50
0
      val = new value__Float(pair->val.f);
51
0
      break;
52
3
    case flag_type_e::Str: {
53
3
      const char* s = pair->val.s;
54
3
      if (s == nullptr) {
55
3
        val = new value__Undef();
56
3
      } else {
57
0
        val = new value__Str(new Str(s));
58
0
      }
59
3
    } break;
60
0
    default:
61
0
      assert(0);  // NOTE(Jesse): Pretty sure this is InvalidCodePath()
62
12
    }
63
12
    out->set(new Str(pair->name), val);
64
12
    ++i;
65
12
  }
66
2
}
67
68
#ifndef CPP_UNIT_TEST
69
void _CreateActions(Action_c* in, Dict<Str*, args::_Action*>* out) {
70
  int i = 0;
71
  while (true) {
72
    Action_c* p = &(in[i]);
73
    if (!p->key) {
74
      break;
75
    }
76
    // log("a1 %s", p->name);
77
    args::_Action* action = nullptr;
78
    switch (p->type) {
79
    case ActionType_c::SetToString: {
80
      List<Str*>* valid = nullptr;
81
      if (p->strs) {
82
        valid = new List<Str*>();
83
        _CreateStrList(p->strs, valid);
84
      }
85
      auto a = new args::SetToString(new Str(p->name), false, valid);
86
      action = a;
87
    } break;
88
    case ActionType_c::SetToString_q:
89
      action = new args::SetToString(new Str(p->name), true, nullptr);
90
      break;
91
    case ActionType_c::SetToInt:
92
      action = new args::SetToInt(new Str(p->name));
93
      break;
94
    case ActionType_c::SetToFloat:
95
      action = new args::SetToFloat(new Str(p->name));
96
      break;
97
    case ActionType_c::SetToTrue:
98
      action = new args::SetToTrue(new Str(p->name));
99
      break;
100
    case ActionType_c::SetAttachedBool:
101
      action = new args::SetAttachedBool(new Str(p->name));
102
      break;
103
    case ActionType_c::SetOption:
104
      action = new args::SetOption(new Str(p->name));
105
      break;
106
    case ActionType_c::SetNamedOption: {
107
      auto a = new args::SetNamedOption(false);
108
      if (p->strs) {
109
        _CreateStrList(p->strs, a->names);
110
      }
111
      action = a;
112
    } break;
113
    case ActionType_c::SetNamedOption_shopt: {
114
      auto a = new args::SetNamedOption(true);
115
      if (p->strs) {
116
        _CreateStrList(p->strs, a->names);
117
      }
118
      action = a;
119
    } break;
120
    case ActionType_c::SetAction:
121
      action = new args::SetAction(new Str(p->name));
122
      break;
123
    case ActionType_c::SetNamedAction: {
124
      auto a = new args::SetNamedAction();
125
      if (p->strs) {
126
        _CreateStrList(p->strs, a->names);
127
      }
128
      action = a;
129
    } break;
130
    }
131
132
    if (action) {
133
      out->set(new Str(p->key), action);
134
    }
135
    ++i;
136
  }
137
}
138
#endif
139
140
// "Inflate" the static C data into a heap-allocated ASDL data structure.
141
//
142
// TODO: Make a GLOBAL CACHE?  It could be shared between subinterpreters even?
143
2
flag_spec::_FlagSpec* CreateSpec(FlagSpec_c* in) {
144
2
  auto out = new flag_spec::_FlagSpec();
145
2
  out->arity0 = new List<Str*>();
146
2
  out->arity1 = new Dict<Str*, args::_Action*>();
147
2
  out->actions_long = new Dict<Str*, args::_Action*>();
148
2
  out->plus_flags = new List<Str*>();
149
2
  out->defaults = new Dict<Str*, runtime_asdl::value_t*>();
150
151
2
  if (in->arity0) {
152
2
    _CreateStrList(in->arity0, out->arity0);
153
2
  }
154
#ifndef CPP_UNIT_TEST
155
  if (in->arity1) {
156
    _CreateActions(in->arity1, out->arity1);
157
  }
158
  if (in->actions_long) {
159
    _CreateActions(in->actions_long, out->actions_long);
160
  }
161
#endif
162
2
  if (in->plus_flags) {
163
1
    _CreateStrList(in->plus_flags, out->plus_flags);
164
1
  }
165
2
  if (in->defaults) {
166
2
    _CreateDefaults(in->defaults, out->defaults);
167
2
  }
168
2
  return out;
169
2
}
170
171
0
flag_spec::_FlagSpecAndMore* CreateSpec2(FlagSpecAndMore_c* in) {
172
0
  auto out = new flag_spec::_FlagSpecAndMore();
173
0
  out->actions_short = new Dict<Str*, args::_Action*>();
174
0
  out->actions_long = new Dict<Str*, args::_Action*>();
175
0
  out->plus_flags = new List<Str*>();
176
0
  out->defaults = new Dict<Str*, runtime_asdl::value_t*>();
177
178
#ifndef CPP_UNIT_TEST
179
  if (in->actions_short) {
180
    _CreateActions(in->actions_short, out->actions_short);
181
  }
182
183
  if (in->actions_long) {
184
    _CreateActions(in->actions_long, out->actions_long);
185
  }
186
#endif
187
0
  if (in->plus_flags) {
188
0
    _CreateStrList(in->plus_flags, out->plus_flags);
189
0
  }
190
0
  if (in->defaults) {
191
0
    _CreateDefaults(in->defaults, out->defaults);
192
0
  }
193
0
  return out;
194
0
}
195
196
3
flag_spec::_FlagSpec* LookupFlagSpec(Str* spec_name) {
197
3
  int i = 0;
198
89
  while (true) {
199
89
    const char* name = kFlagSpecs[i].name;
200
89
    if (name == nullptr) {
201
1
      break;
202
1
    }
203
88
    if (str_equals0(name, spec_name)) {
204
      // log("%s found", spec_name->data_);
205
2
      return CreateSpec(&kFlagSpecs[i]);
206
2
    }
207
208
86
    i++;
209
86
  }
210
  // log("%s not found", spec_name->data_);
211
1
  return nullptr;
212
3
}
213
214
0
flag_spec::_FlagSpecAndMore* LookupFlagSpec2(Str* spec_name) {
215
0
  int i = 0;
216
0
  while (true) {
217
0
    const char* name = kFlagSpecsAndMore[i].name;
218
0
    if (name == nullptr) {
219
0
      break;
220
0
    }
221
0
    if (str_equals0(name, spec_name)) {
222
      // log("%s found", spec_name->data_);
223
0
      return CreateSpec2(&kFlagSpecsAndMore[i]);
224
0
    }
225
226
0
    i++;
227
0
  }
228
  // log("%s not found", spec_name->data_);
229
0
  return nullptr;
230
0
}
231
232
0
args::_Attributes* Parse(Str* spec_name, args::Reader* arg_r) {
233
0
  flag_spec::_FlagSpec* spec = LookupFlagSpec(spec_name);
234
0
  assert(spec);  // should always be found
235
236
0
#ifdef CPP_UNIT_TEST
237
  // hack because we don't want to depend on a translation of args.py
238
0
  return nullptr;
239
#else
240
  return args::Parse(spec, arg_r);
241
#endif
242
0
}
243
244
Tuple2<args::_Attributes*, args::Reader*> ParseCmdVal(
245
0
    Str* spec_name, runtime_asdl::cmd_value__Argv* cmd_val) {
246
0
#ifdef CPP_UNIT_TEST
247
0
  return Tuple2<args::_Attributes*, args::Reader*>(nullptr, nullptr);
248
#else
249
  auto arg_r = new args::Reader(cmd_val->argv, cmd_val->arg_spids);
250
  arg_r->Next();  // move past the builtin name
251
252
  flag_spec::_FlagSpec* spec = LookupFlagSpec(spec_name);
253
  assert(spec);  // should always be found
254
  return Tuple2<args::_Attributes*, args::Reader*>(args::Parse(spec, arg_r),
255
                                                   arg_r);
256
#endif
257
0
}
258
259
// With optional arg
260
Tuple2<args::_Attributes*, args::Reader*> ParseCmdVal(
261
    Str* spec_name, runtime_asdl::cmd_value__Argv* cmd_val,
262
0
    bool accept_typed_args) {
263
  // TODO: disallow typed args!
264
0
  return ParseCmdVal(spec_name, cmd_val);
265
0
}
266
267
Tuple2<args::_Attributes*, args::Reader*> ParseLikeEcho(
268
0
    Str* spec_name, runtime_asdl::cmd_value__Argv* cmd_val) {
269
0
#ifdef CPP_UNIT_TEST
270
0
  return Tuple2<args::_Attributes*, args::Reader*>(nullptr, nullptr);
271
#else
272
  auto arg_r = new args::Reader(cmd_val->argv, cmd_val->arg_spids);
273
  arg_r->Next();  // move past the builtin name
274
275
  flag_spec::_FlagSpec* spec = LookupFlagSpec(spec_name);
276
  assert(spec);  // should always be found
277
  return Tuple2<args::_Attributes*, args::Reader*>(
278
      args::ParseLikeEcho(spec, arg_r), arg_r);
279
#endif
280
0
}
281
282
0
args::_Attributes* ParseMore(Str* spec_name, args::Reader* arg_r) {
283
0
#ifdef CPP_UNIT_TEST
284
0
  return nullptr;
285
#else
286
  // TODO: Fill this in from constant data!
287
  flag_spec::_FlagSpecAndMore* spec = LookupFlagSpec2(spec_name);
288
  assert(spec);
289
  // assert(spec);  // should always be found
290
  return args::ParseMore(spec, arg_r);
291
#endif
292
0
}
293
294
}  // namespace flag_spec