From ea1947ffcc606d757357398b24e74a3f4ecefa07 Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 20 Oct 2021 14:54:27 +0000 Subject: Initial commit from steward-fu release --- core/bgdc/src/codeblock.c | 426 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 426 insertions(+) create mode 100644 core/bgdc/src/codeblock.c (limited to 'core/bgdc/src/codeblock.c') diff --git a/core/bgdc/src/codeblock.c b/core/bgdc/src/codeblock.c new file mode 100644 index 0000000..d99808f --- /dev/null +++ b/core/bgdc/src/codeblock.c @@ -0,0 +1,426 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include +#include +#include + +#include "bgdc.h" + +/* + * FUNCTION : codeblock_postprocess + * + * After every codeblock has been completed (all the source code is + * compiled), update a codeblock with all things that couldn't be + * done before. This function does the following: + * + * - Updates all user procedure/function calls with the process + * number instead of its identifier id. Emits a compiler error + * if a process what user but never defined. + * + * - Updates all jumps so that they go to absolute opcode offsets + * inside the procedure, instead of refering to the label table + * + * This function will be called once for each existing code block. + * + * PARAMS : + * code Pointer to the codeblock to modify + * + * RETURN VALUE : + * None + */ + +void codeblock_postprocess (CODEBLOCK * code) +{ + int * ptr = code->data ; + PROCDEF * proc, * my = procdef_search_by_codeblock( code ) ; + + while (ptr < code->data + code->current) + { + if ( !libmode && ( *ptr == MN_CALL || *ptr == MN_PROC || *ptr == MN_TYPE )) + { + proc = procdef_search(ptr[1]) ; + if (!proc || !proc->defined) + { + token.type = IDENTIFIER ; + token.code = ptr[1] ; + /* Patch so linecount gets right */ + line_count = identifier_line(token.code) ; + current_file = identifier_file(token.code) ; + compile_error (MSG_UNDEFINED_PROC) ; + } + ptr[1] = proc->typeid ; + } + if ( !my->imported ) + { + if (*ptr == MN_JUMP || *ptr == MN_NCALL || + *ptr == MN_JFALSE || *ptr == MN_JTFALSE || + *ptr == MN_JTRUE || *ptr == MN_JTTRUE || + *ptr == MN_JNOCASE || *ptr == MN_CLONE || + *ptr == MN_EXITHNDLR || *ptr == MN_ERRHNDLR + ) + { + ptr++ ; + if (*ptr == -1) + { +// *ptr = 0; + ptr++; + continue; + } + if (code->labels[*ptr] == -1) + { + token.type = LABEL ; + token.code = code->labelsextra[*ptr].name ; + /* Patch so linecount gets right */ + line_count = code->labelsextra[*ptr].line ; + current_file = code->labelsextra[*ptr].file ; + compile_error ("Undefined label") ; + } + *ptr = code->labels[*ptr] ; + ptr++ ; + continue ; + } + if (*ptr == MN_REFALSE) + { + *ptr++ = MN_JFALSE ; + *ptr = code->loops[*ptr*2] ; + ptr++ ; + continue ; + } + if (*ptr == MN_REPEAT || *ptr == MN_RETRUE) + { + *ptr = (*ptr == MN_REPEAT ? MN_JUMP : MN_JTRUE) ; + ptr++ ; + *ptr = code->loops[*ptr*2] ; + ptr++ ; + continue ; + } + if (*ptr == MN_BREAK || *ptr == MN_BRFALSE) + { + *ptr = (*ptr == MN_BREAK ? MN_JUMP : MN_JFALSE) ; + ptr++ ; + *ptr = code->loops[*ptr*2 + 1] ; + ptr++ ; + continue ; + } + } + ptr+=MN_PARAMS(*ptr)+1 ; + } +} + +/* + * FUNCTION : codeblock_init + * + * Initializes a new code block and allocates initial data + * for all its internal structs. + * + * PARAMS : + * c Pointer to the codeblock to initialize + * + * RETURN VALUE : + * None + */ + +void codeblock_init(CODEBLOCK * c) +{ + c->data = (int *) calloc (64, sizeof(int)) ; + c->reserved = 64 ; + + c->loops = (int *) calloc (16, sizeof(int)) ; + c->loop_reserved = 8 ; + c->loop_count = 1 ; + c->loop_active = 0 ; + + c->labels = (int *) calloc (16, sizeof(int)) ; + c->labelsextra = (struct _labelsextra *) calloc (16, sizeof(struct _labelsextra)) ; + c->label_count = 0 ; + c->label_reserved = 16 ; + + c->current = 0 ; + c->previous = 0 ; + c->previous2 = 0 ; + + if (!c->data || !c->loops || !c->labels || !c->labelsextra) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +/* + * FUNCTION : codeblock_alloc + * codeblock_loop_alloc + * codeblock_label_alloc + * + * Internal functions that alloc more memory for an + * internal data of the code block. Shouldn't be used + * outside this module. + * + * PARAMS : + * c Pointer to the codeblock + * count Additional size in number of members + * + * RETURN VALUE : + * None + */ + +void codeblock_alloc (CODEBLOCK * c, int count) +{ + c->reserved += count ; + c->data = (int *) realloc (c->data, c->reserved * sizeof(int)) ; + if (!c->data) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +static void codeblock_loop_alloc (CODEBLOCK * c, int count) +{ + c->loop_reserved += count ; + c->loops = (int *) realloc (c->loops, c->loop_reserved * sizeof(int) * 2) ; + if (!c->loops) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +static void codeblock_label_alloc (CODEBLOCK * c, int count) +{ + c->label_reserved += count ; + c->labels = (int *) realloc (c->labels, c->label_reserved * sizeof(int)) ; + c->labelsextra = (struct _labelsextra *) realloc (c->labelsextra, c->label_reserved * sizeof(struct _labelsextra)) ; + if (!c->labels) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +int codeblock_loop_add (CODEBLOCK * c) +{ + return c->loop_count++ ; +} + +void codeblock_loop_start (CODEBLOCK * c, int loop, int begin) +{ + if (c->loop_reserved <= loop) + codeblock_loop_alloc (c, loop + 8 - c->loop_reserved) ; + if (c->loop_count <= loop) + c->loop_count = loop+1 ; + c->loops[loop*2] = begin ; +} + +void codeblock_loop_end (CODEBLOCK * c, int loop, int end) +{ + if (c->loop_reserved <= loop) + codeblock_loop_alloc (c, loop + 8 - c->loop_reserved) ; + if (c->loop_count <= loop) + c->loop_count = loop+1 ; + c->loops[loop*2+1] = end ; +} + +int codeblock_label_add (CODEBLOCK * c, int identifier) +{ + if (c->label_count == c->label_reserved) codeblock_label_alloc (c, c->label_count + 16) ; + c->labels[c->label_count] = -1; + c->labelsextra[c->label_count].name = identifier; + c->labelsextra[c->label_count].file = current_file; + c->labelsextra[c->label_count].line = line_count; + c->label_count++ ; + return c->label_count - 1 ; +} + +void codeblock_label_set (CODEBLOCK * c, int label, int offset) +{ + c->labels[label] = offset ; +} + +int codeblock_label_get (CODEBLOCK * c, int label) +{ + return c->labels[label] ; +} + +int codeblock_label_get_id_by_name (CODEBLOCK * c, int identifier) +{ + int i; + for (i = 0; i < c->label_count; i++) if (c->labelsextra[i].name != -1 && c->labelsextra[i].name == identifier) return i; + return -1; +} + +void codeblock_stepback (CODEBLOCK * c) +{ + int code = c->data[c->previous]; + int param = 0; + + if (MN_PARAMS(code) > 0) + param = c->data[c->previous+1]; + + if (c->previous != c->previous2) + { + c->current = c->previous; + c->previous = c->previous2; + codeblock_add (c, code, param); + } +} + +CODEBLOCK_POS codeblock_pos(CODEBLOCK * c) +{ + CODEBLOCK_POS p; + + p.current = c->current; + p.previous = c->previous; + p.previous2 = c->previous2; + return p; +} + +void codeblock_setpos(CODEBLOCK * c, CODEBLOCK_POS p) +{ + c->current = p.current; + c->previous = p.previous; + c->previous2 = p.previous2; +} + +void codeblock_add_block (CODEBLOCK * c, CODEBLOCK_POS from, CODEBLOCK_POS to) +{ + if (c->current+(to.current - from.current)+2 >= c->reserved) + codeblock_alloc (c, (to.current - from.current + 34) & 0x1F) ; + + memcpy (c->data + c->current, c->data + from.current, 4*(to.current - from.current)); + c->current += to.current - from.current; + c->previous = c->current - (to.current - to.previous); + if (to.current - from.current > 2) + c->previous2 = c->current - (to.current - to.previous2); + else + c->previous2 = c->previous; +} + +void codeblock_add (CODEBLOCK * c, int code, int param) +{ + if (!c) return ; + + if (MN_PARAMS(code) == 0 && param) + fprintf (stdout, "WARNING: mnemonic 0x%02X don't get params\n", code) ; + + if (c->current > 0) + { + if (code == MN_ARRAY && c->data[c->previous] == MN_PUSH) + { + c->data[c->previous] = MN_INDEX ; + c->data[c->previous+1] *= param ; + codeblock_stepback(c); + return ; + } + else if (code == MN_ADD && c->data[c->previous] == MN_PUSH) + { + c->data[c->previous] = MN_INDEX ; + codeblock_stepback(c); + return ; + } + else if (code == MN_SUB && c->data[c->previous] == MN_PUSH) + { + c->data[c->previous] = MN_INDEX ; + c->data[c->previous+1] = -c->data[c->previous+1] ; + codeblock_stepback(c); + return ; + } + else if ((code & MN_MASK) == MN_INDEX) + { + if (c->data[c->previous] == MN_INDEX) + { + c->data[c->previous+1] += param ; + return ; + } + if ((c->data[c->previous] & MN_MASK) == MN_GLOBAL + || (c->data[c->previous] & MN_MASK) == MN_LOCAL + || (c->data[c->previous] & MN_MASK) == MN_PUBLIC + || (c->data[c->previous] & MN_MASK) == MN_REMOTE_PUBLIC + || (c->data[c->previous] & MN_MASK) == MN_PRIVATE + || (c->data[c->previous] & MN_MASK) == MN_REMOTE) + { + c->data[c->previous+1] += param ; + return ; + } + } + else if (code == MN_POP) + { + switch (c->data[c->previous] & MN_MASK) + { + case MN_LET: + c->data[c->previous] = MN_LETNP | (c->data[c->previous] & ~MN_MASK); + return ; + case MN_CALL: + c->data[c->previous] = MN_PROC ; + return ; + case MN_SYSCALL: + c->data[c->previous] = MN_SYSPROC ; + return ; + } + } + else if ((code & MN_MASK) == MN_PTR) + { + /* Mismo caso */ + + switch (c->data[c->previous] & MN_MASK) + { + case MN_PRIVATE: + c->data[c->previous] = MN_GET_PRIV | (code & ~MN_MASK) ; + return ; + case MN_LOCAL: + c->data[c->previous] = MN_GET_LOCAL | (code & ~MN_MASK) ; + return ; + case MN_PUBLIC: + c->data[c->previous] = MN_GET_PUBLIC | (code & ~MN_MASK) ; + return ; + case MN_REMOTE_PUBLIC: + c->data[c->previous] = MN_GET_REMOTE_PUBLIC | (code & ~MN_MASK) ; + return ; + case MN_GLOBAL: + c->data[c->previous] = MN_GET_GLOBAL | (code & ~MN_MASK) ; + return ; + case MN_REMOTE: + c->data[c->previous] = MN_GET_REMOTE | (code & ~MN_MASK) ; + return ; + case MN_PUSH: + return ; + } + } + } + + c->previous2 = c->previous; + c->previous = c->current ; + c->data[c->current++] = code ; + + if (MN_PARAMS(code) > 0) { + c->data[c->current++] = param ; + } + + if (c->current+2 >= c->reserved) codeblock_alloc (c, 32) ; +} + -- cgit v1.2.3