PageRenderTime 97ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/dcodesrc.c

https://github.com/filmor/SoulFu
C | 3144 lines | 2683 code | 190 blank | 271 comment | 552 complexity | 6548c8cf7cc972541d6d68d141a549cd MD5 | raw file
  1. // <ZZ> This file contains functions to compile SRC (script source) files
  2. // src_close_jumps - Fills in all of the previous jump locations
  3. // src_add_return_opcode - Puts a return opcode in the compiled code
  4. // src_get_define - Returns an index to the first matching define, or -1
  5. // src_set_priority - Helper for src_find_priority
  6. // src_find_priority - Generates the RPN order for a line of code, Recursive
  7. // src_read_token - Reads the next word-like thing of a file
  8. // src_add_define - #define's a token and it's replacement value
  9. // src_undefine_level - Gets rid of temporary defines (used for variable names...)
  10. // src_define_setup - Reads global defines from "DEFINE.TXT"
  11. // src_generate_opcodes - Writes the opcodes for a line
  12. // src_figure_variable_types - Determines any type casting that needs to be done
  13. // src_find_function_entry - Returns an offset to the start of a function's header, or 0
  14. // src_find_string_entry - Returns an offset to the start of a string's header, or 0
  15. // src_mega_find_function - Better than src_find_function_entry...
  16. // src_make_arrays - Helper for src_find_priority, sets up data...
  17. // src_functionize - Fill in all of the function jumps for a RUN file (helper)
  18. // src_compilerize - The main function to compile an SRC file
  19. // src_headerize - Generate header data before compiling an SRC file
  20. // src_stage_compile - Wrapper for headerize, compilerize, and functionize
  21. #include "dcodesrc.h"
  22. #include "soulfu.h"
  23. #include "datafile.h"
  24. #include "object.h"
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. // !!!BAD!!!
  29. // !!!BAD!!!
  30. // !!!BAD!!!
  31. // !!!BAD!!!
  32. // !!!BAD!!! Should ifdef some of these functions out...
  33. // !!!BAD!!!
  34. // !!!BAD!!!
  35. // !!!BAD!!!
  36. // !!!BAD!!!
  37. #define MAX_VARIABLE 32 // I00 - I31, F00 - F31...
  38. #define MAX_ARGUMENT 16
  39. unsigned short put_jump_offset_here[SRC_MAX_INDENT]; // For figurin' out indentation jumps
  40. unsigned short while_jumps_back_to_here[SRC_MAX_INDENT]; // For figurin' out indentation jumps
  41. unsigned char last_jump_type_found[SRC_MAX_INDENT]; // Not used, If, Else, While...
  42. unsigned char token_buffer[SRC_MAX_TOKEN][SRC_MAX_TOKEN_SIZE]; // A place to put the pieces
  43. unsigned char token_priority[SRC_MAX_TOKEN]; // For figurin' out the RPN order
  44. unsigned char token_priority_list[SRC_MAX_TOKEN]; // List of tokens in order...
  45. unsigned char token_is_operand[SRC_MAX_TOKEN]; // For figurin' out the RPN order
  46. unsigned char token_is_operator[SRC_MAX_TOKEN]; // For figurin' out the RPN order
  47. unsigned char token_is_function[SRC_MAX_TOKEN]; // For figurin' out the RPN order
  48. unsigned char token_opcode[SRC_MAX_TOKEN]; // For figurin' out the RPN data
  49. unsigned char token_variable_type[SRC_MAX_TOKEN]; // F or I or ?...
  50. signed char token_number_to_destroy[SRC_MAX_TOKEN]; // The number of arguments to a function
  51. unsigned char token_change_type[SRC_MAX_TOKEN]; // For variable type conversions
  52. unsigned char token_is_destroyed[SRC_MAX_TOKEN]; // For variable type conversions
  53. unsigned char token_is_string[SRC_MAX_TOKEN]; // 'Cause string pointers are filled in during functionize...
  54. unsigned char* token_arg_list[SRC_MAX_TOKEN]; // Points to somethin' like "FII" for a function...
  55. unsigned char line_is_a_conditional; // While, If, or Else on line...
  56. int token_extension[SRC_MAX_TOKEN]; // For figurin' out the RPN data
  57. char define_token[SRC_MAX_DEFINE][SRC_MAX_TOKEN_SIZE]; // ex. "TRUE"
  58. char define_value[SRC_MAX_DEFINE][SRC_MAX_TOKEN_SIZE]; // ex. "1"
  59. char define_temporary_level[SRC_MAX_DEFINE]; // 0 is global, 1 is file, 2 is function
  60. int src_num_define = 0; // The number of defined values... May be higher than actual...
  61. #define SRC_BUFFER_SIZE 65550 //16384 extra big so src_buffer_used doesn't write other stuff... // Size of the RUN file...
  62. unsigned char src_buffer[SRC_BUFFER_SIZE]; // Stick the RUN file here while building it...
  63. unsigned short src_buffer_used = 0; // Current size
  64. unsigned char token_order; // For determining RPN order/priority...
  65. signed char found_error; // For compiler errors
  66. unsigned char last_function_returns_integer;
  67. unsigned char last_return_type;
  68. signed char float_variable_set[MAX_VARIABLE]; // Make sure variables are set before they're
  69. signed char int_variable_set[MAX_VARIABLE]; // used in expressions... x = 0 before y = x...
  70. char arg_list_none[]=""; // Argument lists for basic functions
  71. char arg_list_int[]="I"; //
  72. char arg_list_int_int[]="II"; //
  73. char arg_list_float[]="F"; //
  74. char arg_list_float_float[]="FF"; //
  75. char arg_list_iii[] = "III"; //
  76. char arg_list_iif[] = "IIF"; //
  77. char arg_list_iiii[] = "IIII"; //
  78. char arg_list_iffi[] = "IFFI"; //
  79. char arg_list_ffii[] = "FFII"; //
  80. char arg_list_iiiii[] = "IIIII"; //
  81. char arg_list_ifffi[] = "IFFFI"; //
  82. char arg_list_ffiii[] = "FFIII"; //
  83. char arg_list_iiiiii[] = "IIIIII"; //
  84. char arg_list_iffiii[] = "IFFIII"; //
  85. char arg_list_ffiiii[] = "FFIIII"; //
  86. char arg_list_ffiiiii[] = "FFIIIII"; //
  87. char arg_list_fffi[] = "FFFI"; //
  88. char arg_list_fffiiii[] = "FFFIIII"; //
  89. char arg_list_ffffi[] = "FFFFI"; //
  90. char arg_list_ffffiii[] = "FFFFIII"; //
  91. char arg_list_ffffiiiiii[] = "FFFFIIIIII"; //
  92. char arg_list_ffffffffffffiii[] = "FFFFFFFFFFFFIII";
  93. // For reading -5 as negative 5 instead of minus 5
  94. signed char next_token_may_be_negative;
  95. void src_close_jumps(unsigned char indent, unsigned char last_indent)
  96. {
  97. // <ZZ> This function closes all of the if's and else's and while's down to the
  98. // given indent level.
  99. int i;
  100. int j;
  101. i = last_indent;
  102. while(i > indent)
  103. {
  104. i--;
  105. if(i != 0)
  106. {
  107. if(last_jump_type_found[i] == SRC_JUMP_ELSE)
  108. {
  109. #ifdef VERBOSE_COMPILE
  110. log_message("INFO: ELSE SKIPPER JUMPS TO HERE 0x%x", src_buffer_used);
  111. #endif
  112. sdf_write_unsigned_short(src_buffer+put_jump_offset_here[i], src_buffer_used);
  113. }
  114. if(last_jump_type_found[i] == SRC_JUMP_IF)
  115. {
  116. // Insert implied jumps in order to skip over elses
  117. j = put_jump_offset_here[i];
  118. if(strcmp(token_buffer[0], "ELSE") == 0 && i == indent)
  119. {
  120. #ifdef VERBOSE_COMPILE
  121. log_message("INFO: OPC: 0x%02x", OPCODE_JUMP);
  122. log_message("INFO: 0x%02x", 0);
  123. log_message("INFO: 0x%02x", 0);
  124. #endif
  125. src_buffer[src_buffer_used] = OPCODE_JUMP; src_buffer_used++;
  126. sdf_write_unsigned_short(src_buffer+src_buffer_used, 0);
  127. put_jump_offset_here[i] = src_buffer_used;
  128. src_buffer_used+=2;
  129. last_jump_type_found[i] = SRC_JUMP_ELSE;
  130. }
  131. #ifdef VERBOSE_COMPILE
  132. log_message("INFO: FAILED IF JUMPS TO HERE 0x%x", src_buffer_used);
  133. #endif
  134. sdf_write_unsigned_short(src_buffer+j, src_buffer_used);
  135. }
  136. if(last_jump_type_found[i] == SRC_JUMP_WHILE)
  137. {
  138. #ifdef VERBOSE_COMPILE
  139. log_message("INFO: JUMP BACK TO START OF WHILE 0x%x", while_jumps_back_to_here[i]);
  140. log_message("INFO: OPC: 0x%02x", OPCODE_JUMP);
  141. log_message("INFO: 0x%02x", 0);
  142. log_message("INFO: 0x%02x", 0);
  143. #endif
  144. src_buffer[src_buffer_used] = OPCODE_JUMP; src_buffer_used++;
  145. sdf_write_unsigned_short(src_buffer+src_buffer_used, while_jumps_back_to_here[i]);
  146. src_buffer_used+=2;
  147. #ifdef VERBOSE_COMPILE
  148. log_message("INFO: FAILED WHILE JUMPS TO HERE 0x%x", src_buffer_used);
  149. #endif
  150. sdf_write_unsigned_short(src_buffer+put_jump_offset_here[i], src_buffer_used);
  151. }
  152. last_jump_type_found[i] == SRC_JUMP_INVALID;
  153. }
  154. }
  155. }
  156. void src_add_return_opcode(void)
  157. {
  158. // <ZZ> This function appends a return opcode to the src_buffer. Done to make
  159. // sure function calls go back to where they came from.
  160. if(last_function_returns_integer)
  161. {
  162. #ifdef VERBOSE_COMPILE
  163. // Opcode for integer 1 is 225
  164. log_message("INFO: OPC: 0x%02x", 225);
  165. log_message("INFO: OPC: 0x%02x", OPCODE_RETURNINT);
  166. #endif
  167. src_buffer[src_buffer_used] = 225; src_buffer_used++;
  168. src_buffer[src_buffer_used] = OPCODE_RETURNINT; src_buffer_used++;
  169. }
  170. else
  171. {
  172. #ifdef VERBOSE_COMPILE
  173. // Opcode for float 1.0 is 226
  174. log_message("INFO: OPC: 0x%02x", 226);
  175. log_message("INFO: OPC: 0x%02x", OPCODE_RETURNFLOAT);
  176. #endif
  177. src_buffer[src_buffer_used] = 226; src_buffer_used++;
  178. src_buffer[src_buffer_used] = OPCODE_RETURNFLOAT; src_buffer_used++;
  179. }
  180. }
  181. int src_get_define(char* token)
  182. {
  183. // <ZZ> This function returns the index of the first #define that matches token.
  184. // If there aren't any matches, it returns -1.
  185. int i;
  186. // Check each define...
  187. repeat(i, src_num_define)
  188. {
  189. if(strcmp(token, define_token[i]) == 0) return i;
  190. }
  191. return -1;
  192. }
  193. void src_set_priority(int start, int i, int end, signed char any_type)
  194. {
  195. // <ZZ> This function is a helper for the RPN code. It sets the given token to be the
  196. // next most important token.
  197. if(i >= start && i <= end)
  198. {
  199. if(token_priority[i] == 0 && token_buffer[i][0] != ',')
  200. {
  201. if(token_is_operand[i] || any_type)
  202. {
  203. token_priority_list[token_order-1] = i;
  204. token_priority[i] = token_order; token_order++;
  205. }
  206. }
  207. }
  208. }
  209. //-----------------------------------------------------------------------------------------------
  210. void src_find_priority(int start, int end, signed char change_signs, signed char first_check)
  211. {
  212. // <ZZ> This function looks at the tokens in token_buffer to determine the reverse polish
  213. // ordering for the tokens. Start is the first token to be examined, end is the last.
  214. // If the expression is complex (as it usually is), it is cut in half at the lowest
  215. // priority operator, and each half is fed back into the function recursively. If the
  216. // expression is simple enough to figure out, the priorities are assigned.
  217. int i;
  218. int priority;
  219. int lowest_token;
  220. int lowest_priority;
  221. int highest_priority;
  222. int nest_level;
  223. int our_nest_level;
  224. // Just in case something weird happens...
  225. if(end < start || start < 0 || start >= SRC_MAX_TOKEN || end < 0 || start >= SRC_MAX_TOKEN)
  226. {
  227. return;
  228. }
  229. // Change signs if negative... Don't propogate through parentheses...
  230. if(change_signs)
  231. {
  232. nest_level = 0;
  233. i = start;
  234. while(i <= end)
  235. {
  236. if(token_buffer[i][0] == '(')
  237. {
  238. nest_level++;
  239. }
  240. if(token_buffer[i][0] == ')')
  241. {
  242. nest_level--;
  243. }
  244. if(nest_level == 0)
  245. {
  246. if(token_opcode[i] == OPCODE_ADD)
  247. {
  248. token_opcode[i] = OPCODE_SUBTRACT;
  249. token_buffer[i][0] = '-';
  250. }
  251. else if(token_opcode[i] == OPCODE_SUBTRACT)
  252. {
  253. token_opcode[i] = OPCODE_ADD;
  254. token_buffer[i][0] = '+';
  255. }
  256. }
  257. i++;
  258. }
  259. }
  260. // Draw in ends to ignore parentheses...
  261. while(token_buffer[start][0] == '(' && token_buffer[end][0] == ')')
  262. {
  263. start++;
  264. end--;
  265. }
  266. // Just in case something weird happens...
  267. if(end < start)
  268. {
  269. return;
  270. }
  271. #ifdef VERBOSE_COMPILE
  272. log_message("INFO: Checking priority from %d to %d", start, end);
  273. #endif
  274. // Find the lowest nest level...
  275. our_nest_level = 0;
  276. nest_level = 0;
  277. i = start;
  278. while(i <= end)
  279. {
  280. // Check for nest level changes...
  281. if(token_buffer[i][0] == '(')
  282. {
  283. nest_level++;
  284. }
  285. if(token_buffer[i][0] == ')')
  286. {
  287. nest_level--;
  288. }
  289. if(token_buffer[i][0] != '(' && token_buffer[i][0] != ')')
  290. {
  291. // Find the first useable token...
  292. our_nest_level = nest_level;
  293. i = end;
  294. }
  295. i++;
  296. }
  297. nest_level = 0;
  298. i = start;
  299. while(i <= end)
  300. {
  301. // Check for nest level changes...
  302. if(token_buffer[i][0] == '(')
  303. {
  304. nest_level++;
  305. }
  306. if(token_buffer[i][0] == ')')
  307. {
  308. nest_level--;
  309. }
  310. if(token_buffer[i][0] != '(' && token_buffer[i][0] != ')')
  311. {
  312. // Only take nest levels that actually have tokens...
  313. if(nest_level < our_nest_level) our_nest_level = nest_level;
  314. }
  315. i++;
  316. }
  317. // Search for the lowest and highest priority tokens
  318. lowest_token = -1;
  319. lowest_priority = 1000000;
  320. highest_priority = -1;
  321. nest_level = 0;
  322. i = start;
  323. while(i <= end)
  324. {
  325. // Check for nest level changes...
  326. if(token_buffer[i][0] == '(')
  327. {
  328. nest_level++;
  329. highest_priority = 100000; // Force a split
  330. }
  331. if(token_buffer[i][0] == ')')
  332. {
  333. nest_level--;
  334. }
  335. // Only handle tokens at our nest level...
  336. else if(nest_level == our_nest_level)
  337. {
  338. priority = -1;
  339. // First come increment and decrement
  340. if(token_opcode[i] == OPCODE_INCREMENT || token_opcode[i] == OPCODE_DECREMENT)
  341. {
  342. priority = 9;
  343. }
  344. // Then not and negate...
  345. else if(token_opcode[i] == OPCODE_LOGICALNOT || token_opcode[i] == OPCODE_NEGATE)
  346. {
  347. priority = 8;
  348. }
  349. // Then function calls
  350. else if(token_is_function[i])
  351. {
  352. priority = 7;
  353. }
  354. // Then multiply, divide, and modulus
  355. else if(token_opcode[i] == OPCODE_MULTIPLY || token_opcode[i] == OPCODE_DIVIDE || token_opcode[i] == OPCODE_MODULUS)
  356. {
  357. priority = 6;
  358. }
  359. // Then add and subtract
  360. else if(token_opcode[i] == OPCODE_ADD || token_opcode[i] == OPCODE_SUBTRACT)
  361. {
  362. priority = 5;
  363. }
  364. // Then bitwise operations
  365. else if(token_opcode[i] >= OPCODE_BITWISEAND && token_opcode[i] <= OPCODE_BITWISERIGHT)
  366. {
  367. priority = 4;
  368. }
  369. // Then comparison operations
  370. else if(token_opcode[i] >= OPCODE_ISEQUAL && token_opcode[i] <= OPCODE_ISLESSER)
  371. {
  372. priority = 3;
  373. }
  374. // Then logical operations
  375. else if(token_opcode[i] == OPCODE_LOGICALAND || token_opcode[i] == OPCODE_LOGICALOR)
  376. {
  377. priority = 2;
  378. }
  379. // Then commas
  380. else if(token_buffer[i][0] == ',')
  381. {
  382. priority = 1;
  383. }
  384. // Then equates
  385. else if(token_opcode[i] == OPCODE_EQUALS)
  386. {
  387. priority = 0;
  388. }
  389. // Now remember the priority...
  390. if(priority > -1)
  391. {
  392. if(priority > highest_priority)
  393. {
  394. highest_priority = priority;
  395. }
  396. if(priority < lowest_priority || (priority == 6 && lowest_priority == 6))
  397. {
  398. lowest_token = i;
  399. lowest_priority = priority;
  400. }
  401. }
  402. }
  403. i++;
  404. }
  405. // Check for errors...
  406. if(nest_level != 0 && first_check)
  407. {
  408. log_message("ERROR: Line %d, Unbalanced parentheses", sdf_read_line_number);
  409. found_error = TRUE;
  410. return;
  411. }
  412. // Now, if the expression only contains tokens of one priority, we can solve it...
  413. if((highest_priority == lowest_priority && lowest_priority != 7 && lowest_priority != 0 && lowest_priority != 1) || lowest_token == -1)
  414. {
  415. // Solve the expression...
  416. i = start;
  417. while(i <= end)
  418. {
  419. if(token_is_operator[i])
  420. {
  421. if(token_opcode[i] == OPCODE_INCREMENT || token_opcode[i] == OPCODE_DECREMENT)
  422. {
  423. // Handle self
  424. src_set_priority(start, i, end, TRUE);
  425. // Handle operand to left
  426. src_set_priority(start, i-1, end, FALSE);
  427. }
  428. else
  429. {
  430. // Handle operand to left
  431. src_set_priority(start, i-1, end, FALSE);
  432. // Handle operand to right
  433. src_set_priority(start, i+1, end, FALSE);
  434. // Handle self
  435. src_set_priority(start, i, end, TRUE);
  436. }
  437. }
  438. else if(lowest_token == -1)
  439. {
  440. // Handle self
  441. src_set_priority(start, i, end, FALSE);
  442. }
  443. i++;
  444. }
  445. }
  446. else
  447. {
  448. // Too complex, so split it in two and try again...
  449. if(token_opcode[lowest_token] == OPCODE_EQUALS || token_is_function[lowest_token])
  450. {
  451. // Right side
  452. src_find_priority(lowest_token+1, end, FALSE, FALSE);
  453. // Middle
  454. src_set_priority(start, lowest_token, end, TRUE);
  455. // Left side
  456. src_find_priority(start, lowest_token-1, FALSE, FALSE);
  457. }
  458. else if(token_opcode[lowest_token] == OPCODE_LOGICALNOT || token_opcode[lowest_token] == OPCODE_NEGATE)
  459. {
  460. // Right side
  461. src_find_priority(lowest_token+1, end, FALSE, FALSE);
  462. // Middle
  463. src_set_priority(start, lowest_token, end, TRUE);
  464. }
  465. else
  466. {
  467. // Left side
  468. src_find_priority(start, lowest_token-1, FALSE, FALSE);
  469. // Right side
  470. if(token_opcode[lowest_token] == OPCODE_SUBTRACT) src_find_priority(lowest_token+1, end, TRUE, FALSE);
  471. else src_find_priority(lowest_token+1, end, FALSE, FALSE);
  472. // Middle
  473. src_set_priority(start, lowest_token, end, TRUE);
  474. }
  475. }
  476. return;
  477. }
  478. //-----------------------------------------------------------------------------------------------
  479. signed char src_read_token(unsigned char* buffer)
  480. {
  481. // <ZZ> This function reads the next token (like a word) in a file that has been
  482. // sdf_open()'d and puts that token in buffer. The token can't be any longer than
  483. // SRC_MAX_TOKEN_SIZE. It returns TRUE if there was a token to read, or FALSE if
  484. // not. next_token_may_be_negative is also important for reading negative numbers
  485. // correctly.
  486. int count;
  487. int value;
  488. // Skip any whitespace...
  489. while((*sdf_read_file) == ' ' && sdf_read_remaining > 0)
  490. {
  491. sdf_read_remaining--;
  492. sdf_read_file++;
  493. }
  494. // Check for a string token...
  495. count = 0;
  496. if((*sdf_read_file) == '\'' && (*(sdf_read_file+2)) == '\'')
  497. {
  498. sprintf(buffer, "%d", *(sdf_read_file+1));
  499. sdf_read_remaining-=3;
  500. sdf_read_file+=3;
  501. count=3;
  502. }
  503. else if((*sdf_read_file) == '"')
  504. {
  505. // Read the string token
  506. buffer[count] = '"';
  507. sdf_read_remaining--;
  508. sdf_read_file++;
  509. count++;
  510. while(count < SRC_MAX_TOKEN_SIZE-2 && sdf_read_remaining > 0 && (*sdf_read_file) != '"' && (*sdf_read_file) != 0)
  511. {
  512. buffer[count] = (*sdf_read_file);
  513. sdf_read_remaining--;
  514. sdf_read_file++;
  515. if(buffer[count] == '\\' && (*sdf_read_file) >= '0' && (*sdf_read_file) <= '9')
  516. {
  517. // It's an escape sequence, so read in the value...
  518. value = 0;
  519. while((*sdf_read_file) >= '0' && (*sdf_read_file) <= '9')
  520. {
  521. value = (value*10) + (*sdf_read_file) - '0';
  522. sdf_read_remaining--;
  523. sdf_read_file++;
  524. }
  525. buffer[count] = value;
  526. }
  527. count++;
  528. }
  529. buffer[count] = '"';
  530. sdf_read_remaining--;
  531. sdf_read_file++;
  532. count++;
  533. buffer[count] = 0;
  534. next_token_may_be_negative = FALSE;
  535. }
  536. else
  537. {
  538. // Is the token alphanumeric or a special operator token???
  539. 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') ))
  540. {
  541. // Read the alphanumeric token
  542. 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') )))
  543. {
  544. buffer[count] = (*sdf_read_file);
  545. sdf_read_remaining--;
  546. sdf_read_file++;
  547. count++;
  548. }
  549. buffer[count] = 0;
  550. make_uppercase(buffer);
  551. next_token_may_be_negative = FALSE;
  552. }
  553. else
  554. {
  555. // Read one character...
  556. if((*sdf_read_file) != 0)
  557. {
  558. if(sdf_read_remaining > 0)
  559. {
  560. buffer[count] = (*sdf_read_file);
  561. sdf_read_remaining--;
  562. sdf_read_file++;
  563. count++;
  564. }
  565. // Do we need another?
  566. if((buffer[0] == '>' && (*sdf_read_file) == '>') ||
  567. (buffer[0] == '<' && (*sdf_read_file) == '<') ||
  568. (buffer[0] == '&' && (*sdf_read_file) == '&') ||
  569. (buffer[0] == '|' && (*sdf_read_file) == '|') ||
  570. (buffer[0] == '>' && (*sdf_read_file) == '=') ||
  571. (buffer[0] == '<' && (*sdf_read_file) == '=') ||
  572. (buffer[0] == '=' && (*sdf_read_file) == '=') ||
  573. (buffer[0] == '+' && (*sdf_read_file) == '+') ||
  574. (buffer[0] == '-' && (*sdf_read_file) == '-') ||
  575. (buffer[0] == '/' && (*sdf_read_file) == '/') ||
  576. (buffer[0] == '!' && (*sdf_read_file) == '='))
  577. {
  578. buffer[count] = (*sdf_read_file);
  579. sdf_read_remaining--;
  580. sdf_read_file++;
  581. count++;
  582. }
  583. // Ignore comments...
  584. if(buffer[0] == '/' && buffer[1] == '/') return FALSE;
  585. // May need to read a whole number in... Negative numbers...
  586. if(next_token_may_be_negative)
  587. {
  588. if(buffer[0] == '-' && (*sdf_read_file) >= '0' && (*sdf_read_file) <= '9')
  589. {
  590. // Read the numeric token...
  591. while(count < SRC_MAX_TOKEN_SIZE-1 && sdf_read_remaining > 0 && (((*sdf_read_file) == '.' || ((*sdf_read_file) >= '0' && (*sdf_read_file) <= '9'))))
  592. {
  593. buffer[count] = (*sdf_read_file);
  594. sdf_read_remaining--;
  595. sdf_read_file++;
  596. count++;
  597. }
  598. next_token_may_be_negative = FALSE;
  599. }
  600. }
  601. else
  602. {
  603. next_token_may_be_negative = TRUE;
  604. }
  605. buffer[count] = 0;
  606. // Figure out if the next one can be negative...
  607. if(strcmp(buffer, ")") == 0) next_token_may_be_negative = FALSE;
  608. if(strcmp(buffer, "--") == 0) next_token_may_be_negative = FALSE;
  609. if(strcmp(buffer, "++") == 0) next_token_may_be_negative = FALSE;
  610. if(strcmp(buffer, "%") == 0) next_token_may_be_negative = FALSE;
  611. }
  612. }
  613. }
  614. if(count > 0) return TRUE;
  615. return FALSE;
  616. }
  617. //-----------------------------------------------------------------------------------------------
  618. void src_add_define(char* token, char* value, char temporary_level)
  619. {
  620. // <ZZ> This function registers a new #define'd value. Temporary_level determines if the
  621. // define is removed after a file or function is done being parsed.
  622. char temptoken[SRC_MAX_TOKEN_SIZE];
  623. unsigned char* tempptr;
  624. int tempint;
  625. int tempnum;
  626. int i;
  627. int j;
  628. int found;
  629. int define_to_use;
  630. char define_is_new;
  631. // Look for an unused define to use...
  632. next_token_may_be_negative = TRUE;
  633. define_is_new = TRUE;
  634. define_to_use = src_num_define;
  635. repeat(i, src_num_define)
  636. {
  637. // Has this one been cleared?
  638. if(define_token[i][0] == 0)
  639. {
  640. define_to_use = i;
  641. define_is_new = FALSE;
  642. i = src_num_define;
  643. }
  644. }
  645. // Fill in the data
  646. if(define_to_use < SRC_MAX_DEFINE)
  647. {
  648. // Skip whitespace...
  649. while((*token) == ' ') token++;
  650. while((*value) == ' ') value++;
  651. // Copy the token...
  652. i = 0;
  653. while(i < SRC_MAX_TOKEN_SIZE-1 && token[i] != 0)
  654. {
  655. define_token[define_to_use][i] = token[i];
  656. i++;
  657. }
  658. define_token[define_to_use][i] = 0;
  659. define_temporary_level[define_to_use] = temporary_level;
  660. // Now search through the value, looking for previously #defined tokens...
  661. tempptr = sdf_read_file;
  662. tempint = sdf_read_remaining;
  663. tempnum = sdf_read_line_number;
  664. sdf_read_file = value;
  665. sdf_read_remaining = SRC_MAX_TOKEN_SIZE;
  666. i = 0;
  667. while(src_read_token(temptoken))
  668. {
  669. found = src_get_define(temptoken);
  670. if(found > -1)
  671. {
  672. // Copy the value of the old token into the new one...
  673. j = 0;
  674. while(define_value[found][j] != 0 && i < SRC_MAX_TOKEN_SIZE-1)
  675. {
  676. define_value[define_to_use][i] = define_value[found][j];
  677. i++;
  678. j++;
  679. }
  680. if(i < SRC_MAX_TOKEN_SIZE-1)
  681. {
  682. define_value[define_to_use][i] = ' ';
  683. i++;
  684. }
  685. }
  686. else
  687. {
  688. // Copy the token into the new define...
  689. j = 0;
  690. while(temptoken[j] != 0 && i < SRC_MAX_TOKEN_SIZE-1)
  691. {
  692. define_value[define_to_use][i] = temptoken[j];
  693. i++;
  694. j++;
  695. }
  696. if(i < SRC_MAX_TOKEN_SIZE-1)
  697. {
  698. define_value[define_to_use][i] = ' ';
  699. i++;
  700. }
  701. }
  702. }
  703. if(i < SRC_MAX_TOKEN_SIZE)
  704. {
  705. define_value[define_to_use][i] = 0;
  706. i--;
  707. }
  708. if(i >= 0)
  709. {
  710. if(define_value[define_to_use][i] == ' ')
  711. {
  712. define_value[define_to_use][i] = 0;
  713. }
  714. }
  715. sdf_read_line_number = tempnum;
  716. sdf_read_remaining = tempint;
  717. sdf_read_file = tempptr;
  718. #ifdef VERBOSE_COMPILE
  719. log_message("INFO: Defined... %s == %s", define_token[define_to_use], define_value[define_to_use]);
  720. #endif
  721. // Increment the number of defines if we added a new one
  722. if(define_is_new) src_num_define++;
  723. }
  724. else
  725. {
  726. log_message("ERROR: Couldn't define %s... Out of tokens to use...", token);
  727. found_error = TRUE;
  728. }
  729. }
  730. //-----------------------------------------------------------------------------------------------
  731. void src_undefine_level(char temporary_level)
  732. {
  733. // <ZZ> This function gets rid of any defines that we don't need
  734. int i;
  735. repeat(i, src_num_define)
  736. {
  737. if(define_temporary_level[i] >= temporary_level)
  738. {
  739. define_token[i][0] = 0;
  740. define_value[i][0] = 0;
  741. define_temporary_level[i] = 0;
  742. }
  743. }
  744. }
  745. //-----------------------------------------------------------------------------------------------
  746. signed char src_define_setup(void)
  747. {
  748. // <ZZ> This function looks at "DEFINE.TXT" to see what global #define's we've got,
  749. // including ID strings. It returns TRUE if it worked okay, or FALSE if not.
  750. unsigned char indent;
  751. obj_reset_property();
  752. next_token_may_be_negative = TRUE;
  753. src_num_define = 0;
  754. if(sdf_open("DEFINE.TXT"))
  755. {
  756. log_message("INFO: Setting up the global #defines...");
  757. while(sdf_read_line())
  758. {
  759. // Count the indentation (by 2's), and skip over any whitespace...
  760. indent = count_indentation(sdf_read_file);
  761. sdf_read_file+=indent;
  762. sdf_read_remaining-=indent;
  763. indent = indent>>1;
  764. // Check for a #define...
  765. if(sdf_read_file[0] == '#')
  766. {
  767. if(sdf_read_file[1] == 'd')
  768. {
  769. if(sdf_read_file[2] == 'e')
  770. {
  771. if(sdf_read_file[3] == 'f')
  772. {
  773. if(sdf_read_file[4] == 'i')
  774. {
  775. if(sdf_read_file[5] == 'n')
  776. {
  777. if(sdf_read_file[6] == 'e')
  778. {
  779. sdf_read_file+=7;
  780. sdf_read_remaining-=7;
  781. if(src_read_token(token_buffer[0]))
  782. {
  783. src_add_define(token_buffer[0], sdf_read_file, SRC_PERMANENT);
  784. }
  785. }
  786. }
  787. }
  788. }
  789. }
  790. }
  791. else if(sdf_read_file[1] == 'p')
  792. {
  793. if(sdf_read_file[2] == 'r')
  794. {
  795. if(sdf_read_file[3] == 'o')
  796. {
  797. if(sdf_read_file[4] == 'p')
  798. {
  799. if(sdf_read_file[5] == 'e')
  800. {
  801. if(sdf_read_file[6] == 'r')
  802. {
  803. sdf_read_file+=7;
  804. sdf_read_remaining-=7;
  805. if(src_read_token(token_buffer[0])) // tag
  806. {
  807. if(src_read_token(token_buffer[1])) // type
  808. {
  809. if(src_read_token(token_buffer[2])) // offset
  810. {
  811. obj_add_property(token_buffer[0], token_buffer[1][0], token_buffer[2]);
  812. }
  813. }
  814. }
  815. }
  816. }
  817. }
  818. }
  819. }
  820. }
  821. }
  822. }
  823. log_message("INFO: %d of %d properties used", obj_num_property, MAX_PROPERTY);
  824. log_message("INFO: %d of %d defines used", src_num_define, SRC_MAX_DEFINE);
  825. return TRUE;
  826. }
  827. log_message("ERROR: DEFINE.TXT could not be found in the database");
  828. return FALSE;
  829. }
  830. //-----------------------------------------------------------------------------------------------
  831. void src_generate_opcodes(int token_count)
  832. {
  833. // <ZZ> This function writes the finalized opcodes for a single line of a SRC file. The
  834. // opcodes are put in the src_buffer. Token_count is the number of RPN symbols found
  835. // previously, which doesn't include tokens like '(' and ','.
  836. int i;
  837. int token;
  838. unsigned int tempint;
  839. signed char last_token_was_equals;
  840. last_token_was_equals = FALSE;
  841. repeat(i, token_count)
  842. {
  843. // Write out the opcode and any extended data...
  844. token = token_priority_list[i];
  845. // ...But ignore else's...
  846. if(strcmp(token_buffer[token], "ELSE") != 0)
  847. {
  848. #ifdef VERBOSE_COMPILE
  849. log_message("INFO: OPC: 0x%02x", token_opcode[token]);
  850. #endif
  851. src_buffer[src_buffer_used] = token_opcode[token]; src_buffer_used++;
  852. // Look for variables that are used before being set...
  853. if(last_token_was_equals)
  854. {
  855. // Variables being set...
  856. if(token_opcode[token] >= 128 && token_opcode[token] < 224)
  857. {
  858. if((token_opcode[token] & 224) == 192)
  859. {
  860. // Float variable has been set...
  861. float_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] = TRUE;
  862. }
  863. if((token_opcode[token] & 224) == 128)
  864. {
  865. // Integer variable has been set...
  866. int_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] = TRUE;
  867. }
  868. }
  869. else
  870. {
  871. log_message("ERROR: Line %d, Can only set/assign variables", sdf_read_line_number);
  872. }
  873. }
  874. else
  875. {
  876. // Variables being used...
  877. if(token_opcode[token] >= 128 && token_opcode[token] < 224)
  878. {
  879. if((token_opcode[token] & 224) == 192)
  880. {
  881. if(float_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] == FALSE)
  882. {
  883. // Variable has been used before being set...
  884. log_message("ERROR: Line %d, Variable F%02d used before being set", sdf_read_line_number, (token_opcode[token] & (MAX_VARIABLE-1)));
  885. found_error = TRUE;
  886. }
  887. }
  888. else
  889. {
  890. if(int_variable_set[token_opcode[token] & (MAX_VARIABLE-1)] == FALSE)
  891. {
  892. // Variable has been used before being set...
  893. log_message("ERROR: Line %d, Variable I%02d used before being set", sdf_read_line_number, (token_opcode[token] & (MAX_VARIABLE-1)));
  894. found_error = TRUE;
  895. }
  896. }
  897. }
  898. }
  899. last_token_was_equals = FALSE;
  900. if(token_opcode[token] == OPCODE_EQUALS || token_opcode[token] == OPCODE_F_EQUALS)
  901. {
  902. last_token_was_equals = TRUE;
  903. }
  904. if(token_opcode[token] == OPCODE_CALLFUNCTION)
  905. {
  906. // Call function... 4 byte jump location, 4 byte return
  907. // position, 4 byte argument list pointer, 4 byte file start address,
  908. // then the zero terminated function name
  909. #ifdef VERBOSE_COMPILE
  910. log_message("INFO: : 0x00 (jump)");
  911. log_message("INFO: : 0x00 (jump)");
  912. log_message("INFO: : 0x00 (jump)");
  913. log_message("INFO: : 0x00 (jump)");
  914. log_message("INFO: : 0x00 (return)");
  915. log_message("INFO: : 0x00 (return)");
  916. log_message("INFO: : 0x00 (return)");
  917. log_message("INFO: : 0x00 (return)");
  918. log_message("INFO: : 0x00 (arg)");
  919. log_message("INFO: : 0x00 (arg)");
  920. log_message("INFO: : 0x00 (arg)");
  921. log_message("INFO: : 0x00 (arg)");
  922. log_message("INFO: : 0x00 (filestart)");
  923. log_message("INFO: : 0x00 (filestart)");
  924. log_message("INFO: : 0x00 (filestart)");
  925. log_message("INFO: : 0x00 (filestart)");
  926. log_message("INFO: : %s", token_buffer[token]);
  927. log_message("INFO: : 0x00");
  928. #endif
  929. sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
  930. sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
  931. sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
  932. sdf_write_unsigned_int(src_buffer+src_buffer_used, 0); src_buffer_used+=4;
  933. sprintf(src_buffer+src_buffer_used, "%s", token_buffer[token]);
  934. src_buffer_used+=strlen(token_buffer[token])+1;
  935. }
  936. if(token_opcode[token] == OPCODE_IFFALSEJUMP)
  937. {
  938. // Jump function (if or while)... 2 byte address... Filled in later...
  939. #ifdef VERBOSE_COMPILE
  940. log_message("INFO: : 0x00");
  941. log_message("INFO: : 0x00");
  942. #endif
  943. sprintf(src_buffer+src_buffer_used, "%c%c", 0, 0);
  944. src_buffer_used+=2;
  945. }
  946. if((token_opcode[token]&0xE0) == 0xA0 || token_opcode[token] == 227)
  947. {
  948. // 101xxxxx... Integer variable with dot parameter... One byte index follows
  949. // 227... Integer numeric token.... 1 byte data follows (signed)
  950. tempint = *((unsigned int*) &token_extension[token]);
  951. #ifdef VERBOSE_COMPILE
  952. log_message("INFO: : 0x%02x", (tempint)&255);
  953. #endif
  954. *(src_buffer+src_buffer_used) = (tempint)&255; src_buffer_used++;
  955. }
  956. if(token_opcode[token] == 228)
  957. {
  958. // Integer numeric token... 2 byte data follows (signed)...
  959. tempint = *((unsigned int*) &token_extension[token]);
  960. #ifdef VERBOSE_COMPILE
  961. log_message("INFO: : 0x%02x", (tempint>>8)&255);
  962. log_message("INFO: : 0x%02x", (tempint)&255);
  963. #endif
  964. *(src_buffer+src_buffer_used) = (tempint>>8)&255; src_buffer_used++;
  965. *(src_buffer+src_buffer_used) = (tempint)&255; src_buffer_used++;
  966. }
  967. if(token_opcode[token] == 229 || token_opcode[token] == 230)
  968. {
  969. // 229... Integer numeric token... 4 byte data follows (signed)...
  970. // 230... Float numeric token... 4 byte data follows (signed)...
  971. tempint = *((unsigned int*) &token_extension[token]);
  972. if(token_is_string[token])
  973. {
  974. // This is a string type of integer, so we need to remember where
  975. // it is, so functionize can change the numbers... Write the opcode offset
  976. // into the string header area...
  977. #ifdef VERBOSE_COMPILE
  978. log_message("INFO: Weird string fill-in-later thing.... %s", src_buffer+token_extension[token]);
  979. #endif
  980. sdf_write_unsigned_short((src_buffer+token_extension[token]-2), (src_buffer_used));
  981. tempint = 0;
  982. }
  983. #ifdef VERBOSE_COMPILE
  984. log_message("INFO: : 0x%02x", (tempint>>24)&255);
  985. log_message("INFO: : 0x%02x", (tempint>>16)&255);
  986. log_message("INFO: : 0x%02x", (tempint>>8)&255);
  987. log_message("INFO: : 0x%02x", (tempint)&255);
  988. #endif
  989. *(src_buffer+src_buffer_used) = (tempint>>24)&255; src_buffer_used++;
  990. *(src_buffer+src_buffer_used) = (tempint>>16)&255; src_buffer_used++;
  991. *(src_buffer+src_buffer_used) = (tempint>>8)&255; src_buffer_used++;
  992. *(src_buffer+src_buffer_used) = (tempint)&255; src_buffer_used++;
  993. // !!!BAD!!!
  994. // !!!BAD!!!
  995. // !!!BAD!!! Probably won't compile RUN's same on Macs... Floats will be screwed up... Maybe reverse bytes here...
  996. // !!!BAD!!!
  997. // !!!BAD!!!
  998. }
  999. // Now insert variable type conversions...
  1000. if(token_change_type[token] == VAR_INT)
  1001. {
  1002. #ifdef VERBOSE_COMPILE
  1003. log_message("INFO: OPC: 0x%02x (to int)", OPCODE_TOINT);
  1004. #endif
  1005. src_buffer[src_buffer_used] = OPCODE_TOINT; src_buffer_used++;
  1006. }
  1007. if(token_change_type[token] == VAR_FLOAT)
  1008. {
  1009. #ifdef VERBOSE_COMPILE
  1010. log_message("INFO: OPC: 0x%02x (to float)", OPCODE_TOFLOAT);
  1011. #endif
  1012. src_buffer[src_buffer_used] = OPCODE_TOFLOAT; src_buffer_used++;
  1013. }
  1014. }
  1015. }
  1016. #ifdef VERBOSE_COMPILE
  1017. log_message("INFO: ");
  1018. #endif
  1019. }
  1020. //-----------------------------------------------------------------------------------------------
  1021. void src_figure_variable_types(int token_count)
  1022. {
  1023. // <ZZ> This function determines where to place the ToInt and ToFloat opcodes for a line.
  1024. // Token_count is the number of RPN symbols found previously, which doesn't include
  1025. // tokens like '(' and ','.
  1026. int i;
  1027. int j;
  1028. int destroyed;
  1029. int total_destroyed;
  1030. int token;
  1031. int other_token;
  1032. unsigned char type_needed;
  1033. repeat(i, token_count)
  1034. {
  1035. // Look for tokens in order of their priority...
  1036. token = token_priority_list[i];
  1037. token_is_destroyed[token] = FALSE;
  1038. // Look through previous tokens to find arguments for functions/operations
  1039. type_needed = VAR_INT;
  1040. if(token_number_to_destroy[token] > 0)
  1041. {
  1042. // Look for errors with equals, increment, and decrement
  1043. if(token_variable_type[token] == VAR_INVALID)
  1044. {
  1045. if(token_opcode[token] == OPCODE_EQUALS || token_opcode[token] == OPCODE_INCREMENT || token_opcode[token] == OPCODE_DECREMENT)
  1046. {
  1047. // Need to know what type of variable is being set... Check it...
  1048. if(i < token_count)
  1049. {
  1050. // Make sure the token to the left is a valid data storage token...
  1051. other_token = token_priority_list[i+1];
  1052. if(token_opcode[other_token] >= 128 && token_opcode[other_token] < 224 )
  1053. {
  1054. if(token_opcode[token] == OPCODE_EQUALS)
  1055. {
  1056. // Check to the right for equals, now that we've checked for errors...
  1057. if(i > 0)
  1058. {
  1059. other_token = token_priority_list[i-1];
  1060. type_needed = token_variable_type[other_token];
  1061. }
  1062. else
  1063. {
  1064. log_message("ERROR: Line %d, Missing value to right of =", sdf_read_line_number);
  1065. found_error = TRUE;
  1066. }
  1067. }
  1068. else
  1069. {
  1070. type_needed = token_variable_type[other_token];
  1071. }
  1072. }
  1073. else
  1074. {
  1075. log_message("ERROR: Line %d, Invalid storage variable to left of =, ++, or, --", sdf_read_line_number);
  1076. found_error = TRUE;
  1077. }
  1078. }
  1079. }
  1080. }
  1081. // Look for any floating point arguments... This is needed for basic functions
  1082. // and operations that can handle either float or integer... If an Add has a float
  1083. // and an int, the int should be changed to float and a FloatAdd performed...
  1084. if(token_arg_list[token] == NULL)
  1085. {
  1086. destroyed = 0;
  1087. j = i;
  1088. while(j > 0 && destroyed < token_number_to_destroy[token])
  1089. {
  1090. // Go to the last token and see if we can use it...
  1091. j--;
  1092. other_token = token_priority_list[j];
  1093. if(token_is_destroyed[other_token] == FALSE)
  1094. {
  1095. // Okay, we can use it... Check if it's a float...
  1096. if(token_variable_type[other_token] == VAR_FLOAT) type_needed = VAR_FLOAT;
  1097. destroyed++;
  1098. }
  1099. }
  1100. // Now change the opcodes from IntAdd to FloatAdd... Others too...
  1101. if(type_needed == VAR_FLOAT)
  1102. {
  1103. if(token_opcode[token] <= OPCODE_NEGATE)
  1104. {
  1105. token_opcode[token]+=32; // Float operations start with opcode 32...
  1106. }
  1107. }
  1108. }
  1109. // Fill in the correct variable type...
  1110. if(token_variable_type[token] == VAR_INVALID)
  1111. {
  1112. token_variable_type[token] = type_needed;
  1113. // Some floating point functions return integers...
  1114. if(token_opcode[token] >= OPCODE_F_ISEQUAL && token_opcode[token] <= OPCODE_F_LOGICALNOT)
  1115. {
  1116. token_variable_type[token] = VAR_INT;
  1117. }
  1118. }
  1119. // Now type cast any of those arguments we found... Do the search again...
  1120. destroyed = 0;
  1121. j = i;
  1122. while(j > 0 && destroyed < token_number_to_destroy[token])
  1123. {
  1124. // Go to the last token and see if we can use it...
  1125. j--;
  1126. other_token = token_priority_list[j];
  1127. if(token_is_destroyed[other_token] == FALSE)
  1128. {
  1129. // Remember that we ate it up, so other functions don't try to use it too...
  1130. token_is_destroyed[other_token] = TRUE;
  1131. destroyed++;
  1132. // Okay, we can use it... Do we need to change all ints to float?
  1133. if(token_arg_list[token] != NULL)
  1134. {
  1135. // Looks like a function with a set argument list, so just cast any
  1136. // argument we need to
  1137. type_needed = *(token_arg_list[token]+token_number_to_destroy[token]-destroyed);
  1138. }
  1139. if(token_variable_type[other_token] != type_needed)
  1140. {
  1141. // Don't insert ToInt or ToFloat for equates...
  1142. if(token_opcode[token] != OPCODE_EQUALS && token_opcode[token] != OPCODE_F_EQUALS)
  1143. {
  1144. token_change_type[other_token] = type_needed;
  1145. }
  1146. }
  1147. }
  1148. }
  1149. }
  1150. last_return_type = token_variable_type[token];
  1151. }
  1152. // Make sure we had the correct number of arguments
  1153. total_destroyed = 0;
  1154. repeat(i, token_count)
  1155. {
  1156. token = token_priority_list[i];
  1157. if(token_opcode[token] == OPCODE_EQUALS || token_opcode[token] == OPCODE_F_EQUALS) token_number_to_destroy[token]++;
  1158. if(token_number_to_destroy[token] >= 0) token_number_to_destroy[token]--;
  1159. total_destroyed += token_number_to_destroy[token];
  1160. #ifdef VERBOSE_COMPILE
  1161. log_message("INFO: RPN: %s DES: %d", token_buffer[token], token_number_to_destroy[token]);
  1162. #endif
  1163. }
  1164. #ifdef VERBOSE_COMPILE
  1165. log_message("INFO: ");
  1166. #endif
  1167. if(total_destroyed != -1)
  1168. {
  1169. log_message("ERROR: Line %d, Wrong number of arguments (%d to %d)", sdf_read_line_number, total_destroyed, -1);
  1170. found_error = TRUE;
  1171. }
  1172. // Debug stuff...
  1173. #ifdef VERBOSE_COMPILE
  1174. repeat(i, token_count)
  1175. {
  1176. token = token_priority_list[i];
  1177. log_message("INFO: TYP: %c CHG: %c RPN: %s", token_variable_type[token], token_change_type[token], token_buffer[token]);
  1178. }
  1179. log_message("INFO: ");
  1180. #endif
  1181. }
  1182. //-----------------------------------------------------------------------------------------------
  1183. int src_find_function_entry(unsigned char* filedata, char* functionname)
  1184. {
  1185. // <ZZ> This function searches a .RUN file's header for a given function, and returns
  1186. // the function's entry (offset in the header) if it finds a match. If there weren't
  1187. // any matches, it returns 0. Functionname should be all uppercase...
  1188. int number_of_functions;
  1189. int i;
  1190. unsigned char* filedatastart;
  1191. // For each function in the header...
  1192. filedatastart = filedata;
  1193. filedata+=MAX_FAST_FUNCTION<<1; // Skip the fast function lookups...
  1194. number_of_functions = sdf_read_unsigned_short(filedata);
  1195. filedata+=4;
  1196. repeat(i, number_of_functions)
  1197. {
  1198. // Check for a match...
  1199. if(strcmp(functionname, (filedata+2)) == 0)
  1200. {
  1201. return (filedata-filedatastart);
  1202. }
  1203. // Go to the next entry
  1204. filedata+=2; // Skip the address
  1205. filedata+=strlen(filedata)+1; // Skip the name and 0
  1206. filedata+=strlen(filedata)+1; // Skip the return and any arguments and 0
  1207. }
  1208. // Didn't find a match
  1209. return 0;
  1210. }
  1211. //-----------------------------------------------------------------------------------------------
  1212. int src_find_string_entry(unsigned char* filedata, char* stringname)
  1213. {
  1214. // <ZZ> This function searches a .RUN file's header for a given string, and returns
  1215. // the string's entry (offset in the header) if it finds a match. If there weren't
  1216. // any matches, it returns 0.
  1217. int number_of_functions;
  1218. int number_of_strings;
  1219. int i;
  1220. unsigned short j;
  1221. unsigned char* filedatastart;
  1222. #ifdef VERBOSE_COMPILE
  1223. log_message("INFO: Looking for string %s...", stringname);
  1224. #endif
  1225. // For each function in the header...
  1226. filedatastart = filedata;
  1227. filedata+=MAX_FAST_FUNCTION<<1; // Skip the fast function lookups...
  1228. number_of_functions = sdf_read_unsigned_short(filedata);
  1229. filedata+=2;
  1230. number_of_strings = sdf_read_unsigned_short(filedata);
  1231. filedata+=2;
  1232. repeat(i, number_of_functions)
  1233. {
  1234. // Go to the next entry
  1235. filedata+=2; // Skip the address
  1236. filedata+=strlen(filedata)+1; // Skip the name and 0
  1237. filedata+=strlen(filedata)+1; // Skip the return and any arguments and 0
  1238. }
  1239. repeat(i, number_of_strings)
  1240. {
  1241. // Only return strings that haven't been returned yet... FFFF offset...
  1242. j = sdf_read_unsigned_short(filedata);
  1243. if(j == 65535)
  1244. {
  1245. // Check for a match...
  1246. if(strcmp(stringname, filedata+2) == 0)
  1247. {
  1248. #ifdef VERBOSE_COMPILE
  1249. log_message("INFO: Found string %s at 0x%x", stringname, (filedata-filedatastart));
  1250. #endif
  1251. sdf_write_unsigned_short(filedata, 0);
  1252. return (filedata-filedatastart);
  1253. }
  1254. }
  1255. // Go to the next entry
  1256. filedata+=2; // Skip the address
  1257. filedata+=strlen(filedata)+1; // Skip the name and 0
  1258. }
  1259. // Didn't find a match
  1260. return 0;
  1261. }
  1262. //-----------------------------------------------------------------------------------------------
  1263. unsigned char* src_mega_find_function(unsigned char* functionstring, unsigned char* filename, unsigned char request)
  1264. {
  1265. // <ZZ> This function may only be called after a complete headerize has been performed. It
  1266. // determines the header entry location of a function based on a "file.function" type
  1267. // string or just a "function" string, and then returns a bit of requested information
  1268. // about that function. Filename is the name of the file in which the string was found,
  1269. // not necessarily the file the function is found in. It returns NULL if no matching
  1270. // function could be found.
  1271. unsigned char* functionname;
  1272. unsigned char must_fix_dot;
  1273. unsigned char* data;
  1274. unsigned int entry_offset;
  1275. unsigned char* entry;
  1276. unsigned char* index;
  1277. // Split a two part string into two parts by figuring out where the dot is...
  1278. must_fix_dot = FALSE;
  1279. functionname = strpbrk(functionstring, ".");
  1280. if(functionname != NULL)
  1281. {
  1282. // Found a dot, so we should have an explicit filename...
  1283. filename = functionstring;
  1284. *functionname = 0; // Split into two strings...
  1285. must_fix_dot = TRUE; // ...But remember to put the dot back later...
  1286. functionname++;
  1287. }
  1288. else
  1289. {
  1290. // No dot, so it's just a function name, no file name
  1291. functionname = functionstring;
  1292. }
  1293. // Open the file that we think it's in...
  1294. entry = NULL;
  1295. index = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
  1296. if(index != NULL)
  1297. {
  1298. // Found the file, so now look for the function
  1299. data = (unsigned char*) sdf_read_unsigned_int(index);
  1300. entry_offset = src_find_function_entry(data, functionname);
  1301. if(entry_offset)
  1302. {
  1303. entry = data + entry_offset;
  1304. }
  1305. }
  1306. if(entry == NULL)
  1307. {
  1308. // Didn't find the function on our first guess, so let's check GENERIC.RUN
  1309. if(must_fix_dot == FALSE)
  1310. {
  1311. index = sdf_find_filetype("GENERIC", SDF_FILE_IS_RUN);
  1312. if(index != NULL)
  1313. {
  1314. // Found the file, so now look for the function
  1315. data = (unsigned char*) sdf_read_unsigned_int(index);
  1316. entry_offset = src_find_function_entry(data, functionname);
  1317. if(entry_offset)
  1318. {
  1319. entry = data + entry_offset;
  1320. }
  1321. }
  1322. }
  1323. }
  1324. // Put the dot back if we took it out...
  1325. if(must_fix_dot)
  1326. {
  1327. *(functionname-1) = '.';
  1328. }
  1329. // Now see about filling the request...
  1330. if(entry != NULL)
  1331. {
  1332. // Found the function's entry in the RUN file... So log it...
  1333. #ifdef VERBOSE_COMPILE
  1334. log_message("INFO: Mega_found function %s", functionstring);
  1335. #endif
  1336. // And return whatever was requested...
  1337. if(request == SRC_REQUEST_ENTRY)
  1338. {
  1339. return entry;
  1340. }
  1341. if(request == SRC_REQUEST_OFFSET)
  1342. {
  1343. return (data+sdf_read_unsigned_short(entry));
  1344. }
  1345. if(request == SRC_REQUEST_ARGUMENTS)
  1346. {
  1347. entry+=2; // Skip the offset
  1348. entry+=strlen(entry)+1; // Skip the function name
  1349. return entry; // Return a pointer to the arguments
  1350. }
  1351. if(request == SRC_REQUEST_FILESTART)
  1352. {
  1353. return data;
  1354. }
  1355. }
  1356. return NULL;
  1357. }
  1358. //-----------------------------------------------------------------------------------------------
  1359. void src_make_arrays(int token_count, char* filename)
  1360. {
  1361. // <ZZ> This function helps the RPN code figure out what a given token is. It breaks tokens
  1362. // into operands, functions, and operators (filling in the corresponding flag arrays).
  1363. int i;
  1364. int j;
  1365. int length;
  1366. char* dotread;
  1367. // Clear out the order of operation for Reverse Polish Notation
  1368. line_is_a_conditional = FALSE;
  1369. repeat(i, token_count)
  1370. {
  1371. token_priority[i] = 0;
  1372. token_variable_type[i] = VAR_INVALID;
  1373. token_change_type[i] = VAR_INVALID;
  1374. token_arg_list[i] = NULL;
  1375. token_is_string[i] = FALSE;
  1376. }
  1377. // Figure out the opcode for each token, and what type of token it is...
  1378. repeat(i, token_count)
  1379. {
  1380. token_opcode[i] = OPCODE_CALLFUNCTION;
  1381. token_extension[i] = -1;
  1382. token_number_to_destroy[i] = 0;
  1383. if(strcmp(token_buffer[i], "=") == 0) { token_opcode[i] = OPCODE_EQUALS; token_number_to_destroy[i] = 1; }
  1384. if(strcmp(token_buffer[i], "+") == 0) { token_opcode[i] = OPCODE_ADD; token_number_to_destroy[i] = 2; }
  1385. if(strcmp(token_buffer[i], "-") == 0) { token_opcode[i] = OPCODE_SUBTRACT; token_number_to_destroy[i] = 2; }
  1386. if(strcmp(token_buffer[i], "*") == 0) { token_opcode[i] = OPCODE_MULTIPLY; token_number_to_destroy[i] = 2; }
  1387. if(strcmp(token_buffer[i], "/") == 0) { token_opcode[i] = OPCODE_DIVIDE; token_number_to_destroy[i] = 2; }
  1388. if(strcmp(token_buffer[i], "++") == 0) { token_opcode[i] = OPCODE_INCREMENT; token_number_to_destroy[i] = 1; }
  1389. if(strcmp(token_buffer[i], "--") == 0) { token_opcode[i] = OPCODE_DECREMENT; token_number_to_destroy[i] = 1; }
  1390. if(strcmp(token_buffer[i], "==") == 0) { token_opcode[i] = OPCODE_ISEQUAL; token_number_to_destroy[i] = 2; }
  1391. if(strcmp(token_buffer[i], "!=") == 0) { token_opcode[i] = OPCODE_ISNOTEQUAL; token_number_to_destroy[i] = 2; }
  1392. if(strcmp(token_buffer[i], ">=") == 0) { token_opcode[i] = OPCODE_ISGREATEREQUAL; token_number_to_destroy[i] = 2; }
  1393. if(strcmp(token_buffer[i], "<=") == 0) { token_opcode[i] = OPCODE_ISLESSEREQUAL; token_number_to_destroy[i] = 2; }
  1394. if(strcmp(token_buffer[i], ">") == 0) { token_opcode[i] = OPCODE_ISGREATER; token_number_to_destroy[i] = 2; }
  1395. if(strcmp(token_buffer[i], "<") == 0) { token_opcode[i] = OPCODE_ISLESSER; token_number_to_destroy[i] = 2; }
  1396. if(strcmp(token_buffer[i], "&&") == 0) { token_opcode[i] = OPCODE_LOGICALAND; token_number_to_destroy[i] = 2; }
  1397. if(strcmp(token_buffer[i], "||") == 0) { token_opcode[i] = OPCODE_LOGICALOR; token_number_to_destroy[i] = 2; }
  1398. if(strcmp(token_buffer[i], "!") == 0) { token_opcode[i] = OPCODE_LOGICALNOT; token_number_to_destroy[i] = 1; }
  1399. if(strcmp(token_buffer[i], "&") == 0) { token_opcode[i] = OPCODE_BITWISEAND; token_number_to_destroy[i] = 2; }
  1400. if(strcmp(token_buffer[i], "|") == 0) { token_opcode[i] = OPCODE_BITWISEOR; token_number_to_destroy[i] = 2; }
  1401. if(strcmp(token_buffer[i], "<<") == 0) { token_opcode[i] = OPCODE_BITWISELEFT; token_number_to_destroy[i] = 2; }
  1402. if(strcmp(token_buffer[i], ">>") == 0) { token_opcode[i] = OPCODE_BITWISERIGHT; token_number_to_destroy[i] = 2; }
  1403. if(strcmp(token_buffer[i], "%") == 0) { token_opcode[i] = OPCODE_MODULUS; token_number_to_destroy[i] = 2; }
  1404. // Subtract and Negate use the same symbol, '-', so see if it's a Negate...
  1405. if(token_opcode[i] == OPCODE_SUBTRACT)
  1406. {
  1407. // Check the value to the left...
  1408. if(i > 0)
  1409. {
  1410. if(token_is_operand[i-1] == FALSE && token_buffer[i-1][0] != ')')
  1411. {
  1412. // It's a negate...
  1413. token_opcode[i] = OPCODE_NEGATE;
  1414. token_number_to_destroy[i] = 1;
  1415. }
  1416. }
  1417. }
  1418. // We should now know if it's an operator or not...
  1419. token_is_operator[i] = (token_opcode[i] != OPCODE_CALLFUNCTION);
  1420. // Are we still looking?
  1421. if(token_opcode[i] == OPCODE_CALLFUNCTION)
  1422. {
  1423. // Yup... Maybe it's an integer or a float...
  1424. if(token_buffer[i][0] == 'I')
  1425. {
  1426. j = -1;
  1427. if(token_buffer[i][1] >= '0' && token_buffer[i][1] <= '9')
  1428. {
  1429. j = token_buffer[i][1] - '0';
  1430. if(token_buffer[i][2] >= '0' && token_buffer[i][2] <= '9')
  1431. {
  1432. j = j * 10;
  1433. j += token_buffer[i][2] - '0';
  1434. }
  1435. if(token_buffer[i][2] == '.')
  1436. {
  1437. sscanf(token_buffer[i]+3, "%d", &token_extension[i]);
  1438. }
  1439. if(token_buffer[i][3] == '.' && token_buffer[i][2] != 0)
  1440. {
  1441. sscanf(token_buffer[i]+4, "%d", &token_extension[i]);
  1442. }
  1443. token_variable_type[i] = VAR_INT;
  1444. }
  1445. if(j >= 0 && j < MAX_VARIABLE) token_opcode[i] = 128 + j;
  1446. if(token_extension[i] > -1)
  1447. {
  1448. // It's a property... Set the variable type correctly...
  1449. token_opcode[i] += 32;
  1450. if(property_type[token_extension[i]] == 'F')
  1451. {
  1452. token_variable_type[i] = VAR_FLOAT;
  1453. }
  1454. }
  1455. token_number_to_destroy[i] = -1;
  1456. }
  1457. if(token_buffer[i][0] == 'F')
  1458. {
  1459. j = -1;
  1460. if(token_buffer[i][1] >= '0' && token_buffer[i][1] <= '9')
  1461. {
  1462. j = token_buffer[i][1] - '0';
  1463. if(token_buffer[i][2] >= '0' && token_buffer[i][2] <= '9')
  1464. {
  1465. j = j * 10;
  1466. j += token_buffer[i][2] - '0';
  1467. }
  1468. token_variable_type[i] = VAR_FLOAT;
  1469. }
  1470. if(j >= 0 && j < MAX_VARIABLE) token_opcode[i] = 192 + j;
  1471. token_number_to_destroy[i] = -1;
  1472. }
  1473. }
  1474. // Are we still looking?
  1475. if(token_opcode[i] == OPCODE_CALLFUNCTION)
  1476. {
  1477. // Yup... Maybe it's a numerical token...
  1478. if((token_buffer[i][0] >= '0' && token_buffer[i][0] <= '9') || token_buffer[i][0] == '-')
  1479. {
  1480. // Does it have a dot?
  1481. dotread = strpbrk(token_buffer[i], ".");
  1482. if(dotread != NULL)
  1483. {
  1484. // Treat it as a numerical float
  1485. sscanf(token_buffer[i], "%f", (float *) (&token_extension[i]));
  1486. token_opcode[i] = 230;
  1487. if(strcmp(token_buffer[i], "1.0") == 0) token_opcode[i] = 226;
  1488. if(strcmp(token_buffer[i], "1.00") == 0) token_opcode[i] = 226;
  1489. if(strcmp(token_buffer[i], "1.000") == 0) token_opcode[i] = 226;
  1490. if(strcmp(token_buffer[i], "1.0000") == 0) token_opcode[i] = 226;
  1491. token_variable_type[i] = VAR_FLOAT;
  1492. }
  1493. else
  1494. {
  1495. // Treat it as a numerical integer
  1496. sscanf(token_buffer[i], "%d", &token_extension[i]);
  1497. token_opcode[i] = 228;
  1498. if(token_extension[i] >= -128 && token_extension[i] <= 127) token_opcode[i] = 227;
  1499. if(token_extension[i] < -32768 || token_extension[i] > 32767) token_opcode[i] = 229;
  1500. if(token_extension[i] == 0) token_opcode[i] = 224;
  1501. if(token_extension[i] == 1) token_opcode[i] = 225;
  1502. token_variable_type[i] = VAR_INT;
  1503. }
  1504. token_number_to_destroy[i] = -1;
  1505. }
  1506. }
  1507. // Are we still looking?
  1508. if(token_opcode[i] == OPCODE_CALLFUNCTION)
  1509. {
  1510. // Yup... Maybe it's a string... Treat as a 4 byte integer...
  1511. if(token_buffer[i][0] == '"')
  1512. {
  1513. // Cut of the last " mark...
  1514. length = strlen(token_buffer[i]+1);
  1515. token_buffer[i][length] = 0;
  1516. // Figure out the offset of the string in memory... 2 to skip address in header...
  1517. token_extension[i] = src_find_string_entry(src_buffer, token_buffer[i]+1)+2;
  1518. token_variable_type[i] = VAR_INT;
  1519. // Need to go back through these during functionize...
  1520. // ...But in order to do that, we need to remember where the opcode is...
  1521. // ...But we don't know where it is yet, so we'll have to wait 'til later...
  1522. token_is_string[i] = TRUE;
  1523. token_opcode[i] = 229;
  1524. // Put the " mark back on... Just in case there's something weird I forgot about...
  1525. token_buffer[i][length] = '"';
  1526. token_number_to_destroy[i] = -1;
  1527. }
  1528. }
  1529. // We should now know if it's a function or not...
  1530. token_is_function[i] = (token_opcode[i] == OPCODE_CALLFUNCTION);
  1531. // We should now know if it's an operand or not...
  1532. token_is_operand[i] = 1 - token_is_function[i] - token_is_operator[i];
  1533. if(token_buffer[i][0] == ',' || token_buffer[i][0] == '(' || token_buffer[i][0] == ')')
  1534. {
  1535. token_is_operator[i] = FALSE;
  1536. token_is_function[i] = FALSE;
  1537. token_is_operand[i] = FALSE;
  1538. token_variable_type[i] = VAR_INVALID;
  1539. token_number_to_destroy[i] = 0;
  1540. }
  1541. // Are we still looking?
  1542. if(token_is_function[i])
  1543. {
  1544. // Yup... Maybe it's a basic function...
  1545. 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; }
  1546. 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; }
  1547. if(strcmp(token_buffer[i], "ELSE") == 0) { line_is_a_conditional = TRUE; }
  1548. 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; }
  1549. 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; }
  1550. 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; }
  1551. 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; }
  1552. 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; }
  1553. 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; }
  1554. 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; }
  1555. 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; }
  1556. 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; }
  1557. 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; }
  1558. 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; }
  1559. 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; }
  1560. 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; }
  1561. 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; }
  1562. 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; }
  1563. 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; }
  1564. 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; }
  1565. 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; }
  1566. 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; }
  1567. 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; }
  1568. 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; }
  1569. 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; }
  1570. 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;}
  1571. 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; }
  1572. // String functions...
  1573. 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; }
  1574. 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; }
  1575. 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; }
  1576. 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; }
  1577. 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; }
  1578. 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; }
  1579. 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; }
  1580. 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; }
  1581. 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; }
  1582. 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...
  1583. 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...
  1584. 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; }
  1585. 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; }
  1586. 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; }
  1587. 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; }
  1588. 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; }
  1589. // Window functions
  1590. 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; }
  1591. 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; }
  1592. 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; }
  1593. 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; }
  1594. 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; }
  1595. 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; }
  1596. 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; }
  1597. 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; }
  1598. 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; }
  1599. 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; }
  1600. 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; }
  1601. 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; }
  1602. 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; }
  1603. 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; }
  1604. 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; }
  1605. 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; }
  1606. 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; }
  1607. 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; }
  1608. // Other functions...
  1609. 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; }
  1610. 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; }
  1611. 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; }
  1612. 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; }
  1613. 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; }
  1614. 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; }
  1615. 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; }
  1616. 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; }
  1617. 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; }
  1618. 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; }
  1619. 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; }
  1620. 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; }
  1621. 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; }
  1622. 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; }
  1623. 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; }
  1624. 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; }
  1625. 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; }
  1626. // Return function...
  1627. if(strcmp(token_buffer[i], "RETURN") == 0)
  1628. {
  1629. token_number_to_destroy[i] = 1;
  1630. if(last_function_returns_integer) { token_opcode[i] = OPCODE_RETURNINT; token_arg_list[i] = arg_list_int; }
  1631. else { token_opcode[i] = OPCODE_RETURNFLOAT; token_arg_list[i] = arg_list_float; }
  1632. }
  1633. // !!!BAD!!!
  1634. // !!!BAD!!!
  1635. // !!!BAD!!! More basic functions
  1636. // !!!BAD!!!
  1637. // !!!BAD!!!
  1638. }
  1639. // Or it might be a user function...
  1640. if(token_is_function[i] && token_opcode[i] == OPCODE_CALLFUNCTION)
  1641. {
  1642. // Ignore else...
  1643. if(strcmp(token_buffer[i], "ELSE") != 0)
  1644. {
  1645. // Search for the function, so we can figure out what arguments it requires...
  1646. token_arg_list[i] = src_mega_find_function(token_buffer[i], filename, SRC_REQUEST_ARGUMENTS);
  1647. if(token_arg_list[i])
  1648. {
  1649. token_variable_type[i] = token_arg_list[i][0];
  1650. token_arg_list[i]++; // Skip the return code
  1651. token_number_to_destroy[i] = strlen(token_arg_list[i]);
  1652. }
  1653. else
  1654. {
  1655. // Function not found...
  1656. log_message("ERROR: Line %d, Unrecognized symbol %s found", sdf_read_line_number, token_buffer[i]);
  1657. found_error = TRUE;
  1658. }
  1659. }
  1660. }
  1661. }
  1662. }
  1663. //-----------------------------------------------------------------------------------------------
  1664. signed char src_functionize(unsigned char* index, char* filename)
  1665. {
  1666. // <ZZ> This function fills in the CallFunction addresses for a single file. If it finds
  1667. // an error, the file is deleted... This is the last stage of SRC compilation, sorta
  1668. // like a linker stage... Returns FALSE if it had trouble, TRUE if not.
  1669. unsigned char* datastart;
  1670. unsigned char* data;
  1671. unsigned char* lastdata;
  1672. unsigned char* calladdress;
  1673. unsigned char* addresslocation;
  1674. unsigned short number_of_functions;
  1675. unsigned short number_of_strings;
  1676. unsigned char opcode;
  1677. unsigned short offset;
  1678. unsigned int file_index;
  1679. int i, j;
  1680. unsigned char newfilename[9], newfiletype;
  1681. // Log what we're doing
  1682. #ifdef DEVTOOL
  1683. log_message("INFO: Functionizing %s.RUN", filename);
  1684. #endif
  1685. found_error = FALSE;
  1686. // Figure out where our data is, and where it stops
  1687. data = (unsigned char*) sdf_read_unsigned_int(index);
  1688. lastdata = data + (sdf_read_unsigned_int(index+4) & 0x00FFFFFF);
  1689. datastart = data;
  1690. // Skip over the header data for this RUN file...
  1691. data+=MAX_FAST_FUNCTION<<1; // Skip the fast function lookups...
  1692. number_of_functions = sdf_read_unsigned_short(data);
  1693. data+=2;
  1694. number_of_strings = sdf_read_unsigned_short(data);
  1695. data+=2;
  1696. repeat(i, number_of_functions)
  1697. {
  1698. // Check the name to see if it's one of the fast functions...
  1699. j = -1;
  1700. if(strcmp(data+2, "SPAWN") == 0) j = FAST_FUNCTION_SPAWN;
  1701. else if(strcmp(data+2, "REFRESH") == 0) j = FAST_FUNCTION_REFRESH;
  1702. else if(strcmp(data+2, "EVENT") == 0) j = FAST_FUNCTION_EVENT;
  1703. else if(strcmp(data+2, "AISCRIPT") == 0) j = FAST_FUNCTION_AISCRIPT;
  1704. else if(strcmp(data+2, "BUTTONEVENT") == 0) j = FAST_FUNCTION_BUTTONEVENT;
  1705. else if(strcmp(data+2, "GETNAME") == 0) j = FAST_FUNCTION_GETNAME;
  1706. else if(strcmp(data+2, "UNPRESSED") == 0) j = FAST_FUNCTION_UNPRESSED;
  1707. else if(strcmp(data+2, "FRAMEEVENT") == 0) j = FAST_FUNCTION_FRAMEEVENT;
  1708. else if(strcmp(data+2, "MODELSETUP") == 0) j = FAST_FUNCTION_MODELSETUP;
  1709. else if(strcmp(data+2, "DEFENSERATING") == 0) j = FAST_FUNCTION_DEFENSERATING;
  1710. else if(strcmp(data+2, "SETUP") == 0) j = FAST_FUNCTION_SETUP;
  1711. else if(strcmp(data+2, "DIRECTUSAGE") == 0) j = FAST_FUNCTION_DIRECTUSAGE;
  1712. else if(strcmp(data+2, "ENCHANTUSAGE") == 0) j = FAST_FUNCTION_ENCHANTUSAGE;
  1713. // !!!BAD!!!
  1714. // !!!BAD!!!
  1715. // !!!BAD!!! More fast functions go here...
  1716. // !!!BAD!!!
  1717. // !!!BAD!!!
  1718. // !!!BAD!!!
  1719. if(j != -1)
  1720. {
  1721. // It is a fast function, so fill in the look up table with it's entry point...
  1722. *(datastart+j) = *(data);
  1723. *(datastart+j+1) = *(data+1);
  1724. }
  1725. // Go to the next entry
  1726. data+=2; // Skip the address
  1727. data+=strlen(data)+1; // Skip the name and 0
  1728. data+=strlen(data)+1; // Skip the return and any arguments and 0
  1729. }
  1730. repeat(i, number_of_strings)
  1731. {
  1732. // Check each string...
  1733. offset = sdf_read_unsigned_short(data);
  1734. if(data[2] == 'F' && data[3] == 'I' && data[4] == 'L' && data[5] == 'E' && data[6] == ':')
  1735. {
  1736. // It's a weird "FILE:BLAH.BLA" type of string
  1737. file_index = (unsigned int) sdf_find_index(data+2+5);
  1738. if(file_index)
  1739. {
  1740. file_index = sdf_read_unsigned_int((unsigned char*) file_index);
  1741. #ifdef VERBOSE_COMPILE
  1742. log_message("INFO: Found file %s at 0x%x", data+2+5, file_index);
  1743. #endif
  1744. sdf_write_unsigned_int(datastart+offset, file_index);
  1745. }
  1746. else
  1747. {
  1748. #ifdef VERBOSE_COMPILE
  1749. log_message("INFO: File %s couldn't be found", data+2+5);
  1750. #endif
  1751. if(sdf_fix_filename(data+2+5, newfilename, &newfiletype))
  1752. {
  1753. if(newfiletype == SDF_FILE_IS_RUN)
  1754. {
  1755. // Probably in a spawn, so we don't need to kill the file...
  1756. #ifdef VERBOSE_COMPILE
  1757. log_message("INFO: Writing a NULL value for RUN file");
  1758. #endif
  1759. sdf_write_unsigned_int(datastart+offset, 0);
  1760. }
  1761. else
  1762. {
  1763. log_message("ERROR: File %s couldn't be found", data+2+5);
  1764. found_error = TRUE;
  1765. }
  1766. }
  1767. else
  1768. {
  1769. log_message("ERROR: File %s couldn't be found", data+2+5);
  1770. found_error = TRUE;
  1771. }
  1772. }
  1773. }
  1774. else
  1775. {
  1776. // It's a normal "BLAH BLAH BLAH" type of string
  1777. #ifdef VERBOSE_COMPILE
  1778. log_message("INFO: Found string %s at 0x%x", data+2, (data+2));
  1779. #endif
  1780. sdf_write_unsigned_int(datastart+offset, (unsigned int) (data+2));
  1781. }
  1782. // Go to the next entry
  1783. data+=2; // Skip the address
  1784. data+=strlen(data)+1; // Skip the name and 0
  1785. }
  1786. // Now we're at the start of the opcodes... Go through every opcode, looking for
  1787. // OPCODE_CALLFUNCTION, and stick in the correct address...
  1788. while(data < lastdata && found_error == FALSE)
  1789. {
  1790. // Read the opcode
  1791. opcode = *data;
  1792. #ifdef VERBOSE_COMPILE
  1793. log_message("INFO: FUNC-OP: 0x%02x at 0x%04x", opcode, data-datastart);
  1794. #endif
  1795. data++;
  1796. if(opcode == OPCODE_CALLFUNCTION)
  1797. {
  1798. // Make sure there's still data left to read, before reading the extension...
  1799. if(data < lastdata-19)
  1800. {
  1801. // Check for errors in the extension...
  1802. addresslocation = data;
  1803. // Spit out debug info...
  1804. #ifdef VERBOSE_COMPILE
  1805. log_message("INFO: Function %s at 0x%04x", data+16, data-datastart+16);
  1806. log_message("INFO: Address at: 0x%04x", data-datastart);
  1807. log_message("INFO: Return at: 0x%04x", data-datastart+4);
  1808. log_message("INFO: Arguments at: 0x%04x", data-datastart+8);
  1809. log_message("INFO: File Start at: 0x%04x", data-datastart+12);
  1810. #endif
  1811. // Skip the call address, return address, argument address, and filestart address...
  1812. // Data should now be at the function name
  1813. data+=16;
  1814. // Fill in the call address...
  1815. calladdress = src_mega_find_function(data, filename, SRC_REQUEST_OFFSET);
  1816. sdf_write_unsigned_int(addresslocation, (unsigned int) calladdress);
  1817. // Error check...
  1818. if(calladdress == NULL)
  1819. {
  1820. #ifdef VERBOSE_COMPILE
  1821. log_message("INFO: Couldn't find function %s", data);
  1822. #endif
  1823. // Don't destroy file, because a null address should just be ignored...
  1824. }
  1825. // Fill in the argument address... +1 to ignore return value...
  1826. calladdress = src_mega_find_function(data, filename, SRC_REQUEST_ARGUMENTS)+1;
  1827. sdf_write_unsigned_int(addresslocation+8, (unsigned int) calladdress);
  1828. // Fill in the filestart address...
  1829. calladdress = src_mega_find_function(data, filename, SRC_REQUEST_FILESTART);
  1830. sdf_write_unsigned_int(addresslocation+12, (unsigned int) calladdress);
  1831. // Skip the function name and the trailing zero
  1832. data+=strlen(data)+1;
  1833. // Fill in the return address...
  1834. sdf_write_unsigned_int(addresslocation+4, (unsigned int) data);
  1835. }
  1836. else
  1837. {
  1838. log_message("ERROR: Ran out of data while parsing %s.RUN", filename);
  1839. found_error = TRUE;
  1840. }
  1841. }
  1842. else
  1843. {
  1844. // Skip over the extensions of the boring non-function opcodes...
  1845. if(opcode == OPCODE_JUMP || opcode == OPCODE_IFFALSEJUMP) data+=2;
  1846. if((opcode & 224) == 160) data+=1; // integer.property...
  1847. if((opcode & 224) == 224)
  1848. {
  1849. // Extended information...
  1850. if(opcode == 227) data++; // 1 byte integer
  1851. if(opcode == 228) data+=2; // 2 byte integer
  1852. if(opcode == 229) data+=4; // 4 byte integer
  1853. if(opcode == 230) data+=4; // 4 byte float
  1854. }
  1855. }
  1856. i++;
  1857. }
  1858. // Delete the RUN file if there are any linking errors...
  1859. if(found_error)
  1860. {
  1861. log_message("FOUND: Found error functionizing %s.RUN", filename);
  1862. free(datastart);
  1863. *(index+4) = SDF_FILE_IS_UNUSED;
  1864. return FALSE;
  1865. }
  1866. return TRUE;
  1867. }
  1868. //-----------------------------------------------------------------------------------------------
  1869. #ifdef DEVTOOL
  1870. signed char src_compilerize(unsigned char* index, unsigned char* filename)
  1871. {
  1872. // <ZZ> This function compiles an SRC file that has been stored in memory. Index is a
  1873. // pointer to the start of the file's index in sdf_index, and can be gotten from
  1874. // sdf_find_index. If the function works okay, it should create a new RUN file in the
  1875. // index and return TRUE. It might also delete the original file to save space, but
  1876. // that's a compile time option. If it fails it should return FALSE.
  1877. unsigned char* data; // Original, Headerized data
  1878. unsigned char* newdata; // Compiled data
  1879. unsigned int newsize; // Compiled data
  1880. char tempstring[16];
  1881. signed char keepgoing;
  1882. signed char stillgoing;
  1883. unsigned char indent;
  1884. unsigned char last_indent;
  1885. int i;
  1886. int j;
  1887. int token_count;
  1888. signed char tempnext;
  1889. unsigned char* tempptr;
  1890. unsigned char* oldindex;
  1891. int tempint;
  1892. int tempnum;
  1893. int define;
  1894. unsigned short number_of_functions;
  1895. int function_offset;
  1896. int num_int_variables = 0;
  1897. int num_float_variables = 0;
  1898. char operation_line;
  1899. // Don't create the RUN file if we find any errors...
  1900. found_error = FALSE;
  1901. // Log what we're doing
  1902. #ifdef VERBOSE_COMPILE
  1903. log_message("INFO: Decoding %s.SRC to %s.RUN", filename, filename);
  1904. #endif
  1905. // Undefine any variables and defines used by the last file
  1906. src_undefine_level(SRC_TEMPORARY_FILE);
  1907. // Clear out our jump data...
  1908. repeat(i, SRC_MAX_INDENT)
  1909. {
  1910. last_jump_type_found[i] = SRC_JUMP_INVALID;
  1911. }
  1912. last_indent = 0;
  1913. last_function_returns_integer = TRUE;
  1914. // Remember what variables have been set (for generating errors)
  1915. repeat(i, MAX_VARIABLE)
  1916. {
  1917. float_variable_set[i] = FALSE;
  1918. int_variable_set[i] = FALSE;
  1919. }
  1920. // Copy all of the data from the header (that we already compiled)...
  1921. oldindex = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
  1922. if(oldindex != NULL)
  1923. {
  1924. data = (unsigned char*) sdf_read_unsigned_int(oldindex);
  1925. src_buffer_used = (unsigned short) (sdf_read_unsigned_int(oldindex+4) & 0x00FFFFFF);
  1926. memcpy(src_buffer, data, src_buffer_used);
  1927. }
  1928. else
  1929. {
  1930. // Can't proceed without a header...
  1931. log_message("ERROR: Header file for %s.SRC wasn't generated, can't compile");
  1932. return FALSE;
  1933. }
  1934. // Just like sdf_open...
  1935. sdf_read_first_line = FALSE;
  1936. sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
  1937. sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
  1938. sdf_read_line_number = 0;
  1939. next_token_may_be_negative = TRUE;
  1940. // Make a list of all the functions in this file... Figure out offsets in another pass...
  1941. while(sdf_read_line())
  1942. {
  1943. // Count the indentation (by 2's), and skip over any whitespace...
  1944. indent = count_indentation(sdf_read_file);
  1945. sdf_read_file+=indent;
  1946. sdf_read_remaining-=indent;
  1947. indent = indent>>1;
  1948. // Check for a #define...
  1949. if(sdf_read_file[0] == '#')
  1950. {
  1951. if(sdf_read_file[1] == 'd')
  1952. {
  1953. if(sdf_read_file[2] == 'e')
  1954. {
  1955. if(sdf_read_file[3] == 'f')
  1956. {
  1957. if(sdf_read_file[4] == 'i')
  1958. {
  1959. if(sdf_read_file[5] == 'n')
  1960. {
  1961. if(sdf_read_file[6] == 'e')
  1962. {
  1963. sdf_read_file+=7;
  1964. sdf_read_remaining-=7;
  1965. if(src_read_token(token_buffer[0]))
  1966. {
  1967. src_add_define(token_buffer[0], sdf_read_file, SRC_TEMPORARY_FILE);
  1968. }
  1969. }
  1970. }
  1971. }
  1972. }
  1973. }
  1974. }
  1975. }
  1976. }
  1977. // Just like sdf_open...
  1978. sdf_read_first_line = FALSE;
  1979. sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
  1980. sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
  1981. sdf_read_line_number = 0;
  1982. // For each line in the file...
  1983. number_of_functions = 0;
  1984. while(sdf_read_line())
  1985. {
  1986. // Count the indentation (by 2's), and skip over any whitespace...
  1987. indent = count_indentation(sdf_read_file);
  1988. sdf_read_file+=indent;
  1989. sdf_read_remaining-=indent;
  1990. indent = indent>>1;
  1991. next_token_may_be_negative = TRUE;
  1992. if(sdf_read_file[0] != '#')
  1993. {
  1994. #ifdef VERBOSE_COMPILE
  1995. log_message("INFO: Line %d, %s", sdf_read_line_number, sdf_read_file);
  1996. #endif
  1997. // Get all of the tokens in the line...
  1998. token_count = 0;
  1999. keepgoing = TRUE;
  2000. while(keepgoing)
  2001. {
  2002. keepgoing = FALSE;
  2003. if(token_count < SRC_MAX_TOKEN)
  2004. {
  2005. if(src_read_token(token_buffer[token_count]))
  2006. {
  2007. // Undefine any variables used by the last function
  2008. if(indent == 0 && token_count == 0)
  2009. {
  2010. src_undefine_level(SRC_TEMPORARY_FUNCTION);
  2011. num_int_variables = 0;
  2012. num_float_variables = 0;
  2013. // Remember what variables have been set (for generating errors)
  2014. repeat(i, MAX_VARIABLE)
  2015. {
  2016. float_variable_set[i] = FALSE;
  2017. int_variable_set[i] = FALSE;
  2018. }
  2019. }
  2020. // See if the token is defined
  2021. define = src_get_define(token_buffer[token_count]);
  2022. if(define > -1)
  2023. {
  2024. // Save the read line stuff...
  2025. tempint = sdf_read_remaining;
  2026. tempptr = sdf_read_file;
  2027. tempnum = sdf_read_line_number;
  2028. tempnext = next_token_may_be_negative;
  2029. // Read in all of the tokens in the #define...
  2030. next_token_may_be_negative = TRUE;
  2031. sdf_read_remaining = SRC_MAX_TOKEN_SIZE;
  2032. sdf_read_file = define_value[define];
  2033. stillgoing = TRUE;
  2034. while(stillgoing)
  2035. {
  2036. stillgoing = FALSE;
  2037. if(token_count < SRC_MAX_TOKEN)
  2038. {
  2039. if(src_read_token(token_buffer[token_count]))
  2040. {
  2041. token_count++;
  2042. stillgoing = TRUE;
  2043. }
  2044. }
  2045. }
  2046. token_count--;
  2047. // Restore the read line stuff...
  2048. next_token_may_be_negative = tempnext;
  2049. sdf_read_line_number = tempnum;
  2050. sdf_read_file = tempptr;
  2051. sdf_read_remaining = tempint;
  2052. }
  2053. // See if the token has a dot style property
  2054. tempptr = strpbrk(token_buffer[token_count], ".");
  2055. if(((token_buffer[token_count][0] >= 'A' && token_buffer[token_count][0] <= 'Z') || token_buffer[token_count][0] == '_') && tempptr)
  2056. {
  2057. // Looks like it is... Need to break it into two parts...
  2058. // First find the property extension...
  2059. *tempptr = 0;
  2060. tempint = obj_get_property(tempptr+1);
  2061. define = src_get_define(token_buffer[token_count]);
  2062. if(tempint > -1 && define > -1)
  2063. {
  2064. // Okay, we found the property and variable... Now reguritate 'em
  2065. // If we didn't find anything, it may be an external function...
  2066. sprintf(token_buffer[token_count], "%s.%d", define_value[define], tempint);
  2067. }
  2068. else
  2069. {
  2070. // Must be an external function call... Replace the period we removed...
  2071. *tempptr = '.';
  2072. }
  2073. }
  2074. token_count++;
  2075. keepgoing = TRUE;
  2076. }
  2077. }
  2078. }
  2079. // Did we actually read anything on this line?
  2080. if(token_count > 0)
  2081. {
  2082. // Show me all of the tokens...
  2083. #ifdef VERBOSE_COMPILE
  2084. repeat(i, token_count)
  2085. {
  2086. log_message("INFO: Token == %s", token_buffer[i]);
  2087. }
  2088. log_message("INFO: ");
  2089. #endif
  2090. // Check for errors with if and else and while with nothing after...
  2091. if(line_is_a_conditional == TRUE && indent <= last_indent)
  2092. {
  2093. log_message("ERROR: Line %d, Conditional without a nest", sdf_read_line_number);
  2094. found_error = TRUE;
  2095. }
  2096. // Is this line the start of a function?
  2097. operation_line = TRUE;
  2098. if(indent == 0)
  2099. {
  2100. // It is... Let's write down the offset so we can find it again later...
  2101. operation_line = FALSE;
  2102. if(last_indent > 0)
  2103. {
  2104. // Close out all jumps...
  2105. src_close_jumps(indent, last_indent);
  2106. // Slap in a return 1, just to be on the safe side...
  2107. src_add_return_opcode();
  2108. last_indent = 0;
  2109. }
  2110. // Skip over the return value...
  2111. i = 0;
  2112. last_function_returns_integer = TRUE;
  2113. if(strcmp(token_buffer[0], "INT") == 0) i++;
  2114. if(strcmp(token_buffer[0], "FLOAT") == 0) { last_function_returns_integer = FALSE; i++; }
  2115. // Find the function in the RUN header...
  2116. function_offset = src_find_function_entry(src_buffer, token_buffer[i]);
  2117. if(function_offset)
  2118. {
  2119. // Then write down the offset...
  2120. sdf_write_unsigned_short(src_buffer+function_offset, src_buffer_used);
  2121. number_of_functions++;
  2122. i++;
  2123. // Now define any arguments... #define value i0
  2124. i++; // Skip the parentheses
  2125. while(i < token_count)
  2126. {
  2127. if(strcmp(token_buffer[i], "INT") == 0 && num_int_variables < MAX_VARIABLE)
  2128. {
  2129. i++;
  2130. if(i < token_count)
  2131. {
  2132. sprintf(tempstring, "I%d", num_int_variables);
  2133. src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
  2134. int_variable_set[num_int_variables] = TRUE;
  2135. num_int_variables++;
  2136. }
  2137. }
  2138. else if(strcmp(token_buffer[i], "FLOAT") == 0 && num_float_variables < MAX_VARIABLE)
  2139. {
  2140. i++;
  2141. if(i < token_count)
  2142. {
  2143. sprintf(tempstring, "F%d", num_float_variables);
  2144. src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
  2145. float_variable_set[num_float_variables] = TRUE;
  2146. num_float_variables++;
  2147. }
  2148. }
  2149. i++;
  2150. }
  2151. }
  2152. else
  2153. {
  2154. log_message("ERROR: Line %d, Problem with function %s (corrupt header?)", sdf_read_line_number, token_buffer[i]);
  2155. found_error = TRUE;
  2156. }
  2157. }
  2158. // Check for local int and float declarations... Use temporary defines... I0-I31, F0-F31
  2159. if(indent == 1)
  2160. {
  2161. if(strcmp(token_buffer[0], "INT") == 0)
  2162. {
  2163. operation_line = FALSE;
  2164. i = 1;
  2165. while(i < token_count)
  2166. {
  2167. if(token_buffer[i][0] != ',' && num_int_variables < MAX_VARIABLE)
  2168. {
  2169. sprintf(tempstring, "I%d", num_int_variables);
  2170. src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
  2171. num_int_variables++;
  2172. }
  2173. i++;
  2174. }
  2175. #ifdef VERBOSE_COMPILE
  2176. log_message("INFO: ");
  2177. #endif
  2178. }
  2179. else if(strcmp(token_buffer[0], "FLOAT") == 0)
  2180. {
  2181. operation_line = FALSE;
  2182. i = 1;
  2183. while(i < token_count)
  2184. {
  2185. if(token_buffer[i][0] != ',' && num_float_variables < MAX_VARIABLE)
  2186. {
  2187. sprintf(tempstring, "F%d", num_float_variables);
  2188. src_add_define(token_buffer[i], tempstring, SRC_TEMPORARY_FUNCTION);
  2189. num_float_variables++;
  2190. }
  2191. i++;
  2192. }
  2193. #ifdef VERBOSE_COMPILE
  2194. log_message("INFO: ");
  2195. #endif
  2196. }
  2197. }
  2198. if(operation_line)
  2199. {
  2200. // Must have a conditional to change indentation levels...
  2201. if(indent > last_indent && last_indent != 0)
  2202. {
  2203. if(last_jump_type_found[last_indent] == SRC_JUMP_INVALID)
  2204. {
  2205. // Throw an error
  2206. log_message("ERROR: Line %d, Must have a conditional statement to indent", sdf_read_line_number);
  2207. found_error = TRUE;
  2208. }
  2209. }
  2210. // Going down an indentation level allows us to fill in jump locations...
  2211. src_close_jumps(indent, last_indent);
  2212. // Remember where while's start, because we need to jump back to 'em...
  2213. if(strcmp(token_buffer[0], "WHILE") == 0)
  2214. {
  2215. #ifdef VERBOSE_COMPILE
  2216. log_message("INFO: WHILE BEGINS HERE 0x%x", src_buffer_used);
  2217. #endif
  2218. while_jumps_back_to_here[indent] = src_buffer_used;
  2219. }
  2220. // // Going down an indentation level allows us to fill in jump locations...
  2221. // src_close_jumps(indent, last_indent);
  2222. // Moved this up a couple lines because two whiles in a row would break it...
  2223. // Fixed that problem, but something else mighta broken in the process...
  2224. // Remember indentation level for next time
  2225. last_indent = indent;
  2226. // Clear out the RPN data and fill in some of the helper arrays...
  2227. src_make_arrays(token_count, filename);
  2228. // Figure out the RPN order...
  2229. token_order = 1;
  2230. src_find_priority(0, token_count-1, FALSE, TRUE);
  2231. // Debug stuff
  2232. #ifdef VERBOSE_COMPILE
  2233. repeat(i, token_order-1)
  2234. {
  2235. j = token_priority_list[i];
  2236. log_message("INFO: RPN: %s", token_buffer[j]);
  2237. }
  2238. log_message("INFO: ");
  2239. #endif
  2240. // Figure out type casting based on RPN data...
  2241. src_figure_variable_types(token_order-1);
  2242. // Write out the opcode data...
  2243. src_generate_opcodes(token_order-1);
  2244. // Figure out where to write jump locations and stuff for indentation levels
  2245. if(found_error == FALSE)
  2246. {
  2247. if(strcmp(token_buffer[0], "IF") == 0)
  2248. {
  2249. // Make sure there's an if opcode where it should be...
  2250. if(src_buffer_used >= 5)
  2251. {
  2252. if(src_buffer[src_buffer_used-3] == OPCODE_IFFALSEJUMP)
  2253. {
  2254. put_jump_offset_here[indent] = src_buffer_used-2;
  2255. last_jump_type_found[indent] = SRC_JUMP_IF;
  2256. #ifdef VERBOSE_COMPILE
  2257. log_message("INFO: STARTED A NEW IF STATEMENT");
  2258. #endif
  2259. }
  2260. else
  2261. {
  2262. log_message("ERROR: Line %d, Praxis syllabication error", sdf_read_line_number);
  2263. found_error = TRUE;
  2264. }
  2265. }
  2266. else found_error = TRUE;
  2267. }
  2268. if(strcmp(token_buffer[0], "WHILE") == 0)
  2269. {
  2270. // Make sure there's an if opcode where it should be...
  2271. if(src_buffer_used >= 5)
  2272. {
  2273. if(src_buffer[src_buffer_used-3] == OPCODE_IFFALSEJUMP)
  2274. {
  2275. put_jump_offset_here[indent] = src_buffer_used-2;
  2276. last_jump_type_found[indent] = SRC_JUMP_WHILE;
  2277. #ifdef VERBOSE_COMPILE
  2278. log_message("INFO: STARTED A NEW WHILE STATEMENT");
  2279. #endif
  2280. }
  2281. else
  2282. {
  2283. log_message("ERROR: Line %d, Praxis syllabication error", sdf_read_line_number);
  2284. found_error = TRUE;
  2285. }
  2286. }
  2287. else found_error = TRUE;
  2288. }
  2289. }
  2290. }
  2291. }
  2292. }
  2293. }
  2294. // Clean up any unresolved jumps...
  2295. src_close_jumps(indent, last_indent);
  2296. // Slap in a return 1, just to be on the safe side...
  2297. src_add_return_opcode();
  2298. if(found_error == FALSE)
  2299. {
  2300. //Allocate memory for the new file...
  2301. newsize = src_buffer_used;
  2302. newdata = malloc(newsize);
  2303. if(newdata)
  2304. {
  2305. // Write the index... Should overwrite headerized RUN file...
  2306. sdf_write_unsigned_int(oldindex, (unsigned int) newdata);
  2307. sdf_write_unsigned_int(oldindex+4, newsize);
  2308. *(oldindex+4) = SDF_FILE_IS_RUN;
  2309. repeat(j, 8) { *(oldindex+8+j) = 0; }
  2310. memcpy(oldindex+8, filename, strlen(filename));
  2311. // Copy the data out of the buffer, and free up the old data...
  2312. memcpy(newdata, src_buffer, newsize);
  2313. free(data);
  2314. return TRUE;
  2315. }
  2316. else
  2317. {
  2318. log_message("ERROR: Out of memory while compilerizing %s.SRC", filename);
  2319. }
  2320. }
  2321. else
  2322. {
  2323. log_message("FOUND: Found error compilerizing %s.SRC", filename);
  2324. }
  2325. // Delete the headerized file, since we had trouble...
  2326. free(data);
  2327. *(oldindex+4) = SDF_FILE_IS_UNUSED;
  2328. return FALSE;
  2329. }
  2330. #endif
  2331. //-----------------------------------------------------------------------------------------------
  2332. #ifdef DEVTOOL
  2333. signed char src_headerize(unsigned char* index, unsigned char* filename)
  2334. {
  2335. // <ZZ> This function runs through an SRC file that has been stored in memory and finds
  2336. // function information to store in the header. This must be done for every file
  2337. // before compilation can occur. Index is a pointer to the start of the file's
  2338. // index in sdf_index, and can be gotten from sdf_find_index. If the function
  2339. // works okay, it should create a new RUN file in the index and return TRUE. If
  2340. // it fails it should return FALSE.
  2341. unsigned char* data; // Original, pre-existing RUN file
  2342. unsigned char* newdata; // New header
  2343. unsigned int newsize; // New header
  2344. signed char keepgoing;
  2345. unsigned char indent;
  2346. unsigned short number_of_functions;
  2347. unsigned short number_of_strings;
  2348. int i;
  2349. int j;
  2350. int length;
  2351. int token_count;
  2352. char returncode;
  2353. char make_new_file;
  2354. char read_char;
  2355. int def;
  2356. // Don't create the RUN file if we find any errors...
  2357. found_error = FALSE;
  2358. // Log what we're doing
  2359. #ifdef VERBOSE_COMPILE
  2360. log_message("INFO: Generating header file for %s.SRC", filename);
  2361. #endif
  2362. // Undefine any variables and defines used by the last file
  2363. src_undefine_level(SRC_TEMPORARY_FILE);
  2364. // Just like sdf_open...
  2365. sdf_read_first_line = FALSE;
  2366. sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
  2367. sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
  2368. sdf_read_line_number = 0;
  2369. next_token_may_be_negative = TRUE;
  2370. // Pad the start of the header with fast function offsets...
  2371. src_buffer_used = 0;
  2372. repeat(i, MAX_FAST_FUNCTION)
  2373. {
  2374. // 2 bytes each...
  2375. src_buffer[src_buffer_used] = 0;
  2376. src_buffer_used++;
  2377. src_buffer[src_buffer_used] = 0;
  2378. src_buffer_used++;
  2379. }
  2380. // Something like this in the src_buffer...
  2381. // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  2382. // Make a list of all the functions in this file... Figure out offsets in another pass...
  2383. src_buffer_used+=4; // Skip a word for the string count... Filled in after counting...
  2384. #ifdef VERBOSE_COMPILE
  2385. log_message("INFO: Headerizing functions...");
  2386. #endif
  2387. number_of_functions = 0;
  2388. while(sdf_read_line())
  2389. {
  2390. // Count the indentation (by 2's), and skip over any whitespace...
  2391. indent = count_indentation(sdf_read_file);
  2392. sdf_read_file+=indent;
  2393. sdf_read_remaining-=indent;
  2394. indent = indent>>1;
  2395. // Skip #defines, we're only interested in functions...
  2396. if(sdf_read_file[0] != '#' && indent == 0)
  2397. {
  2398. // Read all of the tokens on this line...
  2399. token_count = 0;
  2400. keepgoing = TRUE;
  2401. while(keepgoing)
  2402. {
  2403. keepgoing = FALSE;
  2404. if(token_count < SRC_MAX_TOKEN)
  2405. {
  2406. if(src_read_token(token_buffer[token_count]))
  2407. {
  2408. #ifdef VERBOSE_COMPILE
  2409. log_message("INFO: Line %d, %s", sdf_read_line_number, token_buffer[token_count]);
  2410. #endif
  2411. token_count++;
  2412. keepgoing = TRUE;
  2413. }
  2414. }
  2415. }
  2416. // Did we read anything?
  2417. if(token_count > 0)
  2418. {
  2419. // Get the return type for the function...
  2420. i = 0;
  2421. returncode = 'I';
  2422. if(strcmp(token_buffer[0], "INT") == 0) { returncode = 'I'; i++; }
  2423. if(strcmp(token_buffer[0], "FLOAT") == 0) { returncode = 'F'; i++; }
  2424. // Make sure the function has parentheses after it
  2425. if(token_buffer[i+1][0] == '(')
  2426. {
  2427. // Now stick the function address and name in our RUN file...
  2428. sprintf((src_buffer+src_buffer_used), "%c%c%s%c", 0, 0, token_buffer[i], 0);
  2429. src_buffer_used += strlen(token_buffer[i]) + 3;
  2430. #ifdef VERBOSE_COMPILE
  2431. log_message("INFO: function... %s()", token_buffer[i]);
  2432. #endif
  2433. // Now store the return code type...
  2434. sprintf((src_buffer+src_buffer_used), "%c", returncode);
  2435. src_buffer_used++;
  2436. // Now store any arguments types...
  2437. i = i+2;
  2438. while(i < token_count)
  2439. {
  2440. if(strcmp(token_buffer[i], "INT") == 0)
  2441. {
  2442. sprintf((src_buffer+src_buffer_used), "I");
  2443. src_buffer_used++;
  2444. }
  2445. else if(strcmp(token_buffer[i], "FLOAT") == 0)
  2446. {
  2447. sprintf((src_buffer+src_buffer_used), "F");
  2448. src_buffer_used++;
  2449. }
  2450. i++;
  2451. }
  2452. // And zero terminate the string...
  2453. sprintf((src_buffer+src_buffer_used), "%c", 0);
  2454. src_buffer_used++;
  2455. number_of_functions++;
  2456. }
  2457. else
  2458. {
  2459. log_message("ERROR: Line %d, function symbol '%s' not followed by ()", sdf_read_line_number, token_buffer[i]);
  2460. found_error = TRUE;
  2461. }
  2462. }
  2463. }
  2464. }
  2465. sdf_write_unsigned_short(src_buffer+(MAX_FAST_FUNCTION<<1), number_of_functions);
  2466. // Something like this in the src_buffer...
  2467. // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  2468. // 00 03 00 00
  2469. // 0 0 D E A T H 00 I F F F I 00
  2470. // 0 0 B L A H 00 V 00
  2471. // 0 0 A T T A C K 00 V I 00
  2472. // Address FunctionName ReturnAndArgumentTypes
  2473. // Check for errors too...
  2474. if(number_of_functions == 0)
  2475. {
  2476. log_message("ERROR: No functions found");
  2477. found_error = TRUE;
  2478. }
  2479. // Now search for any #defines... Just in case someone #define'd a string...
  2480. #ifdef VERBOSE_COMPILE
  2481. log_message("INFO: Headerizing #define's...");
  2482. #endif
  2483. sdf_read_first_line = FALSE;
  2484. sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
  2485. sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
  2486. sdf_read_line_number = 0;
  2487. next_token_may_be_negative = TRUE;
  2488. // Make a list of all the functions in this file... Figure out offsets in another pass...
  2489. while(sdf_read_line())
  2490. {
  2491. // Count the indentation (by 2's), and skip over any whitespace...
  2492. indent = count_indentation(sdf_read_file);
  2493. sdf_read_file+=indent;
  2494. sdf_read_remaining-=indent;
  2495. indent = indent>>1;
  2496. // Check for a #define...
  2497. if(sdf_read_file[0] == '#')
  2498. {
  2499. if(sdf_read_file[1] == 'D')
  2500. {
  2501. if(sdf_read_file[2] == 'E')
  2502. {
  2503. if(sdf_read_file[3] == 'F')
  2504. {
  2505. if(sdf_read_file[4] == 'I')
  2506. {
  2507. if(sdf_read_file[5] == 'N')
  2508. {
  2509. if(sdf_read_file[6] == 'E')
  2510. {
  2511. sdf_read_file+=7;
  2512. sdf_read_remaining-=7;
  2513. if(src_read_token(token_buffer[0]))
  2514. {
  2515. src_add_define(token_buffer[0], sdf_read_file, SRC_TEMPORARY_FILE);
  2516. }
  2517. }
  2518. }
  2519. }
  2520. }
  2521. }
  2522. }
  2523. }
  2524. }
  2525. // Now search for strings to append to the header... Just like above...
  2526. sdf_read_first_line = FALSE;
  2527. sdf_read_remaining = sdf_read_unsigned_int(index+4) & 0x00FFFFFF;
  2528. sdf_read_file = (unsigned char*) sdf_read_unsigned_int(index);
  2529. sdf_read_line_number = 0;
  2530. next_token_may_be_negative = TRUE;
  2531. // Make a list of all the functions in this file... Figure out offsets in another pass...
  2532. #ifdef VERBOSE_COMPILE
  2533. log_message("INFO: Headerizing strings...");
  2534. #endif
  2535. number_of_strings = 0;
  2536. while(sdf_read_line())
  2537. {
  2538. // Count the indentation (by 2's), and skip over any whitespace...
  2539. indent = count_indentation(sdf_read_file);
  2540. sdf_read_file+=indent;
  2541. sdf_read_remaining-=indent;
  2542. indent = indent>>1;
  2543. // Skip #defines, we're only interested in strings...
  2544. if(sdf_read_file[0] != '#' && indent != 0)
  2545. {
  2546. // Read all of the tokens on this line...
  2547. token_count = 0;
  2548. keepgoing = TRUE;
  2549. while(keepgoing)
  2550. {
  2551. keepgoing = FALSE;
  2552. if(token_count < SRC_MAX_TOKEN)
  2553. {
  2554. if(src_read_token(token_buffer[token_count]))
  2555. {
  2556. token_count++;
  2557. keepgoing = TRUE;
  2558. }
  2559. }
  2560. }
  2561. // Look through all of the tokens for a string token...
  2562. repeat(i, token_count)
  2563. {
  2564. // Look for string tokens...
  2565. #ifdef VERBOSE_COMPILE
  2566. log_message("INFO: Token %s", token_buffer[i]);
  2567. #endif
  2568. if(token_buffer[i][0] == '"')
  2569. {
  2570. // Found a string, so put it in the header
  2571. sdf_write_unsigned_short(src_buffer+src_buffer_used, 65535);
  2572. src_buffer_used+=2;
  2573. length = strlen(token_buffer[i]+1)-1;
  2574. repeat(j, length)
  2575. {
  2576. *(src_buffer+src_buffer_used) = token_buffer[i][j+1];
  2577. src_buffer_used++;
  2578. }
  2579. *(src_buffer+src_buffer_used) = 0;
  2580. src_buffer_used++;
  2581. number_of_strings++;
  2582. }
  2583. else
  2584. {
  2585. // Check for #define'd strings...
  2586. def = src_get_define(token_buffer[i]);
  2587. if(def >= 0)
  2588. {
  2589. #ifdef VERBOSE_COMPILE
  2590. log_message("INFO: Sneaky define... %s", define_token[def]);
  2591. #endif
  2592. // It was a sneaky #define... Search for " characters...
  2593. read_char = define_value[def][0];
  2594. j = 0;
  2595. while(read_char != 0)
  2596. {
  2597. if(read_char == '"')
  2598. {
  2599. // Start of a string, so write it into the header...
  2600. sdf_write_unsigned_short(src_buffer+src_buffer_used, 65535);
  2601. src_buffer_used+=2;
  2602. j++;
  2603. read_char = define_value[def][j];
  2604. while(read_char != 0 && read_char != '"')
  2605. {
  2606. *(src_buffer+src_buffer_used) = read_char;
  2607. src_buffer_used++;
  2608. j++;
  2609. read_char = define_value[def][j];
  2610. }
  2611. *(src_buffer+src_buffer_used) = 0;
  2612. src_buffer_used++;
  2613. number_of_strings++;
  2614. if(read_char == 0) j--;
  2615. }
  2616. j++;
  2617. read_char = define_value[def][j];
  2618. }
  2619. }
  2620. }
  2621. }
  2622. }
  2623. }
  2624. sdf_write_unsigned_short(src_buffer+(MAX_FAST_FUNCTION<<1)+2, number_of_strings);
  2625. // Something like this in the src_buffer...
  2626. // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  2627. // 00 03 00 02
  2628. // 0 0 D E A T H 00 I F F F I 00
  2629. // 0 0 B L A H 00 V 00
  2630. // 0 0 A T T A C K 00 V I 00
  2631. // 0 0 B i g B o b i s c o o l 00
  2632. // FF FF T e s t s t r i n g 00
  2633. // FF FF F I L E : T E S T . T X T 00
  2634. // String address String
  2635. // Now copy the header data into a (temporary) RUN file
  2636. if(found_error == FALSE)
  2637. {
  2638. // Do we need to make a new file, or is there an existing RUN file?
  2639. index = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
  2640. if(index != NULL)
  2641. {
  2642. data = (unsigned char*) sdf_read_unsigned_int(index);
  2643. make_new_file = FALSE;
  2644. }
  2645. else
  2646. {
  2647. make_new_file = TRUE;
  2648. // Make sure we have room in the index for a new file
  2649. if(sdf_extra_files <= 0)
  2650. {
  2651. log_message("ERROR: No room left to add file, program must be restarted");
  2652. return FALSE;
  2653. }
  2654. }
  2655. // Allocate memory for the new file...
  2656. newsize = src_buffer_used;
  2657. newdata = malloc(newsize);
  2658. if(newdata)
  2659. {
  2660. // Create a new index if we gotta
  2661. if(make_new_file)
  2662. {
  2663. index = sdf_index+(sdf_num_files<<4);
  2664. sdf_num_files++;
  2665. sdf_extra_files--;
  2666. }
  2667. // Write the index...
  2668. sdf_write_unsigned_int(index, (unsigned int) newdata);
  2669. sdf_write_unsigned_int(index+4, newsize);
  2670. *(index+4) = SDF_FILE_IS_RUN;
  2671. repeat(j, 8) { *(index+8+j) = 0; }
  2672. memcpy(index+8, filename, strlen(filename));
  2673. // Copy the header information to the new location...
  2674. memcpy(newdata, src_buffer, newsize);
  2675. // Get rid of the old RUN data if we replaced it...
  2676. if(make_new_file==FALSE)
  2677. {
  2678. free(data);
  2679. }
  2680. return TRUE;
  2681. }
  2682. else
  2683. {
  2684. log_message("ERROR: Not enough memory to create header");
  2685. }
  2686. }
  2687. log_message("FOUND: Found error headerizing %s.SRC", filename);
  2688. // Had an error, so delete any existing file...
  2689. index = sdf_find_filetype(filename, SDF_FILE_IS_RUN);
  2690. if(index != NULL)
  2691. {
  2692. data = (unsigned char*) sdf_read_unsigned_int(index);
  2693. free(data);
  2694. *(index+4) = SDF_FILE_IS_UNUSED;
  2695. }
  2696. return FALSE;
  2697. }
  2698. #endif
  2699. //-----------------------------------------------------------------------------------------------
  2700. signed char compiler_error = FALSE;
  2701. signed char src_stage_compile(unsigned char stage, unsigned char mask)
  2702. {
  2703. // <ZZ> This function performs one of the three compilation stages for every SRC file we've
  2704. // got. If it hits any errors, it returns FALSE, otherwise it returns TRUE.
  2705. // mask tells us if we want to recompile all files (SDF_ALL) or only the ones
  2706. // that've been updated (SDF_FLAG_WAS_UPDATED).
  2707. int i;
  2708. unsigned char filename[9];
  2709. unsigned char filetype;
  2710. signed char sofarsogood;
  2711. // Go through each file in the index
  2712. log_message("INFO: Performing stage %d of compilation...", stage);
  2713. sofarsogood = TRUE;
  2714. repeat(i, sdf_num_files)
  2715. {
  2716. // Check the type of file to decompress, then hand off to a subroutine...
  2717. if(sdf_index[(i<<4)+4] & mask)
  2718. {
  2719. sdf_get_filename(i, filename, &filetype);
  2720. if(stage == SRC_HEADERIZE && filetype == SDF_FILE_IS_SRC)
  2721. {
  2722. #ifdef DEVTOOL
  2723. sofarsogood = src_headerize(sdf_index+(i<<4), filename) & sofarsogood;
  2724. #else
  2725. log_message("ERROR: Tried to headerize (should only do in devtool)");
  2726. #endif
  2727. }
  2728. if(stage == SRC_COMPILERIZE && filetype == SDF_FILE_IS_SRC)
  2729. {
  2730. #ifdef DEVTOOL
  2731. sofarsogood = src_compilerize(sdf_index+(i<<4), filename) & sofarsogood;
  2732. #else
  2733. log_message("ERROR: Tried to compilerize (should only do in devtool)");
  2734. #endif
  2735. }
  2736. if(stage == SRC_FUNCTIONIZE && filetype == SDF_FILE_IS_RUN)
  2737. {
  2738. sofarsogood = src_functionize(sdf_index+(i<<4), filename) & sofarsogood;
  2739. }
  2740. }
  2741. }
  2742. if(sofarsogood == FALSE)
  2743. {
  2744. log_message("INFO: Had trouble with at least one of the files...");
  2745. compiler_error = TRUE; // for displaying error message
  2746. }
  2747. else log_message("INFO: Completed stage %d of compilation...", stage);
  2748. return sofarsogood;
  2749. }