diff --git a/cc.c b/cc.c index 8aacd04..59fa46d 100644 --- a/cc.c +++ b/cc.c @@ -51,6 +51,7 @@ int main(int argc, char** argv, char** envp) PREPROCESSOR_MODE = FALSE; STDIO_USED = FALSE; DIRTY_MODE = FALSE; + Architecture = NULL; /* Our fun locals */ int debug_flag = TRUE; @@ -108,6 +109,13 @@ int main(int argc, char** argv, char** envp) fputc('\n', stderr); i+= 2; } + else if(match(argv[i], "-A") || match(argv[i], "--architecture")) + { + hold = argv[i+1]; + require(NULL != hold, "--architecture needs to be passed an architecture\n"); + Architecture = hold; + i += 2; + } else if(match(argv[i], "-f") || match(argv[i], "--file")) { if(NULL == hold_string) @@ -138,6 +146,7 @@ int main(int argc, char** argv, char** envp) else if(match(argv[i], "-o") || match(argv[i], "--output")) { destination_name = argv[i + 1]; + require(NULL != destination_name, "--output option requires a filename to follow\n"); destination_file = fopen(destination_name, "w"); if(NULL == destination_file) { diff --git a/cc_env.c b/cc_env.c index b4f118c..a5ba351 100644 --- a/cc_env.c +++ b/cc_env.c @@ -21,41 +21,57 @@ void init_macro_env(char* sym, char* value, char* source, int num); char* env_lookup(char* variable); +void clear_string(char* s); 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) + char* ARCH; + if(NULL != Architecture) { - fputs("utsname details: ", stderr); - fputs(unameData->machine, stderr); - fputc('\n', stderr); + ARCH = Architecture; + } + else + { + ARCH = NULL; + struct utsname* unameData = calloc(1, sizeof(struct utsname)); + require(NULL != unameData, "unameData calloc failed\n"); + uname(unameData); + 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("environmental override for ARCH: ", stderr); + fputs(ARCH, 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; @@ -63,22 +79,26 @@ void setup_env() BASEADDRESS = "0x0"; if(match("knight-native", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using knight-native architecture\n", stderr); ENDIAN = TRUE; Architecture = "knight-native"; } else if(match("knight-posix", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using knight-posix architecture\n", stderr); ENDIAN = TRUE; Architecture = "knight-posix"; } else if(match("x86", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using x86 architecture\n", stderr); BASEADDRESS = "0x8048000"; Architecture = "x86"; init_macro_env("__i386__", "1", "--architecture", 0); } else if(match("amd64", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using amd64 architecture\n", stderr); BASEADDRESS = "0x00600000"; Architecture = "amd64"; WORDSIZE = 64; @@ -86,12 +106,14 @@ void setup_env() } else if(match("armv7l", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using armv7l architecture\n", stderr); BASEADDRESS = "0x10000"; Architecture = "armv7l"; init_macro_env("__arm__", "1", "--architecture", 0); } else if(match("aarch64", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using aarch64 architecture\n", stderr); BASEADDRESS = "0x400000"; Architecture = "aarch64"; WORDSIZE = 64; @@ -99,14 +121,15 @@ void setup_env() } else if(match("riscv32", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using riscv32 architecture\n", stderr); BASEADDRESS = "0x600000"; Architecture = "riscv32"; - WORDSIZE = 64; init_macro_env("__riscv", "1", "--architecture", 0); init_macro_env("__riscv_xlen", "32", "--architecture", 1); } else if(match("riscv64", ARCH)) { + if(4 <= DEBUG_LEVEL) fputs("Using riscv64 architecture\n", stderr); BASEADDRESS = "0x600000"; Architecture = "riscv64"; WORDSIZE = 64; @@ -159,14 +182,26 @@ int array_length(char** array) /* Search for a variable in the token linked-list */ char* token_lookup(char* variable, struct Token* token) { + if(6 <= DEBUG_LEVEL) + { + fputs("in token_lookup\nLooking for: ", stderr); + fputs(variable, stderr); + fputc('\n', stderr); + } /* Start at the head */ struct Token* n = token; /* Loop over the linked-list */ while(n != NULL) { + if(15 <= DEBUG_LEVEL) + { + fputs(n->var, stderr); + fputc('\n', stderr); + } if(match(variable, n->var)) { + if(6 <= DEBUG_LEVEL) fputs("match found in token_lookup\n", stderr); /* We have found the correct node */ return n->value; /* Done */ } @@ -185,6 +220,67 @@ char* env_lookup(char* variable) return token_lookup(variable, env); } +char* envp_hold; +int envp_index; + +void reset_envp_hold() +{ + clear_string(envp_hold); + envp_index = 0; +} + +void push_env_byte(int c) +{ + envp_hold[envp_index] = c; + envp_index = envp_index + 1; + require(4096 > envp_index, "Token exceeded 4096 char envp limit\n"); +} + +struct Token* process_env_variable(char* envp_line, struct Token* n) +{ + struct Token* node = calloc(1, sizeof(struct Token)); + require(node != NULL, "Memory initialization of node failed\n"); + reset_envp_hold(); + int i = 0; + + while(envp_line[i] != '=') + { + /* Copy over everything up to = to var */ + push_env_byte(envp_line[i]); + i = i + 1; + } + + node->var = calloc(i + 2, sizeof(char)); + require(node->var != NULL, "Memory initialization of n->var in population of env failed\n"); + strcpy(node->var, envp_hold); + + i = i + 1; /* Skip over = */ + + reset_envp_hold(); + while(envp_line[i] != 0) + { + /* Copy everything else to value */ + push_env_byte(envp_line[i]); + i = i + 1; + } + + /* Sometimes, we get lines like VAR=, indicating nothing is in the variable */ + if(0 == strlen(envp_hold)) + { + node->value = ""; + } + else + { + /* but looks like we got something so, lets use it */ + node->value = calloc(strlen(envp_hold) + 2, sizeof(char)); + require(node->value != NULL, "Memory initialization of n->var in population of env failed\n"); + strcpy(node->value, envp_hold); + } + + node->next = n; + return node; +} + void populate_env(char** envp) { if(2 <= DEBUG_LEVEL) fputs("populate_env started\n", stderr); @@ -205,82 +301,51 @@ void populate_env(char** envp) } /* Initialize env and n */ - env = calloc(1, sizeof(struct Token)); - require(env != NULL, "Memory initialization of env failed\n"); - struct Token* n; - n = env; + env = NULL; int i; - int j; - int k; - char* envp_line; + envp_hold = calloc(4096, sizeof(char)); + require(envp_hold != NULL, "Memory initialization of envp_hold in population of env failed\n"); + char* envp_line = calloc(4096, sizeof(char)); + require(envp_line != NULL, "Memory initialization of envp_line in population of env failed\n"); 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"); + clear_string(envp_line); + require(4096 > strlen(envp[i]), "envp line exceeds 4096byte limit\n"); strcpy(envp_line, envp[i]); - while(envp_line[j] != '=') + if(4 <= DEBUG_LEVEL) { - /* Copy over everything up to = to var */ - n->var[j] = envp_line[j]; - j = j + 1; + fputs("trying envp_line: ", stderr); + fputs(envp_line, stderr); + fputc('\n', stderr); } - /* If we get strange input, we need to ignore it */ - if(n->var == NULL) + env = process_env_variable(envp_line, env); + + if(8 <= DEBUG_LEVEL) { - continue; + fputs("got var of: ", stderr); + fputs(env->var, stderr); + fputs("\nAnd value of: ", stderr); + fputs(env->value, stderr); + fputc('\n', stderr); } - - 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) + if(3 <= DEBUG_LEVEL) { - n = n->next; + fputs("\n\nenv loop successful\n", stderr); + fputs(int2str(i, 10, FALSE), stderr); + fputs(" envp records processed\n\n", stderr); } - n->next = NULL; + require(NULL != env, "can't have an empty environment from the creation of a non-null environment\n"); if(2 <= DEBUG_LEVEL) fputs("populate_env successful\n", stderr); } diff --git a/cc_reader.c b/cc_reader.c index 7715b25..3460b8d 100644 --- a/cc_reader.c +++ b/cc_reader.c @@ -59,11 +59,16 @@ int grab_byte() return c; } -int consume_byte(int c) +void push_byte(int c) { hold_string[string_index] = c; string_index = string_index + 1; require(MAX_STRING > string_index, "Token exceeded MAX_STRING char limit\nuse --max-string number to increase\n"); +} + +int consume_byte(int c) +{ + push_byte(c); return grab_byte(); } @@ -104,17 +109,24 @@ int preserve_keyword(int c, char* S) return c; } +void clear_string(char* s) +{ + int i = 0; + while(0 != s[i]) + { + s[i] = 0; + i = i + 1; + require(i < MAX_STRING, "string exceeded max string size while clearing string\n"); + } +} + void reset_hold_string() { - int i = MAX_STRING; - while(0 <= i) - { - hold_string[i] = 0; - i = i - 1; - } + clear_string(hold_string); string_index = 0; } + /* note if this is the first token in the list, head needs fixing up */ struct token_list* eat_token(struct token_list* token) {