blob: d037338c73a8874eec34388c118c764664aa1498 [file] [log] [blame]
Jim Cownie33f7b242014-04-09 15:40:23 +00001//===----------------------------------------------------------------------===//
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
18const int MicEnvVar::any_card = -1;
19
20MicEnvVar::~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
30MicEnvVar::VarValue::~VarValue()
31{
32 free(env_var_value);
33}
34
35MicEnvVar::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
46MicEnvVar::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
64MicEnvVar::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
81void 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
111void 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 Tokerc2d5e612014-06-01 18:28:36 +0000129 // definition for new card occurred
Jim Cownie33f7b242014-04-09 15:40:23 +0000130 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
156MicEnvVarKind 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
228void 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 Tokerc2d5e612014-06-01 18:28:36 +0000302// In the beginning of the vector there are env vars defined as
Jim Cownie33f7b242014-04-09 15:40:23 +0000303// <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
310char** 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}