xref: /haiku/src/servers/launch/SettingsParser.cpp (revision af435dd1c9460acc910170b4f82f44bfd3f557c9)
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 = &target;
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