mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			385 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			385 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|     Copyright (c) 2014-2016 Intel Corporation.  All Rights Reserved.
 | |
| 
 | |
|     Redistribution and use in source and binary forms, with or without
 | |
|     modification, are permitted provided that the following conditions
 | |
|     are met:
 | |
| 
 | |
|       * Redistributions of source code must retain the above copyright
 | |
|         notice, this list of conditions and the following disclaimer.
 | |
|       * Redistributions in binary form must reproduce the above copyright
 | |
|         notice, this list of conditions and the following disclaimer in the
 | |
|         documentation and/or other materials provided with the distribution.
 | |
|       * Neither the name of Intel Corporation nor the names of its
 | |
|         contributors may be used to endorse or promote products derived
 | |
|         from this software without specific prior written permission.
 | |
| 
 | |
|     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
|     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
|     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
|     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
|     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
|     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
|     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
|     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| */
 | |
| 
 | |
| 
 | |
| #include "offload_env.h"
 | |
| #include <string.h>
 | |
| #include <ctype.h>
 | |
| #include "offload_util.h"
 | |
| #include "liboffload_error_codes.h"
 | |
| 
 | |
| // for environment variables valid on all cards
 | |
| const int MicEnvVar::any_card = -1;
 | |
| 
 | |
| MicEnvVar::~MicEnvVar()
 | |
| {
 | |
|     for (std::list<MicEnvVar::CardEnvVars*>::const_iterator
 | |
|          it = card_spec_list.begin();
 | |
|          it != card_spec_list.end(); it++) {
 | |
|         CardEnvVars *card_data = *it;
 | |
|         delete card_data;
 | |
|     }
 | |
| }
 | |
| 
 | |
| MicEnvVar::VarValue::~VarValue()
 | |
| {
 | |
|     free(env_var_value);
 | |
| }
 | |
| 
 | |
| MicEnvVar::CardEnvVars::~CardEnvVars()
 | |
| {
 | |
|     for (std::list<MicEnvVar::VarValue*>::const_iterator it = env_vars.begin();
 | |
|         it != env_vars.end(); it++) {
 | |
|             VarValue *var_value = *it;
 | |
|             delete var_value;
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Searching for card in "card_spec_list" list with the same "number"
 | |
| 
 | |
| MicEnvVar::CardEnvVars* MicEnvVar::get_card(int number)
 | |
| {
 | |
|     if (number == any_card) {
 | |
|         return &common_vars;
 | |
|     }
 | |
|     for (std::list<MicEnvVar::CardEnvVars*>::const_iterator
 | |
|          it = card_spec_list.begin();
 | |
|          it != card_spec_list.end(); it++) {
 | |
|         CardEnvVars *card_data = *it;
 | |
|         if (card_data->card_number == number) {
 | |
|             return card_data;
 | |
|         }
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| // Searching for environment variable in "env_var" list with the same name
 | |
| 
 | |
| MicEnvVar::VarValue* MicEnvVar::CardEnvVars::find_var(
 | |
|     char* env_var_name,
 | |
|     int env_var_name_length
 | |
| )
 | |
| {
 | |
|     for (std::list<MicEnvVar::VarValue*>::const_iterator it = env_vars.begin();
 | |
|         it != env_vars.end(); it++) {
 | |
|             VarValue *var_value = *it;
 | |
|             if (var_value->length == env_var_name_length &&
 | |
|                 !strncmp(var_value->env_var, env_var_name,
 | |
|                          env_var_name_length)) {
 | |
|                 return var_value;
 | |
|             }
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| void MicEnvVar::analyze_env_var(char *env_var_string)
 | |
| {
 | |
|     char          *env_var_name;
 | |
|     char          *env_var_def;
 | |
|     int           card_number;
 | |
|     int           env_var_name_length;
 | |
|     MicEnvVarKind env_var_kind;
 | |
| 
 | |
|     env_var_kind = get_env_var_kind(env_var_string,
 | |
|                                     &card_number,
 | |
|                                     &env_var_name,
 | |
|                                     &env_var_name_length,
 | |
|                                     &env_var_def);
 | |
|     switch (env_var_kind) {
 | |
|         case c_mic_var:
 | |
|         case c_mic_card_var:
 | |
|             add_env_var(card_number,
 | |
|                         env_var_name,
 | |
|                         env_var_name_length,
 | |
|                         env_var_def);
 | |
|             break;
 | |
|         case c_mic_card_env:
 | |
|             mic_parse_env_var_list(card_number, env_var_def);
 | |
|             break;
 | |
|         case c_no_mic:
 | |
|         default:
 | |
|             break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void MicEnvVar::add_env_var(
 | |
|     int card_number,
 | |
|     char *env_var_name,
 | |
|     int env_var_name_length,
 | |
|     char *env_var_def
 | |
| )
 | |
| {
 | |
|     VarValue *var;
 | |
|     CardEnvVars *card;
 | |
| 
 | |
|     // The case corresponds to common env var definition of kind
 | |
|     // <mic-prefix>_<var>
 | |
|     if (card_number == any_card) {
 | |
|         card = &common_vars;
 | |
|     }
 | |
|     else {
 | |
|         card = get_card(card_number);
 | |
|         if (!card) {
 | |
|             // definition for new card occurred
 | |
|             card = new CardEnvVars(card_number);
 | |
|             card_spec_list.push_back(card);
 | |
|         }
 | |
| 
 | |
|     }
 | |
|     var = card->find_var(env_var_name, env_var_name_length);
 | |
|     if (!var) {
 | |
|         // put new env var definition in "env_var" list
 | |
|         var = new VarValue(env_var_name, env_var_name_length, env_var_def);
 | |
|         card->env_vars.push_back(var);
 | |
|     }
 | |
| }
 | |
| 
 | |
| // The routine analyses string pointed by "env_var_string" argument
 | |
| // according to the following syntax:
 | |
| //
 | |
| // Specification of prefix for MIC environment variables
 | |
| // MIC_ENV_PREFIX=<mic-prefix>
 | |
| //
 | |
| // Setting single MIC environment variable
 | |
| // <mic-prefix>_<var>=<value>
 | |
| // <mic-prefix>_<card-number>_<var>=<value>
 | |
| 
 | |
| // Setting multiple MIC environment variables
 | |
| // <mic-prefix>_<card-number>_ENV=<env-vars>
 | |
| 
 | |
| MicEnvVarKind MicEnvVar::get_env_var_kind(
 | |
|     char *env_var_string,
 | |
|     int *card_number,
 | |
|     char **env_var_name,
 | |
|     int *env_var_name_length,
 | |
|     char **env_var_def
 | |
| )
 | |
| {
 | |
|     int len = strlen(prefix);
 | |
|     char *c = env_var_string;
 | |
|     int num = 0;
 | |
|     bool card_is_set = false;
 | |
| 
 | |
|     if (strncmp(c, prefix, len) != 0 || c[len] != '_') {
 | |
|             return c_no_mic;
 | |
|     }
 | |
|     c += len + 1;
 | |
| 
 | |
|     *card_number = any_card;
 | |
|     if (isdigit(*c)) {
 | |
|         while (isdigit (*c)) {
 | |
|             num = (*c++ - '0') + (num * 10);
 | |
|         }
 | |
|     if (*c != '_') {
 | |
|         return c_no_mic;
 | |
|     }
 | |
|     c++;
 | |
|         *card_number = num;
 | |
|         card_is_set = true;
 | |
|     }
 | |
|     if (!isalpha(*c)) {
 | |
|         return c_no_mic;
 | |
|     }
 | |
|     *env_var_name = *env_var_def = c;
 | |
|     if (strncmp(c, "ENV=", 4) == 0) {
 | |
|         if (!card_is_set) {
 | |
|             *env_var_name_length = 3;
 | |
|             *env_var_name = *env_var_def = c;
 | |
|             *env_var_def = strdup(*env_var_def);
 | |
|             if (*env_var_def == NULL)
 | |
|                 LIBOFFLOAD_ERROR(c_malloc);
 | |
|             return  c_mic_var;
 | |
|         }
 | |
|         *env_var_def = c + strlen("ENV=");
 | |
|         *env_var_def = strdup(*env_var_def);
 | |
|         if (*env_var_def == NULL)
 | |
|             LIBOFFLOAD_ERROR(c_malloc);
 | |
|         return c_mic_card_env;
 | |
|     }
 | |
|     if (isalpha(*c)) {
 | |
|         *env_var_name_length = 0;
 | |
|         while (isalnum(*c) || *c == '_') {
 | |
|             c++;
 | |
|             (*env_var_name_length)++;
 | |
|         }
 | |
|     }
 | |
|     if (*c != '=') {
 | |
|         return c_no_mic;
 | |
|     }
 | |
|     *env_var_def = strdup(*env_var_def);
 | |
|     if (*env_var_def == NULL)
 | |
|         LIBOFFLOAD_ERROR(c_malloc);
 | |
|     return card_is_set? c_mic_card_var : c_mic_var;
 | |
| }
 | |
| 
 | |
| // analysing <env-vars> in form:
 | |
| // <mic-prefix>_<card-number>_ENV=<env-vars>
 | |
| // where:
 | |
| //
 | |
| // <env-vars>:
 | |
| //                <env-var>
 | |
| //                <env-vars> | <env-var>
 | |
| //
 | |
| // <env-var>:
 | |
| //                variable=value
 | |
| //                variable="value"
 | |
| //                variable=
 | |
| 
 | |
| void MicEnvVar::mic_parse_env_var_list(
 | |
|     int card_number, char *env_vars_def_list)
 | |
| {
 | |
|     char *c = env_vars_def_list;
 | |
|     char *env_var_name;
 | |
|     int  env_var_name_length;
 | |
|     char *env_var_def;
 | |
|     bool var_is_quoted;
 | |
| 
 | |
|     if (*c == '"') {
 | |
|         c++;
 | |
|     }
 | |
|     while (*c != 0) {
 | |
|         var_is_quoted = false;
 | |
|         env_var_name = c;
 | |
|         env_var_name_length = 0;
 | |
|         if (isalpha(*c)) {
 | |
|             while (isalnum(*c) || *c == '_') {
 | |
|                 c++;
 | |
|                 env_var_name_length++;
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             LIBOFFLOAD_ERROR(c_mic_parse_env_var_list1);
 | |
|             return;
 | |
|         }
 | |
|         if (*c != '=') {
 | |
|             LIBOFFLOAD_ERROR(c_mic_parse_env_var_list2);
 | |
|             return;
 | |
|         }
 | |
|         c++;
 | |
| 
 | |
|         if (*c == '"') {
 | |
|             var_is_quoted = true;
 | |
|             c++;
 | |
|         }
 | |
|         // Environment variable values that contain | will need to be escaped.
 | |
|         while (*c != 0 && *c != '|' &&
 | |
|                (!var_is_quoted || *c != '"'))
 | |
|         {
 | |
|             // skip escaped symbol
 | |
|             if (*c == '\\') {
 | |
|                 c++;
 | |
|             }
 | |
|             c++;
 | |
|         }
 | |
|         if (var_is_quoted) {
 | |
|             c++; // for "
 | |
|             while (*c != 0 && *c != '|') {
 | |
|                 c++;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         int sz = c - env_var_name;
 | |
|         env_var_def = (char*)malloc(sz);
 | |
|         if (env_var_def == NULL)
 | |
|           LIBOFFLOAD_ERROR(c_malloc);
 | |
|         memcpy(env_var_def, env_var_name, sz);
 | |
|         env_var_def[sz] = 0;
 | |
| 
 | |
|         if (*c == '|') {
 | |
|             c++;
 | |
|             while (*c != 0 && *c == ' ') {
 | |
|                 c++;
 | |
|             }
 | |
|         }
 | |
|         add_env_var(card_number,
 | |
|                     env_var_name,
 | |
|                     env_var_name_length,
 | |
|                     env_var_def);
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Collect all definitions for the card with number "card_num".
 | |
| // The returned result is vector of string pointers defining one
 | |
| // environment variable. The vector is terminated by NULL pointer.
 | |
| // In the beginning of the vector there are env vars defined as
 | |
| // <mic-prefix>_<card-number>_<var>=<value>
 | |
| // or
 | |
| // <mic-prefix>_<card-number>_ENV=<env-vars>
 | |
| // where <card-number> is equal to "card_num"
 | |
| // They are followed by definitions valid for any card
 | |
| // and absent in previous definitions.
 | |
| 
 | |
| char** MicEnvVar::create_environ_for_card(int card_num)
 | |
| {
 | |
|     VarValue *var_value;
 | |
|     VarValue *var_value_find;
 | |
|     CardEnvVars *card_data = get_card(card_num);
 | |
|     CardEnvVars *card_data_common;
 | |
|     std::list<char*> new_env;
 | |
|     char **rez;
 | |
| 
 | |
|     if (!prefix) {
 | |
|         return NULL;
 | |
|     }
 | |
|     // There is no personel env var definitions for the card with
 | |
|     // number "card_num"
 | |
|     if (!card_data) {
 | |
|         return create_environ_for_card(any_card);
 | |
|     }
 | |
| 
 | |
|     for (std::list<MicEnvVar::VarValue*>::const_iterator
 | |
|          it = card_data->env_vars.begin();
 | |
|          it != card_data->env_vars.end(); it++) {
 | |
|         var_value = *it;
 | |
|         new_env.push_back(var_value->env_var_value);
 | |
|     }
 | |
| 
 | |
|     if (card_num != any_card) {
 | |
|         card_data_common = get_card(any_card);
 | |
|         for (std::list<MicEnvVar::VarValue*>::const_iterator
 | |
|              it = card_data_common->env_vars.begin();
 | |
|              it != card_data_common->env_vars.end(); it++) {
 | |
|             var_value = *it;
 | |
|             var_value_find = card_data->find_var(var_value->env_var,
 | |
|                                                  var_value->length);
 | |
|             if (!var_value_find) {
 | |
|                 new_env.push_back(var_value->env_var_value);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     int new_env_size = new_env.size();
 | |
|     rez = (char**) malloc((new_env_size + 1) * sizeof(char*));
 | |
|     if (rez == NULL)
 | |
|       LIBOFFLOAD_ERROR(c_malloc);
 | |
|     std::copy(new_env.begin(), new_env.end(), rez);
 | |
|     rez[new_env_size] = 0;
 | |
|     return rez;
 | |
| }
 |