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: 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: 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: 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 83 const char* Name() 84 { 85 return "if"; 86 } 87 }; 88 89 90 class EventConverter : public AbstractArgsConverter { 91 public: 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 108 const char* Name() 109 { 110 return "on"; 111 } 112 }; 113 114 115 class RunConverter : public DriverSettingsConverter { 116 public: 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 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 212 SettingsParser::SettingsParser() 213 { 214 } 215 216 217 status_t 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 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 delete_driver_settings(driverSettings); 240 return status; 241 } 242 243 244 #endif // TEST_HAIKU 245