OILS / cpp / frontend_flag_spec.cc View on Github | oils.pub

234 lines, 164 significant
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
11namespace flag_util {
12
13using runtime_asdl::flag_type_e;
14using value_asdl::value;
15using value_asdl::value_t;
16
17void _CreateStrList(const char** in, List<BigStr*>* out) {
18 int i = 0;
19 while (true) {
20 const char* s = in[i];
21 if (!s) {
22 break;
23 }
24 // log("a0 %s", s);
25 out->append(StrFromC(s));
26 ++i;
27 }
28}
29
30void _CreateDefaults(DefaultPair_c* in,
31 Dict<BigStr*, value_asdl::value_t*>* out) {
32 int i = 0;
33 while (true) {
34 DefaultPair_c* pair = &(in[i]);
35 if (!pair->name) {
36 break;
37 }
38 value_t* val;
39 switch (pair->typ) {
40 case flag_type_e::Bool:
41 val = Alloc<value::Bool>(pair->val.b);
42 break;
43 case flag_type_e::Int:
44 val = Alloc<value::Int>(pair->val.i);
45 break;
46 case flag_type_e::Float:
47 val = Alloc<value::Float>(pair->val.f);
48 break;
49 case flag_type_e::Str: {
50 const char* s = pair->val.s;
51 if (s == nullptr) {
52 val = value::Undef;
53 } else {
54 val = Alloc<value::Str>(StrFromC(s));
55 }
56 } break;
57 default:
58 FAIL(kShouldNotGetHere);
59 }
60 out->set(StrFromC(pair->name), val);
61 ++i;
62 }
63}
64
65void _CreateActions(Action_c* in, Dict<BigStr*, args::_Action*>* out) {
66 int i = 0;
67 while (true) {
68 Action_c* p = &(in[i]);
69 if (!p->key) {
70 break;
71 }
72 // log("a1 %s", p->name);
73 args::_Action* action = nullptr;
74 switch (p->type) {
75 case ActionType_c::SetToString: {
76 List<BigStr*>* valid = nullptr;
77 if (p->strs) {
78 valid = NewList<BigStr*>();
79 _CreateStrList(p->strs, valid);
80 }
81 auto a = Alloc<args::SetToString>(StrFromC(p->name), false, valid);
82 action = a;
83 } break;
84 case ActionType_c::SetToString_q:
85 action = Alloc<args::SetToString>(StrFromC(p->name), true, nullptr);
86 break;
87 case ActionType_c::SetToInt:
88 action = Alloc<args::SetToInt>(StrFromC(p->name));
89 break;
90 case ActionType_c::SetToFloat:
91 action = Alloc<args::SetToFloat>(StrFromC(p->name));
92 break;
93 case ActionType_c::SetToTrue:
94 action = Alloc<args::SetToTrue>(StrFromC(p->name));
95 break;
96 case ActionType_c::SetAttachedBool:
97 action = Alloc<args::SetAttachedBool>(StrFromC(p->name));
98 break;
99 case ActionType_c::SetOption:
100 action = Alloc<args::SetOption>(StrFromC(p->name));
101 break;
102 case ActionType_c::SetNamedOption: {
103 auto a = Alloc<args::SetNamedOption>(false);
104 if (p->strs) {
105 _CreateStrList(p->strs, a->names);
106 }
107 action = a;
108 } break;
109 case ActionType_c::SetNamedOption_shopt: {
110 auto a = Alloc<args::SetNamedOption>(true);
111 if (p->strs) {
112 _CreateStrList(p->strs, a->names);
113 }
114 action = a;
115 } break;
116 case ActionType_c::SetAction:
117 action = Alloc<args::SetAction>(StrFromC(p->name));
118 break;
119 case ActionType_c::SetNamedAction: {
120 auto a = Alloc<args::SetNamedAction>();
121 if (p->strs) {
122 _CreateStrList(p->strs, a->names);
123 }
124 action = a;
125 } break;
126 case ActionType_c::AppendEvalFlag:
127 action = Alloc<args::AppendEvalFlag>(StrFromC(p->name));
128 break;
129 } // switch
130
131 if (action) {
132 out->set(StrFromC(p->key), action);
133 }
134 ++i;
135 }
136}
137
138// Convenience function
139template <typename K, typename V>
140Dict<K, V>* NewDict() {
141 return Alloc<Dict<K, V>>();
142}
143
144// "Inflate" the static C data into a heap-allocated ASDL data structure.
145//
146// TODO: Make a GLOBAL CACHE? It could be shared between subinterpreters even?
147flag_spec::_FlagSpec* CreateSpec(FlagSpec_c* in) {
148 auto out = Alloc<flag_spec::_FlagSpec>();
149 out->arity0 = NewList<BigStr*>();
150 out->arity1 = NewDict<BigStr*, args::_Action*>();
151 out->actions_long = NewDict<BigStr*, args::_Action*>();
152 out->plus_flags = NewList<BigStr*>();
153 out->defaults = NewDict<BigStr*, value_asdl::value_t*>();
154
155 if (in->arity0) {
156 _CreateStrList(in->arity0, out->arity0);
157 }
158 if (in->arity1) {
159 _CreateActions(in->arity1, out->arity1);
160 }
161 if (in->actions_long) {
162 _CreateActions(in->actions_long, out->actions_long);
163 }
164 if (in->plus_flags) {
165 _CreateStrList(in->plus_flags, out->plus_flags);
166 }
167 if (in->defaults) {
168 _CreateDefaults(in->defaults, out->defaults);
169 }
170 return out;
171}
172
173flag_spec::_FlagSpecAndMore* CreateSpec2(FlagSpecAndMore_c* in) {
174 auto out = Alloc<flag_spec::_FlagSpecAndMore>();
175 out->actions_short = NewDict<BigStr*, args::_Action*>();
176 out->actions_long = NewDict<BigStr*, args::_Action*>();
177 out->plus_flags = NewList<BigStr*>();
178 out->defaults = NewDict<BigStr*, value_asdl::value_t*>();
179
180 if (in->actions_short) {
181 _CreateActions(in->actions_short, out->actions_short);
182 }
183 if (in->actions_long) {
184 _CreateActions(in->actions_long, out->actions_long);
185 }
186 if (in->plus_flags) {
187 _CreateStrList(in->plus_flags, out->plus_flags);
188 }
189 if (in->defaults) {
190 _CreateDefaults(in->defaults, out->defaults);
191 }
192 return out;
193}
194
195using arg_types::kFlagSpecs;
196using arg_types::kFlagSpecsAndMore;
197
198flag_spec::_FlagSpec* LookupFlagSpec(BigStr* spec_name) {
199 int i = 0;
200 while (true) {
201 const char* name = kFlagSpecs[i].name;
202 if (name == nullptr) {
203 break;
204 }
205 if (str_equals0(name, spec_name)) {
206 // log("%s found", spec_name->data_);
207 return CreateSpec(&kFlagSpecs[i]);
208 }
209
210 i++;
211 }
212 // log("%s not found", spec_name->data_);
213 return nullptr;
214}
215
216flag_spec::_FlagSpecAndMore* LookupFlagSpec2(BigStr* spec_name) {
217 int i = 0;
218 while (true) {
219 const char* name = kFlagSpecsAndMore[i].name;
220 if (name == nullptr) {
221 break;
222 }
223 if (str_equals0(name, spec_name)) {
224 // log("%s found", spec_name->data_);
225 return CreateSpec2(&kFlagSpecsAndMore[i]);
226 }
227
228 i++;
229 }
230 // log("%s not found", spec_name->data_);
231 return nullptr;
232}
233
234} // namespace flag_util