1 /*
2 * Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "SettingsParser.h"
8
9 #include <string.h>
10
11 #include <DriverSettingsMessageAdapter.h>
12
13
14 class AbstractArgsConverter : public DriverSettingsConverter {
15 public:
ConvertEmptyFromDriverSettings(const driver_parameter & parameter,const char * name,uint32 type,BMessage & target)16 status_t ConvertEmptyFromDriverSettings(
17 const driver_parameter& parameter, const char* name, uint32 type,
18 BMessage& target)
19 {
20 if (parameter.parameter_count != 0 || strcmp(name, Name()) == 0)
21 return B_OK;
22
23 BMessage message;
24 return target.AddMessage(name, &message);
25 }
26
27 protected:
AddSubMessage(const driver_parameter & parameter,int32 index,BMessage & target)28 status_t AddSubMessage(const driver_parameter& parameter, int32 index,
29 BMessage& target)
30 {
31 const char* condition = parameter.values[index];
32 BMessage args;
33 for (index++; index < parameter.value_count; index++) {
34 status_t status = args.AddString("args",
35 parameter.values[index]);
36 if (status != B_OK)
37 return status;
38 }
39 return target.AddMessage(condition, &args);
40 }
41
42 virtual const char* Name() = 0;
43 };
44
45
46 class ConditionConverter : public AbstractArgsConverter {
47 public:
ConvertFromDriverSettings(const driver_parameter & parameter,const char * name,int32 index,uint32 type,BMessage & target)48 status_t ConvertFromDriverSettings(const driver_parameter& parameter,
49 const char* name, int32 index, uint32 type, BMessage& target)
50 {
51 BMessage message;
52 if (strcmp(parameter.name, "if") == 0) {
53 // Parse values directly following "if", with special
54 // handling for the "not" operator.
55 if (index != 0)
56 return B_OK;
57
58 BMessage* add = ⌖
59 bool notOperator = parameter.value_count > 1
60 && strcmp(parameter.values[0], "not") == 0;
61 if (notOperator) {
62 add = &message;
63 index++;
64 }
65
66 status_t status = AddSubMessage(parameter, index, *add);
67 if (status == B_OK && notOperator)
68 status = target.AddMessage("not", &message);
69
70 return status;
71 }
72 if (strcmp(parameter.name, "not") == 0) {
73 if (index != 0)
74 return B_OK;
75
76 return AddSubMessage(parameter, index, target);
77 }
78
79 message.AddString("args", parameter.values[index]);
80 return target.AddMessage(parameter.name, &message);
81 }
82
Name()83 const char* Name()
84 {
85 return "if";
86 }
87 };
88
89
90 class EventConverter : public AbstractArgsConverter {
91 public:
ConvertFromDriverSettings(const driver_parameter & parameter,const char * name,int32 index,uint32 type,BMessage & target)92 status_t ConvertFromDriverSettings(const driver_parameter& parameter,
93 const char* name, int32 index, uint32 type, BMessage& target)
94 {
95 BMessage message;
96 if (strcmp(parameter.name, "on") == 0) {
97 // Parse values directly following "on"
98 if (index != 0)
99 return B_OK;
100
101 return AddSubMessage(parameter, index, target);
102 }
103
104 message.AddString("args", parameter.values[index]);
105 return target.AddMessage(parameter.name, &message);
106 }
107
Name()108 const char* Name()
109 {
110 return "on";
111 }
112 };
113
114
115 class RunConverter : public DriverSettingsConverter {
116 public:
ConvertFromDriverSettings(const driver_parameter & parameter,const char * name,int32 index,uint32 type,BMessage & target)117 status_t ConvertFromDriverSettings(const driver_parameter& parameter,
118 const char* name, int32 index, uint32 type, BMessage& target)
119 {
120 if (parameter.parameter_count == 0)
121 return target.AddString("target", parameter.values[index]);
122
123 return B_NOT_SUPPORTED;
124 }
125
ConvertEmptyFromDriverSettings(const driver_parameter & parameter,const char * name,uint32 type,BMessage & target)126 status_t ConvertEmptyFromDriverSettings(
127 const driver_parameter& parameter, const char* name, uint32 type,
128 BMessage& target)
129 {
130 if (parameter.parameter_count != 0)
131 return B_OK;
132
133 return target.AddString("target", name);
134 }
135 };
136
137
138 const static settings_template kConditionTemplate[] = {
139 {B_STRING_TYPE, NULL, NULL, true, new ConditionConverter()},
140 {B_MESSAGE_TYPE, "not", kConditionTemplate},
141 {B_MESSAGE_TYPE, "and", kConditionTemplate},
142 {B_MESSAGE_TYPE, "or", kConditionTemplate},
143 {0, NULL, NULL}
144 };
145
146 const static settings_template kEventTemplate[] = {
147 {B_STRING_TYPE, NULL, NULL, true, new EventConverter()},
148 {B_MESSAGE_TYPE, "and", kEventTemplate},
149 {B_MESSAGE_TYPE, "or", kEventTemplate},
150 {0, NULL, NULL}
151 };
152
153 const static settings_template kPortTemplate[] = {
154 {B_STRING_TYPE, "name", NULL, true},
155 {B_INT32_TYPE, "capacity", NULL},
156 };
157
158 const static settings_template kEnvTemplate[] = {
159 {B_STRING_TYPE, "from_script", NULL, true},
160 {B_STRING_TYPE, NULL, NULL},
161 };
162
163 const static settings_template kJobTemplate[] = {
164 {B_STRING_TYPE, "name", NULL, true},
165 {B_BOOL_TYPE, "disabled", NULL},
166 {B_STRING_TYPE, "launch", NULL},
167 {B_STRING_TYPE, "requires", NULL},
168 {B_BOOL_TYPE, "legacy", NULL},
169 {B_MESSAGE_TYPE, "port", kPortTemplate},
170 {B_MESSAGE_TYPE, "on", kEventTemplate},
171 {B_MESSAGE_TYPE, "if", kConditionTemplate},
172 {B_BOOL_TYPE, "no_safemode", NULL},
173 {B_BOOL_TYPE, "on_demand", NULL},
174 {B_MESSAGE_TYPE, "env", kEnvTemplate},
175 {0, NULL, NULL}
176 };
177
178 const static settings_template kTargetTemplate[] = {
179 {B_STRING_TYPE, "name", NULL, true},
180 {B_BOOL_TYPE, "reset", NULL},
181 {B_MESSAGE_TYPE, "on", kEventTemplate},
182 {B_MESSAGE_TYPE, "if", kConditionTemplate},
183 {B_BOOL_TYPE, "no_safemode", NULL},
184 {B_MESSAGE_TYPE, "env", kEnvTemplate},
185 {B_MESSAGE_TYPE, "job", kJobTemplate},
186 {B_MESSAGE_TYPE, "service", kJobTemplate},
187 {0, NULL, NULL}
188 };
189
190 const static settings_template kRunConditionalTemplate[] = {
191 {B_STRING_TYPE, NULL, NULL, true, new RunConverter()},
192 {0, NULL, NULL}
193 };
194
195 const static settings_template kRunTemplate[] = {
196 {B_STRING_TYPE, NULL, NULL, true, new RunConverter()},
197 {B_MESSAGE_TYPE, "if", kConditionTemplate},
198 {B_MESSAGE_TYPE, "then", kRunConditionalTemplate},
199 {B_MESSAGE_TYPE, "else", kRunConditionalTemplate},
200 {0, NULL, NULL}
201 };
202
203 const static settings_template kSettingsTemplate[] = {
204 {B_MESSAGE_TYPE, "target", kTargetTemplate},
205 {B_MESSAGE_TYPE, "job", kJobTemplate},
206 {B_MESSAGE_TYPE, "service", kJobTemplate},
207 {B_MESSAGE_TYPE, "run", kRunTemplate},
208 {0, NULL, NULL}
209 };
210
211
SettingsParser()212 SettingsParser::SettingsParser()
213 {
214 }
215
216
217 status_t
ParseFile(const char * path,BMessage & settings)218 SettingsParser::ParseFile(const char* path, BMessage& settings)
219 {
220 DriverSettingsMessageAdapter adapter;
221 return adapter.ConvertFromDriverSettings(path, kSettingsTemplate, settings);
222 }
223
224
225 #ifdef TEST_HAIKU
226
227
228 status_t
Parse(const char * text,BMessage & settings)229 SettingsParser::Parse(const char* text, BMessage& settings)
230 {
231 void* driverSettings = parse_driver_settings_string(text);
232 if (driverSettings == NULL)
233 return B_BAD_VALUE;
234
235 DriverSettingsMessageAdapter adapter;
236 status_t status = adapter.ConvertFromDriverSettings(
237 *get_driver_settings(driverSettings), kSettingsTemplate, settings);
238
239 unload_driver_settings(driverSettings);
240 return status;
241 }
242
243
244 #endif // TEST_HAIKU
245