279 lines
6.9 KiB
C
279 lines
6.9 KiB
C
/* Copyright (C) 2016 Jeremiah Orians
|
|
* Copyright (C) 2020 deesix <deesix@tuta.io>
|
|
* This file is part of M2-Planet.
|
|
*
|
|
* M2-Planet is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* M2-Planet is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with M2-Planet. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include"cc.h"
|
|
#include <sys/utsname.h>
|
|
|
|
void init_macro_env(char* sym, char* value, char* source, int num);
|
|
char* env_lookup(char* variable);
|
|
|
|
void setup_env()
|
|
{
|
|
if(2 <= DEBUG_LEVEL) fputs("Starting setup_env\n", stderr);
|
|
char* ARCH = NULL;
|
|
struct utsname* unameData = calloc(1, sizeof(struct utsname));
|
|
require(NULL != unameData, "unameData calloc failed\n");
|
|
uname(unameData);
|
|
if(3 <= DEBUG_LEVEL) fputs("obtained architecture details\n", stderr);
|
|
if(4 <= DEBUG_LEVEL)
|
|
{
|
|
fputs("utsname details: ", stderr);
|
|
fputs(unameData->machine, stderr);
|
|
fputc('\n', stderr);
|
|
}
|
|
|
|
if(match("i386", unameData->machine) ||
|
|
match("i486", unameData->machine) ||
|
|
match("i586", unameData->machine) ||
|
|
match("i686", unameData->machine) ||
|
|
match("i686-pae", unameData->machine)) ARCH = "x86";
|
|
else if(match("x86_64", unameData->machine)) ARCH = "amd64";
|
|
else ARCH = unameData->machine;
|
|
if(3 <= DEBUG_LEVEL)
|
|
{
|
|
fputs("Architecture selected: ", stderr);
|
|
fputs(ARCH, stderr);
|
|
fputc('\n', stderr);
|
|
}
|
|
|
|
|
|
/* Check for override */
|
|
char* hold = env_lookup("ARCHITECTURE_OVERRIDE");
|
|
if(NULL != hold) ARCH = hold;
|
|
if(3 <= DEBUG_LEVEL) fputs("override?\n", stderr);
|
|
|
|
/* Set desired architecture */
|
|
WORDSIZE = 32;
|
|
ENDIAN = FALSE;
|
|
BASEADDRESS = "0x0";
|
|
if(match("knight-native", ARCH))
|
|
{
|
|
ENDIAN = TRUE;
|
|
Architecture = "knight-native";
|
|
}
|
|
else if(match("knight-posix", ARCH))
|
|
{
|
|
ENDIAN = TRUE;
|
|
Architecture = "knight-posix";
|
|
}
|
|
else if(match("x86", ARCH))
|
|
{
|
|
BASEADDRESS = "0x8048000";
|
|
Architecture = "x86";
|
|
init_macro_env("__i386__", "1", "--architecture", 0);
|
|
}
|
|
else if(match("amd64", ARCH))
|
|
{
|
|
BASEADDRESS = "0x00600000";
|
|
Architecture = "amd64";
|
|
WORDSIZE = 64;
|
|
init_macro_env("__x86_64__", "1", "--architecture", 0);
|
|
}
|
|
else if(match("armv7l", ARCH))
|
|
{
|
|
BASEADDRESS = "0x10000";
|
|
Architecture = "armv7l";
|
|
init_macro_env("__arm__", "1", "--architecture", 0);
|
|
}
|
|
else if(match("aarch64", ARCH))
|
|
{
|
|
BASEADDRESS = "0x400000";
|
|
Architecture = "aarch64";
|
|
WORDSIZE = 64;
|
|
init_macro_env("__aarch64__", "1", "--architecture", 0);
|
|
}
|
|
else if(match("riscv64", ARCH))
|
|
{
|
|
BASEADDRESS = "0x600000";
|
|
Architecture = "riscv64";
|
|
WORDSIZE = 64;
|
|
init_macro_env("__riscv", "1", "--architecture", 0);
|
|
init_macro_env("__riscv_xlen", "64", "--architecture", 1);
|
|
}
|
|
else
|
|
{
|
|
fputs("Unknown architecture: ", stderr);
|
|
fputs(ARCH, stderr);
|
|
fputs(" know values are: knight-native, knight-posix, x86, amd64, armv7l, aarch64 and riscv64\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if(2 <= DEBUG_LEVEL) fputs("setup_env successful\n", stderr);
|
|
}
|
|
|
|
struct Token
|
|
{
|
|
/*
|
|
* For the token linked-list, this stores the token; for the env linked-list
|
|
* this stores the value of the variable.
|
|
*/
|
|
char* value;
|
|
/*
|
|
* Used only for the env linked-list. It holds a string containing the
|
|
* name of the var.
|
|
*/
|
|
char* var;
|
|
/*
|
|
* This struct stores a node of a singly linked list, store the pointer to
|
|
* the next node.
|
|
*/
|
|
struct Token* next;
|
|
};
|
|
|
|
struct Token* env;
|
|
|
|
int array_length(char** array)
|
|
{
|
|
int length = 0;
|
|
|
|
while(array[length] != NULL)
|
|
{
|
|
length = length + 1;
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
/* Search for a variable in the token linked-list */
|
|
char* token_lookup(char* variable, struct Token* token)
|
|
{
|
|
/* Start at the head */
|
|
struct Token* n = token;
|
|
|
|
/* Loop over the linked-list */
|
|
while(n != NULL)
|
|
{
|
|
if(match(variable, n->var))
|
|
{
|
|
/* We have found the correct node */
|
|
return n->value; /* Done */
|
|
}
|
|
|
|
/* Nope, try the next */
|
|
n = n->next;
|
|
}
|
|
|
|
/* We didn't find anything! */
|
|
return NULL;
|
|
}
|
|
|
|
/* Search for a variable in the env linked-list */
|
|
char* env_lookup(char* variable)
|
|
{
|
|
return token_lookup(variable, env);
|
|
}
|
|
|
|
void populate_env(char** envp)
|
|
{
|
|
if(2 <= DEBUG_LEVEL) fputs("populate_env started\n", stderr);
|
|
/* You can't populate a NULL environment */
|
|
if(NULL == envp)
|
|
{
|
|
if(3 <= DEBUG_LEVEL) fputs("NULL envp\n", stderr);
|
|
return;
|
|
}
|
|
|
|
/* avoid empty arrays */
|
|
int max = array_length(envp);
|
|
|
|
if(0 == max)
|
|
{
|
|
if(3 <= DEBUG_LEVEL) fputs("Empty envp\n", stderr);
|
|
return;
|
|
}
|
|
|
|
/* Initialize env and n */
|
|
env = calloc(1, sizeof(struct Token));
|
|
require(env != NULL, "Memory initialization of env failed\n");
|
|
struct Token* n;
|
|
n = env;
|
|
int i;
|
|
int j;
|
|
int k;
|
|
char* envp_line;
|
|
|
|
if(3 <= DEBUG_LEVEL) fputs("starting env loop\n", stderr);
|
|
for(i = 0; i < max; i = i + 1)
|
|
{
|
|
n->var = calloc(MAX_STRING, sizeof(char));
|
|
require(n->var != NULL, "Memory initialization of n->var in population of env failed\n");
|
|
n->value = calloc(MAX_STRING, sizeof(char));
|
|
require(n->value != NULL, "Memory initialization of n->var in population of env failed\n");
|
|
j = 0;
|
|
/*
|
|
* envp is weird.
|
|
* When referencing envp[i]'s characters directly, they were all jumbled.
|
|
* So just copy envp[i] to envp_line, and work with that - that seems
|
|
* to fix it.
|
|
*/
|
|
envp_line = calloc(MAX_STRING, sizeof(char));
|
|
require(envp_line != NULL, "Memory initialization of envp_line in population of env failed\n");
|
|
strcpy(envp_line, envp[i]);
|
|
|
|
while(envp_line[j] != '=')
|
|
{
|
|
/* Copy over everything up to = to var */
|
|
n->var[j] = envp_line[j];
|
|
j = j + 1;
|
|
}
|
|
|
|
/* If we get strange input, we need to ignore it */
|
|
if(n->var == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
j = j + 1; /* Skip over = */
|
|
k = 0; /* As envp[i] will continue as j but n->value begins at 0 */
|
|
|
|
while(envp_line[j] != 0)
|
|
{
|
|
/* Copy everything else to value */
|
|
n->value[k] = envp_line[j];
|
|
j = j + 1;
|
|
k = k + 1;
|
|
}
|
|
|
|
/* Sometimes, we get lines like VAR=, indicating nothing is in the variable */
|
|
if(n->value == NULL)
|
|
{
|
|
n->value = "";
|
|
}
|
|
|
|
/* Advance to next part of linked list */
|
|
n->next = calloc(1, sizeof(struct Token));
|
|
require(n->next != NULL, "Memory initialization of n->next in population of env failed\n");
|
|
n = n->next;
|
|
}
|
|
if(3 <= DEBUG_LEVEL) fputs("env loop successful\n", stderr);
|
|
|
|
/* Get rid of node on the end */
|
|
n = NULL;
|
|
/* Also destroy the n->next reference */
|
|
n = env;
|
|
|
|
require(NULL != n, "can't have an empty environment from the creation of a non-null environment\n");
|
|
require(NULL != n->next, "should have an extra node at the end of the env\n");
|
|
while(n->next->var != NULL)
|
|
{
|
|
n = n->next;
|
|
}
|
|
|
|
n->next = NULL;
|
|
if(2 <= DEBUG_LEVEL) fputs("populate_env successful\n", stderr);
|
|
}
|