/src/dcodesrc.c
C | 3144 lines | 2683 code | 190 blank | 271 comment | 552 complexity | 6548c8cf7cc972541d6d68d141a549cd MD5 | raw 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 += token_number_to_destroy[token];
- #ifdef VERBOSE_COMPILE
- log_message("INFO: RPN: %s DES: %d", token_buffer[token], token_number_to_destroy[token]);
- #endif
- }
- #ifdef VERBOSE_COMPILE
- log_message("INFO: ");
- #endif
- if(total_destroyed != -1)
- {
- log_message("ERROR: Line %d, Wrong number of arguments (%d to %d)", sdf_read_line_number, total_destroyed, -1);
- found_error = TRUE;
- }
- // Debug stuff...
- #ifdef VERBOSE_COMPILE
- repeat(i, token_count)
- {
- token = token_priority_list[i];
- log_message("INFO: TYP: %c CHG: %c RPN: %s", token_variable_type[token], token_change_type[token], token_buffer[token]);
- }
- log_message("INFO: ");
- #endif
- }
- //-----------------------------------------------------------------------------------------------
- int src_find_function_entry(unsigned char* filedata, char* functionname)
- {
- // <ZZ> This function searches a .RUN file's header for a given function, and returns
- // the function's entry (offset in the header) if it finds a match. If there weren't
- // any matches, it returns 0. Functionname should be all uppercase...
- int number_of_functions;
- int i;
- unsigned char* filedatastart;
- // For each function in the header...
- filedatastart = filedata;
- filedata+=MAX_FAST_FUNCTION<<1; // Skip the fast function lookups...
- number_of_functions = sdf_read_unsigned_short(filedata);
- filedata+=4;
- repeat(i, number_of_functions)
- {
- // Check for a match...
- if(strcmp(functionname, (filedata+2)) == 0)
- {
- return (filedata-filedatastart);
- }
- // Go to the next entry
- filedata+=2; // Skip the address
- filedata+=strlen(filedata)+1; // Skip the name and 0
- filedata+=strlen(filedata)+1; // Skip the return and any arguments and 0
- }
- // Didn't find a match
- return 0;
- }
- //-----------------------------------------------------------------------------------------------
- int src_find_string_entry(unsigned char* filedata, char* stringname)
- {
- // <ZZ> This function searches a .RUN file's header for a given string, and returns
- // the string's entry (offset in the header) if it finds a match. If there weren't
- // any matches, it returns 0.
- int number_of_functions;
- int number_of_strings;
- int i;
- unsigned short j;
- unsigned char* filedatastart;
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Looking for string %s...", stringname);
- #endif
- // For each function in the header...
- filedatastart = filedata;
- filedata+=MAX_FAST_FUNCTION<<1; // Skip the fast function lookups...
- number_of_functions = sdf_read_unsigned_short(filedata);
- filedata+=2;
- number_of_strings = sdf_read_unsigned_short(filedata);
- filedata+=2;
- repeat(i, number_of_functions)
- {
- // Go to the next entry
- filedata+=2; // Skip the address
- filedata+=strlen(filedata)+1; // Skip the name and 0
- filedata+=strlen(filedata)+1; // Skip the return and any arguments and 0
- }
- repeat(i, number_of_strings)
- {
- // Only return strings that haven't been returned yet... FFFF offset...
- j = sdf_read_unsigned_short(filedata);
- if(j == 65535)
- {
- // Check for a match...
- if(strcmp(stringname, filedata+2) == 0)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Found string %s at 0x%x", stringname, (filedata-filedatastart));
- #endif
- sdf_write_unsigned_short(filedata, 0);
- return (filedata-filedatastart);
- }
- }
- // Go to the next entry
- filedata+=2; // Skip the address
- filedata+=strlen(filedata)+1; // Skip the name and 0
- }
- // Didn't find a match
- return 0;
- }
- //-----------------------------------------------------------------------------------------------
- unsigned char* src_mega_find_function(unsigned char* functionstring, unsigned char* filename, unsigned char request)
- {
- // <ZZ> This function may only be called after a complete headerize has been performed. It
- // determines the header entry location of a function based on a "file.function" type
- // string or just a "function" string, and then returns a bit of requested information
- // about that function. Filename is the name of the file in which the string was found,
- // not necessarily the file the function is found in. It returns NULL if no matching
- // function could be found.
- unsigned char* functionname;
- unsigned char must_fix_dot;
- unsigned char* data;
- unsigned int entry_offset;
- unsigned char* entry;
- unsigned char* index;
- // Split a two part string into two parts by figuring out where the dot is...
- must_fix_dot = FALSE;
- functionname = strpbrk(functionstring, ".");
- if(functionname != NULL)
- {
- // Found a dot, so we should have an explicit filename...
- filename = functionstring;
- *functionname = 0; // Split into two strings...
- must_fix_dot = TRUE; // ...But remember to put the dot back later...
- functionname++;
- }
- else
- {
- // No dot, so it's just a function name, no file name
- functionname = functionstring;
- }
- // Open the file that we think it's in...
- entry = NULL;
- index = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
- if(index != NULL)
- {
- // Found the file, so now look for the function
- data = (unsigned char*) sdf_read_unsigned_int(index);
- entry_offset = src_find_function_entry(data, functionname);
- if(entry_offset)
- {
- entry = data + entry_offset;
- }
- }
- if(entry == NULL)
- {
- // Didn't find the function on our first guess, so let's check GENERIC.RUN
- if(must_fix_dot == FALSE)
- {
- index = sdf_find_filetype("GENERIC", SDF_FILE_IS_RUN);
- if(index != NULL)
- {
- // Found the file, so now look for the function
- data = (unsigned char*) sdf_read_unsigned_int(index);
- entry_offset = src_find_function_entry(data, functionname);
- if(entry_offset)
- {
- entry = data + entry_offset;
- }
- }
- }
- }
- // Put the dot back if we took it out...
- if(must_fix_dot)
- {
- *(functionname-1) = '.';
- }
- // Now see about filling the request...
- if(entry != NULL)
- {
- // Found the function's entry in the RUN file... So log it...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Mega_found function %s", functionstring);
- #endif
- // And return whatever was requested...
- if(request == SRC_REQUEST_ENTRY)
- {
- return entry;
- }
- if(request == SRC_REQUEST_OFFSET)
- {
- return (data+sdf_read_unsigned_short(entry));
- }
- if(request == SRC_REQUEST_ARGUMENTS)
- {
- entry+=2; // Skip the offset
- entry+=strlen(entry)+1; // Skip the function name
- return entry; // Return a pointer to the arguments
- }
- if(request == SRC_REQUEST_FILESTART)
- {
- return data;
- }
- }
- return NULL;
- }
- //-----------------------------------------------------------------------------------------------
- void src_make_arrays(int token_count, char* filename)
- {
- // <ZZ> This function helps the RPN code figure out what a given token is. It breaks tokens
- // into operands, functions, and operators (filling in the corresponding flag arrays).
- int i;
- int j;
- int length;
- char* dotread;
- // Clear out the order of operation for Reverse Polish Notation
- line_is_a_conditional = FALSE;
- repeat(i, token_count)
- {
- token_priority[i] = 0;
- token_variable_type[i] = VAR_INVALID;
- token_change_type[i] = VAR_INVALID;
- token_arg_list[i] = NULL;
- token_is_string[i] = FALSE;
- }
- // Figure out the opcode for each token, and what type of token it is...
- repeat(i, token_count)
- {
- token_opcode[i] = OPCODE_CALLFUNCTION;
- token_extension[i] = -1;
- token_number_to_destroy[i] = 0;
- if(strcmp(token_buffer[i], "=") == 0) { token_opcode[i] = OPCODE_EQUALS; token_number_to_destroy[i] = 1; }
- if(strcmp(token_buffer[i], "+") == 0) { token_opcode[i] = OPCODE_ADD; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "-") == 0) { token_opcode[i] = OPCODE_SUBTRACT; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "*") == 0) { token_opcode[i] = OPCODE_MULTIPLY; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "/") == 0) { token_opcode[i] = OPCODE_DIVIDE; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "++") == 0) { token_opcode[i] = OPCODE_INCREMENT; token_number_to_destroy[i] = 1; }
- if(strcmp(token_buffer[i], "--") == 0) { token_opcode[i] = OPCODE_DECREMENT; token_number_to_destroy[i] = 1; }
- if(strcmp(token_buffer[i], "==") == 0) { token_opcode[i] = OPCODE_ISEQUAL; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "!=") == 0) { token_opcode[i] = OPCODE_ISNOTEQUAL; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], ">=") == 0) { token_opcode[i] = OPCODE_ISGREATEREQUAL; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "<=") == 0) { token_opcode[i] = OPCODE_ISLESSEREQUAL; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], ">") == 0) { token_opcode[i] = OPCODE_ISGREATER; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "<") == 0) { token_opcode[i] = OPCODE_ISLESSER; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "&&") == 0) { token_opcode[i] = OPCODE_LOGICALAND; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "||") == 0) { token_opcode[i] = OPCODE_LOGICALOR; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "!") == 0) { token_opcode[i] = OPCODE_LOGICALNOT; token_number_to_destroy[i] = 1; }
- if(strcmp(token_buffer[i], "&") == 0) { token_opcode[i] = OPCODE_BITWISEAND; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "|") == 0) { token_opcode[i] = OPCODE_BITWISEOR; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "<<") == 0) { token_opcode[i] = OPCODE_BITWISELEFT; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], ">>") == 0) { token_opcode[i] = OPCODE_BITWISERIGHT; token_number_to_destroy[i] = 2; }
- if(strcmp(token_buffer[i], "%") == 0) { token_opcode[i] = OPCODE_MODULUS; token_number_to_destroy[i] = 2; }
- // Subtract and Negate use the same symbol, '-', so see if it's a Negate...
- if(token_opcode[i] == OPCODE_SUBTRACT)
- {
- // Check the value to the left...
- if(i > 0)
- {
- if(token_is_operand[i-1] == FALSE && token_buffer[i-1][0] != ')')
- {
- // It's a negate...
- token_opcode[i] = OPCODE_NEGATE;
- token_number_to_destroy[i] = 1;
- }
- }
- }
- // We should now know if it's an operator or not...
- token_is_operator[i] = (token_opcode[i] != OPCODE_CALLFUNCTION);
- // Are we still looking?
- if(token_opcode[i] == OPCODE_CALLFUNCTION)
- {
- // Yup... Maybe it's an integer or a float...
- if(token_buffer[i][0] == 'I')
- {
- j = -1;
- if(token_buffer[i][1] >= '0' && token_buffer[i][1] <= '9')
- {
- j = token_buffer[i][1] - '0';
- if(token_buffer[i][2] >= '0' && token_buffer[i][2] <= '9')
- {
- j = j * 10;
- j += token_buffer[i][2] - '0';
- }
- if(token_buffer[i][2] == '.')
- {
- sscanf(token_buffer[i]+3, "%d", &token_extension[i]);
- }
- if(token_buffer[i][3] == '.' && token_buffer[i][2] != 0)
- {
- sscanf(token_buffer[i]+4, "%d", &token_extension[i]);
- }
- token_variable_type[i] = VAR_INT;
- }
- if(j >= 0 && j < MAX_VARIABLE) token_opcode[i] = 128 + j;
- if(token_extension[i] > -1)
- {
- // It's a property... Set the variable type correctly...
- token_opcode[i] += 32;
- if(property_type[token_extension[i]] == 'F')
- {
- token_variable_type[i] = VAR_FLOAT;
- }
- }
- token_number_to_destroy[i] = -1;
- }
- if(token_buffer[i][0] == 'F')
- {
- j = -1;
- if(token_buffer[i][1] >= '0' && token_buffer[i][1] <= '9')
- {
- j = token_buffer[i][1] - '0';
- if(token_buffer[i][2] >= '0' && token_buffer[i][2] <= '9')
- {
- j = j * 10;
- j += token_buffer[i][2] - '0';
- }
- token_variable_type[i] = VAR_FLOAT;
- }
- if(j >= 0 && j < MAX_VARIABLE) token_opcode[i] = 192 + j;
- token_number_to_destroy[i] = -1;
- }
- }
- // Are we still looking?
- if(token_opcode[i] == OPCODE_CALLFUNCTION)
- {
- // Yup... Maybe it's a numerical token...
- if((token_buffer[i][0] >= '0' && token_buffer[i][0] <= '9') || token_buffer[i][0] == '-')
- {
- // Does it have a dot?
- dotread = strpbrk(token_buffer[i], ".");
- if(dotread != NULL)
- {
- // Treat it as a numerical float
- sscanf(token_buffer[i], "%f", (float *) (&token_extension[i]));
- token_opcode[i] = 230;
- if(strcmp(token_buffer[i], "1.0") == 0) token_opcode[i] = 226;
- if(strcmp(token_buffer[i], "1.00") == 0) token_opcode[i] = 226;
- if(strcmp(token_buffer[i], "1.000") == 0) token_opcode[i] = 226;
- if(strcmp(token_buffer[i], "1.0000") == 0) token_opcode[i] = 226;
- token_variable_type[i] = VAR_FLOAT;
- }
- else
- {
- // Treat it as a numerical integer
- sscanf(token_buffer[i], "%d", &token_extension[i]);
- token_opcode[i] = 228;
- if(token_extension[i] >= -128 && token_extension[i] <= 127) token_opcode[i] = 227;
- if(token_extension[i] < -32768 || token_extension[i] > 32767) token_opcode[i] = 229;
- if(token_extension[i] == 0) token_opcode[i] = 224;
- if(token_extension[i] == 1) token_opcode[i] = 225;
- token_variable_type[i] = VAR_INT;
- }
- token_number_to_destroy[i] = -1;
- }
- }
- // Are we still looking?
- if(token_opcode[i] == OPCODE_CALLFUNCTION)
- {
- // Yup... Maybe it's a string... Treat as a 4 byte integer...
- if(token_buffer[i][0] == '"')
- {
- // Cut of the last " mark...
- length = strlen(token_buffer[i]+1);
- token_buffer[i][length] = 0;
- // Figure out the offset of the string in memory... 2 to skip address in header...
- token_extension[i] = src_find_string_entry(src_buffer, token_buffer[i]+1)+2;
- token_variable_type[i] = VAR_INT;
- // Need to go back through these during functionize...
- // ...But in order to do that, we need to remember where the opcode is...
- // ...But we don't know where it is yet, so we'll have to wait 'til later...
- token_is_string[i] = TRUE;
- token_opcode[i] = 229;
- // Put the " mark back on... Just in case there's something weird I forgot about...
- token_buffer[i][length] = '"';
- token_number_to_destroy[i] = -1;
- }
- }
- // We should now know if it's a function or not...
- token_is_function[i] = (token_opcode[i] == OPCODE_CALLFUNCTION);
- // We should now know if it's an operand or not...
- token_is_operand[i] = 1 - token_is_function[i] - token_is_operator[i];
- if(token_buffer[i][0] == ',' || token_buffer[i][0] == '(' || token_buffer[i][0] == ')')
- {
- token_is_operator[i] = FALSE;
- token_is_function[i] = FALSE;
- token_is_operand[i] = FALSE;
- token_variable_type[i] = VAR_INVALID;
- token_number_to_destroy[i] = 0;
- }
- // Are we still looking?
- if(token_is_function[i])
- {
- // Yup... Maybe it's a basic function...
- if(strcmp(token_buffer[i], "IF") == 0) { token_opcode[i] = OPCODE_IFFALSEJUMP; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; line_is_a_conditional = TRUE; }
- if(strcmp(token_buffer[i], "WHILE") == 0) { token_opcode[i] = OPCODE_IFFALSEJUMP; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; line_is_a_conditional = TRUE; }
- if(strcmp(token_buffer[i], "ELSE") == 0) { line_is_a_conditional = TRUE; }
- if(strcmp(token_buffer[i], "TOINT") == 0) { token_opcode[i] = OPCODE_TOINT; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_float; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "TOFLOAT") == 0) { token_opcode[i] = OPCODE_TOFLOAT; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_FLOAT; }
- if(strcmp(token_buffer[i], "LOCALMESSAGE")==0){token_opcode[i]= OPCODE_LOCALMESSAGE; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "NETWORKMESSAGE")==0){token_opcode[i]= OPCODE_NETWORKMESSAGE; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "LOGMESSAGE")==0){ token_opcode[i] = OPCODE_LOGMESSAGE; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "FINDSELF") == 0){ token_opcode[i] = OPCODE_FINDSELF; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "SYSTEMSET") ==0){ token_opcode[i] = OPCODE_SYSTEMSET; token_number_to_destroy[i] = 4; token_arg_list[i] = arg_list_iiii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "SYSTEMGET") ==0){ token_opcode[i] = OPCODE_SYSTEMGET; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "DEBUGMESSAGE")==0){token_opcode[i]= OPCODE_DEBUGMESSAGE; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "SQRT") == 0) { token_opcode[i] = OPCODE_SQRT; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_float; token_variable_type[i] = VAR_FLOAT; }
- if(strcmp(token_buffer[i], "FILEOPEN")==0) { token_opcode[i] = OPCODE_FILEOPEN; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "FILEREADBYTE")==0){token_opcode[i]= OPCODE_FILEREADBYTE; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "FILEWRITEBYTE")==0){token_opcode[i]=OPCODE_FILEWRITEBYTE;token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "FILEINSERT")==0){ token_opcode[i] = OPCODE_FILEINSERT; token_number_to_destroy[i] = 4; token_arg_list[i] = arg_list_iiii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "SPAWN") == 0) { token_opcode[i] = OPCODE_SPAWN; token_number_to_destroy[i] = 5; token_arg_list[i] = arg_list_ifffi; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "GOPOOF") == 0) { token_opcode[i] = OPCODE_GOPOOF; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; }
- if(strcmp(token_buffer[i], "DISMOUNT") == 0){ token_opcode[i] = OPCODE_DISMOUNT; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; }
- if(strcmp(token_buffer[i], "ROLLDICE") ==0) { token_opcode[i] = OPCODE_ROLLDICE; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "PLAYSOUND") ==0){ token_opcode[i] = OPCODE_PLAYSOUND; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "PLAYMEGASOUND")==0){token_opcode[i]=OPCODE_PLAYMEGASOUND;token_number_to_destroy[i] = 5; token_arg_list[i] = arg_list_iiiii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "DISTANCESOUND")==0){token_opcode[i]=OPCODE_DISTANCESOUND;token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "PLAYMUSIC") ==0){ token_opcode[i] = OPCODE_PLAYMUSIC; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "UPDATEFILES")==0){token_opcode[i] = OPCODE_UPDATEFILES; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int;}
- if(strcmp(token_buffer[i], "SIN")==0) { token_opcode[i] = OPCODE_SIN; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_float; token_variable_type[i] = VAR_FLOAT; }
- // String functions...
- if(strcmp(token_buffer[i], "STRING") == 0) { token_opcode[i] = OPCODE_STRING; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGGETNUMBER") == 0) { token_opcode[i] = OPCODE_STRINGGETNUMBER; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGCLEAR") == 0) { token_opcode[i] = OPCODE_STRINGCLEAR; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGCLEARALL") == 0) { token_opcode[i] = OPCODE_STRINGCLEARALL; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGAPPEND") == 0) { token_opcode[i] = OPCODE_STRINGAPPEND; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGCOMPARE") == 0) { token_opcode[i] = OPCODE_STRINGCOMPARE; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGLENGTH") == 0) { token_opcode[i] = OPCODE_STRINGLENGTH; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGCHOPLEFT") == 0) { token_opcode[i] = OPCODE_STRINGCHOPLEFT; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGCHOPRIGHT") == 0) { token_opcode[i] = OPCODE_STRINGCHOPRIGHT; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGGETVALUE") == 0) { token_opcode[i] = OPCODE_FILEREADBYTE; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; } // StringGetValue is the same as FileReadByte...
- if(strcmp(token_buffer[i], "STRINGSETVALUE") == 0) { token_opcode[i] = OPCODE_FILEWRITEBYTE; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; } // StringSetValue is the same as FileWriteByte...
- if(strcmp(token_buffer[i], "STRINGRANDOMNAME") == 0) { token_opcode[i] = OPCODE_STRINGRANDOMNAME; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGSANITIZE") == 0) { token_opcode[i] = OPCODE_STRINGSANITIZE; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGLANGUAGE") == 0) { token_opcode[i] = OPCODE_STRINGLANGUAGE; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGUPPERCASE") == 0) { token_opcode[i] = OPCODE_STRINGUPPERCASE; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "STRINGAPPENDNUMBER") == 0){ token_opcode[i] = OPCODE_STRINGAPPENDNUMBER; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; token_variable_type[i] = VAR_INT; }
- // Window functions
- if(strcmp(token_buffer[i], "WINDOWBORDER") == 0) { token_opcode[i] = OPCODE_WINDOWBORDER; token_number_to_destroy[i] = 6; token_arg_list[i] = arg_list_iffiii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWSTRING") == 0) { token_opcode[i] = OPCODE_WINDOWSTRING; token_number_to_destroy[i] = 4; token_arg_list[i] = arg_list_iffi; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWMINILIST") == 0) { token_opcode[i] = OPCODE_WINDOWMINILIST; token_number_to_destroy[i] = 6; token_arg_list[i] = arg_list_ffiiii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWSLIDER") == 0) { token_opcode[i] = OPCODE_WINDOWSLIDER; token_number_to_destroy[i] = 5; token_arg_list[i] = arg_list_ffiii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWIMAGE") == 0) { token_opcode[i] = OPCODE_WINDOWIMAGE; token_number_to_destroy[i] = 7; token_arg_list[i] = arg_list_ffffiii; token_variable_type[i] = VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWTRACKER") == 0) { token_opcode[i] = OPCODE_WINDOWTRACKER; token_number_to_destroy[i] = 10;token_arg_list[i] = arg_list_ffffiiiiii;token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWBOOK") == 0) { token_opcode[i] = OPCODE_WINDOWBOOK; token_number_to_destroy[i] = 7; token_arg_list[i] = arg_list_ffiiiii; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWINPUT") == 0) { token_opcode[i] = OPCODE_WINDOWINPUT; token_number_to_destroy[i] = 5; token_arg_list[i] = arg_list_ffiii; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWEMACS") == 0) { token_opcode[i] = OPCODE_WINDOWEMACS; token_number_to_destroy[i] = 6; token_arg_list[i] = arg_list_ffiiii; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWMEGAIMAGE") == 0) { token_opcode[i] = OPCODE_WINDOWMEGAIMAGE; token_number_to_destroy[i] = 15;token_arg_list[i] = arg_list_ffffffffffffiii; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOW3DSTART") == 0) { token_opcode[i] = OPCODE_WINDOW3DSTART; token_number_to_destroy[i] = 5; token_arg_list[i] = arg_list_ffffi; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOW3DEND") == 0) { token_opcode[i] = OPCODE_WINDOW3DEND; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOW3DPOSITION") == 0) { token_opcode[i] = OPCODE_WINDOW3DPOSITION; token_number_to_destroy[i] = 4; token_arg_list[i] = arg_list_fffi; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOW3DMODEL") == 0) { token_opcode[i] = OPCODE_WINDOW3DMODEL; token_number_to_destroy[i] = 4; token_arg_list[i] = arg_list_iiii; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "MODELASSIGN") == 0) { token_opcode[i] = OPCODE_MODELASSIGN; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; }
- if(strcmp(token_buffer[i], "PARTICLEBOUNCE") == 0) { token_opcode[i] = OPCODE_PARTICLEBOUNCE; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "WINDOWEDITKANJI") == 0) { token_opcode[i] = OPCODE_WINDOWEDITKANJI; token_number_to_destroy[i] = 5; token_arg_list[i] = arg_list_ifffi; }
- if(strcmp(token_buffer[i], "WINDOW3DROOM") == 0) { token_opcode[i] = OPCODE_WINDOW3DROOM; token_number_to_destroy[i] = 7; token_arg_list[i] = arg_list_fffiiii; }
- // Other functions...
- if(strcmp(token_buffer[i], "INDEXISLOCALPLAYER") == 0) { token_opcode[i] = OPCODE_INDEXISLOCALPLAYER;token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDBINDING") == 0) { token_opcode[i] = OPCODE_FINDBINDING; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDTARGET") == 0) { token_opcode[i] = OPCODE_FINDTARGET; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDOWNER") == 0) { token_opcode[i] = OPCODE_FINDOWNER; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDINDEX") == 0) { token_opcode[i] = OPCODE_FINDINDEX; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDBYINDEX") == 0) { token_opcode[i] = OPCODE_FINDBYINDEX; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDWINDOW") == 0) { token_opcode[i] = OPCODE_FINDWINDOW; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_int_int; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDPARTICLE") == 0) { token_opcode[i] = OPCODE_FINDPARTICLE; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "ATTACHTOTARGET") == 0) { token_opcode[i] = OPCODE_ATTACHTOTARGET; token_number_to_destroy[i] = 1; token_arg_list[i] = arg_list_int; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "GETDIRECTION") == 0) { token_opcode[i] = OPCODE_GETDIRECTION; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_float_float; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "DAMAGETARGET") == 0) { token_opcode[i] = OPCODE_DAMAGETARGET; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; }
- if(strcmp(token_buffer[i], "EXPERIENCEFUNCTION") == 0) { token_opcode[i] = OPCODE_EXPERIENCEFUNCTION;token_number_to_destroy[i] = 4; token_arg_list[i] = arg_list_iiii; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "ACQUIRETARGET") == 0) { token_opcode[i] = OPCODE_ACQUIRETARGET; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iif; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "FINDPATH") == 0) { token_opcode[i] = OPCODE_FINDPATH; token_number_to_destroy[i] = 0; token_arg_list[i] = arg_list_none; token_variable_type[i]= VAR_INT; }
- if(strcmp(token_buffer[i], "BUTTONPRESS") == 0) { token_opcode[i] = OPCODE_BUTTONPRESS; token_number_to_destroy[i] = 3; token_arg_list[i] = arg_list_iii; }
- if(strcmp(token_buffer[i], "AUTOAIM") == 0) { token_opcode[i] = OPCODE_AUTOAIM; token_number_to_destroy[i] = 7; token_arg_list[i] = arg_list_ffiiiii; token_variable_type[i]= VAR_FLOAT; }
- if(strcmp(token_buffer[i], "ROOMHEIGHTXY") == 0) { token_opcode[i] = OPCODE_ROOMHEIGHTXY; token_number_to_destroy[i] = 2; token_arg_list[i] = arg_list_float_float; token_variable_type[i]= VAR_FLOAT; }
- // Return function...
- if(strcmp(token_buffer[i], "RETURN") == 0)
- {
- token_number_to_destroy[i] = 1;
- if(last_function_returns_integer) { token_opcode[i] = OPCODE_RETURNINT; token_arg_list[i] = arg_list_int; }
- else { token_opcode[i] = OPCODE_RETURNFLOAT; token_arg_list[i] = arg_list_float; }
- }
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!! More basic functions
- // !!!BAD!!!
- // !!!BAD!!!
- }
- // Or it might be a user function...
- if(token_is_function[i] && token_opcode[i] == OPCODE_CALLFUNCTION)
- {
- // Ignore else...
- if(strcmp(token_buffer[i], "ELSE") != 0)
- {
- // Search for the function, so we can figure out what arguments it requires...
- token_arg_list[i] = src_mega_find_function(token_buffer[i], filename, SRC_REQUEST_ARGUMENTS);
- if(token_arg_list[i])
- {
- token_variable_type[i] = token_arg_list[i][0];
- token_arg_list[i]++; // Skip the return code
- token_number_to_destroy[i] = strlen(token_arg_list[i]);
- }
- else
- {
- // Function not found...
- log_message("ERROR: Line %d, Unrecognized symbol %s found", sdf_read_line_number, token_buffer[i]);
- found_error = TRUE;
- }
- }
- }
- }
- }
- //-----------------------------------------------------------------------------------------------
- signed char src_functionize(unsigned char* index, char* filename)
- {
- // <ZZ> This function fills in the CallFunction addresses for a single file. If it finds
- // an error, the file is deleted... This is the last stage of SRC compilation, sorta
- // like a linker stage... Returns FALSE if it had trouble, TRUE if not.
- unsigned char* datastart;
- unsigned char* data;
- unsigned char* lastdata;
- unsigned char* calladdress;
- unsigned char* addresslocation;
- unsigned short number_of_functions;
- unsigned short number_of_strings;
- unsigned char opcode;
- unsigned short offset;
- unsigned int file_index;
- int i, j;
- unsigned char newfilename[9], newfiletype;
- // Log what we're doing
- #ifdef DEVTOOL
- log_message("INFO: Functionizing %s.RUN", filename);
- #endif
- found_error = FALSE;
- // Figure out where our data is, and where it stops
- data = (unsigned char*) sdf_read_unsigned_int(index);
- lastdata = data + (sdf_read_unsigned_int(index+4) & 0x00FFFFFF);
- datastart = data;
- // Skip over the header data for this RUN file...
- data+=MAX_FAST_FUNCTION<<1; // Skip the fast function lookups...
- number_of_functions = sdf_read_unsigned_short(data);
- data+=2;
- number_of_strings = sdf_read_unsigned_short(data);
- data+=2;
- repeat(i, number_of_functions)
- {
- // Check the name to see if it's one of the fast functions...
- j = -1;
- if(strcmp(data+2, "SPAWN") == 0) j = FAST_FUNCTION_SPAWN;
- else if(strcmp(data+2, "REFRESH") == 0) j = FAST_FUNCTION_REFRESH;
- else if(strcmp(data+2, "EVENT") == 0) j = FAST_FUNCTION_EVENT;
- else if(strcmp(data+2, "AISCRIPT") == 0) j = FAST_FUNCTION_AISCRIPT;
- else if(strcmp(data+2, "BUTTONEVENT") == 0) j = FAST_FUNCTION_BUTTONEVENT;
- else if(strcmp(data+2, "GETNAME") == 0) j = FAST_FUNCTION_GETNAME;
- else if(strcmp(data+2, "UNPRESSED") == 0) j = FAST_FUNCTION_UNPRESSED;
- else if(strcmp(data+2, "FRAMEEVENT") == 0) j = FAST_FUNCTION_FRAMEEVENT;
- else if(strcmp(data+2, "MODELSETUP") == 0) j = FAST_FUNCTION_MODELSETUP;
- else if(strcmp(data+2, "DEFENSERATING") == 0) j = FAST_FUNCTION_DEFENSERATING;
- else if(strcmp(data+2, "SETUP") == 0) j = FAST_FUNCTION_SETUP;
- else if(strcmp(data+2, "DIRECTUSAGE") == 0) j = FAST_FUNCTION_DIRECTUSAGE;
- else if(strcmp(data+2, "ENCHANTUSAGE") == 0) j = FAST_FUNCTION_ENCHANTUSAGE;
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!! More fast functions go here...
- // !!!BAD!!!
- // !!!BAD!!!
- // !!!BAD!!!
- if(j != -1)
- {
- // It is a fast function, so fill in the look up table with it's entry point...
- *(datastart+j) = *(data);
- *(datastart+j+1) = *(data+1);
- }
- // Go to the next entry
- data+=2; // Skip the address
- data+=strlen(data)+1; // Skip the name and 0
- data+=strlen(data)+1; // Skip the return and any arguments and 0
- }
- repeat(i, number_of_strings)
- {
- // Check each string...
- offset = sdf_read_unsigned_short(data);
- if(data[2] == 'F' && data[3] == 'I' && data[4] == 'L' && data[5] == 'E' && data[6] == ':')
- {
- // It's a weird "FILE:BLAH.BLA" type of string
- file_index = (unsigned int) sdf_find_index(data+2+5);
- if(file_index)
- {
- file_index = sdf_read_unsigned_int((unsigned char*) file_index);
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Found file %s at 0x%x", data+2+5, file_index);
- #endif
- sdf_write_unsigned_int(datastart+offset, file_index);
- }
- else
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: File %s couldn't be found", data+2+5);
- #endif
- if(sdf_fix_filename(data+2+5, newfilename, &newfiletype))
- {
- if(newfiletype == SDF_FILE_IS_RUN)
- {
- // Probably in a spawn, so we don't need to kill the file...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Writing a NULL value for RUN file");
- #endif
- sdf_write_unsigned_int(datastart+offset, 0);
- }
- else
- {
- log_message("ERROR: File %s couldn't be found", data+2+5);
- found_error = TRUE;
- }
- }
- else
- {
- log_message("ERROR: File %s couldn't be found", data+2+5);
- found_error = TRUE;
- }
- }
- }
- else
- {
- // It's a normal "BLAH BLAH BLAH" type of string
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Found string %s at 0x%x", data+2, (data+2));
- #endif
- sdf_write_unsigned_int(datastart+offset, (unsigned int) (data+2));
- }
- // Go to the next entry
- data+=2; // Skip the address
- data+=strlen(data)+1; // Skip the name and 0
- }
- // Now we're at the start of the opcodes... Go through every opcode, looking for
- // OPCODE_CALLFUNCTION, and stick in the correct address...
- while(data < lastdata && found_error == FALSE)
- {
- // Read the opcode
- opcode = *data;
- #ifdef VERBOSE_COMPILE
- log_message("INFO: FUNC-OP: 0x%02x at 0x%04x", opcode, data-datastart);
- #endif
- data++;
- if(opcode == OPCODE_CALLFUNCTION)
- {
- // Make sure there's still data left to read, before reading the extension...
- if(data < lastdata-19)
- {
- // Check for errors in the extension...
- addresslocation = data;
- // Spit out debug info...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Function %s at 0x%04x", data+16, data-datastart+16);
- log_message("INFO: Address at: 0x%04x", data-datastart);
- log_message("INFO: Return at: 0x%04x", data-datastart+4);
- log_message("INFO: Arguments at: 0x%04x", data-datastart+8);
- log_message("INFO: File Start at: 0x%04x", data-datastart+12);
- #endif
- // Skip the call address, return address, argument address, and filestart address...
- // Data should now be at the function name
- data+=16;
- // Fill in the call address...
- calladdress = src_mega_find_function(data, filename, SRC_REQUEST_OFFSET);
- sdf_write_unsigned_int(addresslocation, (unsigned int) calladdress);
- // Error check...
- if(calladdress == NULL)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Couldn't find function %s", data);
- #endif
- // Don't destroy file, because a null address should just be ignored...
- }
- // Fill in the argument address... +1 to ignore return value...
- calladdress = src_mega_find_function(data, filename, SRC_REQUEST_ARGUMENTS)+1;
- sdf_write_unsigned_int(addresslocation+8, (unsigned int) calladdress);
- // Fill in the filestart address...
- calladdress = src_mega_find_function(data, filename, SRC_REQUEST_FILESTART);
- sdf_write_unsigned_int(addresslocation+12, (unsigned int) calladdress);
- // Skip the function name and the trailing zero
- data+=strlen(data)+1;
- // Fill in the return address...
- sdf_write_unsigned_int(addresslocation+4, (unsigned int) data);
- }
- else
- {
- log_message("ERROR: Ran out of data while parsing %s.RUN", filename);
- found_error = TRUE;
- }
- }
- else
- {
- // Skip over the extensions of the boring non-function opcodes...
- if(opcode == OPCODE_JUMP || opcode == OPCODE_IFFALSEJUMP) data+=2;
- if((opcode & 224) == 160) data+=1; // integer.property...
- if((opcode & 224) == 224)
- {
- // Extended information...
- if(opcode == 227) data++; // 1 byte integer
- if(opcode == 228) data+=2; // 2 byte integer
- if(opcode == 229) data+=4; // 4 byte integer
- if(opcode == 230) data+=4; // 4 byte float
- }
- }
- i++;
- }
- // Delete the RUN file if there are any linking errors...
- if(found_error)
- {
- log_message("FOUND: Found error functionizing %s.RUN", filename);
- free(datastart);
- *(index+4) = SDF_FILE_IS_UNUSED;
- return FALSE;
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------------------------
- #ifdef DEVTOOL
- signed char src_compilerize(unsigned char* index, unsigned char* filename)
- {
- // <ZZ> This function compiles an SRC file that has been stored in memory. Index is a
- // pointer to the start of the file's index in sdf_index, and can be gotten from
- // sdf_find_index. If the function works okay, it should create a new RUN file in the
- // index and return TRUE. It might also delete the original file to save space, but
- // that's a compile time option. If it fails it should return FALSE.
- unsigned char* data; // Original, Headerized data
- unsigned char* newdata; // Compiled data
- unsigned int newsize; // Compiled data
- char tempstring[16];
- signed char keepgoing;
- signed char stillgoing;
- unsigned char indent;
- unsigned char last_indent;
- int i;
- int j;
- int token_count;
- signed char tempnext;
- unsigned char* tempptr;
- unsigned char* oldindex;
- int tempint;
- int tempnum;
- int define;
- unsigned short number_of_functions;
- int function_offset;
- int num_int_variables = 0;
- int num_float_variables = 0;
- char operation_line;
- // Don't create the RUN file if we find any errors...
- found_error = FALSE;
- // Log what we're doing
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Decoding %s.SRC to %s.RUN", filename, filename);
- #endif
- // Undefine any variables and defines used by the last file
- src_undefine_level(SRC_TEMPORARY_FILE);
- // Clear out our jump data...
- repeat(i, SRC_MAX_INDENT)
- {
- last_jump_type_found[i] = SRC_JUMP_INVALID;
- }
- last_indent = 0;
- last_function_returns_integer = TRUE;
- // Remember what variables have been set (for generating errors)
- repeat(i, MAX_VARIABLE)
- {
- float_variable_set[i] = FALSE;
- int_variable_set[i] = FALSE;
- }
- // Copy all of the data from the header (that we already compiled)...
- oldindex = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
- if(oldindex != NULL)
- {
- data = (unsigned char*) sdf_read_unsigned_int(oldindex);
- src_buffer_used = (unsigned short) (sdf_read_unsigned_int(oldindex+4) & 0x00FFFFFF);
- memcpy(src_buffer, data, src_buffer_used);
- }
- else
- {
- // Can't proceed without a header...
- log_message("ERROR: Header file for %s.SRC wasn't generated, can't compile");
- return FALSE;
- }
- // Just like sdf_open...
- sdf_read_first_line = FALSE;
- sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
- sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
- sdf_read_line_number = 0;
- next_token_may_be_negative = TRUE;
- // Make a list of all the functions in this file... Figure out offsets in another pass...
- 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_TEMPORARY_FILE);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- // Just like sdf_open...
- sdf_read_first_line = FALSE;
- sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
- sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
- sdf_read_line_number = 0;
- // For each line in the file...
- number_of_functions = 0;
- 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;
- next_token_may_be_negative = TRUE;
- if(sdf_read_file[0] != '#')
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Line %d, %s", sdf_read_line_number, sdf_read_file);
- #endif
- // Get all of the tokens in the line...
- token_count = 0;
- keepgoing = TRUE;
- while(keepgoing)
- {
- keepgoing = FALSE;
- if(token_count < SRC_MAX_TOKEN)
- {
- if(src_read_token(token_buffer[token_count]))
- {
- // Undefine any variables used by the last function
- if(indent == 0 && token_count == 0)
- {
- src_undefine_level(SRC_TEMPORARY_FUNCTION);
- num_int_variables = 0;
- num_float_variables = 0;
- // Remember what variables have been set (for generating errors)
- repeat(i, MAX_VARIABLE)
- {
- float_variable_set[i] = FALSE;
- int_variable_set[i] = FALSE;
- }
- }
- // See if the token is defined
- define = src_get_define(token_buffer[token_count]);
- if(define > -1)
- {
- // Save the read line stuff...
- tempint = sdf_read_remaining;
- tempptr = sdf_read_file;
- tempnum = sdf_read_line_number;
- tempnext = next_token_may_be_negative;
- // Read in all of the tokens in the #define...
- next_token_may_be_negative = TRUE;
- sdf_read_remaining = SRC_MAX_TOKEN_SIZE;
- sdf_read_file = define_value[define];
- stillgoing = TRUE;
- while(stillgoing)
- {
- stillgoing = FALSE;
- if(token_count < SRC_MAX_TOKEN)
- {
- if(src_read_token(token_buffer[token_count]))
- {
- token_count++;
- stillgoing = TRUE;
- }
- }
- }
- token_count--;
- // Restore the read line stuff...
- next_token_may_be_negative = tempnext;
- sdf_read_line_number = tempnum;
- sdf_read_file = tempptr;
- sdf_read_remaining = tempint;
- }
- // See if the token has a dot style property
- tempptr = strpbrk(token_buffer[token_count], ".");
- if(((token_buffer[token_count][0] >= 'A' && token_buffer[token_count][0] <= 'Z') || token_buffer[token_count][0] == '_') && tempptr)
- {
- // Looks like it is... Need to break it into two parts...
- // First find the property extension...
- *tempptr = 0;
- tempint = obj_get_property(tempptr+1);
- define = src_get_define(token_buffer[token_count]);
- if(tempint > -1 && define > -1)
- {
- // Okay, we found the property and variable... Now reguritate 'em
- // If we didn't find anything, it may be an external function...
- sprintf(token_buffer[token_count], "%s.%d", define_value[define], tempint);
- }
- else
- {
- // Must be an external function call... Replace the period we removed...
- *tempptr = '.';
- }
- }
- token_count++;
- keepgoing = TRUE;
- }
- }
- }
- // Did we actually read anything on this line?
- if(token_count > 0)
- {
- // Show me all of the tokens...
- #ifdef VERBOSE_COMPILE
- repeat(i, token_count)
- {
- log_message("INFO: Token == %s", token_buffer[i]);
- }
- log_message("INFO: ");
- #endif
- // Check for errors with if and else and while with nothing after...
- if(line_is_a_conditional == TRUE && indent <= last_indent)
- {
- log_message("ERROR: Line %d, Conditional without a nest", sdf_read_line_number);
- found_error = TRUE;
- }
- // Is this line the start of a function?
- operation_line = TRUE;
- if(indent == 0)
- {
- // It is... Let's write down the offset so we can find it again later...
- operation_line = FALSE;
- if(last_indent > 0)
- {
- // Close out all jumps...
- src_close_jumps(indent, last_indent);
- // Slap in a return 1, just to be on the safe side...
- src_add_return_opcode();
- last_indent = 0;
- }
- // Skip over the return value...
- i = 0;
- last_function_returns_integer = TRUE;
- if(strcmp(token_buffer[0], "INT") == 0) i++;
- if(strcmp(token_buffer[0], "FLOAT") == 0) { last_function_returns_integer = FALSE; i++; }
- // Find the function in the RUN header...
- function_offset = src_find_function_entry(src_buffer, token_buffer[i]);
- if(function_offset)
- {
- // Then write down the offset...
- sdf_write_unsigned_short(src_buffer+function_offset, src_buffer_used);
- number_of_functions++;
- i++;
- // Now define any arguments... #define value i0
- i++; // Skip the parentheses
- while(i < token_count)
- {
- if(strcmp(token_buffer[i], "INT") == 0 && num_int_variables < MAX_VARIABLE)
- {
- i++;
- if(i < token_count)
- {
- sprintf(tempstring, "I%d", num_int_variables);
- src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
- int_variable_set[num_int_variables] = TRUE;
- num_int_variables++;
- }
- }
- else if(strcmp(token_buffer[i], "FLOAT") == 0 && num_float_variables < MAX_VARIABLE)
- {
- i++;
- if(i < token_count)
- {
- sprintf(tempstring, "F%d", num_float_variables);
- src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
- float_variable_set[num_float_variables] = TRUE;
- num_float_variables++;
- }
- }
- i++;
- }
- }
- else
- {
- log_message("ERROR: Line %d, Problem with function %s (corrupt header?)", sdf_read_line_number, token_buffer[i]);
- found_error = TRUE;
- }
- }
- // Check for local int and float declarations... Use temporary defines... I0-I31, F0-F31
- if(indent == 1)
- {
- if(strcmp(token_buffer[0], "INT") == 0)
- {
- operation_line = FALSE;
- i = 1;
- while(i < token_count)
- {
- if(token_buffer[i][0] != ',' && num_int_variables < MAX_VARIABLE)
- {
- sprintf(tempstring, "I%d", num_int_variables);
- src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
- num_int_variables++;
- }
- i++;
- }
- #ifdef VERBOSE_COMPILE
- log_message("INFO: ");
- #endif
- }
- else if(strcmp(token_buffer[0], "FLOAT") == 0)
- {
- operation_line = FALSE;
- i = 1;
- while(i < token_count)
- {
- if(token_buffer[i][0] != ',' && num_float_variables < MAX_VARIABLE)
- {
- sprintf(tempstring, "F%d", num_float_variables);
- src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
- num_float_variables++;
- }
- i++;
- }
- #ifdef VERBOSE_COMPILE
- log_message("INFO: ");
- #endif
- }
- }
- if(operation_line)
- {
- // Must have a conditional to change indentation levels...
- if(indent > last_indent && last_indent != 0)
- {
- if(last_jump_type_found[last_indent] == SRC_JUMP_INVALID)
- {
- // Throw an error
- log_message("ERROR: Line %d, Must have a conditional statement to indent", sdf_read_line_number);
- found_error = TRUE;
- }
- }
- // Going down an indentation level allows us to fill in jump locations...
- src_close_jumps(indent, last_indent);
- // Remember where while's start, because we need to jump back to 'em...
- if(strcmp(token_buffer[0], "WHILE") == 0)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: WHILE BEGINS HERE 0x%x", src_buffer_used);
- #endif
- while_jumps_back_to_here[indent] = src_buffer_used;
- }
- // // Going down an indentation level allows us to fill in jump locations...
- // src_close_jumps(indent, last_indent);
- // Moved this up a couple lines because two whiles in a row would break it...
- // Fixed that problem, but something else mighta broken in the process...
- // Remember indentation level for next time
- last_indent = indent;
- // Clear out the RPN data and fill in some of the helper arrays...
- src_make_arrays(token_count, filename);
- // Figure out the RPN order...
- token_order = 1;
- src_find_priority(0, token_count-1, FALSE, TRUE);
- // Debug stuff
- #ifdef VERBOSE_COMPILE
- repeat(i, token_order-1)
- {
- j = token_priority_list[i];
- log_message("INFO: RPN: %s", token_buffer[j]);
- }
- log_message("INFO: ");
- #endif
- // Figure out type casting based on RPN data...
- src_figure_variable_types(token_order-1);
- // Write out the opcode data...
- src_generate_opcodes(token_order-1);
- // Figure out where to write jump locations and stuff for indentation levels
- if(found_error == FALSE)
- {
- if(strcmp(token_buffer[0], "IF") == 0)
- {
- // Make sure there's an if opcode where it should be...
- if(src_buffer_used >= 5)
- {
- if(src_buffer[src_buffer_used-3] == OPCODE_IFFALSEJUMP)
- {
- put_jump_offset_here[indent] = src_buffer_used-2;
- last_jump_type_found[indent] = SRC_JUMP_IF;
- #ifdef VERBOSE_COMPILE
- log_message("INFO: STARTED A NEW IF STATEMENT");
- #endif
- }
- else
- {
- log_message("ERROR: Line %d, Praxis syllabication error", sdf_read_line_number);
- found_error = TRUE;
- }
- }
- else found_error = TRUE;
- }
- if(strcmp(token_buffer[0], "WHILE") == 0)
- {
- // Make sure there's an if opcode where it should be...
- if(src_buffer_used >= 5)
- {
- if(src_buffer[src_buffer_used-3] == OPCODE_IFFALSEJUMP)
- {
- put_jump_offset_here[indent] = src_buffer_used-2;
- last_jump_type_found[indent] = SRC_JUMP_WHILE;
- #ifdef VERBOSE_COMPILE
- log_message("INFO: STARTED A NEW WHILE STATEMENT");
- #endif
- }
- else
- {
- log_message("ERROR: Line %d, Praxis syllabication error", sdf_read_line_number);
- found_error = TRUE;
- }
- }
- else found_error = TRUE;
- }
- }
- }
- }
- }
- }
- // Clean up any unresolved jumps...
- src_close_jumps(indent, last_indent);
- // Slap in a return 1, just to be on the safe side...
- src_add_return_opcode();
- if(found_error == FALSE)
- {
- //Allocate memory for the new file...
- newsize = src_buffer_used;
- newdata = malloc(newsize);
- if(newdata)
- {
- // Write the index... Should overwrite headerized RUN file...
- sdf_write_unsigned_int(oldindex, (unsigned int) newdata);
- sdf_write_unsigned_int(oldindex+4, newsize);
- *(oldindex+4) = SDF_FILE_IS_RUN;
- repeat(j, 8) { *(oldindex+8+j) = 0; }
- memcpy(oldindex+8, filename, strlen(filename));
- // Copy the data out of the buffer, and free up the old data...
- memcpy(newdata, src_buffer, newsize);
- free(data);
- return TRUE;
- }
- else
- {
- log_message("ERROR: Out of memory while compilerizing %s.SRC", filename);
- }
- }
- else
- {
- log_message("FOUND: Found error compilerizing %s.SRC", filename);
- }
- // Delete the headerized file, since we had trouble...
- free(data);
- *(oldindex+4) = SDF_FILE_IS_UNUSED;
- return FALSE;
- }
- #endif
- //-----------------------------------------------------------------------------------------------
- #ifdef DEVTOOL
- signed char src_headerize(unsigned char* index, unsigned char* filename)
- {
- // <ZZ> This function runs through an SRC file that has been stored in memory and finds
- // function information to store in the header. This must be done for every file
- // before compilation can occur. Index is a pointer to the start of the file's
- // index in sdf_index, and can be gotten from sdf_find_index. If the function
- // works okay, it should create a new RUN file in the index and return TRUE. If
- // it fails it should return FALSE.
- unsigned char* data; // Original, pre-existing RUN file
- unsigned char* newdata; // New header
- unsigned int newsize; // New header
- signed char keepgoing;
- unsigned char indent;
- unsigned short number_of_functions;
- unsigned short number_of_strings;
- int i;
- int j;
- int length;
- int token_count;
- char returncode;
- char make_new_file;
- char read_char;
- int def;
- // Don't create the RUN file if we find any errors...
- found_error = FALSE;
- // Log what we're doing
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Generating header file for %s.SRC", filename);
- #endif
- // Undefine any variables and defines used by the last file
- src_undefine_level(SRC_TEMPORARY_FILE);
- // Just like sdf_open...
- sdf_read_first_line = FALSE;
- sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
- sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
- sdf_read_line_number = 0;
- next_token_may_be_negative = TRUE;
- // Pad the start of the header with fast function offsets...
- src_buffer_used = 0;
- repeat(i, MAX_FAST_FUNCTION)
- {
- // 2 bytes each...
- src_buffer[src_buffer_used] = 0;
- src_buffer_used++;
- src_buffer[src_buffer_used] = 0;
- src_buffer_used++;
- }
- // Something like this in the src_buffer...
- // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- // Make a list of all the functions in this file... Figure out offsets in another pass...
- src_buffer_used+=4; // Skip a word for the string count... Filled in after counting...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Headerizing functions...");
- #endif
- number_of_functions = 0;
- 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;
- // Skip #defines, we're only interested in functions...
- if(sdf_read_file[0] != '#' && indent == 0)
- {
- // Read all of the tokens on this line...
- token_count = 0;
- keepgoing = TRUE;
- while(keepgoing)
- {
- keepgoing = FALSE;
- if(token_count < SRC_MAX_TOKEN)
- {
- if(src_read_token(token_buffer[token_count]))
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Line %d, %s", sdf_read_line_number, token_buffer[token_count]);
- #endif
- token_count++;
- keepgoing = TRUE;
- }
- }
- }
- // Did we read anything?
- if(token_count > 0)
- {
- // Get the return type for the function...
- i = 0;
- returncode = 'I';
- if(strcmp(token_buffer[0], "INT") == 0) { returncode = 'I'; i++; }
- if(strcmp(token_buffer[0], "FLOAT") == 0) { returncode = 'F'; i++; }
- // Make sure the function has parentheses after it
- if(token_buffer[i+1][0] == '(')
- {
- // Now stick the function address and name in our RUN file...
- sprintf((src_buffer+src_buffer_used), "%c%c%s%c", 0, 0, token_buffer[i], 0);
- src_buffer_used += strlen(token_buffer[i]) + 3;
- #ifdef VERBOSE_COMPILE
- log_message("INFO: function... %s()", token_buffer[i]);
- #endif
- // Now store the return code type...
- sprintf((src_buffer+src_buffer_used), "%c", returncode);
- src_buffer_used++;
- // Now store any arguments types...
- i = i+2;
- while(i < token_count)
- {
- if(strcmp(token_buffer[i], "INT") == 0)
- {
- sprintf((src_buffer+src_buffer_used), "I");
- src_buffer_used++;
- }
- else if(strcmp(token_buffer[i], "FLOAT") == 0)
- {
- sprintf((src_buffer+src_buffer_used), "F");
- src_buffer_used++;
- }
- i++;
- }
- // And zero terminate the string...
- sprintf((src_buffer+src_buffer_used), "%c", 0);
- src_buffer_used++;
- number_of_functions++;
- }
- else
- {
- log_message("ERROR: Line %d, function symbol '%s' not followed by ()", sdf_read_line_number, token_buffer[i]);
- found_error = TRUE;
- }
- }
- }
- }
- sdf_write_unsigned_short(src_buffer+(MAX_FAST_FUNCTION<<1), number_of_functions);
- // Something like this in the src_buffer...
- // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- // 00 03 00 00
- // 0 0 D E A T H 00 I F F F I 00
- // 0 0 B L A H 00 V 00
- // 0 0 A T T A C K 00 V I 00
- // Address FunctionName ReturnAndArgumentTypes
- // Check for errors too...
- if(number_of_functions == 0)
- {
- log_message("ERROR: No functions found");
- found_error = TRUE;
- }
- // Now search for any #defines... Just in case someone #define'd a string...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Headerizing #define's...");
- #endif
- sdf_read_first_line = FALSE;
- sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
- sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
- sdf_read_line_number = 0;
- next_token_may_be_negative = TRUE;
- // Make a list of all the functions in this file... Figure out offsets in another pass...
- 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_TEMPORARY_FILE);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- // Now search for strings to append to the header... Just like above...
- sdf_read_first_line = FALSE;
- sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
- sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
- sdf_read_line_number = 0;
- next_token_may_be_negative = TRUE;
- // Make a list of all the functions in this file... Figure out offsets in another pass...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Headerizing strings...");
- #endif
- number_of_strings = 0;
- 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;
- // Skip #defines, we're only interested in strings...
- if(sdf_read_file[0] != '#' && indent != 0)
- {
- // Read all of the tokens on this line...
- token_count = 0;
- keepgoing = TRUE;
- while(keepgoing)
- {
- keepgoing = FALSE;
- if(token_count < SRC_MAX_TOKEN)
- {
- if(src_read_token(token_buffer[token_count]))
- {
- token_count++;
- keepgoing = TRUE;
- }
- }
- }
- // Look through all of the tokens for a string token...
- repeat(i, token_count)
- {
- // Look for string tokens...
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Token %s", token_buffer[i]);
- #endif
- if(token_buffer[i][0] == '"')
- {
- // Found a string, so put it in the header
- sdf_write_unsigned_short(src_buffer+src_buffer_used, 65535);
- src_buffer_used+=2;
- length = strlen(token_buffer[i]+1)-1;
- repeat(j, length)
- {
- *(src_buffer+src_buffer_used) = token_buffer[i][j+1];
- src_buffer_used++;
- }
- *(src_buffer+src_buffer_used) = 0;
- src_buffer_used++;
- number_of_strings++;
- }
- else
- {
- // Check for #define'd strings...
- def = src_get_define(token_buffer[i]);
- if(def >= 0)
- {
- #ifdef VERBOSE_COMPILE
- log_message("INFO: Sneaky define... %s", define_token[def]);
- #endif
- // It was a sneaky #define... Search for " characters...
- read_char = define_value[def][0];
- j = 0;
- while(read_char != 0)
- {
- if(read_char == '"')
- {
- // Start of a string, so write it into the header...
- sdf_write_unsigned_short(src_buffer+src_buffer_used, 65535);
- src_buffer_used+=2;
- j++;
- read_char = define_value[def][j];
- while(read_char != 0 && read_char != '"')
- {
- *(src_buffer+src_buffer_used) = read_char;
- src_buffer_used++;
- j++;
- read_char = define_value[def][j];
- }
- *(src_buffer+src_buffer_used) = 0;
- src_buffer_used++;
- number_of_strings++;
- if(read_char == 0) j--;
- }
- j++;
- read_char = define_value[def][j];
- }
- }
- }
- }
- }
- }
- sdf_write_unsigned_short(src_buffer+(MAX_FAST_FUNCTION<<1)+2, number_of_strings);
- // Something like this in the src_buffer...
- // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- // 00 03 00 02
- // 0 0 D E A T H 00 I F F F I 00
- // 0 0 B L A H 00 V 00
- // 0 0 A T T A C K 00 V I 00
- // 0 0 B i g B o b i s c o o l 00
- // FF FF T e s t s t r i n g 00
- // FF FF F I L E : T E S T . T X T 00
- // String address String
- // Now copy the header data into a (temporary) RUN file
- if(found_error == FALSE)
- {
- // Do we need to make a new file, or is there an existing RUN file?
- index = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
- if(index != NULL)
- {
- data = (unsigned char*) sdf_read_unsigned_int(index);
- make_new_file = FALSE;
- }
- else
- {
- make_new_file = TRUE;
- // Make sure we have room in the index for a new file
- if(sdf_extra_files <= 0)
- {
- log_message("ERROR: No room left to add file, program must be restarted");
- return FALSE;
- }
- }
- // Allocate memory for the new file...
- newsize = src_buffer_used;
- newdata = malloc(newsize);
- if(newdata)
- {
- // Create a new index if we gotta
- if(make_new_file)
- {
- index = sdf_index+(sdf_num_files<<4);
- sdf_num_files++;
- sdf_extra_files--;
- }
- // Write the index...
- sdf_write_unsigned_int(index, (unsigned int) newdata);
- sdf_write_unsigned_int(index+4, newsize);
- *(index+4) = SDF_FILE_IS_RUN;
- repeat(j, 8) { *(index+8+j) = 0; }
- memcpy(index+8, filename, strlen(filename));
- // Copy the header information to the new location...
- memcpy(newdata, src_buffer, newsize);
- // Get rid of the old RUN data if we replaced it...
- if(make_new_file==FALSE)
- {
- free(data);
- }
- return TRUE;
- }
- else
- {
- log_message("ERROR: Not enough memory to create header");
- }
- }
- log_message("FOUND: Found error headerizing %s.SRC", filename);
- // Had an error, so delete any existing file...
- index = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
- if(index != NULL)
- {
- data = (unsigned char*) sdf_read_unsigned_int(index);
- free(data);
- *(index+4) = SDF_FILE_IS_UNUSED;
- }
- return FALSE;
- }
- #endif
- //-----------------------------------------------------------------------------------------------
- signed char compiler_error = FALSE;
- signed char src_stage_compile(unsigned char stage, unsigned char mask)
- {
- // <ZZ> This function performs one of the three compilation stages for every SRC file we've
- // got. If it hits any errors, it returns FALSE, otherwise it returns TRUE.
- // mask tells us if we want to recompile all files (SDF_ALL) or only the ones
- // that've been updated (SDF_FLAG_WAS_UPDATED).
- int i;
- unsigned char filename[9];
- unsigned char filetype;
- signed char sofarsogood;
- // Go through each file in the index
- log_message("INFO: Performing stage %d of compilation...", stage);
- sofarsogood = TRUE;
- repeat(i, sdf_num_files)
- {
- // Check the type of file to decompress, then hand off to a subroutine...
- if(sdf_index[(i<<4)+4] & mask)
- {
- sdf_get_filename(i, filename, &filetype);
- if(stage == SRC_HEADERIZE && filetype == SDF_FILE_IS_SRC)
- {
- #ifdef DEVTOOL
- sofarsogood = src_headerize(sdf_index+(i<<4), filename) & sofarsogood;
- #else
- log_message("ERROR: Tried to headerize (should only do in devtool)");
- #endif
- }
- if(stage == SRC_COMPILERIZE && filetype == SDF_FILE_IS_SRC)
- {
- #ifdef DEVTOOL
- sofarsogood = src_compilerize(sdf_index+(i<<4), filename) & sofarsogood;
- #else
- log_message("ERROR: Tried to compilerize (should only do in devtool)");
- #endif
- }
- if(stage == SRC_FUNCTIONIZE && filetype == SDF_FILE_IS_RUN)
- {
- sofarsogood = src_functionize(sdf_index+(i<<4), filename) & sofarsogood;
- }
- }
- }
- if(sofarsogood == FALSE)
- {
- log_message("INFO: Had trouble with at least one of the files...");
- compiler_error = TRUE; // for displaying error message
- }
- else log_message("INFO: Completed stage %d of compilation...", stage);
- return sofarsogood;
- }