Breaking change in M2-Planet
This commit is contained in:
parent
d711438190
commit
56db0fcad4
31
cc_core.c
31
cc_core.c
|
@ -37,6 +37,7 @@ char* break_target_num;
|
|||
struct token_list* break_frame;
|
||||
int current_count;
|
||||
struct type* last_type;
|
||||
int Address_of;
|
||||
|
||||
/* Imported functions */
|
||||
char* parse_string(char* string);
|
||||
|
@ -44,8 +45,6 @@ int escape_lookup(char* c);
|
|||
char* numerate_number(int a);
|
||||
|
||||
|
||||
|
||||
|
||||
struct token_list* emit(char *s, struct token_list* head)
|
||||
{
|
||||
struct token_list* t = calloc(1, sizeof(struct token_list));
|
||||
|
@ -179,8 +178,8 @@ void variable_load(struct token_list* a)
|
|||
emit_out("LOAD_BASE_ADDRESS_eax %");
|
||||
emit_out(numerate_number(a->depth));
|
||||
emit_out("\n");
|
||||
if(TRUE == Address_of) return;
|
||||
if(match("=", global_token->s)) return;
|
||||
if(match("char**", a->type->name)) return;
|
||||
|
||||
emit_out("LOAD_INTEGER\n");
|
||||
}
|
||||
|
@ -388,7 +387,7 @@ void postfix_expr_arrow()
|
|||
emit_out("\nADD_ebx_to_eax\n");
|
||||
}
|
||||
|
||||
if(!match("=", global_token->s) && !match("char**", current_target->name))
|
||||
if((!match("=", global_token->s) && (4 >= i->size)))
|
||||
{
|
||||
emit_out("LOAD_INTEGER\n");
|
||||
}
|
||||
|
@ -553,6 +552,16 @@ void bitwise_expr()
|
|||
|
||||
void primary_expr()
|
||||
{
|
||||
if(match("&", global_token->s))
|
||||
{
|
||||
Address_of = TRUE;
|
||||
global_token = global_token->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
Address_of = FALSE;
|
||||
}
|
||||
|
||||
if(match("sizeof", global_token->s)) unary_expr_sizeof();
|
||||
else if('-' == global_token->s[0])
|
||||
{
|
||||
|
@ -608,7 +617,7 @@ void collect_local()
|
|||
struct token_list* a = sym_declare(global_token->s, type_size, function->locals);
|
||||
if(match("main", function->s) && (NULL == function->locals))
|
||||
{
|
||||
a->depth = -4;
|
||||
a->depth = -20;
|
||||
}
|
||||
else if((NULL == function->arguments) && (NULL == function->locals))
|
||||
{
|
||||
|
@ -1004,12 +1013,7 @@ void collect_arguments()
|
|||
{
|
||||
/* deal with foo(int a, char b) */
|
||||
struct token_list* a = sym_declare(global_token->s, type_size, function->arguments);
|
||||
if(match("main", function->s))
|
||||
{
|
||||
if(match("argc", a->s)) a->depth = 4;
|
||||
if(match("argv", a->s)) a->depth = 8;
|
||||
}
|
||||
else if(NULL == function->arguments)
|
||||
if(NULL == function->arguments)
|
||||
{
|
||||
a->depth = -4;
|
||||
}
|
||||
|
@ -1047,10 +1051,6 @@ void declare_function()
|
|||
emit_out(":FUNCTION_");
|
||||
emit_out(function->s);
|
||||
emit_out("\n");
|
||||
if(match("main", function->s))
|
||||
{
|
||||
emit_out("COPY_esp_to_ebp\t# Deal with special case\n");
|
||||
}
|
||||
statement();
|
||||
|
||||
/* Prevent duplicate RETURNS */
|
||||
|
@ -1083,6 +1083,7 @@ struct token_list* program()
|
|||
{
|
||||
out = NULL;
|
||||
function = NULL;
|
||||
Address_of = FALSE;
|
||||
struct type* type_size;
|
||||
|
||||
new_type:
|
||||
|
|
|
@ -55,7 +55,7 @@ void initialize_types()
|
|||
struct type* d = calloc(1, sizeof(struct type));
|
||||
d->name = "char**";
|
||||
d->size = 4;
|
||||
d->type = c;
|
||||
d->type = b;
|
||||
d->indirect = d;
|
||||
|
||||
/*fix up indrects for chars */
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
## Copyright (C) 2016 Jeremiah Orians
|
||||
## This file is part of stage0.
|
||||
##
|
||||
## stage0 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.
|
||||
##
|
||||
## stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
void exit(int value);
|
||||
|
||||
void _exit(int value)
|
||||
{
|
||||
exit(value);
|
||||
}
|
||||
|
||||
int waitpid (int pid, int* status_ptr, int options)
|
||||
{
|
||||
asm("LOAD_EFFECTIVE_ADDRESS_ebx %12"
|
||||
"LOAD_INTEGER_ebx"
|
||||
"LOAD_EFFECTIVE_ADDRESS_ecx %8"
|
||||
"LOAD_INTEGER_ecx"
|
||||
"LOAD_EFFECTIVE_ADDRESS_edx %4"
|
||||
"LOAD_INTEGER_edx"
|
||||
"LOAD_IMMEDIATE_eax %7"
|
||||
"INT_80");
|
||||
}
|
||||
|
||||
|
||||
int execve(char* file_name, char** argv, char** envp)
|
||||
{
|
||||
asm("LOAD_EFFECTIVE_ADDRESS_ebx %12"
|
||||
"LOAD_INTEGER_ebx"
|
||||
"LOAD_EFFECTIVE_ADDRESS_ecx %8"
|
||||
"LOAD_INTEGER_ecx"
|
||||
"LOAD_EFFECTIVE_ADDRESS_edx %4"
|
||||
"LOAD_INTEGER_edx"
|
||||
"LOAD_IMMEDIATE_eax %11"
|
||||
"INT_80");
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
## Copyright (C) 2016 Jeremiah Orians
|
||||
## This file is part of stage0.
|
||||
##
|
||||
## stage0 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.
|
||||
##
|
||||
## stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
int fork()
|
||||
{
|
||||
asm("LOAD_IMMEDIATE_eax %2"
|
||||
"LOAD_IMMEDIATE_ebx %0"
|
||||
"INT_80");
|
||||
}
|
|
@ -15,7 +15,28 @@
|
|||
## along with stage0. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
:_start
|
||||
|
||||
COPY_esp_to_ebp ; Protect esp
|
||||
|
||||
;; Prepare argv
|
||||
LOAD_BASE_ADDRESS_eax %4 ; ARGV_address = EBP + 4
|
||||
PUSH_eax ; Put argv on the stack
|
||||
|
||||
;; Prepare envp
|
||||
COPY_ebp_to_eax ; Address we need to load from
|
||||
LOAD_INTEGER ; Get ARGC
|
||||
ADD_IMMEDIATE_to_eax %2 ; OFFSET = ARGC + 2
|
||||
SAL_eax_Immediate8 !2 ; OFFSET = OFFSET * WORDSIZE
|
||||
ADD_ebp_to_eax ; ENVP_address = ESP + OFFSET
|
||||
PUSH_eax ; Put envp on the stack
|
||||
|
||||
;; Stack offset
|
||||
ADD_IMMEDIATE_to_ebp %4 ; Fix ebp
|
||||
|
||||
;; Perform the main loop
|
||||
CALL_IMMEDIATE %FUNCTION_main
|
||||
COPY_eax_to_ebx
|
||||
LOAD_IMMEDIATE_eax %1
|
||||
INT_80
|
||||
|
||||
;; Exit to kernel
|
||||
COPY_eax_to_ebx ; Using the return code given by main
|
||||
LOAD_IMMEDIATE_eax %1 ; Syscall exit
|
||||
INT_80 ; Exit with that code
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
|
||||
struct utsname
|
||||
{
|
||||
char** sysname[65]; /* Operating system name (e.g., "Linux") */
|
||||
char** nodename[65]; /* Name within "some implementation-defined network" */
|
||||
char** release[65]; /* Operating system release (e.g., "2.6.28") */
|
||||
char** version[65]; /* Operating system version */
|
||||
char** machine[65]; /* Hardware identifier */
|
||||
char sysname[65]; /* Operating system name (e.g., "Linux") */
|
||||
char nodename[65]; /* Name within "some implementation-defined network" */
|
||||
char release[65]; /* Operating system release (e.g., "2.6.28") */
|
||||
char version[65]; /* Operating system version */
|
||||
char machine[65]; /* Hardware identifier */
|
||||
};
|
||||
|
||||
int uname(struct utsname* unameData)
|
||||
|
|
|
@ -14,15 +14,19 @@
|
|||
## You should have received a copy of the GNU General Public License
|
||||
## along with stage0. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
DEFINE ADD_ebx_to_eax 01D8
|
||||
DEFINE ADD_IMMEDIATE_to_eax 81C0
|
||||
DEFINE ADD_IMMEDIATE_to_ebp 81C5
|
||||
DEFINE ADD_eax_to_ebx 01C3
|
||||
DEFINE ADD_ebp_to_eax 01E8
|
||||
DEFINE ADD_ebx_to_eax 01D8
|
||||
DEFINE AND_eax_ebx 21D8
|
||||
DEFINE CALL_IMMEDIATE E8
|
||||
DEFINE CALL_eax FFD0
|
||||
DEFINE CALL_IMMEDIATE E8
|
||||
DEFINE CALL_eax FFD0
|
||||
DEFINE CMP 39C3
|
||||
DEFINE COPY_eax_to_ebx 89C3
|
||||
DEFINE COPY_eax_to_ecx 89C1
|
||||
DEFINE COPY_ebp_to_eax 89E8
|
||||
DEFINE COPY_ebx_to_eax 89D8
|
||||
DEFINE COPY_ebx_to_edx 89DA
|
||||
DEFINE COPY_ecx_to_ebp 89CD
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
12977ab3adfa80dd4e98068e3cf30a660bfbd5fc1c2e5ad4b33fb72ef8cb11a4 test/results/test00-binary
|
||||
76b75af92dbaba02222ca1a2ae1ec28d8ea075828039821b445c2368ee31d46d test/results/test01-binary
|
||||
02c8454596a4fddc5d659a547a12386bdde54f1d3e05df2558b0e89d676f2142 test/results/test02-binary
|
||||
735ce831b4c0f9909977d659fe2b5f83920cfd38606a1d833cab4d89f9619398 test/results/test03-binary
|
||||
62cafe3e96763862e802b83666b457ceaf4b3e4032b530349253b95c5c1e7bb3 test/results/test04-binary
|
||||
2cbd9acf2e8069f5d93764e1fe235f0e1606a36e058bad8a976a6d4e97b4b8fe test/results/test05-binary
|
||||
c921f545c7baebe05e1ce60c777d6d7782ba626fdf7520f576d3ee1b849a8bbf test/results/test06-binary
|
||||
b45fae655b7f848b28ebdb8eb2e30ae789fbcf7920bc315395d53986bb1adae4 test/results/test07-binary
|
||||
d511db73158a9544a5b5f828a79751e3de8a04b81c143fd0c146fc22c938aa9f test/results/test08-binary
|
||||
907e1808f2e2b15ac72ebf13898b15c678e68ebd43d673dcd0f408d907e7962f test/results/test09-binary
|
||||
ef179cd359ba1d61d45089e314cd4ac2069c8dc4dd7494d7c766344ea3c8cf88 test/results/test10-binary
|
||||
a6ba14a8d8fe29dccfacdf1723a241ede000d7cee50d82a443f60e73d97e384e test/results/test100-binary
|
||||
5aaf399fe706d4a8c85c121c75ada29a65c293b57c98e8999961a2ef0bab0d62 test/results/test11-binary
|
||||
4f8111e73e07255ae203963438c82ea8bcff7474e1594b52b426c58a03cb30eb test/results/test12-binary
|
||||
dd74dabfdce8657ff440c1eef531cbf67a64854f2020d4d6bcb65c9cc2d199cb test/results/test13-binary
|
||||
ed0960dc5809d8cda84e7df8bf02bd0cd2aeeba4df8c752d68af434408555f8c test/results/test14-binary
|
||||
e216869c3fb06de7a41578517c797169e219b20a5697a822ba11eeef0d04f181 test/results/test15-binary
|
||||
315ae5cc5c9d5bdcae0eddd55371128e53e3e9267a2a7c53832ed0af51693bea test/results/test16-binary
|
||||
fdce9856f885418a7b2f69fc24a6cc0c85922313b49694d8030c544e4b2ad16f test/results/test17-binary
|
||||
9a426972b6df90a158aebe3b8f3eb9ef8a63ce317d764afb92be4fce16542743 test/results/test18-binary
|
||||
91b761d241dd9969230b235c6cb3bc86cc6b0076d9d1a04c4950de32228149f5 test/results/test19-binary
|
||||
48d845d20fff86183047342641cc8a6174e71c0ca004be882f0195a141bd64ea test/results/test20-binary
|
||||
65354ea5f760e42ea054785033a6519e0eee30d21b1b69ac7715ef958c5e0e2f test/results/test21-binary
|
||||
9a79bdfb35c1c17bb0c66357836382bb08d3876ae8c0c77356776d16aa7faa7f test/results/test22-binary
|
||||
96e1789254675815a3ec5ad93c1cc32c4805d1ad7f029721cef102c4501df8e2 test/results/test23-binary
|
||||
50215e4b4e2ce22a959ea7bcfc77c4d6ac45464455f5103afcaea0e84f9bf1d1 test/results/test24-binary
|
||||
0013b8786068520e386a0cf2ce39c5145462439f17c264e62a9eddb1eed0433b test/results/test99-binary
|
||||
c52562bd0aabb86ce8ca177f22f8d0455769b444df2d4d62894faab63b7151d8 test/results/test00-binary
|
||||
eae96857f2b6d8e8ba86ac06e72345ea572622b358b23978bb5f2db1baadf41c test/results/test01-binary
|
||||
8ead336d2f3f72d5874230492e0472edec61d355905e8636e3dfb2731695037c test/results/test02-binary
|
||||
2313cb3f1a2b9eb6bf15f8d43418e15d6c16f7f1b5c22700fdfc2b38beb59192 test/results/test03-binary
|
||||
b7ddb37063c541c6a315809c4438aa235d6702f54bb64f4ffc88dbe78617de81 test/results/test04-binary
|
||||
4d4ec6247a7cc9062a5b3d8adfec7199476715446723a0b882268afe6daad1f3 test/results/test05-binary
|
||||
663fc6eefe965f237b6bf5a211398c8ae1210f97ff39b59603677e92462c68c7 test/results/test06-binary
|
||||
a9a3e332d13ded5f80d7431f8717f26527b3722b33ea57760a9a5723dffc099c test/results/test07-binary
|
||||
f1c01feb865c4d552033186d9ce50dd39468a7e8aebf762886c13ad3e03b5011 test/results/test08-binary
|
||||
3b39e72f3de90ed690adfaf6145af46157cef2ec5e72867ac577fa27a0229894 test/results/test09-binary
|
||||
020e86020819cc4963e6185b22e534fcf8306b6cb116f12643f254a24688ff0a test/results/test10-binary
|
||||
db41db8bc1dc2f94367c41c33d9438634d75994f79a46296bb8907905a64c013 test/results/test100-binary
|
||||
3fd11bad4a426ce1ff8fd9c6d7d2b943effae9f3f5740b7376e426e9b0555851 test/results/test11-binary
|
||||
f98ab8e4bb35580e0dde96126d7a56aff66bda208d02c8d89390b40d6cff591c test/results/test12-binary
|
||||
5051ffca2615144419f8ec1a5d4999486ae81e7781428f59e47e866af97cef92 test/results/test13-binary
|
||||
a8218958b628066e2fda63d3933f1bf607c358d7bdfe84fc02596393698ea5f6 test/results/test14-binary
|
||||
3adb4a5f3995583ba711151361728a26c3fbf0140864d13b4b042978ca45d683 test/results/test15-binary
|
||||
d70e072f4f1f077d10ff65e9216ca8b423b996e35d68d208025db7a78b062f50 test/results/test16-binary
|
||||
9b4ba350b07cc1cf4e12dc77d0d960ded1511f13b887363b0eb33421e2f626de test/results/test17-binary
|
||||
8de7384c4633b1d5c60bbbb298d7f4b738e52fbc266ef4ef9a48b3cb995e3176 test/results/test18-binary
|
||||
b0d7982de3f257d6a5b51ad356c1aa09f24b8a69d862a90f41aef7dc83ec3b2f test/results/test19-binary
|
||||
365c96fb8368710d620a76facd6bebcdeeb6f6d30ceaf0a6f1567fc3fcbe9b54 test/results/test20-binary
|
||||
abb4d9272a262c4bf77d9cbb714cbb8ce16841a128c670394f60cb817ebe7727 test/results/test21-binary
|
||||
24a14bd0641cdbcf49b69a71c80c00fb4f0c42c5ed72f7b44e5119ad1f22d533 test/results/test22-binary
|
||||
dd9081cb6eb908e8a727b05e2fc65efe01e5c33221eee9a70565808a97c7b294 test/results/test23-binary
|
||||
6fb0c0db1732038f945172ef05c33c976396baf86571b1169a3af02e850be0d5 test/results/test24-binary
|
||||
140af7fb3ef89d84b21bd3fe69f0d3260650ec0467c0ffadf9268fad573a397f test/results/test99-binary
|
||||
|
|
|
@ -1 +1 @@
|
|||
d27357f9db85e403cc09ca59123009dd4193db287b91a3414c09eafb7e28d22e test/test100/proof
|
||||
b882976ea4fb2ede866851a57fd3be0653ac1918b87e183e4c1cd6cb5c60d2b4 test/test100/proof
|
||||
|
|
|
@ -1 +1 @@
|
|||
736df1e1db39ffd6738be5efa064e14b26cc88fd7530efb6cf663df03c0db721 test/test23/proof
|
||||
16039cd07d755cff62d61efd6945f214a79cbfa07c32386beea9b9f5b771a976 test/test23/proof
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# Ignore the files created by script
|
||||
*.M1
|
||||
*.hex2
|
||||
proof
|
||||
|
||||
# A place to put a good run for comparison
|
||||
actual.M1
|
|
@ -0,0 +1,6 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test25/kaem.M1
|
||||
rm -f test/test25/kaem-footer.M1
|
||||
rm -f test/test25/kaem.hex2
|
||||
rm -f test/test25/proof
|
||||
exit 0
|
|
@ -0,0 +1,39 @@
|
|||
#! /bin/sh
|
||||
set -x
|
||||
# Build the test
|
||||
./bin/M2-Planet -f functions/exit.c \
|
||||
-f functions/file.c \
|
||||
-f functions/file_print.c \
|
||||
-f functions/malloc.c \
|
||||
-f functions/calloc.c \
|
||||
-f functions/match.c \
|
||||
-f functions/numerate_number.c \
|
||||
-f functions/fork.c \
|
||||
-f functions/execve.c \
|
||||
-f test/test25/kaem.c \
|
||||
--debug \
|
||||
-o test/test25/kaem.M1 || exit 1
|
||||
|
||||
# Build debug footer
|
||||
blood-elf -f test/test25/kaem.M1 \
|
||||
-o test/test25/kaem-footer.M1 || exit 2
|
||||
|
||||
# Macro assemble with libc written in M1-Macro
|
||||
M1 -f test/common_x86/x86_defs.M1 \
|
||||
-f functions/libc-core.M1 \
|
||||
-f test/test25/kaem.M1 \
|
||||
-f test/test25/kaem-footer.M1 \
|
||||
--LittleEndian \
|
||||
--Architecture 1 \
|
||||
-o test/test25/kaem.hex2 || exit 3
|
||||
|
||||
# Resolve all linkages
|
||||
hex2 -f test/common_x86/ELF-i386-debug.hex2 \
|
||||
-f test/test25/kaem.hex2 \
|
||||
--LittleEndian \
|
||||
--Architecture 1 \
|
||||
--BaseAddress 0x8048000 \
|
||||
-o test/results/test25-binary \
|
||||
--exec_enable || exit 4
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,369 @@
|
|||
/* Copyright (C) 2016 Jeremiah Orians
|
||||
* This file is part of mescc-tools.
|
||||
*
|
||||
* mescc-tools 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.
|
||||
*
|
||||
* mescc-tools 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 mescc-tools. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define FALSE 0
|
||||
//CONSTANT FALSE 0
|
||||
#define TRUE 1
|
||||
//CONSTANT TRUE 1
|
||||
#define max_string 4096
|
||||
//CONSTANT max_string 4096
|
||||
#define max_args 256
|
||||
//CONSTANT max_args 256
|
||||
|
||||
void file_print(char* s, FILE* f);
|
||||
char* numerate_number(int a);
|
||||
int match(char* a, char* b);
|
||||
|
||||
char** tokens;
|
||||
int command_done;
|
||||
int VERBOSE;
|
||||
int STRICT;
|
||||
|
||||
/* Function for purging line comments */
|
||||
void collect_comment(FILE* input)
|
||||
{
|
||||
int c;
|
||||
do
|
||||
{
|
||||
c = fgetc(input);
|
||||
if(-1 == c)
|
||||
{
|
||||
file_print("IMPROPERLY TERMINATED LINE COMMENT!\nABORTING HARD\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} while('\n' != c);
|
||||
}
|
||||
|
||||
/* Function for collecting RAW strings and removing the " that goes with them */
|
||||
int collect_string(FILE* input, int index, char* target)
|
||||
{
|
||||
int c;
|
||||
do
|
||||
{
|
||||
c = fgetc(input);
|
||||
if(-1 == c)
|
||||
{ /* We never should hit EOF while collecting a RAW string */
|
||||
file_print("IMPROPERLY TERMINATED RAW string!\nABORTING HARD\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if('"' == c)
|
||||
{ /* Made it to the end */
|
||||
c = 0;
|
||||
}
|
||||
target[index] = c;
|
||||
index = index + 1;
|
||||
} while(0 != c);
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Function to collect an individual argument or purge a comment */
|
||||
char* collect_token(FILE* input)
|
||||
{
|
||||
char* token = calloc(max_string, sizeof(char));
|
||||
char c;
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
c = fgetc(input);
|
||||
if(-1 == c)
|
||||
{ /* Deal with end of file */
|
||||
file_print("execution complete\n", stderr);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if((' ' == c) || ('\t' == c))
|
||||
{ /* space and tab are token seperators */
|
||||
c = 0;
|
||||
}
|
||||
else if('\n' == c)
|
||||
{ /* Command terminates at end of line */
|
||||
c = 0;
|
||||
command_done = 1;
|
||||
}
|
||||
else if('"' == c)
|
||||
{ /* RAW strings are everything between a pair of "" */
|
||||
i = collect_string(input, i, token);
|
||||
c = 0;
|
||||
}
|
||||
else if('#' == c)
|
||||
{ /* Line comments to aid the humans */
|
||||
collect_comment(input);
|
||||
c = 0;
|
||||
command_done = 1;
|
||||
}
|
||||
else if('\\' == c)
|
||||
{ /* Support for end of line escapes, drops the char after */
|
||||
fgetc(input);
|
||||
c = 0;
|
||||
}
|
||||
token[i] = c;
|
||||
i = i + 1;
|
||||
} while (0 != c);
|
||||
|
||||
if(1 == i)
|
||||
{ /* Nothing worth returning */
|
||||
free(token);
|
||||
return NULL;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
char* copy_string(char* target, char* source)
|
||||
{
|
||||
while(0 != source[0])
|
||||
{
|
||||
target[0] = source[0];
|
||||
target = target + 1;
|
||||
source = source + 1;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
char* prepend_string(char* add, char* base)
|
||||
{
|
||||
char* ret = calloc(max_string, sizeof(char));
|
||||
copy_string(copy_string(ret, add), base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* find_char(char* string, char a)
|
||||
{
|
||||
if(0 == string[0]) return NULL;
|
||||
while(a != string[0])
|
||||
{
|
||||
string = string + 1;
|
||||
if(0 == string[0]) return string;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
char* prematch(char* search, char* field)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(search[0] != field[0]) return NULL;
|
||||
search = search + 1;
|
||||
field = field + 1;
|
||||
} while(0 != search[0]);
|
||||
return field;
|
||||
}
|
||||
|
||||
char* env_lookup(char* token, char** envp)
|
||||
{
|
||||
if(NULL == envp) return NULL;
|
||||
int i = 0;
|
||||
char* ret = NULL;
|
||||
do
|
||||
{
|
||||
ret = prematch(token, envp[i]);
|
||||
if(NULL != ret) return ret;
|
||||
i = i + 1;
|
||||
} while(NULL != envp[i]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* find_executable(char* name, char* PATH)
|
||||
{
|
||||
if(('.' == name[0]) || ('/' == name[0]))
|
||||
{ /* assume names that start with . or / are relative or absolute */
|
||||
return name;
|
||||
}
|
||||
|
||||
char* next = find_char(PATH, ':');
|
||||
char* trial;
|
||||
FILE* try;
|
||||
while(NULL != next)
|
||||
{
|
||||
next[0] = 0;
|
||||
trial = prepend_string(PATH, prepend_string("/", name));
|
||||
|
||||
try = fopen(trial, "r");
|
||||
if(NULL != try)
|
||||
{
|
||||
fclose(try);
|
||||
return trial;
|
||||
}
|
||||
PATH = next + 1;
|
||||
next = find_char(PATH, ':');
|
||||
free(trial);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Function for executing our programs with desired arguments */
|
||||
void execute_command(FILE* script, char** envp)
|
||||
{
|
||||
tokens = calloc(max_args, sizeof(char*));
|
||||
char* PATH = env_lookup("PATH=", envp);
|
||||
if(NULL != PATH)
|
||||
{
|
||||
PATH = calloc(max_string, sizeof(char));
|
||||
copy_string(PATH, env_lookup("PATH=", envp));
|
||||
}
|
||||
|
||||
char* USERNAME = env_lookup("LOGNAME=", envp);
|
||||
if((NULL == PATH) && (NULL == USERNAME))
|
||||
{
|
||||
PATH = calloc(max_string, sizeof(char));
|
||||
copy_string(PATH, "/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
|
||||
}
|
||||
else if(NULL == PATH)
|
||||
{
|
||||
PATH = prepend_string("/home/", prepend_string(USERNAME,"/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"));
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int status = 0;
|
||||
command_done = 0;
|
||||
do
|
||||
{
|
||||
char* result = collect_token(script);
|
||||
if(0 != result)
|
||||
{ /* Not a comment string but an actual argument */
|
||||
tokens[i] = result;
|
||||
i = i + 1;
|
||||
}
|
||||
} while(0 == command_done);
|
||||
|
||||
if(VERBOSE && (0 < i))
|
||||
{
|
||||
file_print(" +> ", stdout);
|
||||
int j;
|
||||
for(j = 0; j < i; j = j + 1)
|
||||
{
|
||||
file_print(tokens[j], stdout);
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
file_print("\n", stdout);
|
||||
}
|
||||
|
||||
if(0 < i)
|
||||
{ /* Not a line comment */
|
||||
char* program = find_executable(tokens[0], PATH);
|
||||
if(NULL == program)
|
||||
{
|
||||
file_print(tokens[0], stderr);
|
||||
file_print("Some weird shit went down with: ", stderr);
|
||||
file_print("\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int f = fork();
|
||||
if (f == -1)
|
||||
{
|
||||
file_print("fork() failure", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if (f == 0)
|
||||
{ /* child */
|
||||
/* execve() returns only on error */
|
||||
execve(program, tokens, envp);
|
||||
/* Prevent infinite loops */
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Otherwise we are the parent */
|
||||
/* And we should wait for it to complete */
|
||||
waitpid(f, &status, 0);
|
||||
|
||||
if(STRICT && (0 != status))
|
||||
{ /* Clearly the script hit an issue that should never have happened */
|
||||
file_print("Subprocess error ", stderr);
|
||||
file_print(numerate_number(status), stderr);
|
||||
file_print("\nABORTING HARD\n", stderr);
|
||||
/* stop to prevent damage */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* Then go again */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv, char** envp)
|
||||
{
|
||||
VERBOSE = FALSE;
|
||||
STRICT = FALSE;
|
||||
char* filename = "kaem.run";
|
||||
FILE* script = NULL;
|
||||
|
||||
int i = 1;
|
||||
while(i <= argc)
|
||||
{
|
||||
if(NULL == argv[i])
|
||||
{
|
||||
i = i + 1;
|
||||
}
|
||||
else if(match(argv[i], "-h") || match(argv[i], "--help"))
|
||||
{
|
||||
file_print("kaem only accepts --help, --version, --verbose or no arguments\n", stdout);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if(match(argv[i], "-f") || match(argv[i], "--file"))
|
||||
{
|
||||
filename = argv[i + 1];
|
||||
i = i + 2;
|
||||
}
|
||||
else if(match(argv[i], "n") || match(argv[i], "--nightmare-mode"))
|
||||
{
|
||||
file_print("Begin nightmare", stdout);
|
||||
envp = NULL;
|
||||
i = i + 1;
|
||||
}
|
||||
else if(match(argv[i], "-V") || match(argv[i], "--version"))
|
||||
{
|
||||
file_print("kaem version 0.1\n", stdout);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if(match(argv[i], "--verbose"))
|
||||
{
|
||||
VERBOSE = TRUE;
|
||||
i = i + 1;
|
||||
}
|
||||
else if(match(argv[i], "--strict"))
|
||||
{
|
||||
STRICT = TRUE;
|
||||
i = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
file_print("UNKNOWN ARGUMENT\n", stdout);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
script = fopen(filename, "r");
|
||||
|
||||
if(NULL == script)
|
||||
{
|
||||
file_print("The file: ", stderr);
|
||||
file_print(filename, stderr);
|
||||
file_print(" can not be opened!\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
execute_command(script, envp);
|
||||
}
|
||||
fclose(script);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue