cpp

Coverage Report

Created: 2023-09-13 01:07

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