diff --git a/include/gib_error.h b/include/gib_error.h index 0116a68..1adbd92 100644 --- a/include/gib_error.h +++ b/include/gib_error.h @@ -1,8 +1,11 @@ #define GIB_E_EXIT -2 #define GIB_E_RETURN -1 -#define GIB_E_PARSE 6 -#define GIB_E_NUMARGS 1 -#define GIB_E_ARG 2 -#define GIB_E_CALLS 3 -#define GIB_E_NOSUB 4 -#define GIB_E_NOVAR 5 +#define GIB_E_PARSE 1 +#define GIB_E_NUMARGS 2 +#define GIB_E_ARG 3 +#define GIB_E_CALLS 4 +#define GIB_E_NOSUB 5 +#define GIB_E_NOVAR 6 +#define GIB_E_BUFFER 7 +#define GIB_E_TYPE 8 +#define GIB_E_ULIMIT 9 diff --git a/include/gib_instructions.h b/include/gib_instructions.h index 17a0908..1b7e358 100644 --- a/include/gib_instructions.h +++ b/include/gib_instructions.h @@ -5,3 +5,10 @@ int GIB_Echo_f (void); int GIB_Call_f (void); int GIB_VarPrint_f (void); int GIB_Return_f (void); +int GIB_VarSub_f (void); +int GIB_Con_f (void); +int GIB_Eval_f (void); +int GIB_ListFetch_f (void); +int GIB_BackTick_f (void); +int GIB_ExpandVars (char *source, char *buffer, int bufferlen); +int GIB_ExpandBackticks (char *source, char *buffer, int bufferlen); diff --git a/include/gib_interpret.h b/include/gib_interpret.h index 6ccb03a..d9292c5 100644 --- a/include/gib_interpret.h +++ b/include/gib_interpret.h @@ -6,11 +6,15 @@ extern gib_sub_t *gib_currentsub[GIB_MAXCALLS]; extern int gib_subsp; extern int gib_argc[GIB_MAXCALLS]; -char *gib_argv[GIB_MAXCALLS][80]; +extern char *gib_argv[GIB_MAXCALLS][80]; + +extern int gib_argofs; extern char *GIB_SUBARGV[GIB_MAXSUBARGS]; extern int GIB_SUBARGC; +extern char errorline[1024]; + char *GIB_Argv(int i); int GIB_Argc(void); void GIB_Strip_Arg (char *arg); diff --git a/include/gib_parse.h b/include/gib_parse.h index 1fae670..eb82088 100644 --- a/include/gib_parse.h +++ b/include/gib_parse.h @@ -5,3 +5,4 @@ int GIB_End_DQuote (char *start); int GIB_End_Bracket (char *start); gib_sub_t *GIB_Get_ModSub_Sub (char *modsub); gib_module_t *GIB_Get_ModSub_Mod (char *modsub); +int GIB_ExpandEscapes (char *source); diff --git a/source/gib.c b/source/gib.c index 9ec4320..5344812 100644 --- a/source/gib.c +++ b/source/gib.c @@ -51,7 +51,7 @@ void GIB_Gib_f (void) GIB_SUBARGV[i] = Cmd_Argv(i + 1); ret = GIB_Run_Sub(mod, sub); if (ret != 0) - Con_Printf("Error in execution of %s!\nError code: %i\n", Cmd_Argv(1), ret); + Con_Printf("Error in execution of %s!\nError code: %i\n\nLine at fault: %s\n", Cmd_Argv(1), ret, errorline); } } diff --git a/source/gib_instructions.c b/source/gib_instructions.c index 0dfe574..9226853 100644 --- a/source/gib_instructions.c +++ b/source/gib_instructions.c @@ -4,6 +4,7 @@ #include #include +#include #include "cvar.h" #include "console.h" #include "qargs.h" @@ -50,11 +51,17 @@ void GIB_Init_Instructions (void) GIB_AddInstruction("call", GIB_Call_f); GIB_AddInstruction("varprint", GIB_VarPrint_f); GIB_AddInstruction("return", GIB_Return_f); + GIB_AddInstruction("varsub", GIB_VarSub_f); + GIB_AddInstruction("con", GIB_Con_f); + GIB_AddInstruction("listfetch", GIB_ListFetch_f); + GIB_AddInstruction("eval", GIB_Eval_f); + GIB_AddInstruction("backtick", GIB_BackTick_f); } + int GIB_Echo_f (void) { - Con_Printf("%s\n",GIB_Argv(1)); + Con_Printf(GIB_Argv(1)); return 0; } @@ -76,7 +83,10 @@ int GIB_Call_f (void) GIB_SUBARGV[i] = GIB_Argv(i + 1); ret = GIB_Run_Sub (mod, sub); if (gib_subret) + { GIB_Var_Set("retval", gib_subret); + free (gib_subret); + } gib_subret = 0; return ret; } @@ -104,3 +114,165 @@ int GIB_Return_f (void) strcpy(gib_subret, GIB_Argv(1)); return GIB_E_RETURN; // Signal to block executor to return immediately } + +int GIB_VarSub_f (void) +{ + char buffer[1024]; + int ret; + + if (GIB_Argc() != 1) + return GIB_E_NUMARGS; + + if ((ret = GIB_ExpandVars(GIB_Argv(1), buffer, 1024))) + return ret; + GIB_Var_Set ("retval", buffer); + return 0; +} + +int GIB_ListFetch_f (void) +{ + char *element; + gib_var_t *var; + int i, n, m; + + if (GIB_Argc() != 2) + return GIB_E_NUMARGS; + + if (!(var = GIB_Var_FindLocal(GIB_Argv(1)))) + return GIB_E_NOVAR; + for (i = 0; isspace(var->value[i]); i++); + for (n = 1; n < atoi(GIB_Argv(2)); n++) + { + if ((m = GIB_Get_Arg (var->value + i)) < 1) + return GIB_E_ULIMIT; + i += m; + for (; isspace(var->value[i]); i++); + } + if ((m = GIB_Get_Arg (var->value + i)) < 1) + return GIB_E_ULIMIT; + element = malloc(m + 1); + strncpy(element, var->value + i, m); + element[m] = 0; + GIB_Var_Set ("retval", element); + return 0; +} + +int GIB_Con_f (void) +{ + if (GIB_Argc() != 1) + return GIB_E_NUMARGS; + + Cmd_ExecuteString (GIB_Argv(1), src_command); + + return 0; +} + +int GIB_Eval_f (void) +{ + gib_var_t *var; + char *buffer; + int ret; + + if (GIB_Argc() != 1) + return GIB_E_NUMARGS; + if (!(var = GIB_Var_FindLocal (GIB_Argv(1)))) + return GIB_E_NOVAR; + buffer = malloc(strlen(var->value) + 1); + strcpy(buffer, var->value); + gib_argofs++; /* HACK HACK HACK - This is required or + GIB_Execute_Instruction will smash gib_argv */ + ret = GIB_Execute_Block (buffer, 0); + gib_argofs--; + free (buffer); + return ret; +} + +int GIB_BackTick_f (void) +{ + char buffer[1024]; + int ret; + + if (GIB_Argc() != 1) + return GIB_E_NUMARGS; + if ((ret = GIB_ExpandBackticks (GIB_Argv(1), buffer, 1024))) + return ret; + GIB_Var_Set ("retval", buffer); + return 0; +} + + +int GIB_ExpandVars (char *source, char *buffer, int buffersize) +{ + int i, n, m; + + char varname[256]; + gib_var_t *var; + + for (i = 0, n = 0; i <= strlen(source); i++) + { + if (source[i] == '$') + { + m = 0; + while(isalnum(source[++i])) + varname[m++] = source[i]; + + varname[m++] = 0; + if (!(var = GIB_Var_FindLocal (varname))) + return GIB_E_NOVAR; + if (n + strlen(var->value) >= buffersize) + return GIB_E_BUFFER; + memcpy(buffer + n, var->value, strlen(var->value)); + + n += strlen(var->value); + i--; + } + else + { + if (n >= buffersize + 1) + return GIB_E_BUFFER; + buffer[n++] = source[i]; + } + } + return 0; +} + +int GIB_ExpandBackticks (char *source, char *buffer, int buffersize) +{ + int i, n, m, ret; + + char tick[256]; + gib_var_t *var; + + for (i = 0, n = 0; i <= strlen(source); i++) + { + if (source[i] == '`') + { + m = 0; + while(source[++i] != '`') + tick[m++] = source[i]; + + tick[m++] = 0; + gib_argofs++; + ret = GIB_Execute_Inst (tick); + gib_argofs--; + if (ret) + { + return ret; + } + if (!(var = GIB_Var_FindLocal ("retval"))) + return GIB_E_NOVAR; + if (n + strlen(var->value) >= buffersize) + return GIB_E_BUFFER; + memcpy(buffer + n, var->value, strlen(var->value)); + + n += strlen(var->value); + } + else + { + if (n >= buffersize + 1) + return GIB_E_BUFFER; + buffer[n++] = source[i]; + } + } + return 0; +} \ No newline at end of file diff --git a/source/gib_interpret.c b/source/gib_interpret.c index 2d0982a..b7a7dda 100644 --- a/source/gib_interpret.c +++ b/source/gib_interpret.c @@ -29,14 +29,18 @@ int GIB_SUBARGC; int gib_argc[GIB_MAXCALLS]; char *gib_argv[GIB_MAXCALLS][80]; +int gib_argofs = 0; + +char errorline[1024]; + char *GIB_Argv(int i) { - return gib_argv[gib_subsp][i]; + return gib_argv[gib_subsp + gib_argofs][i]; } int GIB_Argc(void) { - return gib_argc[gib_subsp]; + return gib_argc[gib_subsp + gib_argofs]; } void GIB_Strip_Arg (char *arg) @@ -54,7 +58,7 @@ int GIB_Execute_Block (char *block, int retflag) char *code; i = 0; - + while ((len = GIB_Get_Inst(block + i)) > 0) { code = malloc(len + 1); @@ -65,7 +69,11 @@ int GIB_Execute_Block (char *block, int retflag) if (retflag && ret == GIB_E_RETURN) return 0; else + { + strcpy(errorline, code); + free (code); return ret; + } } free (code); i += len + 1; @@ -76,9 +84,12 @@ int GIB_Execute_Block (char *block, int retflag) int GIB_Execute_Inst (char *inst) { char *buffer; + char *buffer2; + char *buffer3; int i, n, len, ret; gib_inst_t *ginst; + buffer = malloc(strlen(inst) + 1); i = 0; @@ -93,38 +104,48 @@ int GIB_Execute_Inst (char *inst) buffer[n] = inst[i]; n++; } - gib_argc[gib_subsp] = 0; - for (i = 0; buffer[i] != ' '; i++); - gib_argv[gib_subsp][0] = malloc(i + 1); - strncpy(gib_argv[gib_subsp][0], buffer, i); - gib_argv[gib_subsp][0][i] = 0; + + + buffer2 = malloc(2048); + buffer3 = malloc(2048); + GIB_ExpandVars (buffer, buffer2, 2048); + GIB_ExpandBackticks (buffer2, buffer3, 2048); + + gib_argc[gib_subsp + gib_argofs] = 0; + for (i = 0; buffer3[i] != ' '; i++); + gib_argv[gib_subsp + gib_argofs][0] = malloc(i + 1); + strncpy(gib_argv[gib_subsp + gib_argofs][0], buffer3, i); + gib_argv[gib_subsp + gib_argofs][0][i] = 0; for (n = 0;;n++) { - for (;isspace(buffer[i]); i++); - if (buffer[i] == 0) + for (;isspace(buffer3[i]); i++); + if (buffer3[i] == 0) break; - if ((len = GIB_Get_Arg(buffer + i)) < 0) // Parse error - return len; + if ((len = GIB_Get_Arg(buffer3 + i)) < 0) // Parse error + return GIB_E_PARSE; else { - gib_argv[gib_subsp][n + 1] = malloc(len + 1); - strncpy(gib_argv[gib_subsp][n + 1], buffer + i, len); - gib_argv[gib_subsp][n + 1][len] = 0; + gib_argv[gib_subsp + gib_argofs][n + 1] = malloc(len + 1); + strncpy(gib_argv[gib_subsp + gib_argofs][n + 1], buffer3 + i, len); + gib_argv[gib_subsp + gib_argofs][n + 1][len] = 0; + GIB_ExpandEscapes (gib_argv[gib_subsp + gib_argofs][n + 1]); i += len; } } - gib_argc[gib_subsp] = n; + gib_argc[gib_subsp + gib_argofs] = n; free(buffer); + free(buffer2); + free(buffer3); for (i = 1; i <= n; i++) - GIB_Strip_Arg (gib_argv[gib_subsp][i]); - if (!(ginst = GIB_Find_Instruction(gib_argv[gib_subsp][0]))) + GIB_Strip_Arg (gib_argv[gib_subsp + gib_argofs][i]); + if (!(ginst = GIB_Find_Instruction(gib_argv[gib_subsp + gib_argofs][0]))) return 1; ret = ginst->func (); for (i = 0; i <= n; i++) - free(gib_argv[gib_subsp][i]); + free(gib_argv[gib_subsp + gib_argofs][i]); return ret; } diff --git a/source/gib_parse.c b/source/gib_parse.c index 0742437..94c4d13 100644 --- a/source/gib_parse.c +++ b/source/gib_parse.c @@ -16,7 +16,7 @@ #include "gib_modules.h" #include "gib_parse.h" #include "gib_vars.h" - +#include "gib_error.h" int GIB_Get_Inst(char *start) { @@ -40,7 +40,7 @@ int GIB_Get_Inst(char *start) } if (start[i] == '{') { - if ((len = GIB_End_DQuote(start + i)) < 0) + if ((len = GIB_End_Bracket(start + i)) < 0) return len; else i += len; @@ -73,7 +73,7 @@ int GIB_Get_Arg (char *start) } if (start[i] == '{') { - if ((len = GIB_End_DQuote(start + i)) < 0) + if ((len = GIB_End_Bracket(start + i)) < 0) return len; else i += len; @@ -87,23 +87,26 @@ int GIB_End_Quote (char *start) int len = 0; for (i = 1; start[i] != '\''; i++) { - if (start[i] == '\"') + if (start[i - 1] != '\\') { - if ((len = GIB_End_DQuote(start + i)) < 0) - return len; - else - i += len; - } - - if (start[i] == '{') - { - if ((len = GIB_End_Bracket(start +i)) < 0) - return len; - else - i += len; + if (start[i] == '\"') + { + if ((len = GIB_End_DQuote(start + i)) < 0) + return len; + else + i += len; + } + + if (start[i] == '{') + { + if ((len = GIB_End_Bracket(start +i)) < 0) + return len; + else + i += len; + } + if (start[i] == 0) + return -1; } - if (start[i] == 0) - return -1; } return i; } @@ -112,23 +115,26 @@ int GIB_End_DQuote (char *start) int i, ret; for (i = 1; start[i] != '\"'; i++) { - if (start[i] == '\'') + if (start[i - 1] != '\\') { - if ((ret = GIB_End_Quote(start + i)) < 0) - return ret; - else - i += ret; + if (start[i] == '\'') + { + if ((ret = GIB_End_Quote(start + i)) < 0) + return ret; + else + i += ret; + } + + if (start[i] == '{') + { + if ((ret = GIB_End_Bracket(start +i)) < 0) + return ret; + else + i += ret; + } + if (start[i] == 0) + return -1; } - - if (start[i] == '{') - { - if ((ret = GIB_End_Bracket(start +i)) < 0) - return ret; - else - i += ret; - } - if (start[i] == 0) - return -2; } return i; } @@ -138,32 +144,35 @@ int GIB_End_Bracket (char *start) int i, ret; for (i = 1; start[i] != '}'; i++) { - if (start[i] == '\'') + if (start[i - 1] != '\\') { - if ((ret = GIB_End_Quote(start + i)) < 0) - return ret; - else - i += ret; - } - - if (start[i] == '\"') - { - if ((ret = GIB_End_DQuote(start + i)) < 0) - return ret; - else - i += ret; - } - - if (start[i] == '{') - { - if ((ret = GIB_End_Bracket(start + i)) < 0) - return ret; - else - i += ret; - } + if (start[i] == '\'') + { + if ((ret = GIB_End_Quote(start + i)) < 0) + return ret; + else + i += ret; + } + + if (start[i] == '\"') + { + if ((ret = GIB_End_DQuote(start + i)) < 0) + return ret; + else + i += ret; + } + + if (start[i] == '{') + { + if ((ret = GIB_End_Bracket(start + i)) < 0) + return ret; + else + i += ret; + } - if (start[i] == 0) - return -3; + if (start[i] == 0) + return -1; + } } return i; } @@ -197,3 +206,29 @@ gib_module_t *GIB_Get_ModSub_Mod (char *modsub) return mod; } +int GIB_ExpandEscapes (char *source) +{ + int i, m; + for (i = 0, m = 0; i <= strlen(source); i++) + { + if (source[i] == '\\') + { + switch(source[++i]) + { + case 0: + return GIB_E_PARSE; + break; + case 'n': + case 'N': + source[m] = '\n'; + break; + default: + source[m] = source[i]; + } + } + else + source[m] = source[i]; + m++; + } + return 0; +} \ No newline at end of file diff --git a/source/gib_vars.c b/source/gib_vars.c index 695fc29..12d6a67 100644 --- a/source/gib_vars.c +++ b/source/gib_vars.c @@ -47,7 +47,6 @@ void GIB_Var_Set (char *key, char *value) gib_var_t *var; if ((var = GIB_Var_FindLocal(key))) { - Con_Printf("Value already found.\n"); free(var->value); } else