635 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			635 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
| /****** script.c
 | |
|   This is the test/devel environment for the ts interpreter/scripting language. It provides a basic CLI for entering script to be interpreted live.
 | |
| ******/
 | |
| #include <string.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <ctype.h>
 | |
| #include <limits.h> // ULONG_MAX
 | |
| 
 | |
| #define DIGIT 1
 | |
| #define ALPHA 2
 | |
| 
 | |
| #define VAR_SET 1
 | |
| #define RETURN 2
 | |
| 
 | |
| //#define TEST_FUNC "var1 = 2;\nvar2 = 4;\ndam = 2 * 2 / 2;\n.dam;\n"
 | |
| //#define TEST_FUNC "var1 = 8;\ndam = var1 * 2 / 4;\n.dam;\n"
 | |
| //#define TEST_FUNC "var1 = 2;var2 = 3;var3 = 7;dam = var1 * var2 * var3;dam = dam * var2;.dam;"
 | |
| #define TEST_FUNC "var1 = 2;var2 = 3;var3 = 7;var4 = 22;dam = var1 * var2 * var4 / var3;dam = dam * var2;.dam;"
 | |
| #define TEST_FULL_FUNC "test { var1 = 2;var2 = 3;var3 = 7;dam = var1 * var2 * var3;dam = dam * var2;.dam; }"
 | |
| #define TEST_FUNC_CALL "fcall { var = test();.var; }"
 | |
| #define ROLL_FUNC "roll { var=_roll($_1,$_2);.var; }"
 | |
| 
 | |
| struct Arguments {
 | |
|   const char *arg1;
 | |
|   const char *arg2;
 | |
|   const char *arg3;
 | |
|   const char *arg4;
 | |
| };
 | |
| 
 | |
| typedef char *(*fptr)(char*);
 | |
| 
 | |
| struct FuncTable {
 | |
|   int size;
 | |
|   char **keys;
 | |
|   //void (**func)();
 | |
|   fptr *func;
 | |
| };
 | |
| 
 | |
| struct FuncTable *newFuncTable(int size) {
 | |
|   struct FuncTable *func_table = malloc(sizeof(struct FuncTable));
 | |
|   func_table->size = size;
 | |
|   func_table->keys = malloc(sizeof(char*)*size);
 | |
|   //func_table->func = malloc(sizeof(void*)*size);
 | |
|   func_table->func = malloc(sizeof(fptr*)*size);
 | |
|   return func_table;
 | |
| }
 | |
| 
 | |
| void freeFuncTable(struct FuncTable *func_table) {
 | |
|   free(func_table->keys);
 | |
|   free(func_table->func);
 | |
|   free(func_table);
 | |
| }
 | |
| 
 | |
| int getFuncIndex(struct FuncTable *func_table, char *key) {
 | |
|   unsigned long int func = 0;
 | |
|   int i = 0;
 | |
|   while (func < ULONG_MAX && i < strlen(key)) {
 | |
|     func += key[i++];
 | |
|   }
 | |
|   return func % func_table->size;
 | |
| }
 | |
| 
 | |
| void addFunc(struct FuncTable *func_table, char *key, void(*func)) {
 | |
|   int index = getFuncIndex(func_table, key);
 | |
|   func_table->keys[index] = key;
 | |
|   func_table->func[index] = func;
 | |
| }
 | |
| 
 | |
| fptr runFunc(struct FuncTable *func_table, char *key) {
 | |
|   return func_table->func[getFuncIndex(func_table, key)];
 | |
| }
 | |
| 
 | |
| struct HashTable {
 | |
|   int size;
 | |
|   char **keys;
 | |
|   void **values;
 | |
| };
 | |
| 
 | |
| struct FuncTable *g_functions;
 | |
| 
 | |
| struct HashTable *newHashTable(int size) {
 | |
|   struct HashTable *hash_table = malloc(sizeof(struct HashTable));
 | |
|   hash_table->size = size;
 | |
|   hash_table->keys = malloc(sizeof(char*)*size);
 | |
|   hash_table->values = malloc(sizeof(void*)*size);
 | |
|   return hash_table;
 | |
| }
 | |
| 
 | |
| void freeHashTable(struct HashTable *hash_table) {
 | |
|   free(hash_table->keys);
 | |
|   free(hash_table->values);
 | |
|   free(hash_table);
 | |
| }
 | |
| 
 | |
| int getHashIndex(struct HashTable *hash_table, char *key) {
 | |
|   unsigned long int hash = 0;
 | |
|   int i = 0;
 | |
|   while (hash < ULONG_MAX && i < strlen(key)) {
 | |
|     hash += key[i++];
 | |
|   }
 | |
|   return hash % hash_table->size;
 | |
| }
 | |
| 
 | |
| void addHash(struct HashTable *hash_table, char *key, void *value) {
 | |
|   int index = getHashIndex(hash_table, key);
 | |
|   hash_table->keys[index] = key;
 | |
|   hash_table->values[index] = value;
 | |
| }
 | |
| 
 | |
| void *getHash(struct HashTable *hash_table, char *key) {
 | |
|   return hash_table->values[getHashIndex(hash_table, key)];
 | |
| }
 | |
| 
 | |
| struct VarTable {
 | |
|   int size;
 | |
|   char **keys;
 | |
|   char **values;
 | |
| };
 | |
| struct VarTable *function_table;
 | |
| 
 | |
| char *parseAndCallFunction(struct VarTable *var_table, const char *buffer);
 | |
| 
 | |
| struct VarTable *newVarTable(int size) {
 | |
|   struct VarTable *var_table = malloc(sizeof(struct VarTable));
 | |
|   var_table->size = size;
 | |
|   var_table->keys = malloc(sizeof(char*)*size);
 | |
|   var_table->values = malloc(sizeof(char*)*size);
 | |
|   return var_table;
 | |
| }
 | |
| 
 | |
| void freeVarTable(struct VarTable *var_table) {
 | |
|   // TODO: free key-value pairs
 | |
|   free(var_table->keys);
 | |
|   free(var_table->values);
 | |
|   free(var_table);
 | |
| }
 | |
| 
 | |
| int getVarIndex(struct VarTable *var_table, const char *key) {
 | |
| //  int hash = 0;
 | |
|   unsigned long int hash = 0;
 | |
|   int i = 0;
 | |
|   while (hash < ULONG_MAX && i < strlen(key)) {
 | |
|   //while (i < strlen(key)) {
 | |
|     //hash = hash << 8;
 | |
|     hash += key[i++];
 | |
|   }
 | |
|   return hash % var_table->size;
 | |
| }
 | |
| 
 | |
| void addVar(struct VarTable *var_table, const char *key, char *value) {
 | |
|   int index = getVarIndex(var_table, key);
 | |
|   int key_length = strlen(key)+1;
 | |
|   var_table->keys[index] = malloc(key_length);
 | |
|   memcpy(var_table->keys[index], key, key_length);
 | |
|   int value_length = strlen(value)+1;
 | |
|   var_table->values[index] = malloc(value_length);
 | |
|   memcpy(var_table->values[index], value, value_length);
 | |
| }
 | |
| 
 | |
| void freeVar(struct VarTable *var_table, const char *key) {
 | |
|   int index = getVarIndex(var_table, key);
 | |
|   if (var_table->keys[index])
 | |
|     free(var_table->keys[index]);
 | |
|   if (var_table->values[index])
 | |
|     free(var_table->values[index]);
 | |
| }
 | |
| 
 | |
| char *getVar(struct VarTable *var_table, const char *key) {
 | |
|   int index = getVarIndex(var_table, key);
 | |
|   return var_table->values[index];
 | |
| }
 | |
| 
 | |
| struct Var {
 | |
|   int bytes;
 | |
|   char type;
 | |
|   char operation;
 | |
|   char *data;
 | |
| };
 | |
| 
 | |
| char* itoa(int value, char* result, int base) {
 | |
|         // check that the base if valid
 | |
| if (base < 2 || base > 36) { *result = '\0'; return result; }
 | |
| 
 | |
| char* ptr = result, *ptr1 = result, tmp_char;
 | |
| int tmp_value;
 | |
| 
 | |
| do {
 | |
|         tmp_value = value;
 | |
|         value /= base;
 | |
|         *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
 | |
|         } while ( value );
 | |
| 
 | |
|         // Apply negative sign
 | |
|         if (tmp_value < 0) *ptr++ = '-';
 | |
|         *ptr-- = '\0';
 | |
|         while(ptr1 < ptr) {
 | |
|                 tmp_char = *ptr;
 | |
|                 *ptr--= *ptr1;
 | |
|                 *ptr1++ = tmp_char;
 | |
|         }
 | |
|         return result;
 | |
| }
 | |
| 
 | |
| // TODO: replace Arguments with v_printf stuff
 | |
| void doOperation(struct VarTable *var_table, const char **args, int arg_count, char *return_string, const char *string) {
 | |
|   printf("args: %d\n", arg_count);
 | |
|   //printf("operation is %s\n", string);
 | |
|   int s_i = 0; // string iterator
 | |
|   int b_i = 0; // buffer iterator
 | |
|   int bt_i = 0; // buffer type iterator
 | |
|   char buffer[255]; // buffer that holds the portion being processed
 | |
| 
 | |
|   struct Var vars[31]; // max 31 variables
 | |
|   int var_i = 0;
 | |
|   int c_i = 0; // current var iterator
 | |
| 
 | |
|   char *f_return; // function call pointer
 | |
| 
 | |
|   while (string[s_i] != '\0') {
 | |
|     switch (string[s_i]) {
 | |
|       case '+':
 | |
|       case '-':
 | |
|       case '/':
 | |
|       case '*':
 | |
|         if (isdigit(buffer[0]))
 | |
|           vars[var_i].type = DIGIT;
 | |
|         else
 | |
|           vars[var_i].type = ALPHA;
 | |
|         buffer[b_i] = '\0';
 | |
|         if (vars[var_i].type == ALPHA) {
 | |
|           if (arg_count > 0)
 | |
|             printf("first part of arg0: %c\n", args[0][0]);
 | |
|           if (buffer[b_i-1] == ')') {
 | |
|             f_return = parseAndCallFunction(var_table, buffer);
 | |
|             vars[var_i].bytes = strlen(f_return)+1;
 | |
|             vars[var_i].data = malloc(vars[var_i].bytes);
 | |
|             strcpy(vars[var_i].data, f_return);
 | |
|             free(f_return);
 | |
|           } else {
 | |
|             vars[var_i].bytes = strlen(getVar(var_table, buffer))+1;
 | |
|             vars[var_i].data = malloc(vars[var_i].bytes);
 | |
|             strcpy(vars[var_i].data, getVar(var_table, buffer));
 | |
|           }
 | |
|         } else {
 | |
|           vars[var_i].bytes = strlen(buffer)+1;
 | |
|           vars[var_i].data = malloc(vars[var_i].bytes);
 | |
|           strcpy(vars[var_i].data, buffer);
 | |
|         }
 | |
|         memset(&buffer, '\0', 255);
 | |
|         b_i = 0;
 | |
|         vars[var_i].operation = string[s_i];
 | |
|         var_i++;
 | |
|         break;
 | |
|       case ';':
 | |
|         buffer[b_i] = '\0';
 | |
|         // determine variable type
 | |
|         if (isdigit(buffer[0]))
 | |
|           vars[var_i].type = DIGIT;
 | |
|         else
 | |
|           vars[var_i].type = ALPHA;
 | |
|         if (vars[var_i].type == ALPHA) {
 | |
|           if (buffer[b_i-1] == ')') {
 | |
|             f_return = parseAndCallFunction(var_table, buffer);
 | |
|             vars[var_i].bytes = strlen(f_return)+1;
 | |
|             vars[var_i].data = malloc(vars[var_i].bytes);
 | |
|             strcpy(vars[var_i].data, f_return);
 | |
|             free(f_return);
 | |
|           } else {
 | |
|             vars[var_i].bytes = strlen(getVar(var_table, buffer))+1;
 | |
|             vars[var_i].data = malloc(vars[var_i].bytes);
 | |
|             strcpy(vars[var_i].data, getVar(var_table, buffer));
 | |
|           }
 | |
|         } else {
 | |
|           vars[var_i].bytes = strlen(buffer)+1;
 | |
|           vars[var_i].data = malloc(vars[var_i].bytes);
 | |
|           strcpy(vars[var_i].data, buffer);
 | |
|         }
 | |
|         // "clear" buffer
 | |
|         memset(&buffer, '\0', 255);
 | |
|         b_i = 0;
 | |
|         // ALRIGHT, now let's do the operaton
 | |
|         c_i = 0;
 | |
|         while (c_i < var_i) {
 | |
|           switch (vars[c_i].operation) {
 | |
|             case '+':
 | |
|               itoa(atoi(vars[c_i].data) + atoi(vars[c_i+1].data), vars[c_i+1].data, 10); 
 | |
|               break;
 | |
|             case '-':
 | |
|               itoa(atoi(vars[c_i].data) - atoi(vars[c_i+1].data), vars[c_i+1].data, 10); 
 | |
|               break;
 | |
|             case '*':
 | |
|               itoa(atoi(vars[c_i].data) * atoi(vars[c_i+1].data), vars[c_i+1].data, 10); 
 | |
|               break;
 | |
|             case '/':
 | |
|               itoa(atoi(vars[c_i].data) / atoi(vars[c_i+1].data), vars[c_i+1].data, 10); 
 | |
|               break;
 | |
|           }
 | |
|           c_i++;
 | |
|         }
 | |
|         //printf(" = %s\n", vars[c_i].data);
 | |
|         strcpy(return_string, vars[c_i].data);
 | |
|         break;
 | |
|       case ' ':
 | |
|         break;
 | |
|       default:
 | |
|         buffer[b_i] = string[s_i];
 | |
|         b_i++;
 | |
|         break;
 | |
|     }
 | |
|     s_i++;
 | |
|   }
 | |
|   while (var_i >= 0) {
 | |
|     free(vars[var_i--].data);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void doVarSet(struct Var *var, const char *string) {
 | |
|   if (var->data)
 | |
|     free(var);
 | |
|   var->bytes = strlen(string)+1;
 | |
|   var->data = malloc(var->bytes);
 | |
|   memcpy(var->data, string, var->bytes);
 | |
| }
 | |
| 
 | |
| // TODO: use vprintf stuff for arguments (or get byte offsets?)
 | |
| char *doFunction(const char *function, const char *arguments) {
 | |
|   /* get our args from buffer, delimited by ',' */
 | |
|   int ba_i = 0;
 | |
|   char args[2][31];
 | |
|   int a_i = 0;
 | |
|   int arg_offset = 0;
 | |
|   if (arguments[ba_i] != '\0')
 | |
|     arg_offset++;
 | |
|   while (arguments[ba_i] != '\0') {
 | |
|     switch (arguments[ba_i]) {
 | |
|       case ',':
 | |
|         args[arg_offset][a_i] = '\0';
 | |
|         a_i = 0;
 | |
|         arg_offset++;
 | |
|         break;
 | |
|       case ' ':
 | |
|         break;
 | |
|       default:
 | |
|         args[arg_offset][a_i++] = arguments[ba_i];
 | |
|         break;
 | |
|     }
 | |
|     ba_i++;
 | |
|   }
 | |
|   args[arg_offset][a_i] = '\0';
 | |
|   /* okay, let's do the rolling. TODO: handle lack of args */
 | |
|   if (arg_offset > 0)
 | |
|     printf("passed arg 0: %s\n", args[0]);
 | |
| 
 | |
|   printf("running function:\n%s\n-------\n", function);
 | |
| 
 | |
|   struct VarTable *local_vars = newVarTable(127);
 | |
| 
 | |
|   int b_i = 0; // buffer iterator
 | |
|   int bt_i = 0; // buffer type iterator
 | |
|   char buffer[255]; // buffer that holds the portion being processed
 | |
| 
 | |
|   char current_var[31]; // vars cannae have more than 31 chars
 | |
|   char current_value[31];
 | |
|   current_var[0] = '\0';
 | |
|   int mode = 0;
 | |
| 
 | |
|   struct Var vars[31]; // max 31 variables
 | |
|   int var_i = 0;
 | |
|   int c_i = 0; // current var iterator
 | |
| 
 | |
|   int f_i = 0; // function char pos
 | |
|   int l_i = 0; // line pos
 | |
|   int l_c = 0; // line count
 | |
|   size_t f_bytes = 0;
 | |
|   char *f_return = malloc(1);
 | |
|   while (function[f_i] != '\0') {
 | |
|     switch(function[f_i]) {
 | |
|       case '\n':
 | |
|         l_c++;
 | |
|         break;
 | |
|       case ' ': // skip space
 | |
|         break;
 | |
|       case '=':
 | |
|         buffer[b_i] = '\0';
 | |
|         b_i = 0;
 | |
|         strcpy(current_var, buffer);
 | |
|         memset(&buffer, 0, 255);
 | |
|         mode = VAR_SET;
 | |
|         break;
 | |
|       case ';':
 | |
|         if (mode == VAR_SET) {
 | |
|           buffer[b_i++] = ';';
 | |
|           buffer[b_i] = '\0';
 | |
|           b_i = 0;
 | |
|           doOperation(local_vars, &args, arg_offset, current_value, buffer);
 | |
|           addVar(local_vars, current_var, current_value);
 | |
|         } else if (mode == RETURN) {
 | |
|           buffer[b_i] = '\0';
 | |
|           b_i = 0;
 | |
|           strcpy(current_var, buffer);
 | |
|           f_bytes = strlen(getVar(local_vars, current_var))+1;
 | |
|           realloc(f_return, f_bytes);
 | |
|           memcpy(f_return, getVar(local_vars, current_var), f_bytes);
 | |
|           freeVarTable(local_vars); // free up all our local stuff
 | |
|           return f_return;
 | |
|         }
 | |
|         break;
 | |
|       case '.':
 | |
|         if (b_i == 0) {
 | |
|           mode = RETURN;
 | |
|         } else {
 | |
|           buffer[b_i++] = function[f_i];
 | |
|         }
 | |
|         break;
 | |
|       default:
 | |
|         buffer[b_i++] = function[f_i];
 | |
|         break;
 | |
|     }
 | |
|     f_i++; // next char in func
 | |
|   }
 | |
|   freeVarTable(local_vars); // free up all our local stuff
 | |
|   return f_return;
 | |
| }
 | |
| 
 | |
| char *callFunction(const char *f_name, const char *f_args) {
 | |
|   return (doFunction(getVar(function_table, f_name), f_args));
 | |
| }
 | |
| 
 | |
| char *parseAndCallFunction(struct VarTable *var_table, const char *buffer)  {
 | |
|   int b_i = 0;
 | |
|   char f_name[32];
 | |
|   char f_args[63];
 | |
|   int f_i = 0;
 | |
|   int mode = 0;
 | |
| 
 | |
|   while (buffer[b_i] != '\0') {
 | |
|     switch (buffer[b_i]) {
 | |
|       case '(':
 | |
|         f_name[f_i] = '\0';
 | |
|         f_i = 0;
 | |
|         mode = 1;
 | |
|         break;
 | |
|       case ')':
 | |
|         f_args[f_i] = '\0';
 | |
|         f_i = 0;
 | |
|         mode = 2;
 | |
|         break;
 | |
|       case ' ':
 | |
|         break;
 | |
|       default:
 | |
|         if (mode == 0) {
 | |
|           f_name[f_i++] = buffer[b_i];
 | |
|         } else if (mode > 0) {
 | |
|           f_args[f_i++] = buffer[b_i];
 | |
|           // do something with args...
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     b_i++;
 | |
|   }
 | |
|   /* convert args son */
 | |
|   // FIXME: hackish, q'n'd
 | |
|   b_i = 0;
 | |
|   char args[10][31];
 | |
|   int a_i = 0;
 | |
|   int arg_offset = 0;
 | |
|   while (f_args[b_i] != '\0') {
 | |
|     switch (f_args[b_i]) {
 | |
|       case ',':
 | |
|         args[arg_offset][a_i] = '\0';
 | |
|         a_i = 0;
 | |
|         arg_offset++;
 | |
|         break;
 | |
|       case ' ':
 | |
|         break;
 | |
|       default:
 | |
|         args[arg_offset][a_i++] = f_args[b_i];
 | |
|         break;
 | |
|     }
 | |
|     b_i++;
 | |
|   }
 | |
|   args[arg_offset][a_i] = '\0';
 | |
|   if (f_args[0] != '\0') {
 | |
|     a_i = 0;
 | |
|     f_i = 0;
 | |
|     b_i = 0;
 | |
|     while (a_i <= arg_offset) {
 | |
|       if (!isdigit(args[a_i][0])) {
 | |
|         strcpy(args[a_i], getVar(var_table, args[a_i]));
 | |
|       }
 | |
|       //printf("%d = %s\n", a_i, args[a_i]);
 | |
|       b_i = 0;
 | |
|       while (args[a_i][b_i] != '\0') {
 | |
|         f_args[f_i++] = args[a_i][b_i++];
 | |
|       }
 | |
|       if (a_i != arg_offset)
 | |
|         f_args[f_i++] = ',';
 | |
|       a_i++;
 | |
|     }
 | |
|   }
 | |
|   f_args[f_i] = '\0';
 | |
|   if (f_name[0] == '_') {
 | |
|     //printf("trying to run %s\n", f_name);
 | |
|     return runFunc(g_functions, f_name)(f_args);
 | |
|   } else {
 | |
|     // TODO: callFunction should parse f_args as well.
 | |
|     return callFunction(f_name, f_args);
 | |
|   }
 | |
|   //return callFunction(f_name, NULL, NULL, NULL, NULL);
 | |
| }
 | |
| 
 | |
| int addFunction(const char *buffer) {
 | |
|   char func_name[32];
 | |
|   int f_size = 128;
 | |
|   char *func_data = malloc(f_size*sizeof(char)); // start w/ 128 chars
 | |
|   int f_i = 0; // func_data index offset
 | |
|   int c_i = 0; // iterator for function_name
 | |
|   int i = 0; // iterator for the buffer
 | |
|   int depth = 0;
 | |
|   while (buffer[i] != '\0') {
 | |
|     switch (buffer[i]) {
 | |
|       case ' ':
 | |
|         break;
 | |
|       case '{':
 | |
|         if (depth == 0)
 | |
|           func_name[c_i] = '\0';
 | |
|         depth++;
 | |
|         break;
 | |
|       case '}':
 | |
|         depth--;
 | |
|         break;
 | |
|       default:
 | |
|         if (depth == 0) {
 | |
|           func_name[c_i++] = buffer[i];
 | |
|         } else if (depth > 0) {
 | |
|           // resize if function surpasses our temp func_data buffer
 | |
|           if (f_i+1 >= f_size) {
 | |
|             f_size += 128;
 | |
|             realloc(func_data, f_size);
 | |
|           }
 | |
|           func_data[f_i] = buffer[i];
 | |
|           f_i++;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     i++;
 | |
|   }
 | |
|   func_data[f_i] = '\0';
 | |
|   addVar(function_table, func_name, func_data);
 | |
|   free(func_data);
 | |
|   return 0; // should handle errors for malloc...
 | |
| }
 | |
| 
 | |
| char *doRoll(const char *buffer) {
 | |
|   /* get our args from buffer, delimited by ',' */
 | |
|   int b_i = 0;
 | |
|   char args[2][31];
 | |
|   int a_i = 0;
 | |
|   int arg_offset = 0;
 | |
|   while (buffer[b_i] != '\0') {
 | |
|     switch (buffer[b_i]) {
 | |
|       case ',':
 | |
|         args[arg_offset][a_i] = '\0';
 | |
|         a_i = 0;
 | |
|         arg_offset++;
 | |
|         break;
 | |
|       case ' ':
 | |
|         break;
 | |
|       default:
 | |
|         args[arg_offset][a_i++] = buffer[b_i];
 | |
|         break;
 | |
|     }
 | |
|     b_i++;
 | |
|   }
 | |
|   args[arg_offset][a_i] = '\0';
 | |
|   /* okay, let's do the rolling. TODO: handle lack of args */
 | |
|   int count = atoi(args[0]);
 | |
|   int faces = atoi(args[1]);
 | |
|   int total = 0;
 | |
|   while (count > 0) {
 | |
|     total += (rand() % faces + 1);
 | |
|     count--;
 | |
|   }
 | |
|   /* return char array pointer that will be freed outside of this func */
 | |
|   char *f_return = malloc(24);
 | |
|   itoa(total, f_return, 10);
 | |
|   return f_return;
 | |
| }
 | |
| 
 | |
| int main() {
 | |
|   function_table = newVarTable(255);
 | |
| 
 | |
|   g_functions = newFuncTable(127); // function pointers
 | |
|   addFunc(g_functions, "_roll", doRoll);
 | |
| 
 | |
|   /* #define'd function */
 | |
|   addFunction(TEST_FULL_FUNC);
 | |
| 
 | |
|   addFunction(ROLL_FUNC);
 | |
| 
 | |
|   char *f_return;
 | |
|   f_return = callFunction("test", "");
 | |
|   printf("called func \"%s\" returned:\n%s\n", "test", f_return);
 | |
|   free(f_return);
 | |
| 
 | |
|   /* free hand this ish */
 | |
|   addFunction("add { var = 1 + 2; .var; }");
 | |
|   f_return = callFunction("add", "");
 | |
|   printf("called func \"%s\" returned:\n%s\n", "add", f_return);
 | |
|   free(f_return);
 | |
| 
 | |
|   addFunction(TEST_FUNC_CALL);
 | |
|   f_return = callFunction("fcall", "");
 | |
|   printf("called func \"%s\" returned:\n%s\n", "fcall", f_return);
 | |
|   free(f_return);
 | |
| 
 | |
|   char user_input[1024];
 | |
|   printf("Enter script:\n> ");
 | |
|   //scanf("%s", user_input);
 | |
|   fgets(user_input, 1024, stdin);
 | |
|   f_return = doFunction(user_input, "");
 | |
|   printf("return:\n%s\n", f_return);
 | |
|   free(f_return);
 | |
| 
 | |
|   freeVarTable(function_table);
 | |
|   freeFuncTable(g_functions);
 | |
| 
 | |
| /*  char *f_return;
 | |
|   f_return = doFunction(TEST_FUNC, NULL, NULL, NULL, NULL);
 | |
|   printf("return: %s\n", f_return);
 | |
|   free(f_return);*/
 | |
|   return 0;
 | |
| }
 |