/src/dcodesrc.c
C | 3144 lines | 2683 code | 190 blank | 271 comment | 552 complexity | 6548c8cf7cc972541d6d68d141a549cd MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- // <ZZ> This file contains functions to compile SRC (script source) files
- // src_close_jumps - Fills in all of the previous jump locations
- // src_add_return_opcode - Puts a return opcode in the compiled code
- // src_get_define - Returns an index to the first matching define, or -1
- // src_set_priority - Helper for src_find_priority
- // src_find_priority - Generates the RPN order for a line of code, Recursive
- // src_read_token - Reads the next word-like thing of a file
- // src_add_define - #define's a token and it's replacement value
- // src_undefine_level - Gets rid of temporary defines (used for variable names...)
- // src_define_setup - Reads global defines from "DEFINE.TXT"
- // src_generate_opcodes - Writes the opcodes for a line
- // src_figure_variable_types - Determines any type casting that needs to be done
- // src_find_function_entry - Returns an offset to the start of a function's header, or 0
- // src_find_string_entry - Returns an offset to the start of a string's header, or 0
- // src_mega_find_function - Better than src_find_function_entry...
- // src_make_arrays - Helper for src_find_priority, sets up data...
- // src_functionize - Fill in all of the function jumps for a RUN file (helper)
- // src_compilerize - The main function to compile an SRC file
- // src_headerize - Generate header data before compiling an SRC file
- // src_stage_compile - Wrapper for headerize, compilerize, and functionize
- #include "dcodesrc.h"
- #include "soulfu.h"
- #include "datafile.h"
- #include "object.h"
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!! Should ifdef some of these functions out...
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!!
- #define MAX_VARIABLE 32 // I00 - I31, F00 - F31...
- #define MAX_ARGUMENT 16
- unsigned short put_jump_offset_here[SRC_MAX_INDENT]; // For figurin' out indentation jumps
- unsigned short while_jumps_back_to_here[SRC_MAX_INDENT]; // For figurin' out indentation jumps
- unsigned char last_jump_type_found[SRC_MAX_INDENT]; // Not used, If, Else, While...
- unsigned char token_buffer[SRC_MAX_TOKEN][SRC_MAX_TOKEN_SIZE]; // A place to put the pieces
- unsigned char token_priority[SRC_MAX_TOKEN]; // For figurin' out the RPN order
- unsigned char token_priority_list[SRC_MAX_TOKEN]; // List of tokens in order...
- unsigned char token_is_operand[SRC_MAX_TOKEN]; // For figurin' out the RPN order
- unsigned char token_is_operator[SRC_MAX_TOKEN]; // For figurin' out the RPN order
- unsigned char token_is_function[SRC_MAX_TOKEN]; // For figurin' out the RPN order
- unsigned char token_opcode[SRC_MAX_TOKEN]; // For figurin' out the RPN data
- unsigned char token_variable_type[SRC_MAX_TOKEN]; // F or I or ?...
- signed char token_number_to_destroy[SRC_MAX_TOKEN]; // The number of arguments to a function
- unsigned char token_change_type[SRC_MAX_TOKEN]; // For variable type conversions
- unsigned char token_is_destroyed[SRC_MAX_TOKEN]; // For variable type conversions
- unsigned char token_is_string[SRC_MAX_TOKEN]; // 'Cause string pointers are filled in during functionize...
- unsigned char* token_arg_list[SRC_MAX_TOKEN]; // Points to somethin' like "FII" for a function...
- unsigned char line_is_a_conditional; // While, If, or Else on line...
- int token_extension[SRC_MAX_TOKEN]; // For figurin' out the RPN data
- char define_token[SRC_MAX_DEFINE][SRC_MAX_TOKEN_SIZE]; // ex. "TRUE"
- char define_value[SRC_MAX_DEFINE][SRC_MAX_TOKEN_SIZE]; // ex. "1"
- char define_temporary_level[SRC_MAX_DEFINE]; // 0 is global, 1 is file, 2 is function
- int src_num_define = 0; // The number of defined values... May be higher than actual...
- #define SRC_BUFFER_SIZE 65550 //16384 extra big so src_buffer_used doesn't write other stuff... // Size of the RUN file...
- unsigned char src_buffer[SRC_BUFFER_SIZE]; // Stick the RUN file here while building it...
- unsigned short src_buffer_used = 0; // Current size
- unsigned char token_order; // For determining RPN order/priority...
- signed char found_error; // For compiler errors
- unsigned char last_function_returns_integer;
- unsigned char last_return_type;
- signed char float_variable_set[MAX_VARIABLE]; // Make sure variables are set before they're
- signed char int_variable_set[MAX_VARIABLE]; // used in expressions... x = 0 before y = x...
- char arg_list_none[]=""; // Argument lists for basic functions
- char arg_list_int[]="I"; //
- char arg_list_int_int[]="II"; //
- char arg_list_float[]="F"; //
- char arg_list_float_float[]="FF"; //
- char arg_list_iii[] = "III"; //
- char arg_list_iif[] = "IIF"; //
- char arg_list_iiii[] = "IIII"; //
- char arg_list_iffi[] = "IFFI"; //
- char arg_list_ffii[] = "FFII"; //
- char arg_list_iiiii[] = "IIIII"; //
- char arg_list_ifffi[] = "IFFFI"; //
- char arg_list_ffiii[] = "FFIII"; //
- char arg_list_iiiiii[] = "IIIIII"; //
- char arg_list_iffiii[] = "IFFIII"; //
- char arg_list_ffiiii[] = "FFIIII"; //
- char arg_list_ffiiiii[] = "FFIIIII"; //
- char arg_list_fffi[] = "FFFI"; //
- char arg_list_fffiiii[] = "FFFIIII"; //
- char arg_list_ffffi[] = "FFFFI"; //
- char arg_list_ffffiii[] = "FFFFIII"; //
- char arg_list_ffffiiiiii[] = "FFFFIIIIII"; //
- char arg_list_ffffffffffffiii[] = "FFFFFFFFFFFFIII";
- // For reading -5 as negative 5 instead of minus 5
- signed char next_token_may_be_negative;
- void src_close_jumps(unsigned char indent, unsigned char last_indent)
- {
- // <ZZ> This function closes all of the if's and else's and while's down to the
- // given indent level.
- int i;
- int j;
- i = last_indent;
- while(i > indent)
- {
- i--;
- if(i != 0)
- {
- if(last_jump_type_found[i] == SRC_JUMP_ELSE)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: ELSE SKIPPER JUMPS TO HERE 0x%x", src_buffer_used);
- #endif
- sdf_write_unsigned_short(src_buffer+put_jump_offset_here[i], src_buffer_used);
- }
- if(last_jump_type_found[i] == SRC_JUMP_IF)
- {
- // Insert implied jumps in order to skip over elses
- j = put_jump_offset_here[i];
- if(strcmp(token_buffer[0], "ELSE") == 0 && i == indent)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: OPC: 0x%02x", OPCODE_JUMP);
- log_message("INFO: 0x%02x", 0);
- log_message("INFO: 0x%02x", 0);
- #endif
- src_buffer[src_buffer_used] = OPCODE_JUMP; src_buffer_used++;
- sdf_write_unsigned_short(src_buffer+src_buffer_used, 0);
- put_jump_offset_here[i] = src_buffer_used;
- src_buffer_used+=2;
- last_jump_type_found[i] = SRC_JUMP_ELSE;
- }
- #ifdef VERBOSE_COMPILE
- log_message("INFO: FAILED IF JUMPS TO HERE 0x%x", src_buffer_used);
- #endif
- sdf_write_unsigned_short(src_buffer+j, src_buffer_used);
- }
- if(last_jump_type_found[i] == SRC_JUMP_WHILE)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: JUMP BACK TO START OF WHILE 0x%x", while_jumps_back_to_here[i]);
- log_message("INFO: OPC: 0x%02x", OPCODE_JUMP);
- log_message("INFO: 0x%02x", 0);
- log_message("INFO: 0x%02x", 0);
- #endif
- src_buffer[src_buffer_used] = OPCODE_JUMP; src_buffer_used++;
- sdf_write_unsigned_short(src_buffer+src_buffer_used, while_jumps_back_to_here[i]);
- src_buffer_used+=2;
- #ifdef VERBOSE_COMPILE
- log_message("INFO: FAILED WHILE JUMPS TO HERE 0x%x", src_buffer_used);
- #endif
- sdf_write_unsigned_short(src_buffer+put_jump_offset_here[i], src_buffer_used);
- }
- last_jump_type_found[i] == SRC_JUMP_INVALID;
- }
- }
- }
- void src_add_return_opcode(void)
- {
- // <ZZ> This function appends a return opcode to the src_buffer. Done to make
- // sure function calls go back to where they came from.
- if(last_function_returns_integer)
- {
- #ifdef VERBOSE_COMPILE
- // Opcode for integer 1 is 225
- log_message("INFO: OPC: 0x%02x", 225);
- log_message("INFO: OPC: 0x%02x", OPCODE_RETURNINT);
- #endif
- src_buffer[src_buffer_used] = 225; src_buffer_used++;
- src_buffer[src_buffer_used] = OPCODE_RETURNINT; src_buffer_used++;
- }
- else
- {
- #ifdef VERBOSE_COMPILE
- // Opcode for float 1.0 is 226
- log_message("INFO: OPC: 0x%02x", 226);
- log_message("INFO: OPC: 0x%02x", OPCODE_RETURNFLOAT);
- #endif
- src_buffer[src_buffer_used] = 226; src_buffer_used++;
- src_buffer[src_buffer_used] = OPCODE_RETURNFLOAT; src_buffer_used++;
- }
- }
- int src_get_define(char* token)
- {
- // <ZZ> This function returns the index of the first #define that matches token.
- // If there aren't any matches, it returns -1.
- int i;
- // Check each define...
- repeat(i, src_num_define)
- {
- if(strcmp(token, define_token[i]) == 0) return i;
- }
- return -1;
- }
- void src_set_priority(int start, int i, int end, signed char any_type)
- {
- // <ZZ> This function is a helper for the RPN code. It sets the given token to be the
- // next most important token.
- if(i >= start && i <= end)
- {
- if(token_priority[i] == 0 && token_buffer[i][0] != ',')
- {
- if(token_is_operand[i] || any_type)
- {
- token_priority_list[token_order-1] = i;
- token_priority[i] = token_order; token_order++;
- }
- }
- }
- }
- //-----------------------------------------------------------------------------------------------
- void src_find_priority(int start, int end, signed char change_signs, signed char first_check)
- {
- // <ZZ> This function looks at the tokens in token_buffer to determine the reverse polish
- // ordering for the tokens. Start is the first token to be examined, end is the last.
- // If the expression is complex (as it usually is), it is cut in half at the lowest
- // priority operator, and each half is fed back into the function recursively. If the
- // expression is simple enough to figure out, the priorities are assigned.
- int i;
- int priority;
- int lowest_token;
- int lowest_priority;
- int highest_priority;
- int nest_level;
- int our_nest_level;
- // Just in case something weird happens...
- if(end < start || start < 0 || start >= SRC_MAX_TOKEN || end < 0 || start >= SRC_MAX_TOKEN)
- {
- return;
- }
- // Change signs if negative... Don't propogate through parentheses...
- if(change_signs)
- {
- nest_level = 0;
- i = start;
- while(i <= end)
- {
- if(token_buffer[i][0] == '(')
- {
- nest_level++;
- }
- if(token_buffer[i][0] == ')')
- {
- nest_level--;
- }
- if(nest_level == 0)
- {
- if(token_opcode[i] == OPCODE_ADD)
- {
- token_opcode[i] = OPCODE_SUBTRACT;
- token_buffer[i][0] = '-';
- }
- else if(token_opcode[i] == OPCODE_SUBTRACT)
- {
- token_opcode[i] = OPCODE_ADD;
- token_buffer[i][0] = '+';
- }
- }
- i++;
- }
- }
- // Draw in ends to ignore parentheses...
- while(token_buffer[start][0] == '(' && token_buffer[end][0] == ')')
- {
- start++;
- end--;
- }
- // Just in case something weird happens...
- if(end < start)
- {
- return;
- }
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Checking priority from %d to %d", start, end);
- #endif
- // Find the lowest nest level...
- our_nest_level = 0;
- nest_level = 0;
- i = start;
- while(i <= end)
- {
- // Check for nest level changes...
- if(token_buffer[i][0] == '(')
- {
- nest_level++;
- }
- if(token_buffer[i][0] == ')')
- {
- nest_level--;
- }
- if(token_buffer[i][0] != '(' && token_buffer[i][0] != ')')
- {
- // Find the first useable token...
- our_nest_level = nest_level;
- i = end;
- }
- i++;
- }
- nest_level = 0;
- i = start;
- while(i <= end)
- {
- // Check for nest level changes...
- if(token_buffer[i][0] == '(')
- {
- nest_level++;
- }
- if(token_buffer[i][0] == ')')
- {
- nest_level--;
- }
- if(token_buffer[i][0] != '(' && token_buffer[i][0] != ')')
- {
- // Only take nest levels that actually have tokens...
- if(nest_level < our_nest_level) our_nest_level = nest_level;
- }
- i++;
- }
- // Search for the lowest and highest priority tokens
- lowest_token = -1;
- lowest_priority = 1000000;
- highest_priority = -1;
- nest_level = 0;
- i = start;
- while(i <= end)
- {
- // Check for nest level changes...
- if(token_buffer[i][0] == '(')
- {
- nest_level++;
- highest_priority = 100000; // Force a split
- }
- if(token_buffer[i][0] == ')')
- {
- nest_level--;
- }
- // Only handle tokens at our nest level...
- else if(nest_level == our_nest_level)
- {
- priority = -1;
- // First come increment and decrement
- if(token_opcode[i] == OPCODE_INCREMENT || token_opcode[i] == OPCODE_DECREMENT)
- {
- priority = 9;
- }
- // Then not and negate...
- else if(token_opcode[i] == OPCODE_LOGICALNOT || token_opcode[i] == OPCODE_NEGATE)
- {
- priority = 8;
- }
- // Then function calls
- else if(token_is_function[i])
- {
- priority = 7;
- }
- // Then multiply, divide, and modulus
- else if(token_opcode[i] == OPCODE_MULTIPLY || token_opcode[i] == OPCODE_DIVIDE || token_opcode[i] == OPCODE_MODULUS)
- {
- priority = 6;
- }
- // Then add and subtract
- else if(token_opcode[i] == OPCODE_ADD || token_opcode[i] == OPCODE_SUBTRACT)
- {
- priority = 5;
- }
- // Then bitwise operations
- else if(token_opcode[i] >= OPCODE_BITWISEAND && token_opcode[i] <= OPCODE_BITWISERIGHT)
- {
- priority = 4;
- }
- // Then comparison operations
- else if(token_opcode[i] >= OPCODE_ISEQUAL && token_opcode[i] <= OPCODE_ISLESSER)
- {
- priority = 3;
- }
- // Then logical operations
- else if(token_opcode[i] == OPCODE_LOGICALAND || token_opcode[i] == OPCODE_LOGICALOR)
- {
- priority = 2;
- }
- // Then commas
- else if(token_buffer[i][0] == ',')
- {
- priority = 1;
- }
- // Then equates
- else if(token_opcode[i] == OPCODE_EQUALS)
- {
- priority = 0;
- }
- // Now remember the priority...
- if(priority > -1)
- {
- if(priority > highest_priority)
- {
- highest_priority = priority;
- }
- if(priority < lowest_priority || (priority == 6 && lowest_priority == 6))
- {
- lowest_token = i;
- lowest_priority = priority;
- }
- }
- }
- i++;
- }
- // Check for errors...
- if(nest_level != 0 && first_check)
- {
- log_message("ERROR: Line %d, Unbalanced parentheses", sdf_read_line_number);
- found_error = TRUE;
- return;
- }
- // Now, if the expression only contains tokens of one priority, we can solve it...
- if((highest_priority == lowest_priority && lowest_priority != 7 && lowest_priority != 0 && lowest_priority != 1) || lowest_token == -1)
- {
- // Solve the expression...
- i = start;
- while(i <= end)
- {
- if(token_is_operator[i])
- {
- if(token_opcode[i] == OPCODE_INCREMENT || token_opcode[i] == OPCODE_DECREMENT)
- {
- // Handle self
- src_set_priority(start, i, end, TRUE);
- // Handle operand to left
- src_set_priority(start, i-1, end, FALSE);
- }
- else
- {
- // Handle operand to left
- src_set_priority(start, i-1, end, FALSE);
- // Handle operand to right
- src_set_priority(start, i+1, end, FALSE);
- // Handle self
- src_set_priority(start, i, end, TRUE);
- }
- }
- else if(lowest_token == -1)
- {
- // Handle self
- src_set_priority(start, i, end, FALSE);
- }
- i++;
- }
- }
- else
- {
- // Too complex, so split it in two and try again...
- if(token_opcode[lowest_token] == OPCODE_EQUALS || token_is_function[lowest_token])
- {
- // Right side
- src_find_priority(lowest_token+1, end, FALSE, FALSE);
- // Middle
- src_set_priority(start, lowest_token, end, TRUE);
- // Left side
- src_find_priority(start, lowest_token-1, FALSE, FALSE);
- }
- else if(token_opcode[lowest_token] == OPCODE_LOGICALNOT || token_opcode[lowest_token] == OPCODE_NEGATE)
- {
- // Right side
- src_find_priority(lowest_token+1, end, FALSE, FALSE);
- // Middle
- src_set_priority(start, lowest_token, end, TRUE);
- }
- else
- {
- // Left side
- src_find_priority(start, lowest_token-1, FALSE, FALSE);
- // Right side
- if(token_opcode[lowest_token] == OPCODE_SUBTRACT) src_find_priority(lowest_token+1, end, TRUE, FALSE);
- else src_find_priority(lowest_token+1, end, FALSE, FALSE);
- // Middle
- src_set_priority(start, lowest_token, end, TRUE);
- }
- }
- return;
- }
- //-----------------------------------------------------------------------------------------------
- signed char src_read_token(unsigned char* buffer)
- {
- // <ZZ> This function reads the next token (like a word) in a file that has been
- // sdf_open()'d and puts that token in buffer. The token can't be any longer than
- // SRC_MAX_TOKEN_SIZE. It returns TRUE if there was a token to read, or FALSE if
- // not. next_token_may_be_negative is also important for reading negative numbers
- // correctly.
- int count;
- int value;
- // Skip any whitespace...
- while((*sdf_read_file) == ' ' && sdf_read_remaining > 0)
- {
- sdf_read_remaining--;
- sdf_read_file++;
- }
- // Check for a string token...
- count = 0;
- if((*sdf_read_file) == '\'' && (*(sdf_read_file+2)) == '\'')
- {
- sprintf(buffer, "%d", *(sdf_read_file+1));
- sdf_read_remaining-=3;
- sdf_read_file+=3;
- count=3;
- }
- else if((*sdf_read_file) == '"')
- {
- // Read the string token
- buffer[count] = '"';
- sdf_read_remaining--;
- sdf_read_file++;
- count++;
- while(count < SRC_MAX_TOKEN_SIZE-2 && sdf_read_remaining > 0 && (*sdf_read_file) != '"' && (*sdf_read_file) != 0)
- {
- buffer[count] = (*sdf_read_file);
- sdf_read_remaining--;
- sdf_read_file++;
- if(buffer[count] == '\\' && (*sdf_read_file) >= '0' && (*sdf_read_file) <= '9')
- {
- // It's an escape sequence, so read in the value...
- value = 0;
- while((*sdf_read_file) >= '0' && (*sdf_read_file) <= '9')
- {
- value = (value*10) + (*sdf_read_file) - '0';
- sdf_read_remaining--;
- sdf_read_file++;
- }
- buffer[count] = value;
- }
- count++;
- }
- buffer[count] = '"';
- sdf_read_remaining--;
- sdf_read_file++;
- count++;
- buffer[count] = 0;
- next_token_may_be_negative = FALSE;
- }
- else
- {
- // Is the token alphanumeric or a special operator token???
- if((((*sdf_read_file) >= 'A' && (*sdf_read_file) <= 'Z') || ((*sdf_read_file) >= 'a' && (*sdf_read_file) <= 'z') || (*sdf_read_file) == '_' || (*sdf_read_file) == '.' || ((*sdf_read_file) >= '0' && (*sdf_read_file) <= '9') ))
- {
- // Read the alphanumeric token
- while(count < SRC_MAX_TOKEN_SIZE-1 && sdf_read_remaining > 0 && ((((*sdf_read_file) >= 'A' && (*sdf_read_file) <= 'Z') || ((*sdf_read_file) >= 'a' && (*sdf_read_file) <= 'z') || (*sdf_read_file) == '_' || (*sdf_read_file) == '.' || ((*sdf_read_file) >= '0' && (*sdf_read_file) <= '9') )))
- {
- buffer[count] = (*sdf_read_file);
- sdf_read_remaining--;
- sdf_read_file++;
- count++;
- }
- buffer[count] = 0;
- make_uppercase(buffer);
- next_token_may_be_negative = FALSE;
- }
- else
- {
- // Read one character...
- if((*sdf_read_file) != 0)
- {
- if(sdf_read_remaining > 0)
- {
- buffer[count] = (*sdf_read_file);
- sdf_read_remaining--;
- sdf_read_file++;
- count++;
- }
- // Do we need another?
- if((buffer[0] == '>' && (*sdf_read_file) == '>') ||
- (buffer[0] == '<' && (*sdf_read_file) == '<') ||
- (buffer[0] == '&' && (*sdf_read_file) == '&') ||
- (buffer[0] == '|' && (*sdf_read_file) == '|') ||
- (buffer[0] == '>' && (*sdf_read_file) == '=') ||
- (buffer[0] == '<' && (*sdf_read_file) == '=') ||
- (buffer[0] == '=' && (*sdf_read_file) == '=') ||
- (buffer[0] == '+' && (*sdf_read_file) == '+') ||
- (buffer[0] == '-' && (*sdf_read_file) == '-') ||
- (buffer[0] == '/' && (*sdf_read_file) == '/') ||
- (buffer[0] == '!' && (*sdf_read_file) == '='))
- {
- buffer[count] = (*sdf_read_file);
- sdf_read_remaining--;
- sdf_read_file++;
- count++;
- }
- // Ignore comments...
- if(buffer[0] == '/' && buffer[1] == '/') return FALSE;
- // May need to read a whole number in... Negative numbers...
- if(next_token_may_be_negative)
- {
- if(buffer[0] == '-' && (*sdf_read_file) >= '0' && (*sdf_read_file) <= '9')
- {
- // Read the numeric token...
- while(count < SRC_MAX_TOKEN_SIZE-1 && sdf_read_remaining > 0 && (((*sdf_read_file) == '.' || ((*sdf_read_file) >= '0' && (*sdf_read_file) <= '9'))))
- {
- buffer[count] = (*sdf_read_file);
- sdf_read_remaining--;
- sdf_read_file++;
- count++;
- }
- next_token_may_be_negative = FALSE;
- }
- }
- else
- {
- next_token_may_be_negative = TRUE;
- }
- buffer[count] = 0;
- // Figure out if the next one can be negative...
- if(strcmp(buffer, ")") == 0) next_token_may_be_negative = FALSE;
- if(strcmp(buffer, "--") == 0) next_token_may_be_negative = FALSE;
- if(strcmp(buffer, "++") == 0) next_token_may_be_negative = FALSE;
- if(strcmp(buffer, "%") == 0) next_token_may_be_negative = FALSE;
- }
- }
- }
- if(count > 0) return TRUE;
- return FALSE;
- }
- //-----------------------------------------------------------------------------------------------
- void src_add_define(char* token, char* value, char temporary_level)
- {
- // <ZZ> This function registers a new #define'd value. Temporary_level determines if the
- // define is removed after a file or function is done being parsed.
- char temptoken[SRC_MAX_TOKEN_SIZE];
- unsigned char* tempptr;
- int tempint;
- int tempnum;
- int i;
- int j;
- int found;
- int define_to_use;
- char define_is_new;
- // Look for an unused define to use...
- next_token_may_be_negative = TRUE;
- define_is_new = TRUE;
- define_to_use = src_num_define;
- repeat(i, src_num_define)
- {
- // Has this one been cleared?
- if(define_token[i][0] == 0)
- {
- define_to_use = i;
- define_is_new = FALSE;
- i = src_num_define;
- }
- }
- // Fill in the data
- if(define_to_use < SRC_MAX_DEFINE)
- {
- // Skip whitespace...
- while((*token) == ' ') token++;
- while((*value) == ' ') value++;
- // Copy the token...
- i = 0;
- while(i < SRC_MAX_TOKEN_SIZE-1 && token[i] != 0)
- {
- define_token[define_to_use][i] = token[i];
- i++;
- }
- define_token[define_to_use][i] = 0;
- define_temporary_level[define_to_use] = temporary_level;
- // Now search through the value, looking for previously #defined tokens...
- tempptr = sdf_read_file;
- tempint = sdf_read_remaining;
- tempnum = sdf_read_line_number;
- sdf_read_file = value;
- sdf_read_remaining = SRC_MAX_TOKEN_SIZE;
- i = 0;
- while(src_read_token(temptoken))
- {
- found = src_get_define(temptoken);
- if(found > -1)
- {
- // Copy the value of the old token into the new one...
- j = 0;
- while(define_value[found][j] != 0 && i < SRC_MAX_TOKEN_SIZE-1)
- {
- define_value[define_to_use][i] = define_value[found][j];
- i++;
- j++;
- }
- if(i < SRC_MAX_TOKEN_SIZE-1)
- {
- define_value[define_to_use][i] = ' ';
- i++;
- }
- }
- else
- {
- // Copy the token into the new define...
- j = 0;
- while(temptoken[j] != 0 && i < SRC_MAX_TOKEN_SIZE-1)
- {
- define_value[define_to_use][i] = temptoken[j];
- i++;
- j++;
- }
- if(i < SRC_MAX_TOKEN_SIZE-1)
- {
- define_value[define_to_use][i] = ' ';
- i++;
- }
- }
- }
- if(i < SRC_MAX_TOKEN_SIZE)
- {
- define_value[define_to_use][i] = 0;
- i--;
- }
- if(i >= 0)
- {
- if(define_value[define_to_use][i] == ' ')
- {
- define_value[define_to_use][i] = 0;
- }
- }
- sdf_read_line_number = tempnum;
- sdf_read_remaining = tempint;
- sdf_read_file = tempptr;
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Defined... %s == %s", define_token[define_to_use], define_value[define_to_use]);
- #endif
- // Increment the number of defines if we added a new one
- if(define_is_new) src_num_define++;
- }
- else
- {
- log_message("ERROR: Couldn't define %s... Out of tokens to use...", token);
- found_error = TRUE;
- }
- }
- //-----------------------------------------------------------------------------------------------
- void src_undefine_level(char temporary_level)
- {
- // <ZZ> This function gets rid of any defines that we don't need
- int i;
- repeat(i, src_num_define)
- {
- if(define_temporary_level[i] >= temporary_level)
- {
- define_token[i][0] = 0;
- define_value[i][0] = 0;
- define_temporary_level[i] = 0;
- }
- }
- }
- //-----------------------------------------------------------------------------------------------
- signed char src_define_setup(void)
- {
- // <ZZ> This function looks at "DEFINE.TXT" to see what global #define's we've got,
- // including ID strings. It returns TRUE if it worked okay, or FALSE if not.
- unsigned char indent;
- obj_reset_property();
- next_token_may_be_negative = TRUE;
- src_num_define = 0;
- if(sdf_open("DEFINE.TXT"))
- {
- log_message("INFO: Setting up the global #defines...");
- while(sdf_read_line())
- {
- // Count the indentation (by 2's), and skip over any whitespace...
- indent = count_indentation(sdf_read_file);
- sdf_read_file+=indent;
- sdf_read_remaining-=indent;
- indent = indent>>1;
- // Check for a #define...
- if(sdf_read_file[0] == '#')
- {
- if(sdf_read_file[1] == 'd')
- {
- if(sdf_read_file[2] == 'e')
- {
- if(sdf_read_file[3] == 'f')
- {
- if(sdf_read_file[4] == 'i')
- {
- if(sdf_read_file[5] == 'n')
- {
- if(sdf_read_file[6] == 'e')
- {
- sdf_read_file+=7;
- sdf_read_remaining-=7;
- if(src_read_token(token_buffer[0]))
- {
- src_add_define(token_buffer[0], sdf_read_file, SRC_PERMANENT);
- }
- }
- }
- }
- }
- }
- }
- else if(sdf_read_file[1] == 'p')
- {
- if(sdf_read_file[2] == 'r')
- {
- if(sdf_read_file[3] == 'o')
- {
- if(sdf_read_file[4] == 'p')
- {
- if(sdf_read_file[5] == 'e')
- {
- if(sdf_read_file[6] == 'r')
- {
- sdf_read_file+=7;
- sdf_read_remaining-=7;
- if(src_read_token(token_buffer[0])) // tag
- {
- if(src_read_token(token_buffer[1])) // type
- {
- if(src_read_token(token_buffer[2])) // offset
- {
- obj_add_property(token_buffer[0], token_buffer[1][0], token_buffer[2]);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- log_message("INFO: %d of %d properties used", obj_num_property, MAX_PROPERTY);
- log_message("INFO: %d of %d defines used", src_num_define, SRC_MAX_DEFINE);
- return TRUE;
- }
- log_message("ERROR: DEFINE.TXT could not be found in the database");
- return FALSE;
- }
- //-----------------------------------------------------------------------------------------------
- void src_generate_opcodes(int token_count)
- {
- // <ZZ> This function writes the finalized opcodes for a single line of a SRC file. The
- // opcodes are put in the src_buffer. Token_count is the number of RPN symbols found
- // previously, which doesn't include tokens like '(' and ','.
- int i;
- int token;
- unsigned int tempint;
- signed char last_token_was_equals;
- last_token_was_equals = FALSE;
- repeat(i, token_count)
- {
- // Write out the opcode and any extended data...
- token = token_priority_list[i];
- // ...But ignore else's...
- if(strcmp(token_buffer[token], "ELSE") != 0)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: OPC: 0x%02x", token_opcode[token]);
- #endif
- src_buffer[src_buffer_used] = token_opcode[token]; src_buffer_used++;
-
- // Look for variables that are used before being set...
- if(last_token_was_equals)
- {
- // Variables being set...
- if(token_opcode[token] >= 128 && token_opcode[token] < 224)
- {
- if((token_opcode[token] & 224) == 192)
- {
- // Float variable has been set...
- float_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] = TRUE;
- }
- if((token_opcode[token] & 224) == 128)
- {
- // Integer variable has been set...
- int_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] = TRUE;
- }
- }
- else
- {
- log_message("ERROR: Line %d, Can only set/assign variables", sdf_read_line_number);
- }
- }
- else
- {
- // Variables being used...
- if(token_opcode[token] >= 128 && token_opcode[token] < 224)
- {
- if((token_opcode[token] & 224) == 192)
- {
- if(float_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] == FALSE)
- {
- // Variable has been used before being set...
- log_message("ERROR: Line %d, Variable F%02d used before being set", sdf_read_line_number, (token_opcode[token] & (MAX_VARIABLE-1)));
- found_error = TRUE;
- }
- }
- else
- {
- if(int_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] == FALSE)
- {
- // Variable has been used before being set...
- log_message("ERROR: Line %d, Variable I%02d used before being set", sdf_read_line_number, (token_opcode[token] & (MAX_VARIABLE-1)));
- found_error = TRUE;
- }
- }
- }
- }
- last_token_was_equals = FALSE;
- if(token_opcode[token] == OPCODE_EQUALS || token_opcode[token] == OPCODE_F_EQUALS)
- {
- last_token_was_equals = TRUE;
- }
- if(token_opcode[token] == OPCODE_CALLFUNCTION)
- {
- // Call function... 4 byte jump location, 4 byte return
- // position, 4 byte argument list pointer, 4 byte file start address,
- // then the zero terminated function name
- #ifdef VERBOSE_COMPILE
- log_message("INFO: : 0x00 (jump)");
- log_message("INFO: : 0x00 (jump)");
- log_message("INFO: : 0x00 (jump)");
- log_message("INFO: : 0x00 (jump)");
- log_message("INFO: : 0x00 (return)");
- log_message("INFO: : 0x00 (return)");
- log_message("INFO: : 0x00 (return)");
- log_message("INFO: : 0x00 (return)");
- log_message("INFO: : 0x00 (arg)");
- log_message("INFO: : 0x00 (arg)");
- log_message("INFO: : 0x00 (arg)");
- log_message("INFO: : 0x00 (arg)");
- log_message("INFO: : 0x00 (filestart)");
- log_message("INFO: : 0x00 (filestart)");
- log_message("INFO: : 0x00 (filestart)");
- log_message("INFO: : 0x00 (filestart)");
- log_message("INFO: : %s", token_buffer[token]);
- log_message("INFO: : 0x00");
- #endif
- sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
- sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
- sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
- sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
- sprintf(src_buffer+src_buffer_used, "%s", token_buffer[token]);
- src_buffer_used+=strlen(token_buffer[token])+1;
- }
- if(token_opcode[token] == OPCODE_IFFALSEJUMP)
- {
- // Jump function (if or while)... 2 byte address... Filled in later...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: : 0x00");
- log_message("INFO: : 0x00");
- #endif
- sprintf(src_buffer+src_buffer_used, "%c%c", 0, 0);
- src_buffer_used+=2;
- }
- if((token_opcode[token]&0xE0) == 0xA0 || token_opcode[token] == 227)
- {
- // 101xxxxx... Integer variable with dot parameter... One byte index follows
- // 227... Integer numeric token.... 1 byte data follows (signed)
- tempint = *((unsigned int*) &token_extension[token]);
- #ifdef VERBOSE_COMPILE
- log_message("INFO: : 0x%02x", (tempint)&255);
- #endif
- *(src_buffer+src_buffer_used) = (tempint)&255; src_buffer_used++;
- }
- if(token_opcode[token] == 228)
- {
- // Integer numeric token... 2 byte data follows (signed)...
- tempint = *((unsigned int*) &token_extension[token]);
- #ifdef VERBOSE_COMPILE
- log_message("INFO: : 0x%02x", (tempint>>8)&255);
- log_message("INFO: : 0x%02x", (tempint)&255);
- #endif
- *(src_buffer+src_buffer_used) = (tempint>>8)&255; src_buffer_used++;
- *(src_buffer+src_buffer_used) = (tempint)&255; src_buffer_used++;
- }
- if(token_opcode[token] == 229 || token_opcode[token] == 230)
- {
- // 229... Integer numeric token... 4 byte data follows (signed)...
- // 230... Float numeric token... 4 byte data follows (signed)...
- tempint = *((unsigned int*) &token_extension[token]);
- if(token_is_string[token])
- {
- // This is a string type of integer, so we need to remember where
- // it is, so functionize can change the numbers... Write the opcode offset
- // into the string header area...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Weird string fill-in-later thing.... %s", src_buffer+token_extension[token]);
- #endif
- sdf_write_unsigned_short((src_buffer+token_extension[token]-2), (src_buffer_used));
- tempint = 0;
- }
- #ifdef VERBOSE_COMPILE
- log_message("INFO: : 0x%02x", (tempint>>24)&255);
- log_message("INFO: : 0x%02x", (tempint>>16)&255);
- log_message("INFO: : 0x%02x", (tempint>>8)&255);
- log_message("INFO: : 0x%02x", (tempint)&255);
- #endif
- *(src_buffer+src_buffer_used) = (tempint>>24)&255; src_buffer_used++;
- *(src_buffer+src_buffer_used) = (tempint>>16)&255; src_buffer_used++;
- *(src_buffer+src_buffer_used) = (tempint>>8)&255; src_buffer_used++;
- *(src_buffer+src_buffer_used) = (tempint)&255; src_buffer_used++;
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!! Probably won't compile RUN's same on Macs... Floats will be screwed up... Maybe reverse bytes here...
- // !!!BAD!!!
- // !!!BAD!!!
- }
- // Now insert variable type conversions...
- if(token_change_type[token] == VAR_INT)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: OPC: 0x%02x (to int)", OPCODE_TOINT);
- #endif
- src_buffer[src_buffer_used] = OPCODE_TOINT; src_buffer_used++;
- }
- if(token_change_type[token] == VAR_FLOAT)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: OPC: 0x%02x (to float)", OPCODE_TOFLOAT);
- #endif
- src_buffer[src_buffer_used] = OPCODE_TOFLOAT; src_buffer_used++;
- }
- }
- }
- #ifdef VERBOSE_COMPILE
- log_message("INFO: ");
- #endif
- }
- //-----------------------------------------------------------------------------------------------
- void src_figure_variable_types(int token_count)
- {
- // <ZZ> This function determines where to place the ToInt and ToFloat opcodes for a line.
- // Token_count is the number of RPN symbols found previously, which doesn't include
- // tokens like '(' and ','.
- int i;
- int j;
- int destroyed;
- int total_destroyed;
- int token;
- int other_token;
- unsigned char type_needed;
- repeat(i, token_count)
- {
- // Look for tokens in order of their priority...
- token = token_priority_list[i];
- token_is_destroyed[token] = FALSE;
- // Look through previous tokens to find arguments for functions/operations
- type_needed = VAR_INT;
- if(token_number_to_destroy[token] > 0)
- {
- // Look for errors with equals, increment, and decrement
- if(token_variable_type[token] == VAR_INVALID)
- {
- if(token_opcode[token] == OPCODE_EQUALS || token_opcode[token] == OPCODE_INCREMENT || token_opcode[token] == OPCODE_DECREMENT)
- {
- // Need to know what type of variable is being set... Check it...
- if(i < token_count)
- {
- // Make sure the token to the left is a valid data storage token...
- other_token = token_priority_list[i+1];
- if(token_opcode[other_token] >= 128 && token_opcode[other_token] < 224 )
- {
- if(token_opcode[token] == OPCODE_EQUALS)
- {
- // Check to the right for equals, now that we've checked for errors...
- if(i > 0)
- {
- other_token = token_priority_list[i-1];
- type_needed = token_variable_type[other_token];
- }
- else
- {
- log_message("ERROR: Line %d, Missing value to right of =", sdf_read_line_number);
- found_error = TRUE;
- }
- }
- else
- {
- type_needed = token_variable_type[other_token];
- }
- }
- else
- {
- log_message("ERROR: Line %d, Invalid storage variable to left of =, ++, or, --", sdf_read_line_number);
- found_error = TRUE;
- }
- }
- }
- }
- // Look for any floating point arguments... This is needed for basic functions
- // and operations that can handle either float or integer... If an Add has a float
- // and an int, the int should be changed to float and a FloatAdd performed...
- if(token_arg_list[token] == NULL)
- {
- destroyed = 0;
- j = i;
- while(j > 0 && destroyed < token_number_to_destroy[token])
- {
- // Go to the last token and see if we can use it...
- j--;
- other_token = token_priority_list[j];
- if(token_is_destroyed[other_token] == FALSE)
- {
- // Okay, we can use it... Check if it's a float...
- if(token_variable_type[other_token] == VAR_FLOAT) type_needed = VAR_FLOAT;
- destroyed++;
- }
- }
- // Now change the opcodes from IntAdd to FloatAdd... Others too...
- if(type_needed == VAR_FLOAT)
- {
- if(token_opcode[token] <= OPCODE_NEGATE)
- {
- token_opcode[token]+=32; // Float operations start with opcode 32...
- }
- }
- }
- // Fill in the correct variable type...
- if(token_variable_type[token] == VAR_INVALID)
- {
- token_variable_type[token] = type_needed;
- // Some floating point functions return integers...
- if(token_opcode[token] >= OPCODE_F_ISEQUAL && token_opcode[token] <= OPCODE_F_LOGICALNOT)
- {
- token_variable_type[token] = VAR_INT;
- }
- }
- // Now type cast any of those arguments we found... Do the search again...
- destroyed = 0;
- j = i;
- while(j > 0 && destroyed < token_number_to_destroy[token])
- {
- // Go to the last token and see if we can use it...
- j--;
- other_token = token_priority_list[j];
- if(token_is_destroyed[other_token] == FALSE)
- {
- // Remember that we ate it up, so other functions don't try to use it too...
- token_is_destroyed[other_token] = TRUE;
- destroyed++;
- // Okay, we can use it... Do we need to change all ints to float?
- if(token_arg_list[token] != NULL)
- {
- // Looks like a function with a set argument list, so just cast any
- // argument we need to
- type_needed = *(token_arg_list[token]+token_number_to_destroy[token]-destroyed);
- }
- if(token_variable_type[other_token] != type_needed)
- {
- // Don't insert ToInt or ToFloat for equates...
- if(token_opcode[token] != OPCODE_EQUALS && token_opcode[token] != OPCODE_F_EQUALS)
- {
- token_change_type[other_token] = type_needed;
- }
- }
- }
- }
- }
- last_return_type = token_variable_type[token];
- }
- // Make sure we had the correct number of arguments
- total_destroyed = 0;
- repeat(i, token_count)
- {
- token = token_priority_list[i];
- if(token_opcode[token] == OPCODE_EQUALS || token_opcode[token] == OPCODE_F_EQUALS) token_number_to_destroy[token]++;
- if(token_number_to_destroy[token] >= 0) token_number_to_destroy[token]--;
- total_destroyed += to…
Large files files are truncated, but you can click here to view the full file