/quakeforge/branches/release_0_5_3/libs/gib/gib_builtin.c
C | 1070 lines | 869 code | 128 blank | 73 comment | 225 complexity | c9d2c5c3b61b1a9bad961d088d449238 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-3.0, AGPL-1.0, Unlicense
- /*
- #FILENAME#
- #DESCRIPTION#
- Copyright (C) 2002 #AUTHOR#
- Author: #AUTHOR#
- Date: #DATE#
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to:
- Free Software Foundation, Inc.
- 59 Temple Place - Suite 330
- Boston, MA 02111-1307, USA
- */
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- static __attribute__ ((unused))
- const char rcsid[] =
- "$Id: gib_builtin.c 9722 2003-07-15 21:40:37Z snax $";
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <dirent.h>
- #include <fnmatch.h>
- #include <errno.h>
- #include "QF/cvar.h"
- #include "QF/quakefs.h"
- #include "QF/zone.h"
- #include "QF/va.h"
- #include "QF/sys.h"
- #include "QF/cmd.h"
- #include "QF/cbuf.h"
- #include "QF/hash.h"
- #include "QF/dstring.h"
- #include "QF/gib.h"
- #include "regex.h"
- #include "gib_buffer.h"
- #include "gib_parse.h"
- #include "gib_function.h"
- #include "gib_vars.h"
- #include "gib_regex.h"
- #include "gib_thread.h"
- #include "gib_handle.h"
- #include "gib_builtin.h"
- char gib_null_string[] = "";
- hashtab_t *gib_builtins;
- /*
- Hashtable callbacks
- */
- static const char *
- GIB_Builtin_Get_Key (void *ele, void *ptr)
- {
- return ((gib_builtin_t *) ele)->name;
- }
- static void
- GIB_Builtin_Free (void *ele, void *ptr)
- {
- gib_builtin_t *b;
- b = (gib_builtin_t *) ele;
- free ((void *)b->name);
- free (b);
- }
- /*
- GIB_Builtin_Add
-
- Registers a new builtin GIB command.
- */
- void
- GIB_Builtin_Add (const char *name, void (*func) (void))
- {
- gib_builtin_t *new;
- if (!gib_builtins)
- gib_builtins =
- Hash_NewTable (1024, GIB_Builtin_Get_Key, GIB_Builtin_Free, 0);
- new = calloc (1, sizeof (gib_builtin_t));
- new->func = func;
- new->name = strdup (name);
- Hash_Add (gib_builtins, new);
- }
- void
- GIB_Builtin_Remove (const char *name)
- {
- gib_builtin_t *del;
- if ((del = Hash_Del (gib_builtins, name)))
- Hash_Free (gib_builtins, del);
- }
- qboolean
- GIB_Builtin_Exists (const char *name)
- {
- return Hash_Find (gib_builtins, name) ? true : false;
- }
- /*
- GIB_Builtin_Find
-
- Looks up the builtin name in the builtin hash,
- returning a pointer to the struct on success,
- zero otherwise.
- */
- gib_builtin_t *
- GIB_Builtin_Find (const char *name)
- {
- if (!gib_builtins)
- return 0;
- return (gib_builtin_t *) Hash_Find (gib_builtins, name);
- }
- dstring_t *
- GIB_Return (const char *str)
- {
- dstring_t *dstr;
- if (GIB_DATA (cbuf_active)->waitret) {
- dstr = GIB_Buffer_Dsarray_Get (cbuf_active);
- dstring_clearstr (dstr);
- if (!str)
- return dstr;
- else
- dstring_appendstr (dstr, str);
- }
- return 0;
- }
- void
- GIB_Error (const char *type, const char *fmt, ...)
- {
- va_list args;
- va_start (args, fmt);
- GIB_Buffer_Error (cbuf_active, type, fmt, args);
- va_end (args);
- }
- /*
- GIB Builtin functions
-
- See GIB docs for information.
- */
- static void
- GIB_Function_f (void)
- {
- gib_tree_t *program;
- if (GIB_Argc () != 3)
- GIB_USAGE ("name program");
- else {
- // Is the function program already tokenized?
- if (GIB_Argm (2)->delim != '{') {
- // Parse on the fly
- if (!(program = GIB_Parse_Lines (GIB_Argv (2), 0))) {
- // Error!
- GIB_Error ("parse", "Parse error while defining function '%s'.",
- GIB_Argv (1));
- return;
- }
- } else
- program = GIB_Argm (2)->children;
- GIB_Function_Define (GIB_Argv (1), GIB_Argv (2), program,
- GIB_DATA (cbuf_active)->script,
- GIB_DATA (cbuf_active)->globals);
- }
- }
- static void
- GIB_Function_Get_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("name");
- else {
- gib_function_t *f;
- if ((f = GIB_Function_Find (GIB_Argv (1))))
- GIB_Return (f->text->str);
- else
- GIB_Return ("");
- }
- }
- static void
- GIB_Local_f (void)
- {
- gib_var_t *var;
- unsigned int index;
- int i;
- static hashtab_t *zero = 0;
- if (GIB_Argc () < 2)
- GIB_USAGE ("var [= value1 value2 ...] || var [var2 var3 ...]");
- else if (!strcmp (GIB_Argv(2), "=")) {
- var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero,
- GIB_Argv (1), &index, true);
- if (GIB_Argc () >= 3)
- GIB_Var_Assign (var, index, cbuf_active->args->argv + 3,
- GIB_Argc () - 3, GIB_Argv (1)[strlen (GIB_Argv(1)) - 1] != ']');
- if (GIB_CanReturn ())
- for (i = 3; i < GIB_Argc(); i++)
- GIB_Return (GIB_Argv(i));
- } else for (i = 1; i < GIB_Argc(); i++)
- var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero,
- GIB_Argv (i), &index, true);
- }
- static void
- GIB_Global_f (void)
- {
- gib_var_t *var;
- unsigned int index;
- int i;
- static hashtab_t *zero = 0;
- if (GIB_Argc () < 2)
- GIB_USAGE ("var [= value1 value2 ...] || var [var2 var3 ...]");
- else if (!strcmp (GIB_Argv(2), "=")) {
- var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero,
- GIB_Argv (1), &index, true);
- if (GIB_Argc () >= 3)
- GIB_Var_Assign (var, index, cbuf_active->args->argv + 3,
- GIB_Argc () - 3, GIB_Argv (1)[strlen (GIB_Argv(1)) - 1] != ']');
- if (GIB_CanReturn ())
- for (i = 3; i < GIB_Argc(); i++)
- GIB_Return (GIB_Argv(i));
- } else for (i = 1; i < GIB_Argc(); i++)
- var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero,
- GIB_Argv (i), &index, true);
- }
- static void
- GIB_Delete_f (void)
- {
- gib_var_t *var;
- unsigned int index;
- int i;
- hashtab_t *source;
- char *c;
-
- if (GIB_Argc () < 2)
- GIB_USAGE ("var [var2 var2 ...]");
- else for (i = 1; i < GIB_Argc(); i++) {
- if ((c = strrchr (GIB_Argv(i), '.'))) {
- *(c++) = 0;
- if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals,
- &GIB_DATA(cbuf_active)->globals,
- GIB_Argv (i), &index, false)))
- continue;
- source = var->array[index].leaves;
- } else {
- c = GIB_Argv(i);
- source = GIB_DATA(cbuf_active)->globals;
- }
- Hash_Free (source, Hash_Del (source, c));
- }
- }
- static void
- GIB_Domain_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("domain");
- else
- GIB_DATA (cbuf_active)->globals = GIB_Domain_Get (GIB_Argv (1));
- }
- static void
- GIB_Domain_Clear_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("domain");
- else
- Hash_FlushTable (GIB_Domain_Get (GIB_Argv (2)));
- }
- static gib_tree_t fakeip = {0,0,0,0,0,0,0,0};
- static void
- GIB_Return_f (void)
- {
- cbuf_t *sp = cbuf_active->up;
- GIB_DATA (cbuf_active)->ip = &fakeip;
- if (GIB_Argc () > 1 && sp && sp->interpreter == &gib_interp
- && GIB_DATA (sp)->waitret) {
- int i;
- dstring_t *dstr;
- for (i = 1; i < GIB_Argc (); i++) {
- dstr = GIB_Buffer_Dsarray_Get (sp);
- dstring_clearstr (dstr);
- dstring_appendstr (dstr, GIB_Argv (i));
- }
- }
- }
- static void
- GIB_For_f (void)
- {
- dstring_t *dstr;
- int i;
- GIB_Buffer_Push_Sstack (cbuf_active);
- dstr = GIB_Buffer_Dsarray_Get (cbuf_active);
- dstring_clearstr (dstr);
- dstring_appendstr (dstr, GIB_Argv (1));
- for (i = GIB_Argc () - 2; i > 2; i--) {
- dstr = GIB_Buffer_Dsarray_Get (cbuf_active);
- dstring_appendstr (dstr, GIB_Argv (i));
- }
- }
- // Note: this is a standard console command, not a GIB builtin
- static void
- GIB_Runexported_f (void)
- {
- gib_function_t *f;
- const char **args;
- if (!(f = GIB_Function_Find (Cmd_Argv (0))))
- Sys_Printf ("Error: No function found for exported command \"%s\".\n"
- "This is most likely a bug, please report it to"
- "The QuakeForge developers.", Cmd_Argv (0));
- else {
- cbuf_t *sub = Cbuf_PushStack (&gib_interp);
- int i;
- args = malloc (sizeof (char *) * Cmd_Argc());
- for (i = 0; i < Cmd_Argc(); i++)
- args[i] = Cmd_Argv(i);
- GIB_Function_Execute (sub, f, args, Cmd_Argc());
- free (args);
- }
- }
- static void
- GIB_Function_Export_f (void)
- {
- gib_function_t *f;
- int i;
- if (GIB_Argc () < 2)
- GIB_USAGE ("function1 [function2 function3 ...]");
- for (i = 1; i < GIB_Argc (); i++) {
- if (!(f = GIB_Function_Find (GIB_Argv (i))))
- GIB_Error ("function", "%s: function '%s' not found.", GIB_Argv (0),
- GIB_Argv (i));
- else if (!f->exported) {
- if (Cmd_Exists (f->name)) {
- GIB_Error ("export",
- "%s: A console command with the name '%s' already exists.",
- GIB_Argv (0), GIB_Argv (i));
- return;
- } else {
- Cmd_AddCommand (f->name, GIB_Runexported_f,
- "Exported GIB function.");
- f->exported = true;
- }
- }
- }
- }
- static void
- GIB_Length_f (void)
- {
- dstring_t *ret;
- if (GIB_Argc () != 2)
- GIB_USAGE ("string");
- else if ((ret = GIB_Return (0)))
- dsprintf (ret, "%i", (int) strlen (GIB_Argv (1)));
- }
- static void
- GIB_Equal_f (void)
- {
- if (GIB_Argc () != 3)
- GIB_USAGE ("string1 string2");
- else if (strcmp (GIB_Argv (1), GIB_Argv (2)))
- GIB_Return ("0");
- else
- GIB_Return ("1");
- }
- static void
- GIB_Count_f (void)
- {
- if (GIB_CanReturn())
- dsprintf (GIB_Return(0), "%u", GIB_Argc() - 1);
- }
-
- static void
- GIB_Contains_f (void)
- {
- int i;
- if (GIB_Argc () < 2)
- GIB_USAGE ("needle [straw1 straw2 ...]");
- else if (GIB_CanReturn())
- for (i = 2; i < GIB_Argc(); i++)
- if (!strcmp(GIB_Argv(1), GIB_Argv(i))) {
- GIB_Return("1");
- return;
- }
- GIB_Return ("0");
- }
- static void
- GIB_Slice_f (void)
- {
- dstring_t *ret;
- int start, end, len;
- if (GIB_Argc () < 3 || GIB_Argc () > 4)
- GIB_USAGE ("string start [end]");
- else {
- len = strlen (GIB_Argv (1));
- start = atoi (GIB_Argv (2));
- end = *GIB_Argv (3) ? atoi (GIB_Argv (3)) : len;
- if (end < 0)
- end += len;
- else if (end > len)
- end = len;
- if (start < 0) {
- start += len;
- if (start < 0)
- start = 0;
- } else if (start >= len || start >= end)
- return;
- if ((ret = GIB_Return (0)))
- dstring_appendsubstr (ret, GIB_Argv (1) + start, end - start);
- }
- }
- static void
- GIB_Slice_Find_f (void)
- {
- char *res;
- if (GIB_Argc () != 3) {
- GIB_USAGE ("haystack needle");
- return;
- } else if (!GIB_CanReturn ())
- return;
- else if ((res = strstr (GIB_Argv (1), GIB_Argv (2)))) {
- dsprintf (GIB_Return (0), "%lu",
- (unsigned long int) (res - GIB_Argv (1)));
- dsprintf (GIB_Return (0), "%lu",
- (unsigned long int) (res - GIB_Argv (1)) +
- strlen (GIB_Argv (2)));
- }
- }
- static void
- GIB_Split_f (void)
- {
- char *end, *start;
- const char *ifs;
- if (GIB_Argc () < 2 || GIB_Argc () > 3) {
- GIB_USAGE ("string [fs]");
- return;
- }
- ifs = GIB_Argc () == 3 ? GIB_Argv (2) : " \t\r\n";
- end = GIB_Argv (1);
- while (*end) {
- for (; strchr (ifs, *end); end++)
- if (!*end)
- return;
- start = end;
- while (!strchr (ifs, *end))
- end++;
- if (*end)
- *(end++) = 0;
- GIB_Return (start);
- }
- }
- static void
- GIB_Chomp_f (void)
- {
- char *str;
- const char *junk;
- unsigned int i;
- if (GIB_Argc () < 2 || GIB_Argc () > 3) {
- GIB_USAGE ("string [junk]");
- return;
- }
- str = GIB_Argv (1);
- if (GIB_Argc () == 2)
- junk = " \t\n\r";
- else
- junk = GIB_Argv (2);
- for (; *str && strchr (junk, *str); str++);
- for (i = strlen(str) - 1; i && strchr (junk, str[i]); i--);
- str[i+1] = 0;
- GIB_Return (str);
- }
- static void
- GIB_Regex_Match_f (void)
- {
- regex_t *reg;
- if (GIB_Argc () != 4) {
- GIB_USAGE ("string regex options");
- return;
- }
- if (!
- (reg =
- GIB_Regex_Compile (GIB_Argv (2),
- REG_EXTENDED |
- GIB_Regex_Translate_Options (GIB_Argv (3)))))
- GIB_Error ("regex", "%s: %s", GIB_Argv (0), GIB_Regex_Error ());
- else if (regexec (reg, GIB_Argv (1), 0, 0, GIB_Regex_Translate_Runtime_Options (GIB_Argv (3))))
- GIB_Return ("0");
- else
- GIB_Return ("1");
- }
- static void
- GIB_Regex_Replace_f (void)
- {
- regex_t *reg;
- int ofs, len;
- regmatch_t match[10];
- if (GIB_Argc () != 5) {
- GIB_USAGE ("string regex options replacement");
- return;
- }
- ofs = 0;
- len = strlen (GIB_Argv (4));
- if (!
- (reg =
- GIB_Regex_Compile (GIB_Argv (2),
- REG_EXTENDED |
- GIB_Regex_Translate_Options (GIB_Argv (3)))))
- GIB_Error ("regex", "%s: %s", GIB_Argv (0), GIB_Regex_Error ());
- else if (strchr (GIB_Argv (3), 'g'))
- while (!regexec
- (reg, GIB_Argv (1) + ofs, 10, match, ofs > 0 ? REG_NOTBOL : 0)
- && match[0].rm_eo)
- ofs +=
- GIB_Regex_Apply_Match (match, GIB_Argd (1), ofs, GIB_Argv (4));
- else if (!regexec (reg, GIB_Argv (1), 10, match, GIB_Regex_Translate_Runtime_Options (GIB_Argv (3))) && match[0].rm_eo)
- GIB_Regex_Apply_Match (match, GIB_Argd (1), 0, GIB_Argv (4));
- GIB_Return (GIB_Argv (1));
- }
- static void
- GIB_Regex_Extract_f (void)
- {
- regex_t *reg;
- regmatch_t *match;
- int i;
- char o;
- if (GIB_Argc () != 4) {
- GIB_USAGE ("string regex options");
- return;
- } else if (!GIB_CanReturn ())
- return;
- match = calloc (32, sizeof (regmatch_t));
- if (!
- (reg =
- GIB_Regex_Compile (GIB_Argv (2),
- REG_EXTENDED |
- GIB_Regex_Translate_Options (GIB_Argv (3)))))
- GIB_Error ("regex", "%s: %s", GIB_Argv (0), GIB_Regex_Error ());
- else if (!regexec (reg, GIB_Argv (1), 32, match, GIB_Regex_Translate_Runtime_Options (GIB_Argv (3))) && match[0].rm_eo) {
- dsprintf (GIB_Return (0), "%lu", (unsigned long) match[0].rm_eo);
- for (i = 0; i < 32; i++) {
- if (match[i].rm_so != -1) {
- o = GIB_Argv (1)[match[i].rm_eo];
- GIB_Argv (1)[match[i].rm_eo] = 0;
- GIB_Return (GIB_Argv (1) + match[i].rm_so);
- GIB_Argv (1)[match[i].rm_eo] = o;
- }
- }
- }
- free (match);
- }
- static void
- GIB_Text_White_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("text");
- else if (GIB_CanReturn ()) {
- unsigned int i;
- dstring_t *dstr;
- char *str;
- dstr = GIB_Return (0);
- dstring_appendstr (dstr, GIB_Argv(1));
- str = dstr->str;
- for (i = 0; i < dstr->size-1; i++)
- str[i] = str[i] & ~0x80;
- }
- }
- static void
- GIB_Text_Brown_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("text");
- else if (GIB_CanReturn ()) {
- unsigned int i;
- dstring_t *dstr;
- char *str;
- dstr = GIB_Return (0);
- dstring_appendstr (dstr, GIB_Argv(1));
- str = dstr->str;
- for (i = 0; i < dstr->size-1; i++)
- str[i] = str[i] | 0x80;
- }
- }
- /*
- static void
- GIB_Text_To_Gold_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("text");
- else if (GIB_CanReturn ()) {
- dstring_t *dstr;
- char *str;
- dstr = GIB_Return (0);
- dstring_copystr (dstr, GIB_Argv(1));
- for (str = dstr->str; *str; str++) {
- switch (*str) {
- */
- static void
- GIB_Text_To_Decimal_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("text");
- else if (GIB_CanReturn ()) {
- char *str;
- for (str = GIB_Argv(1); *str; str++)
- dsprintf (GIB_Return (0), "%i", (int) *str);
- }
- }
- static void
- GIB_Text_From_Decimal_f (void)
- {
- if (GIB_Argc () < 2)
- GIB_USAGE ("num1 [...]");
- else if (GIB_CanReturn ()) {
- unsigned int i;
- dstring_t *dstr;
- char *str;
- dstr = GIB_Return (0);
- dstr->size = GIB_Argc();
- dstring_adjust (dstr);
- str = dstr->str;
- for (i = 1; i < GIB_Argc(); i++, str++)
- *str = (char) atoi (GIB_Argv(i));
- *str = 0;
- }
- }
- static void
- GIB_Thread_Create_f (void)
- {
- gib_function_t *f;
- if (GIB_Argc () < 2)
- GIB_USAGE ("function [arg1 arg2 ...]");
- else if (!(f = GIB_Function_Find (GIB_Argv (1))))
- GIB_Error ("function", "%s: no function named '%s' exists.",
- GIB_Argv (0), GIB_Argv (1));
- else {
- gib_thread_t *thread = GIB_Thread_New ();
- GIB_Function_Execute_D (thread->cbuf, f, cbuf_active->args->argv + 1,
- cbuf_active->args->argc - 1);
- GIB_Thread_Add (thread);
- if (GIB_CanReturn ())
- dsprintf (GIB_Return (0), "%lu", thread->id);
- }
- }
- static void
- GIB_Thread_Kill_f (void)
- {
- if (GIB_Argc () != 2)
- GIB_USAGE ("id");
- else {
- gib_thread_t *thread;
- cbuf_t *cur;
- unsigned long int id = strtoul (GIB_Argv (1), 0, 10);
- thread = GIB_Handle_Get (id, gib_thread_class);
- if (!thread) {
- GIB_Error ("thread", "%s: thread %lu does not exist.", GIB_Argv (0), id);
- return;
- }
- // If we are currently running this thread, set an error state so we exit it cleanly
- // if it were simply nuked, a crash would result
- for (cur = thread->cbuf; cur->down && cur->down->state != CBUF_STATE_JUNK; cur = cur->down)
- if (cur == cbuf_active) {
- cur->state = CBUF_STATE_ERROR;
- return;
- }
- GIB_Thread_Remove (thread);
- GIB_Thread_Delete (thread);
- }
- }
- static void
- GIB_Thread_List_f (void)
- {
- if (GIB_Argc () != 1)
- GIB_USAGE ("");
- else if (GIB_CanReturn ()) {
- gib_thread_t *cur;
- for (cur = gib_thread_first; cur; cur = cur->next)
- dsprintf (GIB_Return (0), "%lu", cur->id);
- }
- }
- static void
- GIB_Event_Register_f (void)
- {
- gib_function_t *func;
- if (GIB_Argc () != 3)
- GIB_USAGE ("event function");
- else if (!(func = GIB_Function_Find (GIB_Argv (2))) && GIB_Argv (2)[0])
- GIB_Error ("function", "Function %s not found.", GIB_Argv (2));
- else if (GIB_Event_Register (GIB_Argv (1), func))
- GIB_Error ("event", "Event %s not found.", GIB_Argv (1));
- }
- /* File access */
- int (*GIB_File_Transform_Path) (dstring_t * path) = NULL;
- static int
- GIB_File_Transform_Path_Null (dstring_t * path)
- {
- char *s;
- // Convert backslash to forward slash
- for (s = strchr (path->str, '\\'); s; s = strchr (s, '\\'))
- *s = '/';
- return 0;
- }
- static int
- GIB_File_Transform_Path_Secure (dstring_t * path)
- {
- char *s;
- for (s = strchr (path->str, '\\'); s; s = strchr (s, '\\'))
- *s = '/';
- if (Sys_PathType (path->str) != PATHTYPE_RELATIVE_BELOW)
- return -1;
- dstring_insertstr (path, 0, "/");
- dstring_insertstr (path, 0, qfs_gamedir->dir.def);
- dstring_insertstr (path, 0, "/");
- dstring_insertstr (path, 0, qfs_userpath);
- return 0;
- }
- static void
- GIB_File_Read_f (void)
- {
- QFile *file;
- char *path;
- int len;
- dstring_t *ret;
- if (GIB_Argc () != 2) {
- GIB_USAGE ("file");
- return;
- }
- if (!*GIB_Argv (1)) {
- GIB_Error ("file", "%s: null filename provided", GIB_Argv (0));
- return;
- }
- if (!(ret = GIB_Return (0)))
- return;
- path = GIB_Argv (1);
- QFS_FOpenFile (path, &file);
- if (file) {
- len = Qfilesize (file);
- ret->size = len + 1;
- dstring_adjust (ret);
- Qread (file, ret->str, len);
- ret->str[len] = 0;
- Qclose (file);
- } else {
- GIB_Error ("file",
- "%s: could not read %s: %s", GIB_Argv (0), path,
- strerror (errno));
- return;
- }
- }
- static void
- GIB_File_Write_f (void)
- {
- char *path;
- if (GIB_Argc () != 3) {
- GIB_USAGE ("file data");
- return;
- }
- if (!*GIB_Argv (1)) {
- GIB_Error ("file", "%s: null filename provided", GIB_Argv (0));
- return;
- }
- path = GIB_Argv (1);
- QFS_WriteFile (va ("%s/%s", qfs_gamedir->dir.def, path),
- GIB_Argv(2), GIB_Argd(2)->size-1);
- }
- static void
- GIB_File_Find_f (void)
- {
- DIR *directory;
- struct dirent *entry;
- const char *path, *glob = 0;
- char *s;
- if (GIB_Argc () != 2) {
- GIB_USAGE ("glob");
- return;
- }
- if (GIB_File_Transform_Path (GIB_Argd (1))) {
- GIB_Error ("access",
- "%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
- return;
- }
- path = GIB_Argv (1);
- s = strrchr (path, '/');
- if (!s) { // No slash in path
- glob = path; // The glob is the entire argument
- path = "."; // The path is the current directory
- } else if (s == path) // Unix filesystem root (carne only)
- path = "/";
- else {
- *s = 0; // Split the string at the final slash
- glob = s + 1;
- }
- directory = opendir (path);
- if (!directory) {
- GIB_Error ("file",
- "%s: could not open directory %s: %s", GIB_Argv (0), path,
- strerror (errno));
- return;
- }
- while ((entry = readdir (directory)))
- if (strcmp (entry->d_name, ".") && strcmp (entry->d_name, "..")
- && !fnmatch (glob, entry->d_name, 0))
- GIB_Return (entry->d_name);
- closedir (directory);
- }
- static void
- GIB_File_Move_f (void)
- {
- char *path1, *path2;
- if (GIB_Argc () != 3) {
- GIB_USAGE ("from_file to_file");
- return;
- }
- if (GIB_File_Transform_Path (GIB_Argd (1))) {
- GIB_Error ("access",
- "%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
- return;
- }
- if (GIB_File_Transform_Path (GIB_Argd (2))) {
- GIB_Error ("access",
- "%s: access to %s denied", GIB_Argv (0), GIB_Argv (2));
- return;
- }
- path1 = GIB_Argv (1);
- path2 = GIB_Argv (2);
- if (QFS_Rename (path1, path2))
- GIB_Error ("file", "%s: could not move %s to %s: %s", GIB_Argv (0),
- path1, path2, strerror (errno));
- }
- static void
- GIB_File_Delete_f (void)
- {
- char *path;
- if (GIB_Argc () != 2) {
- GIB_USAGE ("file");
- return;
- }
- if (GIB_File_Transform_Path (GIB_Argd (1))) {
- GIB_Error ("access",
- "%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
- return;
- }
- path = GIB_Argv (1);
- if (QFS_Remove (path))
- GIB_Error ("file", "%s: could not delete %s: %s", GIB_Argv (0), path,
- strerror (errno));
- }
- static void
- GIB_Range_f (void)
- {
- double i, inc, start, limit;
- dstring_t *dstr;
- if (GIB_Argc () < 3 || GIB_Argc () > 4) {
- GIB_USAGE ("lower upper [step]");
- return;
- }
- limit = atof (GIB_Argv (2));
- start = atof (GIB_Argv (1));
- if (GIB_Argc () == 4) {
- if ((inc = atof (GIB_Argv (3))) == 0.0)
- return;
- } else
- inc = limit < start ? -1.0 : 1.0;
- for (i = atof (GIB_Argv (1)); inc < 0 ? i >= limit : i <= limit; i += inc) {
- if (!(dstr = GIB_Return (0)))
- return;
- dsprintf (dstr, "%.10g", i);
- }
- }
- static void
- GIB_Print_f (void)
- {
- if (GIB_Argc () != 2) {
- GIB_USAGE ("text");
- return;
- }
- Sys_Printf ("%s", GIB_Argv (1));
- }
- static void
- GIB_bp1_f (void)
- {
- }
- static void
- GIB_bp2_f (void)
- {
- }
- static void
- GIB_bp3_f (void)
- {
- }
- static void
- GIB_bp4_f (void)
- {
- }
- void
- GIB_Builtin_Init (qboolean sandbox)
- {
- if (sandbox)
- GIB_File_Transform_Path = GIB_File_Transform_Path_Secure;
- else
- GIB_File_Transform_Path = GIB_File_Transform_Path_Null;
- GIB_Builtin_Add ("function", GIB_Function_f);
- GIB_Builtin_Add ("function::get", GIB_Function_Get_f);
- GIB_Builtin_Add ("function::export", GIB_Function_Export_f);
- GIB_Builtin_Add ("local", GIB_Local_f);
- GIB_Builtin_Add ("global", GIB_Global_f);
- GIB_Builtin_Add ("delete", GIB_Delete_f);
- GIB_Builtin_Add ("domain", GIB_Domain_f);
- GIB_Builtin_Add ("domain::clear", GIB_Domain_Clear_f);
- GIB_Builtin_Add ("return", GIB_Return_f);
- GIB_Builtin_Add ("for", GIB_For_f);
- GIB_Builtin_Add ("length", GIB_Length_f);
- GIB_Builtin_Add ("equal", GIB_Equal_f);
- GIB_Builtin_Add ("count", GIB_Count_f);
- GIB_Builtin_Add ("contains", GIB_Contains_f);
- GIB_Builtin_Add ("slice", GIB_Slice_f);
- GIB_Builtin_Add ("slice::find", GIB_Slice_Find_f);
- GIB_Builtin_Add ("split", GIB_Split_f);
- GIB_Builtin_Add ("chomp", GIB_Chomp_f);
- GIB_Builtin_Add ("regex::match", GIB_Regex_Match_f);
- GIB_Builtin_Add ("regex::replace", GIB_Regex_Replace_f);
- GIB_Builtin_Add ("regex::extract", GIB_Regex_Extract_f);
- GIB_Builtin_Add ("text::toWhite", GIB_Text_White_f);
- GIB_Builtin_Add ("text::toBrown", GIB_Text_Brown_f);
- GIB_Builtin_Add ("text::toDecimal", GIB_Text_To_Decimal_f);
- GIB_Builtin_Add ("text::fromDecimal", GIB_Text_From_Decimal_f);
- GIB_Builtin_Add ("thread::create", GIB_Thread_Create_f);
- GIB_Builtin_Add ("thread::kill", GIB_Thread_Kill_f);
- GIB_Builtin_Add ("thread::getList", GIB_Thread_List_f);
- GIB_Builtin_Add ("event::register", GIB_Event_Register_f);
- GIB_Builtin_Add ("file::read", GIB_File_Read_f);
- GIB_Builtin_Add ("file::write", GIB_File_Write_f);
- GIB_Builtin_Add ("file::find", GIB_File_Find_f);
- GIB_Builtin_Add ("file::move", GIB_File_Move_f);
- GIB_Builtin_Add ("file::delete", GIB_File_Delete_f);
- GIB_Builtin_Add ("range", GIB_Range_f);
- GIB_Builtin_Add ("print", GIB_Print_f);
- GIB_Builtin_Add ("bp1", GIB_bp1_f);
- GIB_Builtin_Add ("bp2", GIB_bp2_f);
- GIB_Builtin_Add ("bp3", GIB_bp3_f);
- GIB_Builtin_Add ("bp4", GIB_bp4_f);
- }