/home/andy/git/oilshell/oil/cpp/frontend_flag_spec.h
Line | Count | Source |
1 | | // frontend_flag_spec.h |
2 | | |
3 | | #ifndef FRONTEND_FLAG_SPEC_H |
4 | | #define FRONTEND_FLAG_SPEC_H |
5 | | |
6 | | #include "_gen/core/runtime.asdl.h" |
7 | | #include "_gen/core/value.asdl.h" |
8 | | #include "_gen/frontend/id_kind.asdl.h" |
9 | | #include "mycpp/runtime.h" |
10 | | |
11 | | // Forward declarations (can't include osh_eval.h) |
12 | | namespace args { |
13 | | class _Action; |
14 | | class _Attributes; |
15 | | class Reader; |
16 | | }; // namespace args |
17 | | |
18 | | // |
19 | | // Types for compile-time FlagSpec |
20 | | // |
21 | | |
22 | | union Val_c { |
23 | | bool b; |
24 | | int i; |
25 | | float f; |
26 | | const char* s; |
27 | | }; |
28 | | |
29 | | struct DefaultPair_c { |
30 | | const char* name; |
31 | | runtime_asdl::flag_type_t typ; |
32 | | Val_c val; |
33 | | }; |
34 | | |
35 | | // all concrete subtypes of args::_Action |
36 | | enum class ActionType_c { |
37 | | SetToString, // name, valid |
38 | | SetToString_q, // hack for quit_parsing_flags |
39 | | |
40 | | SetToInt, // name |
41 | | SetToFloat, // name |
42 | | SetToTrue, // name |
43 | | SetAttachedBool, // name, for OilFlags |
44 | | |
45 | | SetOption, // name |
46 | | SetNamedOption, // no args, valid |
47 | | SetNamedOption_shopt, // no args, valid |
48 | | SetAction, // name |
49 | | SetNamedAction, // no args, valid |
50 | | }; |
51 | | |
52 | | // TODO: Figure out the difference between name and key |
53 | | // key = '--ast-format' |
54 | | // name = 'ast-format' |
55 | | // out.Set('ast-format', ...) |
56 | | // So I want to compress these two |
57 | | |
58 | | struct Action_c { |
59 | | const char* key; |
60 | | ActionType_c type; |
61 | | const char* name; |
62 | | // for --ast-format, SetNamedAction(), SetNamedOption() |
63 | | const char** strs; |
64 | | }; |
65 | | |
66 | | struct FlagSpec_c { |
67 | | const char* name; // e.g. 'wait' |
68 | | const char** arity0; // NULL terminated array |
69 | | Action_c* arity1; // NULL terminated array |
70 | | Action_c* actions_long; // NULL terminated array |
71 | | const char** plus_flags; // NULL terminated array |
72 | | DefaultPair_c* defaults; |
73 | | }; |
74 | | |
75 | | struct FlagSpecAndMore_c { |
76 | | const char* name; // e.g. 'osh' |
77 | | // These are Dict[str, _Action] |
78 | | Action_c* actions_short; |
79 | | Action_c* actions_long; |
80 | | const char** plus_flags; // NULL terminated array |
81 | | DefaultPair_c* defaults; |
82 | | }; |
83 | | |
84 | | namespace flag_spec { |
85 | | |
86 | | class _FlagSpec { |
87 | | public: |
88 | | _FlagSpec() |
89 | | : arity0(nullptr), |
90 | | arity1(nullptr), |
91 | | plus_flags(nullptr), |
92 | | actions_long(nullptr), |
93 | 3 | defaults(nullptr) { |
94 | 3 | } |
95 | | |
96 | 3 | static constexpr ObjHeader obj_header() { |
97 | 3 | return ObjHeader::ClassFixed(field_mask(), sizeof(_FlagSpec)); |
98 | 3 | } |
99 | | |
100 | | List<BigStr*>* arity0; |
101 | | Dict<BigStr*, args::_Action*>* arity1; |
102 | | List<BigStr*>* plus_flags; |
103 | | Dict<BigStr*, args::_Action*>* actions_long; |
104 | | Dict<BigStr*, value_asdl::value_t*>* defaults; |
105 | | |
106 | 3 | static constexpr uint32_t field_mask() { |
107 | 3 | return maskbit(offsetof(_FlagSpec, arity0)) | |
108 | 3 | maskbit(offsetof(_FlagSpec, arity1)) | |
109 | 3 | maskbit(offsetof(_FlagSpec, plus_flags)) | |
110 | 3 | maskbit(offsetof(_FlagSpec, actions_long)) | |
111 | 3 | maskbit(offsetof(_FlagSpec, defaults)); |
112 | 3 | } |
113 | | }; |
114 | | |
115 | | class _FlagSpecAndMore { |
116 | | public: |
117 | | _FlagSpecAndMore() |
118 | | : actions_long(nullptr), |
119 | | actions_short(nullptr), |
120 | | plus_flags(nullptr), |
121 | 2 | defaults(nullptr) { |
122 | 2 | } |
123 | | |
124 | 2 | static constexpr ObjHeader obj_header() { |
125 | 2 | return ObjHeader::ClassFixed(field_mask(), sizeof(_FlagSpecAndMore)); |
126 | 2 | } |
127 | | |
128 | | Dict<BigStr*, args::_Action*>* actions_long; |
129 | | Dict<BigStr*, args::_Action*>* actions_short; |
130 | | List<BigStr*>* plus_flags; |
131 | | Dict<BigStr*, value_asdl::value_t*>* defaults; |
132 | | |
133 | 2 | static constexpr uint32_t field_mask() { |
134 | 2 | return maskbit(offsetof(_FlagSpecAndMore, actions_long)) | |
135 | 2 | maskbit(offsetof(_FlagSpecAndMore, actions_short)) | |
136 | 2 | maskbit(offsetof(_FlagSpecAndMore, plus_flags)) | |
137 | 2 | maskbit(offsetof(_FlagSpecAndMore, defaults)); |
138 | 2 | } |
139 | | }; |
140 | | |
141 | | // for testing only |
142 | | flag_spec::_FlagSpec* LookupFlagSpec(BigStr* spec_name); |
143 | | flag_spec::_FlagSpecAndMore* LookupFlagSpec2(BigStr* spec_name); |
144 | | |
145 | | args::_Attributes* Parse(BigStr* spec_name, args::Reader* arg_r); |
146 | | |
147 | | Tuple2<args::_Attributes*, args::Reader*> ParseCmdVal( |
148 | | BigStr* spec_name, runtime_asdl::cmd_value::Argv* cmd_val); |
149 | | |
150 | | // With optional arg |
151 | | Tuple2<args::_Attributes*, args::Reader*> ParseCmdVal( |
152 | | BigStr* spec_name, runtime_asdl::cmd_value::Argv* cmd_val, |
153 | | bool accept_typed_args); |
154 | | |
155 | | Tuple2<args::_Attributes*, args::Reader*> ParseLikeEcho( |
156 | | BigStr* spec_name, runtime_asdl::cmd_value::Argv* cmd_val); |
157 | | |
158 | | args::_Attributes* ParseMore(BigStr* spec_name, args::Reader* arg_r); |
159 | | |
160 | | } // namespace flag_spec |
161 | | |
162 | | #endif // FRONTEND_FLAG_SPEC_H |