Jim Cownie | 33f7b24 | 2014-04-09 15:40:23 +0000 | [diff] [blame] | 1 | //===----------------------------------------------------------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is dual licensed under the MIT and the University of Illinois Open |
| 6 | // Source Licenses. See LICENSE.txt for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | |
| 11 | #include "offload_env.h" |
| 12 | #include <string.h> |
| 13 | #include <ctype.h> |
| 14 | #include "offload_util.h" |
| 15 | #include "liboffload_error_codes.h" |
| 16 | |
| 17 | // for environment variables valid on all cards |
| 18 | const int MicEnvVar::any_card = -1; |
| 19 | |
| 20 | MicEnvVar::~MicEnvVar() |
| 21 | { |
| 22 | for (std::list<MicEnvVar::CardEnvVars*>::const_iterator |
| 23 | it = card_spec_list.begin(); |
| 24 | it != card_spec_list.end(); it++) { |
| 25 | CardEnvVars *card_data = *it; |
| 26 | delete card_data; |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | MicEnvVar::VarValue::~VarValue() |
| 31 | { |
| 32 | free(env_var_value); |
| 33 | } |
| 34 | |
| 35 | MicEnvVar::CardEnvVars::~CardEnvVars() |
| 36 | { |
| 37 | for (std::list<MicEnvVar::VarValue*>::const_iterator it = env_vars.begin(); |
| 38 | it != env_vars.end(); it++) { |
| 39 | VarValue *var_value = *it; |
| 40 | delete var_value; |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | // Searching for card in "card_spec_list" list with the same "number" |
| 45 | |
| 46 | MicEnvVar::CardEnvVars* MicEnvVar::get_card(int number) |
| 47 | { |
| 48 | if (number == any_card) { |
| 49 | return &common_vars; |
| 50 | } |
| 51 | for (std::list<MicEnvVar::CardEnvVars*>::const_iterator |
| 52 | it = card_spec_list.begin(); |
| 53 | it != card_spec_list.end(); it++) { |
| 54 | CardEnvVars *card_data = *it; |
| 55 | if (card_data->card_number == number) { |
| 56 | return card_data; |
| 57 | } |
| 58 | } |
| 59 | return NULL; |
| 60 | } |
| 61 | |
| 62 | // Searching for environment variable in "env_var" list with the same name |
| 63 | |
| 64 | MicEnvVar::VarValue* MicEnvVar::CardEnvVars::find_var( |
| 65 | char* env_var_name, |
| 66 | int env_var_name_length |
| 67 | ) |
| 68 | { |
| 69 | for (std::list<MicEnvVar::VarValue*>::const_iterator it = env_vars.begin(); |
| 70 | it != env_vars.end(); it++) { |
| 71 | VarValue *var_value = *it; |
| 72 | if (var_value->length == env_var_name_length && |
| 73 | !strncmp(var_value->env_var, env_var_name, |
| 74 | env_var_name_length)) { |
| 75 | return var_value; |
| 76 | } |
| 77 | } |
| 78 | return NULL; |
| 79 | } |
| 80 | |
| 81 | void MicEnvVar::analyze_env_var(char *env_var_string) |
| 82 | { |
| 83 | char *env_var_name; |
| 84 | char *env_var_def; |
| 85 | int card_number; |
| 86 | int env_var_name_length; |
| 87 | MicEnvVarKind env_var_kind; |
| 88 | |
| 89 | env_var_kind = get_env_var_kind(env_var_string, |
| 90 | &card_number, |
| 91 | &env_var_name, |
| 92 | &env_var_name_length, |
| 93 | &env_var_def); |
| 94 | switch (env_var_kind) { |
| 95 | case c_mic_var: |
| 96 | case c_mic_card_var: |
| 97 | add_env_var(card_number, |
| 98 | env_var_name, |
| 99 | env_var_name_length, |
| 100 | env_var_def); |
| 101 | break; |
| 102 | case c_mic_card_env: |
| 103 | mic_parse_env_var_list(card_number, env_var_def); |
| 104 | break; |
| 105 | case c_no_mic: |
| 106 | default: |
| 107 | break; |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | void MicEnvVar::add_env_var( |
| 112 | int card_number, |
| 113 | char *env_var_name, |
| 114 | int env_var_name_length, |
| 115 | char *env_var_def |
| 116 | ) |
| 117 | { |
| 118 | VarValue *var; |
| 119 | CardEnvVars *card; |
| 120 | |
| 121 | // The case corresponds to common env var definition of kind |
| 122 | // <mic-prefix>_<var> |
| 123 | if (card_number == any_card) { |
| 124 | card = &common_vars; |
| 125 | } |
| 126 | else { |
| 127 | card = get_card(card_number); |
| 128 | if (!card) { |
Alp Toker | c2d5e61 | 2014-06-01 18:28:36 +0000 | [diff] [blame] | 129 | // definition for new card occurred |
Jim Cownie | 33f7b24 | 2014-04-09 15:40:23 +0000 | [diff] [blame] | 130 | card = new CardEnvVars(card_number); |
| 131 | card_spec_list.push_back(card); |
| 132 | } |
| 133 | |
| 134 | } |
| 135 | var = card->find_var(env_var_name, env_var_name_length); |
| 136 | if (!var) { |
| 137 | // put new env var definition in "env_var" list |
| 138 | var = new VarValue(env_var_name, env_var_name_length, env_var_def); |
| 139 | card->env_vars.push_back(var); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | // The routine analyses string pointed by "env_var_string" argument |
| 144 | // according to the following syntax: |
| 145 | // |
| 146 | // Specification of prefix for MIC environment variables |
| 147 | // MIC_ENV_PREFIX=<mic-prefix> |
| 148 | // |
| 149 | // Setting single MIC environment variable |
| 150 | // <mic-prefix>_<var>=<value> |
| 151 | // <mic-prefix>_<card-number>_<var>=<value> |
| 152 | |
| 153 | // Setting multiple MIC environment variables |
| 154 | // <mic-prefix>_<card-number>_ENV=<env-vars> |
| 155 | |
| 156 | MicEnvVarKind MicEnvVar::get_env_var_kind( |
| 157 | char *env_var_string, |
| 158 | int *card_number, |
| 159 | char **env_var_name, |
| 160 | int *env_var_name_length, |
| 161 | char **env_var_def |
| 162 | ) |
| 163 | { |
| 164 | int len = strlen(prefix); |
| 165 | char *c = env_var_string; |
| 166 | int num = 0; |
| 167 | bool card_is_set = false; |
| 168 | |
| 169 | if (strncmp(c, prefix, len) != 0 || c[len] != '_') { |
| 170 | return c_no_mic; |
| 171 | } |
| 172 | c += len + 1; |
| 173 | |
| 174 | *card_number = any_card; |
| 175 | if (isdigit(*c)) { |
| 176 | while (isdigit (*c)) { |
| 177 | num = (*c++ - '0') + (num * 10); |
| 178 | } |
| 179 | if (*c != '_') { |
| 180 | return c_no_mic; |
| 181 | } |
| 182 | c++; |
| 183 | *card_number = num; |
| 184 | card_is_set = true; |
| 185 | } |
| 186 | if (!isalpha(*c)) { |
| 187 | return c_no_mic; |
| 188 | } |
| 189 | *env_var_name = *env_var_def = c; |
| 190 | if (strncmp(c, "ENV=", 4) == 0) { |
| 191 | if (!card_is_set) { |
| 192 | *env_var_name_length = 3; |
| 193 | *env_var_name = *env_var_def = c; |
| 194 | *env_var_def = strdup(*env_var_def); |
| 195 | return c_mic_var; |
| 196 | } |
| 197 | *env_var_def = c + strlen("ENV="); |
| 198 | *env_var_def = strdup(*env_var_def); |
| 199 | return c_mic_card_env; |
| 200 | } |
| 201 | if (isalpha(*c)) { |
| 202 | *env_var_name_length = 0; |
| 203 | while (isalnum(*c) || *c == '_') { |
| 204 | c++; |
| 205 | (*env_var_name_length)++; |
| 206 | } |
| 207 | } |
| 208 | if (*c != '=') { |
| 209 | return c_no_mic; |
| 210 | } |
| 211 | *env_var_def = strdup(*env_var_def); |
| 212 | return card_is_set? c_mic_card_var : c_mic_var; |
| 213 | } |
| 214 | |
| 215 | // analysing <env-vars> in form: |
| 216 | // <mic-prefix>_<card-number>_ENV=<env-vars> |
| 217 | // where: |
| 218 | // |
| 219 | // <env-vars>: |
| 220 | // <env-var> |
| 221 | // <env-vars> | <env-var> |
| 222 | // |
| 223 | // <env-var>: |
| 224 | // variable=value |
| 225 | // variable="value" |
| 226 | // variable= |
| 227 | |
| 228 | void MicEnvVar::mic_parse_env_var_list( |
| 229 | int card_number, char *env_vars_def_list) |
| 230 | { |
| 231 | char *c = env_vars_def_list; |
| 232 | char *env_var_name; |
| 233 | int env_var_name_length; |
| 234 | char *env_var_def; |
| 235 | bool var_is_quoted; |
| 236 | |
| 237 | if (*c == '"') { |
| 238 | c++; |
| 239 | } |
| 240 | while (*c != 0) { |
| 241 | var_is_quoted = false; |
| 242 | env_var_name = c; |
| 243 | env_var_name_length = 0; |
| 244 | if (isalpha(*c)) { |
| 245 | while (isalnum(*c) || *c == '_') { |
| 246 | c++; |
| 247 | env_var_name_length++; |
| 248 | } |
| 249 | } |
| 250 | else { |
| 251 | LIBOFFLOAD_ERROR(c_mic_parse_env_var_list1); |
| 252 | return; |
| 253 | } |
| 254 | if (*c != '=') { |
| 255 | LIBOFFLOAD_ERROR(c_mic_parse_env_var_list2); |
| 256 | return; |
| 257 | } |
| 258 | c++; |
| 259 | |
| 260 | if (*c == '"') { |
| 261 | var_is_quoted = true; |
| 262 | c++; |
| 263 | } |
| 264 | // Environment variable values that contain | will need to be escaped. |
| 265 | while (*c != 0 && *c != '|' && |
| 266 | (!var_is_quoted || *c != '"')) |
| 267 | { |
| 268 | // skip escaped symbol |
| 269 | if (*c == '\\') { |
| 270 | c++; |
| 271 | } |
| 272 | c++; |
| 273 | } |
| 274 | if (var_is_quoted) { |
| 275 | c++; // for " |
| 276 | while (*c != 0 && *c != '|') { |
| 277 | c++; |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | int sz = c - env_var_name; |
| 282 | env_var_def = (char*)malloc(sz); |
| 283 | memcpy(env_var_def, env_var_name, sz); |
| 284 | env_var_def[sz] = 0; |
| 285 | |
| 286 | if (*c == '|') { |
| 287 | c++; |
| 288 | while (*c != 0 && *c == ' ') { |
| 289 | c++; |
| 290 | } |
| 291 | } |
| 292 | add_env_var(card_number, |
| 293 | env_var_name, |
| 294 | env_var_name_length, |
| 295 | env_var_def); |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | // Collect all definitions for the card with number "card_num". |
| 300 | // The returned result is vector of string pointers defining one |
| 301 | // environment variable. The vector is terminated by NULL pointer. |
Alp Toker | c2d5e61 | 2014-06-01 18:28:36 +0000 | [diff] [blame] | 302 | // In the beginning of the vector there are env vars defined as |
Jim Cownie | 33f7b24 | 2014-04-09 15:40:23 +0000 | [diff] [blame] | 303 | // <mic-prefix>_<card-number>_<var>=<value> |
| 304 | // or |
| 305 | // <mic-prefix>_<card-number>_ENV=<env-vars> |
| 306 | // where <card-number> is equal to "card_num" |
| 307 | // They are followed by definitions valid for any card |
| 308 | // and absent in previous definitions. |
| 309 | |
| 310 | char** MicEnvVar::create_environ_for_card(int card_num) |
| 311 | { |
| 312 | VarValue *var_value; |
| 313 | VarValue *var_value_find; |
| 314 | CardEnvVars *card_data = get_card(card_num); |
| 315 | CardEnvVars *card_data_common; |
| 316 | std::list<char*> new_env; |
| 317 | char **rez; |
| 318 | |
| 319 | if (!prefix) { |
| 320 | return NULL; |
| 321 | } |
| 322 | // There is no personel env var definitions for the card with |
| 323 | // number "card_num" |
| 324 | if (!card_data) { |
| 325 | return create_environ_for_card(any_card); |
| 326 | } |
| 327 | |
| 328 | for (std::list<MicEnvVar::VarValue*>::const_iterator |
| 329 | it = card_data->env_vars.begin(); |
| 330 | it != card_data->env_vars.end(); it++) { |
| 331 | var_value = *it; |
| 332 | new_env.push_back(var_value->env_var_value); |
| 333 | } |
| 334 | |
| 335 | if (card_num != any_card) { |
| 336 | card_data_common = get_card(any_card); |
| 337 | for (std::list<MicEnvVar::VarValue*>::const_iterator |
| 338 | it = card_data_common->env_vars.begin(); |
| 339 | it != card_data_common->env_vars.end(); it++) { |
| 340 | var_value = *it; |
| 341 | var_value_find = card_data->find_var(var_value->env_var, |
| 342 | var_value->length); |
| 343 | if (!var_value_find) { |
| 344 | new_env.push_back(var_value->env_var_value); |
| 345 | } |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | int new_env_size = new_env.size(); |
| 350 | rez = (char**) malloc((new_env_size + 1) * sizeof(char*)); |
| 351 | std::copy(new_env.begin(), new_env.end(), rez); |
| 352 | rez[new_env_size] = 0; |
| 353 | return rez; |
| 354 | } |