2021-11-23 21:49:09 +00:00
/* Copyright (C) 2016, 2021 Jeremiah Orians
2021-01-10 14:32:42 +00:00
* Copyright ( C ) 2020 deesix < deesix @ tuta . io >
2021-11-23 21:49:09 +00:00
* Copyright ( C ) 2020 Gabriel Wicki
2021-01-10 14:32:42 +00:00
* 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/>.
*/
2021-11-23 00:53:12 +00:00
2021-01-10 14:32:42 +00:00
# include "cc.h"
/* The core functions */
2021-11-21 23:30:20 +00:00
void populate_env ( char * * envp ) ;
2022-01-22 03:36:31 +00:00
void setup_env ( ) ;
2021-11-21 23:30:20 +00:00
char * env_lookup ( char * variable ) ;
2021-01-10 14:32:42 +00:00
void initialize_types ( ) ;
struct token_list * read_all_tokens ( FILE * a , struct token_list * current , char * filename ) ;
struct token_list * reverse_list ( struct token_list * head ) ;
2021-11-21 21:39:45 +00:00
void init_macro_env ( char * sym , char * value , char * source , int num ) ;
2021-01-10 14:32:42 +00:00
void preprocess ( ) ;
void output_tokens ( struct token_list * i , FILE * out ) ;
2021-11-21 21:09:14 +00:00
int strtoint ( char * a ) ;
2021-11-23 00:53:12 +00:00
void spawn_processes ( int debug_flag , char * preprocessed_file , char * destination , char * * envp ) ;
2021-01-10 14:32:42 +00:00
2021-11-21 23:30:20 +00:00
int main ( int argc , char * * argv , char * * envp )
2021-01-10 14:32:42 +00:00
{
2022-01-24 02:22:54 +00:00
/****************************************************************************
* Manually change debug level if you need testing of functionality prior *
* to - - debug - mode functionality . *
* Zero means no debugging messages and larger positive values means more *
* chatty output . Level 15 means EVERYTHING but 7 should cover most magic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
DEBUG_LEVEL = 0 ;
/* Setup __M2__ (It is very very special *DO NOT MESS WITH IT* ) */
init_macro_env ( " __M2__ " , " __M2__ " , " __INTERNAL_M2__ " , 0 ) ;
/* Our fun globals */
2021-11-23 00:53:12 +00:00
FUZZING = FALSE ;
2022-01-20 12:58:03 +00:00
MAX_STRING = 65536 ;
2021-01-10 14:32:42 +00:00
PREPROCESSOR_MODE = FALSE ;
2021-11-23 10:58:45 +00:00
STDIO_USED = FALSE ;
2022-01-24 02:22:54 +00:00
DIRTY_MODE = FALSE ;
2022-01-25 02:39:43 +00:00
Architecture = NULL ;
2022-01-24 02:22:54 +00:00
/* Our fun locals */
2021-11-23 02:41:11 +00:00
int debug_flag = TRUE ;
2021-01-10 14:32:42 +00:00
FILE * in = stdin ;
2021-11-23 00:53:12 +00:00
FILE * tempfile ;
2021-11-23 11:48:52 +00:00
char * destination_name = " a.out " ;
2021-01-10 14:32:42 +00:00
FILE * destination_file = stdout ;
char * name ;
2021-11-21 21:09:14 +00:00
char * hold ;
2021-12-26 12:42:54 +00:00
int DUMP_MODE = FALSE ;
2022-01-21 02:35:14 +00:00
2022-01-24 02:22:54 +00:00
/* Get the environmental bits */
if ( 1 < = DEBUG_LEVEL ) fputs ( " Starting to setup Environment \n " , stderr ) ;
populate_env ( envp ) ;
setup_env ( ) ;
if ( 1 < = DEBUG_LEVEL ) fputs ( " Environment setup \n " , stderr ) ;
M2LIBC_PATH = env_lookup ( " M2LIBC_PATH " ) ;
if ( NULL = = M2LIBC_PATH ) M2LIBC_PATH = " ./M2libc " ;
else if ( 1 < = DEBUG_LEVEL )
{
fputs ( " M2LIBC_PATH set by environment variable to " , stderr ) ;
fputs ( M2LIBC_PATH , stderr ) ;
fputc ( ' \n ' , stderr ) ;
}
2021-01-10 14:32:42 +00:00
int i = 1 ;
while ( i < = argc )
{
if ( NULL = = argv [ i ] )
{
2021-11-21 21:39:45 +00:00
i + = 1 ;
2021-01-10 14:32:42 +00:00
}
2021-11-21 22:54:39 +00:00
else if ( match ( argv [ i ] , " -E " ) | | match ( argv [ i ] , " --preprocess-only " ) )
{
PREPROCESSOR_MODE = TRUE ;
i + = 1 ;
}
2021-12-26 12:42:54 +00:00
else if ( match ( argv [ i ] , " --dump-mode " ) )
{
DUMP_MODE = TRUE ;
i + = 1 ;
}
2022-01-20 12:58:03 +00:00
else if ( match ( argv [ i ] , " --dirty-mode " ) )
{
DIRTY_MODE = TRUE ;
i + = 1 ;
}
2022-01-21 02:35:14 +00:00
else if ( match ( argv [ i ] , " --debug-mode " ) )
{
hold = argv [ i + 1 ] ;
DEBUG_LEVEL = strtoint ( hold ) ;
fputs ( " DEBUG_LEVEL set to: " , stderr ) ;
fputs ( hold , stderr ) ;
fputc ( ' \n ' , stderr ) ;
i + = 2 ;
}
2022-01-25 02:39:43 +00:00
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 ;
}
2021-01-10 14:32:42 +00:00
else if ( match ( argv [ i ] , " -f " ) | | match ( argv [ i ] , " --file " ) )
{
if ( NULL = = hold_string )
{
2021-11-21 21:39:45 +00:00
hold_string = calloc ( MAX_STRING + 4 , sizeof ( char ) ) ;
require ( NULL ! = hold_string , " Impossible Exhaustion has occured \n " ) ;
2021-01-10 14:32:42 +00:00
}
name = argv [ i + 1 ] ;
2021-11-21 21:39:45 +00:00
if ( NULL = = name )
{
fputs ( " did not receive a file name \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
}
2021-01-10 14:32:42 +00:00
in = fopen ( name , " r " ) ;
if ( NULL = = in )
{
fputs ( " Unable to open for reading file: " , stderr ) ;
fputs ( name , stderr ) ;
fputs ( " \n Aborting to avoid problems \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
}
global_token = read_all_tokens ( in , global_token , name ) ;
fclose ( in ) ;
2021-11-21 21:39:45 +00:00
i + = 2 ;
2021-01-10 14:32:42 +00:00
}
else if ( match ( argv [ i ] , " -o " ) | | match ( argv [ i ] , " --output " ) )
{
2021-11-23 10:58:45 +00:00
destination_name = argv [ i + 1 ] ;
2022-01-25 02:39:43 +00:00
require ( NULL ! = destination_name , " --output option requires a filename to follow \n " ) ;
2021-11-23 10:58:45 +00:00
destination_file = fopen ( destination_name , " w " ) ;
2021-01-10 14:32:42 +00:00
if ( NULL = = destination_file )
{
fputs ( " Unable to open for writing file: " , stderr ) ;
fputs ( argv [ i + 1 ] , stderr ) ;
fputs ( " \n Aborting to avoid problems \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
}
2021-11-21 21:39:45 +00:00
i + = 2 ;
}
2021-01-10 14:32:42 +00:00
else if ( match ( argv [ i ] , " --max-string " ) )
{
2021-11-21 21:09:14 +00:00
hold = argv [ i + 1 ] ;
if ( NULL = = hold )
{
fputs ( " --max-string requires a numeric argument \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
}
MAX_STRING = strtoint ( hold ) ;
2021-01-10 14:32:42 +00:00
require ( 0 < MAX_STRING , " Not a valid string size \n Abort and fix your --max-string \n " ) ;
2021-11-21 21:39:45 +00:00
i + = 2 ;
2021-01-10 14:32:42 +00:00
}
2022-01-23 17:18:46 +00:00
else if ( match ( argv [ i ] , " -I " ) )
{
hold = argv [ i + 1 ] ;
if ( NULL = = hold )
{
fputs ( " -I requires a PATH \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
}
2022-01-24 02:22:54 +00:00
if ( 1 < = DEBUG_LEVEL )
{
fputs ( " M2LIBC_PATH set by -I to " , stderr ) ;
fputs ( M2LIBC_PATH , stderr ) ;
fputc ( ' \n ' , stderr ) ;
}
2022-01-23 17:18:46 +00:00
M2LIBC_PATH = hold ;
i + = 2 ;
}
2021-01-10 14:32:42 +00:00
else if ( match ( argv [ i ] , " -h " ) | | match ( argv [ i ] , " --help " ) )
{
2021-11-23 21:49:09 +00:00
fputs ( " -f input file \n -o output file \n --help for this message \n --version for file version \n -E or --preprocess-only \n --max-string N (N is a number) \n --fuzz \n --no-debug \n " , stdout ) ;
2021-01-10 14:32:42 +00:00
exit ( EXIT_SUCCESS ) ;
}
else if ( match ( argv [ i ] , " -V " ) | | match ( argv [ i ] , " --version " ) )
{
2021-11-21 21:39:45 +00:00
fputs ( " M2-Mesoplanet v1.10.0 \n " , stderr ) ;
2021-01-10 14:32:42 +00:00
exit ( EXIT_SUCCESS ) ;
}
2021-11-23 00:53:12 +00:00
else if ( match ( argv [ i ] , " --fuzz " ) )
{
/* Set fuzzing */
FUZZING = TRUE ;
i + = 1 ;
}
2021-11-23 11:06:42 +00:00
else if ( match ( argv [ i ] , " --no-debug " ) )
{
/* strip things down */
debug_flag = FALSE ;
i + = 1 ;
}
2021-01-10 14:32:42 +00:00
else
{
fputs ( " UNKNOWN ARGUMENT \n " , stdout ) ;
exit ( EXIT_FAILURE ) ;
}
}
2022-01-21 02:35:14 +00:00
if ( 1 < = DEBUG_LEVEL ) fputs ( " READ all files \n " , stderr ) ;
2021-01-10 14:32:42 +00:00
/* Deal with special case of wanting to read from standard input */
if ( stdin = = in )
{
hold_string = calloc ( MAX_STRING , sizeof ( char ) ) ;
2021-11-21 21:39:45 +00:00
require ( NULL ! = hold_string , " Impossible Exhaustion has occured \n " ) ;
2021-01-10 14:32:42 +00:00
global_token = read_all_tokens ( in , global_token , " STDIN " ) ;
}
if ( NULL = = global_token )
{
fputs ( " Either no input files were given or they were empty \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
}
2022-01-21 02:35:14 +00:00
if ( 1 < = DEBUG_LEVEL ) fputs ( " Start to reverse list \n " , stderr ) ;
2021-01-10 14:32:42 +00:00
global_token = reverse_list ( global_token ) ;
2022-01-21 02:35:14 +00:00
if ( 1 < = DEBUG_LEVEL ) fputs ( " List reversed \n " , stderr ) ;
2021-01-10 14:32:42 +00:00
2021-12-26 12:42:54 +00:00
if ( DUMP_MODE )
{
output_tokens ( global_token , destination_file ) ;
exit ( EXIT_SUCCESS ) ;
}
2021-01-10 14:32:42 +00:00
preprocess ( ) ;
2021-11-21 22:54:39 +00:00
if ( PREPROCESSOR_MODE )
{
2021-12-26 12:42:54 +00:00
fputs ( " /* M2-Mesoplanet Preprocessed source */ \n " , destination_file ) ;
2021-11-21 22:54:39 +00:00
output_tokens ( global_token , destination_file ) ;
2021-11-23 11:48:52 +00:00
fclose ( destination_file ) ;
2021-11-21 22:54:39 +00:00
}
else
2021-01-10 14:32:42 +00:00
{
2021-11-23 02:41:11 +00:00
name = calloc ( 100 , sizeof ( char ) ) ;
strcpy ( name , " /tmp/M2-Mesoplanet-XXXXXX " ) ;
i = mkstemp ( name ) ;
2021-11-26 19:22:58 +00:00
tempfile = fdopen ( i , " w " ) ;
2021-11-23 00:53:12 +00:00
if ( NULL ! = tempfile )
{
2021-11-23 02:41:11 +00:00
/* Our preprocessed crap */
2021-11-23 00:53:12 +00:00
output_tokens ( global_token , tempfile ) ;
2021-11-23 02:41:11 +00:00
fclose ( tempfile ) ;
/* Make me a real binary */
spawn_processes ( debug_flag , name , destination_name , envp ) ;
/* And clean up the donkey */
2022-01-20 12:58:03 +00:00
if ( ! DIRTY_MODE ) remove ( name ) ;
2021-11-23 00:53:12 +00:00
}
else
{
fputs ( " unable to get a tempfile for M2-Mesoplanet output \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
}
2021-01-10 14:32:42 +00:00
}
return EXIT_SUCCESS ;
}